Nodejsencryption的string不符合java:AES-256-CBC

嗨,我写了nodejsencryption和javaencryption通过使用相同的algorithm在一边。 但Java和NodeJS正在返回不同的encryptionstring。 请帮我这里。

//这是我的Java代码

import java.io.UnsupportedEncodingException; import java.security.Key; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.spec.AlgorithmParameterSpec; import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import java.util.Base64; public enum AESUtil { ; private static final String ENCRYPTION_KEY = "RwcmlVpg"; private static final String ENCRYPTION_IV = "4e5Wa71fYoT7MFEX"; public static String encrypt(String src) { try { Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); cipher.init(Cipher.ENCRYPT_MODE, makeKey(), makeIv()); Base64.Encoder encoder = Base64.getEncoder(); return encoder.encodeToString(cipher.doFinal(src.getBytes())); } catch (Exception e) { throw new RuntimeException(e); } } public static String decrypt(String src) { String decrypted = ""; try { Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); cipher.init(Cipher.DECRYPT_MODE, makeKey(), makeIv()); Base64.Decoder decoder = Base64.getDecoder(); decrypted = new String(cipher.doFinal(decoder.decode(src))); } catch (Exception e) { throw new RuntimeException(e); } return decrypted; } static AlgorithmParameterSpec makeIv() { try { return new IvParameterSpec(ENCRYPTION_IV.getBytes("UTF-8")); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return null; } static Key makeKey() { try { MessageDigest md = MessageDigest.getInstance("SHA-256"); byte[] key = md.digest(ENCRYPTION_KEY.getBytes("UTF-8")); return new SecretKeySpec(key, "AES"); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return null; } } 

//下面是testing上述代码的代码

  public class AESMain { /** * @param args */ public static void main(String[] args) { String src = "Hello,CryptWorld"; String encrypted = AESUtil.encrypt(src); String decrypted = AESUtil.decrypt(encrypted); System.out.println("src: " + src); System.out.println("encrypted: " + encrypted); System.out.println("decrypted: " + decrypted); } } 

上述代码的回应是

 src: Hello,CryptWorld encrypted: rh7ro9NH1XZeLX95paLETDgYxRbnDoOIrxarO0Sy73s= decrypted: Hello,CryptWorld 

//节点的JS代码

 var Encrypt, crypto; crypto = require("crypto"); Encrypt = module.exports = (function() { var b64dec, b64enc, cipher, decrypt, encrypt, iv, key; key = crypto.createHash("sha256").update("RwcmlVpg").digest(); iv = '4e5Wa71fYoT7MFEX'; cipher = function(mode, data) { var encipher, encoded; encipher = crypto[mode]("aes-256-cbc", key, iv); encoded = encipher.update(data); encoded += encipher.final(); return encoded; }; encrypt = function(data) { return b64enc(cipher("createCipheriv", data)); }; decrypt = function(data) { return cipher("createDecipheriv", b64dec(data)); }; b64enc = function(data) { var b; b = new Buffer(data, "binary"); return b.toString("base64"); }; b64dec = function(data) { var b; b = new Buffer(data, "base64"); return b.toString("binary"); }; return { encrypt: encrypt, decrypt: decrypt }; })(); var expected = Encrypt.encrypt("Hello,CryptWorld"); console.log("expected " + expected); 

从节点JS的响应是

 expected /R79/f1H/XZeLX95/f39TDgY/Rb9Dv39/Rb9O0T9/Xs= 

节点js版本是v6.10.1和JDK版本1.8.0_77。

我真的不知道我错过了什么。

我不是一个JavaScript或node.js专家,但我认为问题是, cipher.update()cipher.final()返回Buffer实例,而不是string。 因此,您必须使用Buffer.concat(...)来连接它们,即

 cipher = function (mode, data) { var encipher, encoded; encipher = crypto[mode]("aes-256-cbc", key, iv); cipher1 = encipher.update(data); cipher2 = encipher.final(); return Buffer.concat([cipher1, cipher2]); }; 

另外,你不应该在任何代码中使用这个String.getBytes()方法和这个String(byte[])构造函数来实现可移植性或者互操作性。 相反,总是明确指定字符集。 我会推荐UTF_8独占,例如使用String.getBytes(StandardCharsets.UTF_8)new String(byte[], StandardCharsets.UTF_8)

我的第一个暗示就是要确保你完全一样:

  1. 字符编码
  2. 行结束

在你的两个程序中,encryption文本和密钥。 尝试打印文本缓冲区和密钥为hex,并进行比较之前,你甚至做任何encryption。 如果他们不同,那么你的问题。 如果它们是相同的,那么它可能是encryption本身的问题。

请注意,Node默认使用UTF-8,而据我所知,Java使用UCS-2。 我看到你正在做一些转换编码的尝试,但在encryption步骤之前再次检查两个环境中的密钥和明文的结果。

另外,请确保您不是对string的base64表示进行encryption,而是对string本身进行encryption,或者如果您使用base64作为密钥,则始终如此。

另外,在encryption之前打印两个密钥。 你正在以编程方式构build它们,所以要确保你知道它到底是什么。

如果你确定你有相同的密钥,相同的消息,相同的编码,行结尾和表示(hex,base64等),然后使用一些在线工具进行AESencryption,如:

并比较你的哪个程序正确地执行了这项工作。