【发布时间】:2020-08-19 06:31:26
【问题描述】:
我需要将数据从 PHP 迁移到 JAVA 应用程序。
数据已使用此 PHP 函数加密:
function encrypt($text, $encryptionKey) {
return utf8_encode(base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $encryptionKey, $text, MCRYPT_MODE_CBC, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0")));
}
...使用此函数可以成功解密:
function decrypt($text, $encryptionKey) {
return utf8_decode(rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $encryptionKey, base64_decode($text), MCRYPT_MODE_CBC, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0")));
}
它存储在 MySql-InnoDB 中,collation=latin1_swedish_ci 在一个表中,charset=utf8 在 VARCHAR(255) 列中。
在 JAVA 中,数据通过使用 Hibernate 的 JPA 存储库检索,然后呈现给此 基于Rijndael 256 encryption with Java & Bouncy Castle 的方法:
protected String decryptRijndael256_(String encryptedBase64Text) {
byte[] encryptedBytes = Base64.getDecoder().decode(encryptedBase64Text.getBytes(StandardCharsets.UTF_8));
byte[] key = encryptionKey.getBytes(StandardCharsets.UTF_8);
RijndaelEngine rijndaelEngine = new RijndaelEngine(256);
KeyParameter keyParam = new KeyParameter(key);
rijndaelEngine.init(false, keyParam);
PaddedBufferedBlockCipher bufferedBlock = new PaddedBufferedBlockCipher(rijndaelEngine, new ZeroBytePadding());
byte[] decryptedBytes = new byte[bufferedBlock.getOutputSize(encryptedBytes.length)];
int processed = bufferedBlock.processBytes(encryptedBytes, 0, encryptedBytes.length, decryptedBytes, 0);
processed += bufferedBlock.doFinal(decryptedBytes, processed);
decryptedBytes = Arrays.copyOfRange(decryptedBytes, 0, processed);
return new String(decryptedBytes, StandardCharsets.UTF_8);
}
虽然这在加密文本如下所示的大多数情况下都有效:
5VTv/x2f41Aj2iES7B9lRUi8Q9gH3MYnSR3xc4X1di4= => account.name@gmail.com
...如果文本很长并且看起来像这样,则会失败:
p77KGdWlexQXLGPZzkAqk2OK6oC9r7TDfMfaDhofu0et7RaPcA0hUCq0mBnY4oakjZpIrBeMadwhYonVKwJlGw== => very.long.account.name@gmail.c���ե{.c��@*�c�ꀽ���|���G
所以它大部分被正确解码,但最后一个块似乎是问题所在。我怀疑问题出在字符编码或MCRYPT_MODE_CBC 及其IV (\0\0...) 上。
我还没有找到任何方法将模式和 IV 添加到 java 实现中。
关于 Base64 加密。我从java.util.Base64、org.apache.commons.codec.binary.Base64 和org.bouncycastle.util.encoders.Base64 尝试了任何可能的方法。
结果要么如上,要么:
org.bouncycastle.crypto.DataLengthException: last block incomplete in decryption
at org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher.doFinal(Unknown Source)
我的猜测是问题与 PHP 如何进行填充有关。
问题:
PHP 和 JAVA 处理解密的方式有何不同?如何正确解码所有值?
(PHP:5.6.40,JAVA:11.0.7_10 Amazon Corretto)
【问题讨论】:
-
仅供参考:MCrypt 扩展已被弃用了 很长 时间,并在 PHP7 中被删除。此外,Rijndael 密码有时几乎是 AES,但实际上并非如此,如果您将数据迁移到实际的 AES,您的生活会更轻松。
-
@Sammitch 以及它的遗留代码,因此我们正在迁移 - 使用一种我有点过敏的语言 - 但是现在看起来我可能还需要使用一些 PHP 进行迁移,除非我得到答案在这里
标签: java php base64 mcrypt rijndael