不同的输出加密CryptoJS和Java代码

我需要从客户端(JavaScript)加密肯定字符串并从服务器端(Java)解密,所以我找到了CryptoJS,我用mi Java Code的相同params /配置编写代码,但输出总是不同的,你有什么想法或发生了什么?

我在NoPadding上使用CBC

CryptoJS

http://jsfiddle.net/Soldier/gCHAG/

    function padString(source) { var paddingChar = ' '; var size = 16; var x = source.length % size; var padLength = size - x; for (var i = 0; i < padLength; i++) source += paddingChar; return source; } var key = CryptoJS.enc.Hex.parse('0123456789abcdef'); var iv = CryptoJS.enc.Hex.parse('fedcba9876543210'); var message = "soldier"; var padMsg = padString(message); var encrypted = CryptoJS.AES.encrypt(padMsg, key, { iv: iv, padding: CryptoJS.pad.NoPadding, mode: CryptoJS.mode.CBC}); console.log("Encrypted: "+encrypted); console.log("Encrypted text: "+encrypted.ciphertext);  

Java代码

 import java.security.Key; import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import sun.misc.*; public class AesCipher { private static final String algorithm = "AES/CBC/NoPadding"; private static final byte[] keyValue = new byte[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; private static final byte[] ivValue = new byte[] { 'f', 'e', 'd', 'c', 'b', 'a', '9', '8', '7', '6', '5', '4', '3', '2', '1', '0' }; private static final IvParameterSpec ivspec = new IvParameterSpec(ivValue); private static final SecretKeySpec keyspec = new SecretKeySpec(keyValue, "AES"); final protected static char[] hexArray = "0123456789ABCDEF".toCharArray(); public static String encrypt(String Data) throws Exception { Cipher c = Cipher.getInstance(algorithm); c.init(Cipher.ENCRYPT_MODE, keyspec, ivspec); byte[] encVal = c.doFinal(Data.getBytes()); String encryptedValue = new BASE64Encoder().encode(encVal); return encryptedValue; } public static String decrypt(String encryptedData) throws Exception { Cipher c = Cipher.getInstance(algorithm); c.init(Cipher.DECRYPT_MODE, keyspec, ivspec); byte[] decordedValue = new BASE64Decoder().decodeBuffer(encryptedData); byte[] decValue = c.doFinal(decordedValue); String decryptedValue = new String(decValue); return decryptedValue; } public static String bytesToHex(byte[] bytes) { char[] hexChars = new char[bytes.length * 2]; int v; for ( int j = 0; j >> 4]; hexChars[j * 2 + 1] = hexArray[v & 0x0F]; } return new String(hexChars); } private static String padString(String source) { char paddingChar = ' '; int size = 16; int x = source.length() % size; int padLength = size - x; for (int i = 0; i < padLength; i++) { source += paddingChar; } return source; } public static void main(String[] args) throws Exception { String password = "soldier"; String passwordEnc = AesCipher.encrypt(padString(password)); String passwordDec = AesCipher.decrypt(passwordEnc); System.out.println("Plain Text : " + password); System.out.println("Encrypted Text : " + passwordEnc); System.out.println("Decrypted Text : " + passwordDec); } } 

原始字符串:

 soldier 

CryptoJS的输出:

 Encrypted: VNzZNKJTqfRbM7zO/M4cDQ== Encrypted Hex: 54dcd934a253a9f45b33bccefcce1c0d 

Java代码的输出:

 Encrypted: j6dSmg2lfjY2RpN91GNgNw== Encrypted Hex: 6a3664536d67326c666a593252704e3931474e674e773d3d 

加密的base64字符串具有相同的长度但不是hex。 如果我将CryptoJS的输出结果放在Java代码中,则解密不正确。

问候,

这里的问题是你的键输入不一致。

  • CryptoJS.enc.Hex.parse('0123456789abcdef')将输入读取为一系列字节,表示为两位hex值: CryptoJS.enc.Hex.parse('0123456789abcdef')等。

  • 您的Java数组使用字符的字符编码值指定字节值。 因此,字节序列(hex)是: 30 (十进制48, '0' ASCII代码),然后是31 (十进制49, '1' ASCII代码)等。

您可以使用CryptoJS.enc.Latin1.parse使JavaScript符合Java实现,它将读取单个字符值并将其用作字节值: http : //jsfiddle.net/gCHAG/1/ (这会产生相同的j6dSm...输出)

但是,您可能希望每个数字都是它自己的字节。 为此,您需要更改两个实现。

Java的:

 // use hex literals, not characters byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }; // array values: 0x00, 0x01, 0x02, etc 

JavaScript的:

 // remember each bytes is two digits wide CryptoJS.enc.Hex.parse('000102030405060708090a0b0c0d0e0f') // array values: 0x00, 0x01, 0x02, etc 

字符“0”与hex值0不同.CryptoJS键很可能与Java键不同,因为您将它们实例化为不同的对象类型。 在创建和比较后,用两种语言打印出键/ IV。

编辑:也就是说,这可能会转移到StackOverflow,因为有关特定加密库的问题不在此处。

非常有用的例子SoldierCorp,谢谢!

几乎没有什么可以改善你的榜样:

  • 方法padString不支持UTF8,而不是修复此方法,让我们删除它并使用标准填充

在javascript替换

 padding: CryptoJS.pad.Pkcs7 

在java中替换

 algorithm = "AES/CBC/PKCS5Padding" 
  • 从任何字符串短语生成密钥(对于IV可以是相同的)

在javascript替换

 var key = CryptoJS.MD5("Secret Passphrase"); 

在java中替换

 byte[] keyValue = org.apache.commons.codec.digest.DigestUtils.md5("Secret Passphrase");