Как расшифровать текст с помощью node.js, который был зашифрован с помощью Java Spring Spring Security TextEncryptor - PullRequest
1 голос
/ 06 ноября 2019

У нас есть Java-бэкэнд, который шифрует некоторые столбцы с помощью:

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

}

Пока все хорошо - важно знать, что config.textEncryptor.hexEncodedSalt, предоставленный функции node.js, уже является шестнадцатеричным. поваренная соль. Я сгенерировал его, используя:

//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) генерирует такое же зашифрованное сообщение, как textEncryptor.encrypt(msg) в java, но все же textEncryptor.decrypt(msg) в node.js не может расшифроватьтак же, как textEncryptor.decrypt(msg) в java.

Этот тестовый код в node.js не работает:

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

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

Он выводит только расшифрованный текст, за которым следует пустая строка.
Есть идеи - чего мне не хватает?

1 Ответ

0 голосов
/ 06 ноября 2019

Забавно, вскоре после того, как спросил это, я узнал, чего мне не хватало. Это работает, но я не ожидал, что так, потому что это отличается от того, что описано в статье, на которую я ссылаюсь в своем вопросе. 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);

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...