web-dev-qa-db-fra.com

Comment diviser un fichier PEM

Note: Ce n'est pas vraiment une question car j'ai déjà trouvé la réponse mais comme je ne l'ai pas trouvée facilement ici je vais la poster pour qu'elle puisse profiter aux 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 :

Suivre @slugchewer answer , csplit pourrait être une option plus claire avec:

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

C'était précédemment répondu sur StackOverflow :

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

Modifier le 29/03/2016 : Voir @slugchewer réponse

16
Cerber

L'extrait 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 sur 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
26

La commande split est disponible sur la plupart des systèmes et son appel est probablement plus facile à retenir.

Si vous avez un fichier collection.pem que vous souhaitez diviser en individual-* fichiers, utilisez:

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

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

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

Si vous souhaitez obtenir un seul certificat à partir d'un ensemble PEM multi-certificats, essayez:

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

source1 , source2

6
cmcginty

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

3
mgalgs

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é 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 (qui sont des outils puissants mais pas toujours disponibles, c'est-à-dire 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, retournez la plus longue correspondance de sous-chaîne, puis concattez -----END CERTIFICATE----- Au fur et à 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, retourne la correspondance de sous-chaîne la plus courte, puis supprime les nouvelles lignes de début. De même, le * Correspond à tous les caractères avant -----END CERTIFICATE-----.

Pour une référence rapide (alors que vous pouvez en savoir plus sur la manipulation de chaînes dans bash 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 depuis la fin du contenu de VAR

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

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

2
Fabio

Hmmm ... presque de la même manière que j'ai préparé la solution (comme suggéré y @Cerber) sans réaliser que cette situation semble avoir beaucoup de gens. Ma solution suit presque la même logique mais utilise des commandes plus basiques:

Tous mes certificats 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

Cela continue essentiellement à écrire dans un fichier jusqu'à ce qu'il rencontre "END", puis commence à écrire dans un autre fichier de manière incrémentée. De cette façon, vous aurez un nombre "N" de fichiers de sortie (certout0.pem, certout1.pem et ainsi de suite ..) fichiers en fonction du nombre de certificats présents dans votre fichier pem d'entrée (certin.pem).

0
Ashish K Srivastava