在java中加密字符串,在node.js中解密,错误:解密错误

时间:2022-07-16 18:26:52

I'm trying to encrypt a string in java, send it to my node.js server, and decrypt it. However, when I try to do this I get keep getting errors when trying to decrypt.

我正在尝试加密java中的字符串,将其发送到我的node.js服务器,并解密它。但是,当我尝试这样做时,我会在尝试解密时不断收到错误。

Java encrypt:

String privateKey = "someprivatekey";
String data = "dataToEncrypt";

DESKeySpec keySpec = new DESKeySpec(privateKey.getBytes("UTF-8"));
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
SecretKey key = keyFactory.generateSecret(keySpec);

byte[] dataToBytes = data.getBytes("UTF-8");      

Cipher cipher = Cipher.getInstance("DES"); 
cipher.init(Cipher.ENCRYPT_MODE, key);

// send this string to server 
String encryptedStr = Base64.encodeToString(cipher.doFinal(dataToBytes), 0);

node.js decrypt:

var privateKey = 'someprivatekey';
var decipher = crypto.createDecipher('des', privateKey);
var dec = decipher.update(textToDecipher, 'base64', 'utf8'); 
dec += decipher.final('utf8'); 
console.log('deciphered: ' + dec);

However, I get this error on the node.js side on the decipher.final() line:

但是,我在decipher.final()行的node.js端遇到此错误:

TypeError: error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt

I've tried decoding the string and using a buffer on the node side, but it didn't seem to work either, I get the same bad decrypt error.

我已经尝试解码字符串并在节点端使用缓冲区,但它似乎也没有工作,我得到相同的错误解密错误。

var buffer = new Buffer(textToDecipher, 'base64');
var decipher = crypto.createDecipher('des', privateKey);
var dec = Buffer.concat([decipher.update(buffer), decipher.final()]);

Any ideas what I could be doing wrong?

我有什么想法可能做错了吗?

2 个解决方案

#1


5  

When you create the decipher object on the node server, you are passing a password rather than an actual key. In order to specify the actual key, you need to use crypto.createDecipheriv(), but this requires an actual IV (this example uses 8 null bytes, but that's not recommended for real encryption; Initialization Vector on wikipedia)

在节点服务器上创建解密对象时,您将传递密码而不是实际密钥。为了指定实际的密钥,你需要使用crypto.createDecipheriv(),但这需要一个实际的IV(这个例子使用8个空字节,但不推荐用于真正的加密;*上的初始化向量)

I was able to get your example working by explicitly specifying padding, block mode, and IV:

通过显式指定填充,块模式和IV,我能够使您的示例正常工作:

String privateKey = "someprivatekey";
String data = "dataToEncrypt";

DESKeySpec keySpec = new DESKeySpec(privateKey.getBytes("UTF-8"));
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
SecretKey key = keyFactory.generateSecret(keySpec);

byte[] dataToBytes = data.getBytes("UTF-8");      

Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding"); 
cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(new byte[8]));

// send this string to server 
String encryptedStr = Base64.encodeToString(cipher.doFinal(dataToBytes), 0);

The decryption version also explicitly specifies the block mode (des-cbc), and correctly truncates the key text to the first 8 bytes:

解密版本还明确指定了块模式(des-cbc),并正确地将密钥文本截断为前8个字节:

var privateKey = 'someprivatekey';
var textToDecipher = '9Y8GTNxhQkKSIm5pmH91VA=='; // Text "dataToEncrypt" encrypted using DES using CBC and PKCS5 padding with the key "someprivatekey"

var iv = new Buffer(8);
iv.fill(0);

var decipher = crypto.createDecipheriv('des-cbc', privateKey.substr(0,8), iv);
var dec = decipher.update(textToDecipher, 'base64', 'utf8');
dec += decipher.final('utf8');
console.log('deciphered: ' + dec);

#2


1  

Java crypto's default mode for DES is ECB, which you need to specify in nodejs:

Java crypto的DES默认模式是ECB,您需要在nodejs中指定:

var decipher = crypto.createDecipheriv('des-ecb', key, new Buffer(0))
var txt = decipher.update(encrypt_text, 'hex', 'utf8');
txt += decipher.final('utf8')
return txt

#1


5  

When you create the decipher object on the node server, you are passing a password rather than an actual key. In order to specify the actual key, you need to use crypto.createDecipheriv(), but this requires an actual IV (this example uses 8 null bytes, but that's not recommended for real encryption; Initialization Vector on wikipedia)

在节点服务器上创建解密对象时,您将传递密码而不是实际密钥。为了指定实际的密钥,你需要使用crypto.createDecipheriv(),但这需要一个实际的IV(这个例子使用8个空字节,但不推荐用于真正的加密;*上的初始化向量)

I was able to get your example working by explicitly specifying padding, block mode, and IV:

通过显式指定填充,块模式和IV,我能够使您的示例正常工作:

String privateKey = "someprivatekey";
String data = "dataToEncrypt";

DESKeySpec keySpec = new DESKeySpec(privateKey.getBytes("UTF-8"));
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
SecretKey key = keyFactory.generateSecret(keySpec);

byte[] dataToBytes = data.getBytes("UTF-8");      

Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding"); 
cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(new byte[8]));

// send this string to server 
String encryptedStr = Base64.encodeToString(cipher.doFinal(dataToBytes), 0);

The decryption version also explicitly specifies the block mode (des-cbc), and correctly truncates the key text to the first 8 bytes:

解密版本还明确指定了块模式(des-cbc),并正确地将密钥文本截断为前8个字节:

var privateKey = 'someprivatekey';
var textToDecipher = '9Y8GTNxhQkKSIm5pmH91VA=='; // Text "dataToEncrypt" encrypted using DES using CBC and PKCS5 padding with the key "someprivatekey"

var iv = new Buffer(8);
iv.fill(0);

var decipher = crypto.createDecipheriv('des-cbc', privateKey.substr(0,8), iv);
var dec = decipher.update(textToDecipher, 'base64', 'utf8');
dec += decipher.final('utf8');
console.log('deciphered: ' + dec);

#2


1  

Java crypto's default mode for DES is ECB, which you need to specify in nodejs:

Java crypto的DES默认模式是ECB,您需要在nodejs中指定:

var decipher = crypto.createDecipheriv('des-ecb', key, new Buffer(0))
var txt = decipher.update(encrypt_text, 'hex', 'utf8');
txt += decipher.final('utf8')
return txt