Php aes-256-cbc在nodejs中使用初始向量加密解密

Php aes-256-cbc在nodejs中使用初始向量加密解密,php,node.js,encryption,cryptojs,Php,Node.js,Encryption,Cryptojs,我试图将一些现有php代码转换为nodejs,但nodejs代码返回: TypeError:盐必须是缓冲区 我正在使用节点版本=>v8.11.2 PHP代码: class SecurityModel { protected $key; protected $method; protected $data; protected $iv; function __construct($data, $key = 'testing', $method = 'AE

我试图将一些现有php代码转换为nodejs,但nodejs代码返回:

TypeError:盐必须是缓冲区

我正在使用节点版本=>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
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}....`));

PBKDF2是一个很好的想法,也是PHP代码首先应该做的事情。不幸的是,
passwordDeriveBytes()
中发生的事情离PBKDF2还很远。如果要匹配循环,需要像在
passwordDeriveBytes()
中发生的那样复制循环

噢,“Salt必须是一个缓冲区”是通过将IV转换成一个缓冲区来解决的,缓冲区使用
buffer.from(IV)
(这也是一个信号,表明一个好的IV不应该是字符串,而应该是随机字节)


您使用的是node.js的哪个版本?node version=>v8.11.2Did您打算使用
createCipheriv
两次或者第二次应该是
createDecipheriv
?@rustyx,请检查更新的问题,使用crypto.pbkdf2实现passwordDeriveBytes()。完美答案,我已经用var iv=crypto.randomBytes(16)转换了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);