将AESA从AES解密到node.js [英] decryptAES from Java to node.js

查看:115
本文介绍了将AESA从AES解密到node.js的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  public String encryptWithAES(String value,String key,String encoding)throws NoSuchAlgorithmException,NoSuchPaddingException,DecoderException,UnsupportedEncodingException,InvalidKeyException,IllegalBlockSizeException,BadPaddingException {
byte [] keyBytes = Hex.decodeHex(key.toLowerCase() toCharArray());
byte [] dataToSend = value.getBytes(encoding);
密码c = Cipher.getInstance(AES);
SecretKeySpec k = new SecretKeySpec(keyBytes,AES);
c.init(1,k);
byte [] encryptedData = c.doFinal(dataToSend);
return new String(Hex.encodeHex(encryptedData));


public String decryptAES(String encrypted,String key,String encoding)throws NoSuchAlgorithmException,NoSuchPaddingException,DecoderException,UnsupportedEncodingException,InvalidKeyException,IllegalBlockSizeException,BadPaddingException {
byte [] keyBytes = Hex.decodeHex(key.toCharArray());
byte [] encryptedData = Hex.decodeHex(encrypted.toCharArray());
密码c = Cipher.getInstance(AES);
SecretKeySpec k = new SecretKeySpec(keyBytes,AES);
c.init(2,k);
byte [] dencryptedData = c.doFinal(encryptedData);
return new String(dencryptedData,encoding);
}

我在互联网上发现了很多例子,但没有人给我一个正确的结果。



现在我尝试使用该代码解密:

 aes-128-cbc','aes-128-cfb','aes-128-cfb1','aes-128-cbc','aes-128-cbc' 'aes-128-ecb','aes-128-gcm','aes-128-ofb','aes-128-xts','aes-256-cbc','aes-256-cfb' -256-cfb1','aes-256-cfb8','aes-256-ctr','aes-256-ecb','aes-256-gcm','aes-256-ofb' -xts','aes128','aes256']; 
// var masterData - 像'c07abe96dde490b3aba7d2f21a43ba94960619ff110ffb53433f0ff39f4cf138e48511b1fb4030'的字符串
// const ENCRYPTION_KEY - 带有32个符号的字符串'94960619ff110ffb53433f0ff39f4cf1'

函数解密(文本,算法){
var decipher = crypto.createDecipher(algorithm,ENCRYPTION_KEY);

var dec = decipher.update(text,'hex','utf8');

dec + = decipher.final('utf8');
return dec;
}

algos.map(algo => {
try {
const dec = decrypt(masterData,algo);

console.log(algo,dec);
} catch(error){
console.log(algo,'error',error);
}
});

编码的字符串是一个JSON。

解决方案

这是真的不安全的代码,不应该被使用。



密码.getInstance(AES); 未完全指定,可能会导致不同的密码,具体取决于默认安全提供程序。它最有可能导致AES / ECB / PKCS5Padding,但它不一定是。如果更改,您将失去不同JVM之间的兼容性。

始终使用完全限定的密码字符串。



所以你应该尝试的第一件事是将你的密码限制在那些使用ECB模式的密码。 Node.js的加密模块自动应用PKCS#5 / PKCS#7填充,所以你不需要做任何特别的处理。



接下来是键。您的示例键长度为32个字符。因为如果我们研究Java代码,它应该是十六进制编码的,这意味着密钥实际上只有16字节(八位字节)或128位长。您需要在使用Hex之前对该密钥进行解码。



另一个问题是 crypto.createDecipher expects a密码作为参数,但您似乎有一个关键。在这种情况下,您需要使用 crypto.createDecipheriv 。请不要混淆密码和密钥。它们具有非常不同的属性,但是好处是通常可以从密码中获取密钥。有关详细信息,请参阅:如何安全地哈希密码?



如前所述,Java使用填充。为了加密任意长的明文,许多操作模式需要填充。其中之一是欧洲央行模式。填充添加1到16个字节(16字节是AES的块大小)。这意味着您的密文必须有32个字符(十六进制编码)的倍数。如果不是密文无效。



由于示例密文无效,未验证的代码:

  var crypto = require('crypto'); 

var masterData ='...'; // 32个字符的倍数!
var ENCRYPTION_KEY ='94960619ff110ffb53433f0ff39f4cf1';

函数解密(text,key){
var decipher = crypto.createDecipheriv('aes-128-ecb',new Buffer(key,'hex'),'');

var dec = decipher.update(text,'hex','utf8');

dec + = decipher.final('utf8');
return dec;
}

console.log(decrypt(masterData,ENCRYPTION_KEY));






这段代码真的不安全:使用ECB模式,不随机,无认证!你不应该使用这个密码。


I have a Java algorithm for AES encryption and decryption and have to realize the decryption in JavaScript.

public String encryptWithAES(String value, String key, String encoding) throws NoSuchAlgorithmException, NoSuchPaddingException, DecoderException, UnsupportedEncodingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
    byte[] keyBytes = Hex.decodeHex(key.toLowerCase().toCharArray());
    byte[] dataToSend = value.getBytes(encoding);
    Cipher c = Cipher.getInstance("AES");
    SecretKeySpec k = new SecretKeySpec(keyBytes, "AES");
    c.init(1, k);
    byte[] encryptedData = c.doFinal(dataToSend);
    return new String(Hex.encodeHex(encryptedData));
}

public String decryptAES(String encrypted, String key, String encoding) throws NoSuchAlgorithmException, NoSuchPaddingException, DecoderException, UnsupportedEncodingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
    byte[] keyBytes = Hex.decodeHex(key.toCharArray());
    byte[] encryptedData = Hex.decodeHex(encrypted.toCharArray());
    Cipher c = Cipher.getInstance("AES");
    SecretKeySpec k = new SecretKeySpec(keyBytes, "AES");
    c.init(2, k);
    byte[] dencryptedData = c.doFinal(encryptedData);
    return new String(dencryptedData, encoding);
}

I have found many examples in the Internet, but no one gave me a proper result.

Now I try decrypt with that code:

var algos = ['aes-128-cbc', 'aes-128-cfb', 'aes-128-cfb1', 'aes-128-cfb8', 'aes-128-ctr', 'aes-128-ecb', 'aes-128-gcm', 'aes-128-ofb', 'aes-128-xts', 'aes-256-cbc', 'aes-256-cfb', 'aes-256-cfb1', 'aes-256-cfb8', 'aes-256-ctr', 'aes-256-ecb', 'aes-256-gcm', 'aes-256-ofb', 'aes-256-xts', 'aes128', 'aes256'];
//var masterData - string like 'c07abe96dde490b3aba7d2f21a43ba94960619ff110ffb53433f0ff39f4cf138e48511b1fb4030'
//const ENCRYPTION_KEY - string like '94960619ff110ffb53433f0ff39f4cf1' with 32 symbols

function decrypt(text, algorithm) {
    var decipher = crypto.createDecipher(algorithm, ENCRYPTION_KEY);

    var dec = decipher.update(text, 'hex', 'utf8');

    dec += decipher.final('utf8');
    return dec;
}

algos.map(algo => {
    try {
        const dec = decrypt(masterData, algo);

        console.log(algo, dec);
    } catch (error) {
        console.log(algo, 'error', error);
    }
});

Encoded string is a JSON.

解决方案

This is really insecure code and should never be used.

Cipher.getInstance("AES"); is not fully specified and may result in different ciphers depending on the default security provider. It most likely results in "AES/ECB/PKCS5Padding", but it doesn't have to be. If it changes, you'll lose compatibility between different JVMs.
Always use a fully qualified Cipher string.

So the first thing that you should try is to limit your cipher to those with ECB mode. Node.js' crypto module automatically applies PKCS#5/PKCS#7 padding, so you don't have to do anything special in that regard.

Next up is the key. Your example key is 32 characters long. Since it's supposed to be Hex-encoded if we look into the Java code, it means that the key is actually only 16 bytes (octets) or 128 bits long. You need to decode the key from Hex before you use it.

Another problem is that crypto.createDecipher expects a password as a parameter, but you seem to have a key. In that case, you need to use crypto.createDecipheriv. Please don't confuse passwords and keys. They have vastly different properties, but the good thing is that you can usually derive a key from a password. See this for more information: How to securely hash passwords?

As I said before, Java uses padding. Many modes of operation need padding in order to encrypt arbitrarily long plaintext. One of them is the ECB mode. Padding adds between 1 to 16 bytes (16 bytes is the block size of AES). This means that your ciphertext must have a multiple of 32 characters (Hex-encoded). If it doesn't it isn't valid ciphertext.

Untested code because the example ciphertext is invalid:

var crypto = require('crypto');

var masterData = '...'; // multiple of 32 characters!
var ENCRYPTION_KEY = '94960619ff110ffb53433f0ff39f4cf1';

function decrypt(text, key) {
    var decipher = crypto.createDecipheriv('aes-128-ecb', new Buffer(key, 'hex'), '');

    var dec = decipher.update(text, 'hex', 'utf8');

    dec += decipher.final('utf8');
    return dec;
}

console.log(decrypt(masterData, ENCRYPTION_KEY));


This code is really insecure: Uses ECB mode, not randomized, no authentication! You should not use this crypto code at all.

这篇关于将AESA从AES解密到node.js的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆