J'ai crypté une chaîne avec AES 256-bit (mode CBC) en utilisant BouncyCastle (techniquement, SpongyCastle) sous Android et connecté les valeurs codées en base64 du texte chiffré, clé et iv. J'ai ensuite écrit un programme de test (en tant que test d'instrument Android) qui code les trois valeurs codées en base64. Il décrypte avec succès quand je cours le code ci-dessous sous Android.AES256-CBC Ciphertext de BouncyCastle décrypte en BC, mais PHP openssl_decrypt échoue w/mêmes entrées
Le même texte chiffré, la même clé et le même code iv encodés en base64 échouent sous PHP (5.6.30). J'ai du mal à comprendre pourquoi. Dans les deux cas, le texte chiffré, la clé et l'iv commencent tous par des chaînes encodées en base64 codées en dur avec exactement les mêmes valeurs.
Entre autres choses, il se plaint que la longueur de clé (32 octets) est invalide (la dernière fois que j'ai vérifié, 32 * 8 == 256).
applications (SpongyCastle) Code:
@Test
public void crossplatformTest() {
String ciphertext64 = "gfcC6t1BarndpzMuvYj2JFpWHqlWSJMhTtxPN7QjyEg=";
String key64 = "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8=";
String iv64="AAECAwQFBgcICQoLDA0ODw==";
byte[] ciphertext = Base64.decode(ciphertext64, Base64.DEFAULT);
byte[] key = Base64.decode(key64, Base64.DEFAULT);
byte[] iv = Base64.decode(iv64, Base64.DEFAULT);
byte[] decrypted = Crypto.decryptWithAesCBC(ciphertext, key, iv);
// the following assertion succeeds.
assertEquals("Ugh! Endless grief!", new String(decrypted, StandardCharsets.UTF_8));
}
PHP (OpenSSL) Code:
<?php
$ciphertext64 = "gfcC6t1BarndpzMuvYj2JFpWHqlWSJMhTtxPN7QjyEg=";
$key64 = "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8=";
$iv64="AAECAwQFBgcICQoLDA0ODw==";
// UPDATE: THE LINE BELOW IS THE PROBLEM. SEE ANSWER FOR SOLUTION.
$decrypted = openssl_decrypt($ciphertext64, 'aes-256-cbc', $key64, 0, $iv64);
if ($decrypted == false) {
while ($msg = openssl_error_string())
echo "<p>$msg</p>\n";
echo("key length=" . strlen(base64_decode($key64, true))."<BR>\n");
echo("iv length=" . strlen(base64_decode($iv64, true))."<BR>\n");
}
la sortie de PHP:
error:0607A082:digital envelope routines:EVP_CIPHER_CTX_set_key_length:invalid key length
error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt
key length=32
iv length=16
Ac En raison de la petite documentation pour openssl_decrypt qui semble exister sur php.net (http://php.net/manual/en/function.openssl-decrypt.php), openssl_decrypt veut des chaînes codées en base64 pour le texte chiffré, la clé et iv.
Pour ce que ça vaut la peine, voici le code que j'utilisé pour chiffrer la chaîne d'origine, et le code que je utilise sur Android pour décrypter:
public static byte[] decryptWithAesCBC(byte[] ciphertext, byte[] key, byte[] iv) {
try {
PaddedBufferedBlockCipher aes = new PaddedBufferedBlockCipher(new CBCBlockCipher(new AESEngine()));
CipherParameters ivAndKey = new ParametersWithIV(new KeyParameter(key), iv);
aes.init(false, ivAndKey);
return cipherData(aes, ciphertext);
}
catch (InvalidCipherTextException e) {
throw new RuntimeException(e);
}
}
private static byte[] cipherData(PaddedBufferedBlockCipher cipher, byte[] data) throws InvalidCipherTextException {
int minSize = cipher.getOutputSize(data.length);
byte[] outBuf = new byte[minSize];
int length1 = cipher.processBytes(data, 0, data.length, outBuf, 0);
int length2 = cipher.doFinal(outBuf, length1);
int actualLength = length1 + length2;
byte[] ciphertext = new byte[actualLength];
for (int x=0; x < actualLength; x++) {
ciphertext[x] = outBuf[x];
}
return ciphertext;
}
public static byte[] encryptWithAesCBC(byte[] plaintext, byte[] key, byte[] iv) {
try {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding", "SC");
PaddedBufferedBlockCipher aes = new PaddedBufferedBlockCipher(new CBCBlockCipher(new AESEngine()));
CipherParameters ivAndKey = new ParametersWithIV(new KeyParameter(key), iv);
aes.init(true, ivAndKey);
return cipherData(aes, plaintext);
}
catch (NoSuchAlgorithmException | NoSuchProviderException | NoSuchPaddingException | InvalidCipherTextException e) {
throw new RuntimeException(e);
}
}
commentaires Lire dans la documentation http://php.net/manual/es/function.openssl-decrypt.php, il ressemble à IV et le mot de passe devrait être binaire (pas base64). Je suppose que vous avez besoin de 'base64_decode' en premier – pedrofb
Hmmm ... J'ai eu l'impression inverse du premier commentaire, qui dit" $ data peut être comme la description dit brut ou base64 .Si aucune option $ n'est définie (c'est, si valeur de 0 est passé dans ce paramètre), les données seront supposées être codées en base64. " – Bitbang3r
Oui, c'est déroutant, mais dans le second commentaire, l'auteur dit explicitement: _Le paramètre string $ password doit être sous forme binaire_ – pedrofb