Java和PHP之间的加密不匹配

我正在研究一种将数据传递给第三方应用程序的加密系统。 加密是用Java完成的,解密是用PHP完成的。 尽管多次尝试,但我无法通过PHP应用程序打开加密字符串。

出于测试目的,我创建了一个PHP脚本,它也加密了数据,因此我可以比较Java和PHP加密的字符串。 结果与第21个字符匹配,然后它们不同。 这就是我所拥有的:

// Java - Encrypt private String EncryptAES(String text,String key) throws Exception { SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes(), "AES"); // Instantiate the cipher Cipher cipher = Cipher.getInstance("AES"); cipher.init(Cipher.ENCRYPT_MODE, skeySpec); byte[] encrypted = cipher.doFinal(text.getBytes()); String encrypttext = new BASE64Encoder().encode(encrypted); return encrypttext; } RESULT: TeUZAFxoFoQy/roPm5tXyPzJP/TLAwR1aIGn2xHbZpsbY1qrKwXfO+F/DAqmeTwB0b8e6dsSM+Yy0zrQt22E2Q== 

 // PHP - Encrypt  RESULT: TeUZAFxoFoQy/roPm5tXyC05wta1Z5YOXcq4OtgFoSbfVi/bHAuD6B5tDthT8EcGXQir08UAx0QvcqRJ2fJmbQ== 

显然正在做的事情正确,因为部分字符串匹配,但显然并非一切都是正确的,因为其余部分不匹配。 此外,如果我尝试在PHP中解密Java字符串,则没有任何反应:

 // PHP - Decrypt <?php $toDecrypt = "TeUZAFxoFoQy/roPm5tXyPzJP/TLAwR1aIGn2xHbZpsbY1qrKwXfO+F/DAqmeTwB0b8e6dsSM+Yy0zrQt22E2Q=="; $decrypt = openssl_decrypt($toDecrypt,"AES256",""); echo $decrypt; ?> RESULT:  

有没有人有任何想法可能会发生什么?

由于两个加密字符串都以相同的字符开头,因此看起来您在一个中使用ECB而在另一个中使用CBC。

这个怎么样(在你的PHP中解密):

 $toDecrypt = "TeUZAFxoFoQy/roPm5tXyPzJP/TLAwR1aIGn2xHbZpsbY1qrKwXfO+F/DAqmeTwB0b8e6dsSM+Yy0zrQt22E2Q=="; $decrypt = openssl_decrypt(base64_decode($toDecrypt),"AES256","key-32-char-long"); echo $decrypt; 

你应该解密base64解码的字符串并解密你应该调用openssl_decrypt而不是openssl_encrypt 🙂

你在java中使用getBytes

而是使用getBytes(Charset)方法来确保与php中使用的密钥和明文相同的编码

(将字节数组转储到两者中并在继续之前查看它们是否匹配)

一些评论:

  • 密钥大小在java程序中不明确
  • 你检查了两个程序的分组密码操作模式是什么? 加拿大广播公司,欧洲央行,OFB等……? 有些人可能需要IV来加密加密数据。
  • 最后的想法:Java和PHP程序使用的填充是什么?

本文档可以帮助您:您拥有所有有效组合密码/分组密码模式/填充模式/密钥大小。

我刚刚开始工作了。 要做的是在填充之前将字符串编码为UTF-8,然后将字节数组发送到加密。 UTF-8将重音字符表示为两个hex字节c3 xx,因此如果转换后的字符串包含需要编码的字符,则它将更长。 顺便说一句,c3字符是“A”,顶部带有“〜”,所以如果你的解密出现了这些奇怪的字符,那么你就没有重新编码解密。

 import java.security.NoSuchAlgorithmException; 

import javax.crypto.Cipher; import javax.crypto.NoSuchPaddingException; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec;

import android.util.Log;

公共课MCrypt {

 private IvParameterSpec ivspec; private SecretKeySpec keyspec; private Cipher cipher; private String iv = "cant hear you"; private String SecretKey = "top secret"; public MCrypt() { ivspec = new IvParameterSpec(iv.getBytes()); keyspec = new SecretKeySpec(SecretKey.getBytes(), "AES"); try { cipher = Cipher.getInstance("AES/CBC/NoPadding"); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (NoSuchPaddingException e) { e.printStackTrace(); } } public byte[] encrypt(String text) throws Exception{ if(text == null || text.length() == 0) throw new Exception("Empty string"); byte[] bs = text.getBytes("UTF-8"); byte[] toEncrypt = padBytes(bs); byte[] encrypted = null; try { cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec); encrypted = cipher.doFinal(toEncrypt); } catch (Exception e){ throw new Exception("[encrypt] " + e.getMessage()); } return encrypted; } public byte[] decrypt(String code) throws Exception{ if(code == null || code.length() == 0) throw new Exception("Empty string"); byte[] decrypted = null; try { cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec); decrypted = cipher.doFinal(hexToBytes(code)); } catch (Exception e){ throw new Exception("[decrypt] " + e.getMessage()); } return decrypted; } public static String bytesToHex(byte[] data){ if (data==null){ return null; } int len = data.length; String str = ""; for (int i=0; i 

pHp方面类似......(我无法弄清楚如何输入pHp代码!!!!

 class MCrypt { private $iv = 'adfdadfgfd'; #Same as in JAVA private $key = 'adfadfdfdafadfa'; #Same as in JAVA function __construct() { } function encrypt($str) { $iv = $this->iv; $td = mcrypt_module_open('rijndael-128', '', 'cbc', $iv); mcrypt_generic_init($td, $this->key, $iv); $s = padString(utf8_encode($str)); $encrypted = mcrypt_generic($td, $s); //echo $encrypted; mcrypt_generic_deinit($td); mcrypt_module_close($td); return bin2hex($encrypted); } function decrypt($code) { $code = $this->hex2bin($code); $iv = $this->iv; $td = mcrypt_module_open('rijndael-128', '', 'cbc', $iv); mcrypt_generic_init($td, $this->key, $iv); $decrypted = mdecrypt_generic($td, $code); mcrypt_generic_deinit($td); mcrypt_module_close($td); return (trim(utf8_decode($decrypted))); } protected function hex2bin($hexdata) { $bindata = ''; for ($i = 0; $i < strlen($hexdata); $i += 2) { $bindata .= chr(hexdec(substr($hexdata, $i, 2))); } return $bindata; } } 

就是这样,非常简单......哦顺便说一句,如果你自己填充,那么无论方法是Padding还是NoPadding都没关系!