Encoder et décoder une chaîne
printf '%s' 'héllo wörld' | openssl base64 # aMOpbGxvIHfDtnJsZA==
echo 'aMOpbGxvIHfDtnJsZA==' | openssl base64 -d # héllo wörld
openssl base64 est un raccourci pour openssl enc -base64 ; les deux écritures acceptent les mêmes options. Utilisez printf '%s' pour encoder, afin qu’aucun saut de ligne ne se glisse dans les données, et echo pour décoder, pour la raison expliquée ci-dessous.
Le piège du saut de ligne final et -A
Par défaut, OpenSSL traite le Base64 comme des lignes de texte terminées par un saut de ligne. Au décodage, une dernière ligne sans \n est ignorée : cette commande n’affiche donc rien du tout.
printf 'aGVsbG8K' | openssl base64 -d # (no output)
printf 'aGVsbG8K\n' | openssl base64 -d # hello
printf 'aGVsbG8K' | openssl base64 -d -A # hello
-A indique à OpenSSL de traiter toute l’entrée comme une seule ligne. Utilisez-le dans les deux sens :
- À l’encodage : sans
-A, la sortie est coupée à 64 caractères par ligne. Avec-A, vous obtenez une seule ligne, ce dont ont besoin les en-têtes HTTP, le JSON et les variables d’environnement. - Au décodage : avec
-A, l’entrée doit tenir sur une seule ligne, sans saut de ligne. Sans-A, une entrée sur plusieurs lignes, comme le corps d’un PEM, se décode sans problème.
head -c 60 /dev/zero | tr '\0' x | openssl base64 # 64 chars, newline, 16 chars
head -c 60 /dev/zero | tr '\0' x | openssl base64 -A # 80 chars on one line
Le découpage à 64 caractères correspond au format PEM (RFC 7468), pas à MIME, qui va jusqu’à 76. Pour une sortie MIME, l’encodeur Base64 MIME ou GNU base64 (76 par défaut) conviennent mieux.
Base64 URL-safe
OpenSSL n’a pas de mode Base64URL. Convertissez avec tr :
printf '%s' '<<???>>' | openssl base64 -A | tr '+/' '-_' | tr -d '='
# PDw_Pz8-Pg
Pour décoder, inversez la correspondance et rétablissez le remplissage ; la page Base64 en Bash propose une boucle qui le fait. OpenSSL ignore lui-même - et _ sans rien dire, comme le montre la suite : ne lui passez jamais directement une entrée URL-safe. Base64 ou Base64URL explique la différence.
Encoder et décoder des fichiers
openssl base64 -in photo.jpg -out photo.b64
openssl base64 -d -in photo.b64 -out photo-copy.jpg
OpenSSL travaille en flux : les gros fichiers ne posent pas de problème. Un fichier aléatoire de 100 Ko a survécu à l’aller-retour octet pour octet. Le fichier encodé est coupé à 64 caractères et se termine par un saut de ligne : le décoder sans -A fonctionne donc. S’il vous faut un fichier d’une seule ligne, ajoutez -A à l’encodage et de nouveau au décodage.
Pour une data URI :
printf 'data:image/jpeg;base64,%s' "$(openssl base64 -A -in photo.jpg)"
La section BUGS du manuel enc d’OpenSSL 3.5 mentionne toujours deux problèmes liés : -A « doesn’t work properly » avec les gros fichiers, et au décodage sans -A, si les 1024 premiers octets de l’entrée ne contiennent aucun saut de ligne, les deux premières lignes sont ignorées. Pour un gros fichier d’une seule ligne, coupez-le d’abord avec fold -w 64 et décodez sans -A.
Échecs silencieux : valider le résultat
OpenSSL ne signale pas le Base64 invalide. Il s’arrête sur les données fautives, écrit ce qu’il a décodé et se termine avec le code 0. Résultats avec OpenSSL 3.5 :
| Entrée | Sortie | Code de sortie |
|---|---|---|
aGVsbG8K + saut de ligne | hello\n | 0 |
aGVsbG8K (sans saut de ligne) | rien | 0 |
aGk + saut de ligne (sans remplissage) | rien | 0 |
aGk=!! + saut de ligne | rien | 0 |
PDw_Pz8-Pg== + saut de ligne (URL-safe) | rien | 0 |
not base64 at all + saut de ligne | rien | 0 |
Les scripts doivent donc vérifier eux-mêmes la sortie :
n=$(echo "$b64" | openssl base64 -d | wc -c)
[ "$n" -gt 0 ] || echo "decode failed or input was empty" >&2
Cela détecte les échecs complets, mais pas les échecs partiels, où OpenSSL a décodé un début de chaîne avant de tomber sur des données invalides.
Sinon, passez à GNU base64 -d, qui affiche base64: invalid input et se termine avec le code 1. Pour savoir ce qui ne va pas dans une chaîne précise, le validateur Base64 signale le caractère fautif, et les erreurs Base64 courantes en expliquent les causes.
Hachages, clés et sortie chiffrée
La plupart du temps, OpenSSL produit du Base64 en combinaison avec d’autres commandes :
printf '%s' hi | openssl dgst -sha256 -binary | openssl base64 -A
# j0NDRmSPa5bfid2pAcUXaxCm2Dlh3TwayItZstwyeqQ=
openssl rand -base64 32 # 32 random bytes -> 44 characters
La première forme produit des empreintes SHA-256 en Base64, ce qu’utilisent les hachages SRI et de nombreuses signatures d’API ; la version navigateur est l’outil SHA-256 en Base64. -binary est essentiel : sans lui, vous encodez le texte hexadécimal du hachage, pas le hachage lui-même.
openssl rand -base64 32 est un moyen courant de créer des secrets et des clés ; le générateur de clés Base64 fait la même chose dans le navigateur.
openssl enc avec -a (équivalent de -base64) encode le texte chiffré en Base64 :
printf '%s' 'secret text' | openssl enc -aes-256-cbc -pbkdf2 -a -pass pass:demo
# U2FsdGVkX1/eMk5T8FT9dX8OyAxLRn/ukvgmovOQOeA= (salt is random, changes every run)
Le préfixe U2FsdGVkX1 est le Base64 de Salted__. Le décoder sans le mot de passe ne révèle rien de lisible. Cette différence entre encoder et chiffrer est traitée dans encodage ou chiffrement.
Fichiers PEM
Les certificats et les clés au format PEM sont du DER en Base64 entre des lignes -----BEGIN ...-----, coupé à 64 caractères. OpenSSL les convertit directement, sans manipulation Base64 à la main :
openssl x509 -in cert.pem -outform der -out cert.der
openssl x509 -in cert.der -inform der -outform pem
Pour inspecter un bloc PEM dans le navigateur, utilisez le décodeur de certificat ou PEM en DER.
FAQ
Pourquoi openssl base64 -d n'affiche-t-il rien ?
Soit l’entrée n’a pas de saut de ligne final, soit elle est invalide. Sans -A, OpenSSL attend des lignes terminées par un saut de ligne et abandonne discrètement une dernière ligne qui n’en a pas. Ajoutez -A, ou utilisez echo au lieu de printf '%s' pour envoyer la chaîne.
openssl base64 et openssl enc -base64, c'est la même chose ?
Oui. openssl base64 est un raccourci pour openssl enc -base64, et les deux acceptent -d, -A, -in et -out.
Comment savoir si openssl base64 -d a réussi ?
Le code de sortie ne suffit pas : une entrée invalide renvoie le code 0 avec une sortie vide ou partielle. Vérifiez que la sortie n’est pas vide, ou utilisez GNU base64 -d, qui se termine avec le code 1 sur une entrée invalide.
Que signifie U2FsdGVkX1 au début d'une chaîne Base64 ?
C’est le Base64 de Salted__, l’en-tête qu’openssl enc écrit devant les données chiffrées quand un mot de passe est utilisé. La chaîne est un texte chiffré : la décoder donne du bruit binaire, pas le texte en clair.