寻找一种在node中加密数据(主要是字符串)并在android应用(java)中解密的方法。
在每个节点中都成功做到了这一点(在节点中进行加密/解密,在Java中进行加密/解密),但是似乎无法使其在它们之间起作用。
可能我不是以相同的方式进行加密/解密,但是每种语言的每个库对于相同的事物都有不同的名称…
任何帮助表示赞赏。
这是一些代码:Node.js
var crypto = require('crypto') var cipher = crypto.createCipher('aes-128-cbc','somepass') var text = "uncle had a little farm" var crypted = cipher.update(text,'utf8','hex') crypted += cipher.final('hex') //now crypted contains the hex representation of the ciphertext
和java
private static String decrypt(byte[] raw, byte[] encrypted) throws Exception { SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); Cipher cipher = Cipher.getInstance("AES"); cipher.init(Cipher.DECRYPT_MODE, skeySpec ); byte[] decrypted = cipher.doFinal(encrypted); return new String(decrypted); }
原始密钥是这样创建的
private static byte[] getRawKey(String seed) throws Exception { KeyGenerator kgen = KeyGenerator.getInstance("AES"); SecureRandom sr = SecureRandom.getInstance("SHA1PRNG"); byte[] seedBytes = seed.getBytes() sr.setSeed(seedBytes); kgen.init(128, sr); // 192 and 256 bits may not be available SecretKey skey = kgen.generateKey(); byte[] raw = skey.getEncoded(); return raw; }
而加密的十六进制字符串会像这样转换为字节
public static byte[] toByte(String hexString) { int len = hexString.length()/2; byte[] result = new byte[len]; for (int i = 0; i < len; i++) result[i] = Integer.valueOf(hexString.substring(2*i, 2*i+2), 16).byteValue(); return result; }
显然,如果您将密码传递给crypto.createCipher()它,则使用OpenSSL EVP_BytesToKey()派生密钥。您可以传递一个原始字节缓冲区并使用它来初始化Java的SecretKey,也可以EVP_BytesToKey()在Java代码中进行仿真。使用$ man EVP_BytesToKey可获得更多详细信息,但本质上它会用MD5多次散列密码短语并连接一个盐。
crypto.createCipher()
EVP_BytesToKey()
SecretKey
$ man EVP_BytesToKey
至于使用原始密钥,类似这样的方法应该可以让您使用原始密钥:
var c = crypto.createCipheriv("aes-128-ecb", new Buffer("00010203050607080a0b0c0d0f101112", "hex").toString("binary"), "");
请注意,由于您使用的是CBC,因此需要使用相同的IV进行加密和解密(您可能希望将其附加到消息中,等等)。
强制性警告:自己实施加密协议很少是个好主意。即使您可以使用此功能,您是否也将对所有消息使用相同的密钥?多长时间?如果决定旋转钥匙,该如何管理。等等