Java descifra el mensaje openssl_encrypt de PHP. Siempre obtiene una discrepancia de etiqueta.
Estoy intentando implementar un método de descifrado para texto cifrado con php openssl_encrypted. Tengo la iv codificada en Base64, la etiqueta codificada en Base64 y el texto cifrado. Sin embargo, mi código siempre me muestra esta excepción: Exception in thread “main” javax.crypto.AEADBadTagException: Tag mismatch! ¿Alguna idea de lo que hice mal en el código de abajo?
Código PHP
<? php
//$key should have been previously generated in a cryptographically safe way, like opensslrandompseudo_bytes
$key="jKtbuVSQlhfbxF0zVjZh1839DLTNSvS5";
$plaintext = "121";
$cipher = "aes-128-gcm";
if (inarray($cipher, opensslgetciphermethods()))
{
$ivlen = opensslcipherivlength($cipher);
$iv = opensslrandompseudobytes($ivlen);
echo "iv " . base64_encode($iv) . "\n";
$ciphertext = openssl_encrypt($plaintext, $cipher, $key, $options=0, $iv, $tag);
echo "ciphertext " . $ciphertext . "\n";
echo "tag " . base64_encode($tag) . "\n";
echo "final message: " . base64_encode($iv) . ":" . base64_encode($tag) . ":" . $ciphertext . "\n";
//store $cipher, $iv, and $tag for decryption later
$original_plaintext = openssl_decrypt($ciphertext, $cipher, $key, $options=0, $iv, $tag);
echo $original_plaintext."\n";
}
?>
Código Java
String ENCRYPT_ALGO = "AES/GCM/NoPadding";
SecretKeySpec secretKeySpec = new SecretKeySpec("jKtbuVSQlhfbxF0zVjZh1839DLTNSvS5" . substring(0,16) . getBytes(), "AES");
//"Base64 encoded iv:Base64 encoded tag:cipherText"
String[] chunks = "Axb5mI6ULfBrYjRC:A2Uxa8sFa8j1gK2YNZ6UTw==:PmAR".split(":");
Cipher cipher = Cipher.getInstance(ENCRYPT_ALGO);
byte[] iv = Base64.getDecoder().decode(chunks[0]);
byte[] tag = Base64.getDecoder().decode(chunks[1]);
byte[] cipherText = Base64.getDecoder().decode(chunks[2]);
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, new GCMParameterSpec(tag.length * 8, iv));
byte[] destination = new byte[cipherText.length + tag.length];
System.arraycopy(cipherText, 0, destination, 0, cipherText.length);
System.arraycopy(tag, 0, destination, cipherText.length, tag.length);
byte[] plainText = cipher.doFinal(destination);
System.out.println("Decrypted Text : " + new String(plainText));
davy.ai
Parece que le falta el parámetro $options en su llamada a openssl_decrypt. Según la documentación, el parámetro $options debe estar configurado en OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING al utilizar el cifrado aes-128-gcm.