如何将此PHP算法移植到Java并获得相同的加密结果


How to port this PHP algorithm to Java and get the same encryption results

我的任务是将此代码移植到Java:

define('SALT', 'my_salt');
function auth_encrypt($text){
    return trim(base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, SALT, $text, MCRYPT_MODE_ECB, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND))));
 }

我已经用Java实现了这一点,这是我目前所知道的最好的方法,但我既不是加密专家,也不是PHP专家(充其量是新手)。有人能帮我弄清楚如何完成下面的块,这样我在Java中的输出就和他们在PHP中的输出一样吗?

byte[] sessionKey = Base64.encodeBase64("my_salt".getBytes());
byte[] iv = Base64.encodeBase64("WHAT-GOES-HERE??".getBytes());
byte[] plaintext = rawText.getBytes();
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(sessionKey, "AES"), new IvParameterSpec(iv));
byte[] ciphertext = cipher.doFinal(plaintext);
return new String(ciphertext, "UTF8");

ECB模式与CBC模式不同。由于ECB模式不使用初始化向量(IV),因此不必将其传递给Cipher#init

但这并不能解决您的问题,因为MCRYPT_RIJNDAEL_256是块大小为256位的Rijndael,而AES是块大小128位的Rijindael。默认的安全提供程序通常不会在Java中提供Rijndael,因此您将不得不使用非标准的提供程序,如BouncyCastle(示例)。


安全注意事项:

  • 永远不要使用ECB模式,因为它在语义上不安全
  • CBC模式提供了语义安全性,但只能使用不可预测的(随机读取)IV。IV不一定是秘密的,所以你可以在解密前将其预处理到密文中并切片
  • 对密文进行身份验证可以防止许多攻击。您可以使用GCM或EAX等身份验证模式,也可以应用HMAC-SHA256等具有强大MAC功能的先加密后MAC方案