简体   繁体   English

如何使用已用 java spring 加密的 node.js 解密文本

[英]How to decrypt text using node.js that has been encrypted with java spring security TextEncryptor

We have a java spring backend that encrypts some columns using:我们有一个 java spring 后端,它使用以下方法加密一些列:

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

This creates an object of type TextEncryptor in a specific configuration which then can encrypt with textEncryptor.encrypt(msg) and decrypt with textEncryptor.decrypt(msg) .这会在特定配置中创建一个 TextEncryptor 类型的 object,然后可以使用 textEncryptor.encrypt(msg) 进行加密并使用textEncryptor.decrypt(msg) textEncryptor.encrypt(msg)进行解密。 This method of encryption provided by spring security is used to make encrypted columns queryable. spring 安全性提供的这种加密方法用于使加密列可查询。 The same text will always lead to the same encrypted String.相同的文本将始终导致相同的加密字符串。

Another node.js backends now needs to access some of the encrypted columns for generating aggregated reports.另一个 node.js 后端现在需要访问一些加密列以生成聚合报告。

I found some article that seems to address that problem quite well: https://stackanswers.net/questions/spring-4-encryptors-vs-cryptojs我发现了一些似乎很好地解决了这个问题的文章: https://stackanswers.net/questions/spring-4-encryptors-vs-cryptojs

I changed that code to fit my needs.我更改了该代码以满足我的需要。 IV and salt had to be fix like specified by Encryptors.queryableText() : IV 和 salt 必须像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);

}

So far so good - important to know is that the config.textEncryptor.hexEncodedSalt given to the node.js function is the already hexencoded salt.到目前为止一切顺利 - 重要的是要知道给予 node.js function 的 config.textEncryptor.hexEncodedSalt 是已经十六进制编码的盐。 I generated it using:我使用以下方法生成它:

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

The node.js textEncryptor.encrypt(msg) method does generate the same encrypted message as textEncryptor.encrypt(msg) in java, but still textEncryptor.decrypt(msg) in node.js isn't able to decrypt in the same way as textEncryptor.decrypt(msg) in java does. The node.js textEncryptor.encrypt(msg) method does generate the same encrypted message as textEncryptor.encrypt(msg) in java, but still textEncryptor.decrypt(msg) in node.js isn't able to decrypt in the same way as textEncryptor.decrypt(msg)在 java 中。

This test code in node.js does not work: node.js 中的此测试代码不起作用:

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

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

It prints out just the decrypted text followed by an empty line.它只打印出解密的文本,后跟一个空行。
Any idea - what I am missing?任何想法 - 我错过了什么?

Funny shortly after asking this I found out, what I was missing.有趣的是,在问这个问题后不久,我发现了我错过了什么。 It works, but I didn't expect it that way, because this is different than described in the article I linked in my question.它有效,但我没想到会这样,因为这与我在问题中链接的文章中描述的不同。 The encryptedMessage has to be hex parsed first and put into an object. encryptedMessage必须首先进行十六进制解析并放入 object。

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);

}

Correct solution:正确解决方案:

/*! 
* 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);

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM