web-dev-qa-db-fra.com

Où est le sel sur le chiffrement OpenSSL AES?

Je souhaite savoir comment et où OpenSSL insère le sel généré sur des données cryptées AES. Pourquoi? Je crypte les données dans les classes Java et je dois garantir que je peux utiliser OpenSSL pour les décrypter.

Par exemple, supposons que j'ai cette chaîne base64 chiffrée, générée avec la phrase secrète "abc":

U2FsdGVkX1+tfvgUkjErP6j2kUAVwWZzNlaAmTqhzTk= 

# generated with "openssl enc -aes-256-cbc -a"

Pour le décrypter, nous pouvons utiliser:

echo U2FsdGVkX1+tfvgUkjErP6j2kUAVwWZzNlaAmTqhzTk= | openssl enc -d -a -aes-256-cbc -p

# enc -d
#     decryption
# -a 
#     input is base64
# -aes-256-cbc 
#     the aes algorithm used in encryption
# -p 
#     print salt, key and iv params

L'exécution à l'aide de "abc" la phrase secrète entraînera:

salt=AD7EF81492312B3F
key=DEC1F5A1E5EAAA7DD539BBCFCEB1BB18868B974186ED056C27046ADD3A752C8B
iv =95A770DE9E0130E77C8E5D796D1B4EF5
Polaco

Maintenant, nous savons que pour que AES déchiffre les données, il a besoin de la clé et du vecteur d'initialisation.

Dans le cas d'OpenSSL, le manuel indique que la clé est générée à partir de la phrase secrète et d'un sel, et que le vecteur d'initialisation est dérivé de la clé elle-même (s'il n'est pas spécifié manuellement). Cela signifie que les données générées n'ont pas besoin d'avoir l'IV dessus, mais elles doivent avoir le sel dessus, sinon la clé de déchiffrement ne sera jamais générée correctement.

Donc, le point est, où est le sel et comment est-il inséré dans les données résultantes? En faisant une analyse de base sur les données générées (décodage à partir de base64 et sortie des valeurs hexadécimales), nous pouvons voir que le sel n'est pas ajouté ou ajouté aux données résultantes, mais il est en quelque sorte là:

# salt: AD7EF81492312B3F
echo U2FsdGVkX1+tfvgUkjErP6j2kUAVwWZzNlaAmTqhzTk= | openssl enc -d -base64 | od -x                                                                                                                                                                                         
0000000 6153 746c 6465 5f5f 7ead 14f8 3192 3f2b
0000020 f6a8 4091 c115 7366 5636 9980 a13a 39cd
0000040

Vous pouvez voir que le sel "AD7E..." n'est pas directement présent dans les données chiffrées. On dirait qu'une transformation s'est produite.

Il semble que le sel soit changé paire par paire et inséré dans les données, en commençant par l'octet # 9. Est-ce une pratique courante ou quelque chose que seul OpenSSL implémente?

# salt:                     AD7E F814 9231 2B3F
# switch pair by pair:      7EAD 14F8 3192 3F2B
# data: 6153 746c 6465 5f5f 7ead 14f8 3192 3f2b f6a8 4091 c115 7366 5636 9980 a13a 39cd

Éditer

Comme l'a déclaré Thomas Pornin, le problème ici est que od -x sort les données brutes. Comme mon ordinateur est x86_64, les données sont en petit endian et le sel a l'air "échangé". J'avais oublié comment endianness est délicat. Maintenant, je me souviendrai toujours d'utiliser od -t x1

Quoi qu'il en soit, je suis toujours intéressé de savoir si l'insertion du sel au 9e octet est une pratique courante ou une implémentation spécifique à OpenSSL. J'ai également remarqué que les premiers octets sont les caractères Salted__

18
bcap

Oui, une transformation s'est produite: endianité ...

Regardez les octets 8 à 15: 7ead 14f8 3192 3f2b. C'est ton sel. C'est une bizarrerie connue de od: il décode les données par unités de 16 bits, little-endian , puis les affiche "numériquement" , cela entraîne donc un échange d'octets apparent.

Utilisation od -t x1 pour obtenir une sortie plus agréable.

Edit: pour répondre à votre autre question, ce qu'OpenSSL fait n'est ni standard ni pratique courante; c'est juste "ce qu'OpenSSL a toujours fait". Ce n'est pas bien documenté.

13
Thomas Pornin

Les versions précédentes de openssl utilisaient un processus de dérivation de clé très faible pour dériver une clé de chiffrement à partir du mot de passe. La version 1.1.1 de openssl prend désormais en charge la dérivation de clés à l'aide de PBKDF2 avec un sel généré de manière aléatoire et plusieurs itérations (10 000 par défaut) de hachage sha256. Cette réponse est basée sur openssl version 1.1.1, utilisant PBKDF2 avec un sel généré aléatoirement et 10 000 itérations de sha256 pour dériver une clé (et iv) du mot de passe.

Tout d'abord, utilisez openssl pour crypter du texte en clair, en utilisant le processus de dérivation de clé décrit ci-dessus:

echo -n 'this is the plaintext' | openssl aes-256-cbc -e -salt -pbkdf2 -iter 10000 -out ciphertext.enc -p

Pour plus d'informations sur les options utilisées dans la commande openssl ci-dessus, voir https://www.openssl.org/docs/man1.1.1/man1/openssl-enc.html . L'option -p est utilisée pour que openssl affiche le sel, la clé et iv. Après avoir entré le mot de passe, l'option -p produit:

salt=7EFCC65B38A0ACAA
key=5A81937CD1FBB6A32C2DB9BDB2AAE5CB47D82198ED861C0C1AF6CAA18B21295E
iv =D829763E72F2DFEEBEFAA30E12E29266

xxd peut être utilisé pour afficher les octets dans le fichier de texte chiffré produit par openssl:

xxd ciphertext.enc 

Cela produit:

00000000: 5361 6c74 6564 5f5f 7efc c65b 38a0 acaa  Salted__~..[8...
00000010: 5d4d 957f 380e 71ba 4a1c 0913 43ee 5791  ]M..8.q.J...C.W.
00000020: 0c29 c5c8 9f0c 1c0e f8d5 c453 e7c1 b3b6  .).........S....

Comme vous pouvez le voir, les huit premiers octets du fichier sont les codes ascii de la chaîne "Salted__". Ensuite, les huit octets suivants sont le sel lui-même, les mêmes que ceux affichés dans la sortie produite par l'option -p dans la commande openssl utilisée ci-dessus pour crypter le texte en clair.

La commande suivante peut être utilisée pour déchiffrer le fichier de texte chiffré:

openssl aes-256-cbc -d -salt -pbkdf2 -iter 10000 -in ciphertext.enc -p

Encore une fois, l'option -p est utilisée pour afficher le sel, la clé et iv. Après avoir entré le mot de passe, l'option -p affiche le même sel, la même clé et iv que précédemment. Ensuite, le texte chiffré est déchiffré, produisant le texte en clair d'origine:

salt=0E2FC30932D8371F
key=88DA1F925B6B64A36844FC0EC33A2DBB01B6F72C98AE36602217D00E126AC237
iv =1D5F234D86FA64C208A59FC1BA3AC915
this is the plaintext

Pour ce que ça vaut, le iv est généré par la fonction PBKDF2, ainsi que la clé. La fonction PBKDF2 génère 48 octets. Les octets 0 à 31 sont la clé. Les octets 32-47 sont le iv. Pour plus d'informations, voir https://crypto.stackexchange.com/questions/3298/is-there-a-standard-for-openssl-interoperable-aes-encryption/79855#79855 .

0
mti2935