我们有一个java spring后端,它使用以下方法加密某些列:

Encryptors.queryableText(secretKey, new String(Hex.encode(salt.getBytes(Charsets.UTF_8))));


这将在特定配置中创建类型为TextEncryptor的对象,然后可以使用textEncryptor.encrypt(msg)进行加密并使用textEncryptor.decrypt(msg)进行解密。
Spring Security提供的这种加密方法用于使加密列可查询。相同的文本将始终导致相同的加密字符串。

现在,另一个node.js后端需要访问一些加密列以生成汇总报告。

我发现一些文章似乎很好地解决了这个问题:
https://stackanswers.net/questions/spring-4-encryptors-vs-cryptojs

我更改了代码以适合我的需求。 IV和盐必须按照Encryptors.queryableText()的说明进行修复:

/*!
* Author: flohall
* date: 2019-11-05
* file: module/textEncryptor.js
*/
var CryptoJS = require("crypto-js");
var config = require('../config.json');
//keySize and iteration like specified in spring for AesBytesEncryptor
const keySize = 256;
const iterations = 1024;
//see config.json
const salt = CryptoJS.enc.Hex.parse(config.textEncryptor.hexEncodedSalt);
const secretKey = config.textEncryptor.secretKey;
const key = CryptoJS.PBKDF2(secretKey, salt, {
    keySize: keySize / 32,
    iterations: iterations
});

//same as NULL_IV_GENERATOR of AesBytesEncryptor - so encryption creates always same cipher text for same input
const iv = {words: [0, 0, 0, 0, 0, 0, 0, 0], sigBytes: 0}
const cfg = {
    iv: iv,
    padding: CryptoJS.pad.Pkcs7,
    mode: CryptoJS.mode.CBC
}

exports.encrypt = function (msg) {

    const encrypted = CryptoJS.AES.encrypt(msg, key, cfg);
    return encrypted.ciphertext.toString();
}

exports.decrypt = function (encryptedMessage) {

    var decrypted = CryptoJS.AES.decrypt(encryptedMessage, key, cfg)
    return decrypted.toString(CryptoJS.enc.Utf8);

}


到目前为止,一切都很好-重要的是要知道,赋予给node.js函数的config.textEncryptor.hexEncodedSalt是已经十六进制编码的盐。
我使用以下命令生成了它:

//salt is read from application.yml and not hexencoded yet
System.out.println(new String(Hex.encode(salt.getBytes(Charsets.UTF_8))));


node.js textEncryptor.encrypt(msg)方法的确生成与Java中textEncryptor.encrypt(msg)相同的加密消息,但是node.js中的textEncryptor.decrypt(msg)仍无法以与Java中的textEncryptor.decrypt(msg)相同的方式解密。

node.js中的此测试代码不起作用:

var textEncryptor = require('./modules/textEncryptor.js');

var encrypted = textEncryptor.encrypt("helloWorld")
var decrypted = textEncryptor.decrypt(encrypted)
console.log(encrypted);
console.log(decrypted);


它只打印出解密后的文本,后跟一个空行。
任何想法-我想念什么?

最佳答案

在问了这个之后不久,我发现我所缺少的很有趣。它有效,但是我没想到那样,因为这与我在问题中链接的文章中所描述的不同。 encryptedMessage必须先进行十六进制解析,然后放入对象中。

exports.decrypt = function (encryptedMessage) {

    var encrypted = { ciphertext: CryptoJS.enc.Hex.parse(encryptedMessage)};
    var decrypted = CryptoJS.AES.decrypt(encrypted, key, cfg)
    return decrypted.toString(CryptoJS.enc.Utf8);

}


正确的解决方案:

/*!
* Author: flohall
* date: 2019-11-05
* file: module/textEncryptor.js
*/
var CryptoJS = require("crypto-js");
var config = require('../config.json');
//keySize and iteration like specified in spring for AesBytesEncryptor
const keySize = 256;
const iterations = 1024;
//see config.json
const salt = CryptoJS.enc.Hex.parse(config.textEncryptor.hexEncodedSalt);
const secretKey = config.textEncryptor.secretKey;
const key = CryptoJS.PBKDF2(secretKey, salt, {
    keySize: keySize / 32,
    iterations: iterations
});

//same as NULL_IV_GENERATOR of AesBytesEncryptor - so encryption creates always same cipher text for same input
const iv = {words: [0, 0, 0, 0, 0, 0, 0, 0], sigBytes: 0}
const cfg = {
    iv: iv,
    padding: CryptoJS.pad.Pkcs7,
    mode: CryptoJS.mode.CBC
}

exports.encrypt = function (msg) {

    const encrypted = CryptoJS.AES.encrypt(msg, key, cfg);
    return encrypted.ciphertext.toString();
}

exports.decrypt = function (encryptedMessage) {

    var encrypted = { ciphertext: CryptoJS.enc.Hex.parse(encryptedMessage)};
    var decrypted = CryptoJS.AES.decrypt(encrypted, key, cfg)
    return decrypted.toString(CryptoJS.enc.Utf8);

}

10-07 23:19