I am trying to encode in nodejs and decryption for the same in nodejs works well. But when I try to do the decryption in Java using the same IV and secret, it doesn't behave as expected.
我试图在nodejs中编码,并且在nodejs中解密相同的效果很好。但是当我尝试使用相同的IV和秘密在Java中进行解密时,它的行为并不像预期的那样。
Here is the code snippet:
这是代码片段:
Encryption in nodeJs:
nodeJs中的加密:
var crypto = require('crypto'),
algorithm = 'aes-256-ctr',
_ = require('lodash');
var secret = 'd6F3231q7d19428743234@123nab@234';
function encrypt(text, secret) {
var iv = crypto.randomBytes(16);
console.log(iv);
var cipher = crypto.createCipheriv(algorithm, new Buffer(secret), iv);
var encrypted = cipher.update(text);
encrypted = Buffer.concat([encrypted, cipher.final()]);
return iv.toString('hex') + ':' + encrypted.toString('hex');
}
var encrypted = encrypt("8123497494", secret);
console.log(encrypted);
And the output is:
输出是:
<Buffer 94 fa a4 f4 a1 3c bf f6 d7 90 18 3f 3b db 3f b9>
94faa4f4a13cbff6d790183f3bdb3fb9:fae8b07a135e084eb91e
Code Snippet for decryption in JAVA:
用于在JAVA中解密的代码片段:
public class Test {
public static void main(String[] args) throws Exception {
String s = "94faa4f4a13cbff6d790183f3bdb3fb9:fae8b07a135e084eb91e";
String seed = "d6F3231q7d19428743234@123nab@234";
decrypt(s, seed);
}
private static void decrypt(String s, String seed)
throws NoSuchAlgorithmException, NoSuchPaddingException, UnsupportedEncodingException, InvalidKeyException,
InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
String parts[] = s.split(":");
String ivString = parts[0];
String encodedString = parts[1];
Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");
byte[] secretBytes = seed.getBytes("UTF-8");
IvParameterSpec ivSpec = new IvParameterSpec(hexStringToByteArray(ivString));
/*Removed after the accepted answer
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] thedigest = md.digest(secretBytes);*/
SecretKeySpec skey = new SecretKeySpec(thedigest, "AES");
cipher.init(Cipher.DECRYPT_MODE, skey, ivSpec);
byte[] output = cipher.doFinal(hexStringToByteArray(encodedString));
System.out.println(new String(output));
}
}
Output: �s˸8ƍ�
I am getting some junk value in the response. Tried a lot of options, but none of them seem to be working. Any lead/help is appreciated.
我在回复中得到了一些垃圾值。试了很多选择,但似乎都没有。任何领导/帮助表示赞赏。
2 个解决方案
#1
2
In your JS code, you're using the 32-character string d6F3231q7d19428743234@123nab@234
directly as the AES key, with each ASCII character directly mapped to a single key byte.
在您的JS代码中,您直接使用32个字符的字符串d6F3231q7d19428743234 @ 123nab @ 234作为AES密钥,每个ASCII字符直接映射到单个密钥字节。
In the Java code, you're instead first hashing the same string with MD5, and then using the MD5 output as the AES key. It's no wonder that they won't match.
在Java代码中,您首先使用MD5对相同的字符串进行哈希处理,然后使用MD5输出作为AES密钥。难怪他们不会匹配。
What you probably should be doing, in both cases, is either:
在这两种情况下,您可能应该做的是:
- randomly generating a string of 32 bytes (most of which won't be printable ASCII characters) and using it as the key; or
- using a key derivation function (KDF) to take an arbitrary input string and turn it into a pseudorandom AES key.
随机生成一个32字节的字符串(其中大部分不是可打印的ASCII字符)并将其用作密钥;要么
使用密钥派生函数(KDF)获取任意输入字符串并将其转换为伪随机AES密钥。
In the latter case, if the input string is likely to have less than 256 bits of entropy (e.g. if it's a user-chosen password, most of which only have a few dozen bits of entropy at best), then you should make sure to use a KDF that implements key stretching to slow down brute force guessing attacks.
在后一种情况下,如果输入字符串可能具有少于256位的熵(例如,如果它是用户选择的密码,其中大部分最多只有几十位熵),那么你应该确保使用实现键拉伸的KDF来减缓暴力猜测攻击。
#2
2
In the Java code you are taking the MD5 hash of secret
before using it as a key:
在Java代码中,在将其用作密钥之前,您将获取秘密的MD5哈希值:
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] thedigest = md.digest(secretBytes);
SecretKeySpec skey = new SecretKeySpec(thedigest, "AES");
Whereas, in your NodeJS code, you don't do this anywhere. So you're using two different keys when encrypting and decrypting.
然而,在您的NodeJS代码中,您不会在任何地方执行此操作。因此,在加密和解密时,您使用了两个不同的密钥。
Don't copy and paste code without understanding it. Especially crypto code.
不要在不理解代码的情况下复制和粘贴代码。特别是加密代码。
#1
2
In your JS code, you're using the 32-character string d6F3231q7d19428743234@123nab@234
directly as the AES key, with each ASCII character directly mapped to a single key byte.
在您的JS代码中,您直接使用32个字符的字符串d6F3231q7d19428743234 @ 123nab @ 234作为AES密钥,每个ASCII字符直接映射到单个密钥字节。
In the Java code, you're instead first hashing the same string with MD5, and then using the MD5 output as the AES key. It's no wonder that they won't match.
在Java代码中,您首先使用MD5对相同的字符串进行哈希处理,然后使用MD5输出作为AES密钥。难怪他们不会匹配。
What you probably should be doing, in both cases, is either:
在这两种情况下,您可能应该做的是:
- randomly generating a string of 32 bytes (most of which won't be printable ASCII characters) and using it as the key; or
- using a key derivation function (KDF) to take an arbitrary input string and turn it into a pseudorandom AES key.
随机生成一个32字节的字符串(其中大部分不是可打印的ASCII字符)并将其用作密钥;要么
使用密钥派生函数(KDF)获取任意输入字符串并将其转换为伪随机AES密钥。
In the latter case, if the input string is likely to have less than 256 bits of entropy (e.g. if it's a user-chosen password, most of which only have a few dozen bits of entropy at best), then you should make sure to use a KDF that implements key stretching to slow down brute force guessing attacks.
在后一种情况下,如果输入字符串可能具有少于256位的熵(例如,如果它是用户选择的密码,其中大部分最多只有几十位熵),那么你应该确保使用实现键拉伸的KDF来减缓暴力猜测攻击。
#2
2
In the Java code you are taking the MD5 hash of secret
before using it as a key:
在Java代码中,在将其用作密钥之前,您将获取秘密的MD5哈希值:
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] thedigest = md.digest(secretBytes);
SecretKeySpec skey = new SecretKeySpec(thedigest, "AES");
Whereas, in your NodeJS code, you don't do this anywhere. So you're using two different keys when encrypting and decrypting.
然而,在您的NodeJS代码中,您不会在任何地方执行此操作。因此,在加密和解密时,您使用了两个不同的密钥。
Don't copy and paste code without understanding it. Especially crypto code.
不要在不理解代码的情况下复制和粘贴代码。特别是加密代码。