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)
。
我的第一个暗示就是要确保你完全一样:
- 字符编码
- 行结束
在你的两个程序中,encryption文本和密钥。 尝试打印文本缓冲区和密钥为hex,并进行比较之前,你甚至做任何encryption。 如果他们不同,那么你的问题。 如果它们是相同的,那么它可能是encryption本身的问题。
请注意,Node默认使用UTF-8,而据我所知,Java使用UCS-2。 我看到你正在做一些转换编码的尝试,但在encryption步骤之前再次检查两个环境中的密钥和明文的结果。
另外,请确保您不是对string的base64表示进行encryption,而是对string本身进行encryption,或者如果您使用base64作为密钥,则始终如此。
另外,在encryption之前打印两个密钥。 你正在以编程方式构build它们,所以要确保你知道它到底是什么。
如果你确定你有相同的密钥,相同的消息,相同的编码,行结尾和表示(hex,base64等),然后使用一些在线工具进行AESencryption,如:
- http://aesencryption.net/
- http://aes.online-domain-tools.com/
- https://www.browserling.com/tools/aes-encrypt
并比较你的哪个程序正确地执行了这项工作。
- 解密.update上的encryption错误
- NodeJS Decrypt des3 Unicode
- Node.jsencryption中的HMAC与Google Apps脚本(GAS)
- 带有node.jsencryption的PKCS5填充
- 在java中encryptionstring,在node.js中解密,错误:解密不好
- 如果在encryption之前已知明文的开始处是否存在漏洞?
- RSA Javaencryption和Node.js解密不起作用
- Node.js / javascript在PHP中像mcrypt_ecb一样encryptionAES-128
- Node.js'crypto.createSign()的有效algorithminputstring