Расшифровка шифрования aes-256-cbc с начальным вектором в nodejs - PullRequest
0 голосов
/ 27 сентября 2018

Я пытаюсь преобразовать некоторый существующий код php в nodejs, но код узла js возвращает:

TypeError: Salt должен быть буфером

Я использую версию узла=> v8.11.2

Код PHP:

class SecurityModel {

    protected $key;
    protected $method;
    protected $data;
    protected $iv;

    function __construct($data, $key = 'testing', $method = 'AES-256-CBC',$InitialVector = "aw90rela942f65u2") {
        $this->data = $data;
        $this->key = $this->passwordDeriveBytes($key, null);
        $this->method = $method;
        $this->iv = $InitialVector;
    }

    function passwordDeriveBytes($password, $salt, $iterations = 100, $len = 32) {
        $key = $password . $salt;
        for($i = 0; $i < $iterations; $i++) {
            $key = sha1($key, true);
        }
        if (strlen($key) < $len) {
            $hx = $this->passwordDeriveBytes($password, $salt, $iterations - 1, 20);
            $counter = 0;
            while (strlen($key) < $len) {
                $counter += 1;
                $key .= sha1($counter . $hx, true);
            }
        }
        return substr($key, 0, $len);
    }

    function encrypt(): string {
        return openssl_encrypt($this->data, "aes-256-cbc", $this->key, 0, $this->iv);
    }

    function decrypt(): string {
        return openssl_decrypt($this->data, "aes-256-cbc", $this->key, 0, $this->iv);
    }

}

$objSecurityModel = new SecurityModel('437217');
$Encrypted =  $objSecurityModel->encrypt();
echo "Encrypted :".$Encrypted ."<br>"; //returns-->C9xJGa03dRQx9ePm0nLnHg==
$objSecurityModel = new SecurityModel($Encrypted);
echo "Decrypted::".$objSecurityModel->decrypt(); //returns-->437217

Я попробовал кое-что в nodejs

Код NodeJs:

const express = require('express');
const app = express();
var crypto = require('crypto');

key = 'testing'
plaintext = '437217'
iv = 'aw90rela942f65u2'

crypto.pbkdf2('testing', null, 100, 32, 'AES-256-CBC', (err, derivedKey) => {
    if (err) throw err;
    console.log(derivedKey.toString('hex'));  // '3745e48...08d59ae'
    key = derivedKey.toString('hex');
});

cipher = crypto.createCipheriv('aes-256-cbc', key,iv)
decipher = crypto.createDecipheriv('aes-256-cbc', key,iv);

var encryptedPassword = cipher.update(plaintext, 'utf8', 'base64');
encryptedPassword += cipher.final('base64')

var decryptedPassword = decipher.update(encryptedPassword, 'base64', 'utf8');
decryptedPassword += decipher.final('utf8');

console.log('original  :', plaintext); 
console.log('encrypted :', encryptedPassword);
console.log('decrypted :', decryptedPassword);
//PORT
const port = process.env.PORT || 3000;
app.listen(port,() => console.log(`Listening on port ${port}....`));

1 Ответ

0 голосов
/ 28 сентября 2018

PBKDF2 - отличная идея и именно то, что PHP-код должен был сделать в первую очередь.К сожалению, то, что происходит внутри passwordDeriveBytes(), далеко не рядом с PBKDF2.Вам нужно воспроизвести цикл так, как это происходит внутри passwordDeriveBytes(), если вы хотите сопоставить его.

Oh и " Соль должна быть буфером " решается путем преобразования IV в буферс Buffer.from(iv) (это также признак того, что хороший IV должен не быть строкой, а случайными байтами).

const crypto = require('crypto');

function sha1(input) {
    return crypto.createHash('sha1').update(input).digest();
}

function passwordDeriveBytes(password, salt, iterations, len) {
    var key = Buffer.from(password + salt);
    for(var i = 0; i < iterations; i++) {
        key = sha1(key);
    }
    if (key.length < len) {
        var hx = passwordDeriveBytes(password, salt, iterations - 1, 20);
        for (var counter = 1; key.length < len; ++counter) {
            key = Buffer.concat([key, sha1(Buffer.concat([Buffer.from(counter.toString()), hx]))]);
        }
    }
    return Buffer.alloc(len, key);
}

var password = 'testing';
var plaintext = '437217';
var iv = 'aw90rela942f65u2';

//var key = crypto.pbkdf2Sync(password, '', 100, 32, 'sha1'); // How it should be
var key = passwordDeriveBytes(password, '', 100, 32); // How it is
console.log(key.toString('hex'));

var cipher = crypto.createCipheriv('aes-256-cbc', key, Buffer.from(iv));
var decipher = crypto.createDecipheriv('aes-256-cbc', key, Buffer.from(iv));

var part1 = cipher.update(plaintext, 'utf8');
var part2 = cipher.final();
var encrypted = Buffer.concat([part1, part2]).toString('base64');

var decrypted = decipher.update(encrypted, 'base64', 'utf8');
decrypted += decipher.final();

console.log('original  :', plaintext); 
console.log('encrypted :', encrypted);
console.log('decrypted :', decrypted);

Вывод:

df07df624db35d0bcf5fe7ff2dfdfffcef93f098939d750ca55595ae1b33925d
original  : 437217
encrypted : C9xJGa03dRQx9ePm0nLnHg==
decrypted : 437217
...