Comment diviser un fichier PEM


38

Note: Ce n'est pas vraiment une question parce que j'ai déjà trouvé la réponse, mais comme je ne l'ai pas trouvée facilement ici, je la posterai afin que cela profite à d'autres.

Question: Comment lire un fichier PEM concaténé comme celui utilisé par la directive apache / mod_ssl SSLCACertificateFile ?

Réponse (originale) ( source ):

cat $file|awk 'split_after==1{n++;split_after=0} /-----END CERTIFICATE-----/ {split_after=1} {print > "cert" n ".pem"}'

Cela peut laisser un fichier vide s'il y a une ligne vide à la fin, comme avec openssl pkcs7 -outform PEM -in my-chain-file -print_certs. Pour éviter cela, vérifiez la longueur de la ligne avant d’imprimer:

cat $file|awk 'split_after==1{n++;split_after=0}
   /-----END CERTIFICATE-----/ {split_after=1}
   {if(length($0) > 0) print > "cert" n ".pem"}' 

Réponse 29/03/2016 :

Après la réponse de @slugchewer , cela csplitpourrait être une option plus claire avec:

csplit -f cert- $file '/-----BEGIN CERTIFICATE-----/' '{*}'

C'est peut-être une question idiote, mais pourquoi aurais-je besoin de scinder mon fichier PEM?
— Ashwani Agarwal

6
@AshwaniAgarwal Vous souhaitez fractionner un fichier PEM contenant plusieurs certificats et examiner individuellement les certificats à l'aide d'outils tels que ceux-ci, opensslqui prennent un certificat à analyser.
— Law29

De plus, certains outils ou serveurs veulent un fichier combiné avec cert et clé, alors que d'autres veulent les séparer.
— captncraig

J'ai dû ajouter '% ----- BEGIN CERTIFICATE -----%' à la ligne de commande csplit pour empêcher un fichier vide. Semble correspondre à ce que la page de manuel spécifie: csplit -f ./tmp/cert- $ file '% ----- BEGIN CERTIFICATE -----%' '/ ----- BEGIN CERTIFICATE ----- / '' {*} '
— Craig Hicks

2
utilisez "csplit -z" pour ne pas laisser de fichiers vides.
— Paul M

Réponses:


23

L'extrait de code awk fonctionne pour extraire les différentes parties, mais vous devez toujours savoir quelle section est la clé / cert / chaîne. J'avais besoin d'extraire une section spécifique et je l'ai trouvée dans la liste de diffusion OpenSSL: http://openssl.6102.n7.nabble.com/Convert-pem-to-crt-and-key-files-tp47681p47697.html

# Extract key
openssl pkey -in foo.pem -out foo-key.pem

# Extract all the certs
openssl crl2pkcs7 -nocrl -certfile foo.pem |
  openssl pkcs7 -print_certs -out foo-certs.pem

# Extract the textually first cert as DER
openssl x509 -in foo.pem -outform DER -out first-cert.der

nice command set :) Je le garderai pour une utilisation future, mais dans mon cas d'utilisation ci-dessus, je travaille avec un fichier contenant uniquement des certificats contenant plus de 50 certificats CA ==> pas de clé ni de chaîne
— Cerber

2
Je pense que ceci est supérieur à la solution awk, laissez l'OpenSL faire l'analyse + vous obtenez la conversion.
— Rusty

Je suis désolé mais seule la commande pkey est correcte. Les deuxième et troisième ne font pas ce que vous annoncez - ils font autre chose. Dans certains cas, le résultat est bon. Dans certains cas, il peut générer des comportements mystérieux chez les consommateurs. Édité un peu.
— Kubanczyk

Avez-vous une idée de comment obtenir le 3ème certificat textuel de cette manière?
— papillotement le


15

La splitcommande est disponible sur la plupart des systèmes et son invocation est probablement plus facile à mémoriser.

Si vous collection.pemvoulez diviser un fichier en individual-*fichier, utilisez:

split -p "-----BEGIN CERTIFICATE-----" collection.pem individual-

Si vous n'en avez pas split, vous pouvez essayer csplit:

csplit -f individual- collection.pem '/-----BEGIN CERTIFICATE-----/' '{*}'

2
Désolé, aucun de mes systèmes (busybox, fedora, centos) n'affiche d' -poption (ni les pages de manuel que j'ai lues ) sur split. Peut-être utilisez-vous un paquet / paquet spécial
— Cerber

1
@Cerber pourrait essayer à la csplitplace ... (voir modification ci-dessus)
— squidpickles

1
fonctionne bien avec csplit!
— Cerber

Sur FreeBSD, je reçois de csplit: csplit: *}: bad repetition count(mais la scission semble fonctionner)
— Gwyneth Llewelyn

4

Si vous souhaitez extraire un seul certificat d'un ensemble PEM à plusieurs certificats, essayez:

$ openssl crl2pkcs7 -nocrl -certfile INPUT.PEM | \
    openssl pkcs7 -print_certs | \
    awk '/subject.*CN=host.domain.com/,/END CERTIFICATE/'
  • Les deux premières opensslcommandes traiteront un fichier PEM et le cracheront en ajoutant des lignes avant "subject:"et "issuer:"après chaque certificat. Si votre PEM est déjà formaté de cette façon, tout ce dont vous avez besoin est la awkcommande finale .
  • La commande awk crache le PEM individuel correspondant à la chaîne CN (nom commun).

source1 , source2


Je ne vois pas cela dans votre source. De plus, les PEM sont encodés en Base64, vous ne trouverez pas de texte comme "sujet", "CN", ... avec awk
— Cerber

1
Oui, cela ne fonctionne pas pour tous les types de PEM. Si vous extrayez un fichier P7B vers PEM à l'aide de openssl, une ligne d'objet apparaît avant chaque certificat. Ou vous pouvez modifier n'importe quelle chaîne avec laquelle vous segmentez votre fichier PEM.
— cmcginty

Réponse mise à jour à traiter lorsque PEM ne contient pas "subject"
— cmcginty

3

Il convient également de noter que les fichiers PEM sont simplement une collection de clés / certificats à l'intérieur de BEGIN/ ENDblocs, il est donc assez facile de simplement couper / coller s'il ne s'agit que d'un seul fichier avec une ou deux entités intéressantes ...


2

Si vous gérez des certificats de chaîne complète (c'est-à-dire ceux générés par letsencrypt / certbot, etc.), qui sont une concaténation du certificat et de la chaîne d'autorité de certification, vous pouvez utiliser la manipulation de chaîne bash.

Par exemple:

# content of /path/to/fullchain.pem
-----BEGIN CERTIFICATE-----
some long base64 string containing
the certificate
-----END CERTIFICATE-----

-----BEGIN CERTIFICATE-----
another base64 string
containing the first certificate
in the authority chain
-----END CERTIFICATE-----

-----BEGIN CERTIFICATE-----
another base64 string
containing the second certificate
in the authority chain
(there might be more...)
-----END CERTIFICATE-----

Pour extraire le certificat et la chaîne d'autorités de certification en variables:

# load the certificate into a variable
FULLCHAIN=$(</path/to/fullchain.pem)
CERTIFICATE="${FULLCHAIN%%-----END CERTIFICATE-----*}-----END CERTIFICATE-----"
CHAIN=$(echo -e "${FULLCHAIN#*-----END CERTIFICATE-----}" | sed '/./,$!d')

Explication:

Au lieu d'utiliser awk ou openssl (outils puissants mais pas toujours disponibles, par exemple dans les images Docker Alpine), vous pouvez utiliser la manipulation de chaîne bash.

"${FULLCHAIN%%-----END CERTIFICATE-----*}-----END CERTIFICATE-----": à partir de la fin du contenu de FULLCHAIN, retourne la correspondance de sous-chaîne la plus longue, puis concatte à -----END CERTIFICATE-----mesure qu'elle est supprimée. Le *correspond à tous les caractères après -----END CERTIFICATE-----.

$(echo -e "${FULLCHAIN#*-----END CERTIFICATE-----}" | sed '/./,$!d'): depuis le début du contenu de FULLCHAIN, renvoie la correspondance de sous-chaîne la plus courte, puis supprime les nouvelles lignes principales. De même, le *correspond à tous les caractères avant -----END CERTIFICATE-----.

Pour une référence rapide (pour en savoir plus sur la manipulation de chaîne dans bash, cliquez ici ):

${VAR#substring}= la sous-chaîne la plus courte depuis le début du contenu de VAR

${VAR%substring}= la sous-chaîne la plus courte de la fin du contenu de VAR

${VAR##substring}= la plus longue sous-chaîne depuis le début du contenu de VAR

${VAR%%substring}= la plus longue sous-chaîne à partir de la fin du contenu de VAR


Pour les moins avertis, lorsque vous renvoyez en écho ces variables, entourez-les de guillemets afin de préserver la ligne. Je me souviens quand ce n'était pas si évident pour moi. Fabio, bon usage de la manipulation des cordes bash!
— Scintillement du

0

Hmmm ... presque de la même manière, j'ai préparé la solution (comme suggéré y @Cerber) sans me rendre compte que cette situation semble être répandue. Ma solution suit à peu près la même logique mais utilise quelques commandes plus basiques:

Mes tous les certs sont dans le fichier: certin.pem

c=0
while read line
  do
    if echo $line | grep END; then
    echo $line >> certout$c.pem
    c=`expr $c + 1`
    else
     echo $line
     echo $line >> certout$c.pem
    fi
done < /tmp/certin.pem

En gros, cela continue à écrire dans un fichier jusqu’à rencontrer "END", puis commence à écrire dans un autre fichier de manière incrémentée. De cette manière, vous aurez "N" nombre de fichiers de sortie ( certout0.pem, certout1.pem , etc.) en fonction du nombre de certificats présents dans votre fichier PEM d’entrée ( certin.pem ).

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.