我们有一个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);
}