Нужна помощь для преобразования Encryption Blowfi sh php в Nodejs с использованием криптографии - PullRequest
2 голосов
/ 18 апреля 2020

Здравствуйте, мне нужна помощь для преобразования функции шифрования My PHP в Nodejs с использованием криптомодуля:

Этот код уже работает

// Constructor params
$this->algorithm = "blowfish";
$this->token = "3SzzaErRzj0#RuGr@JTkh[MO0AMIW*d!Sul/CEL!*rPnq$oOEgYaH}fNw{jw1b/DyLUdL])+JOMES@Z7MIRI>(p*nY{yl%h]4ylx";

    public function decrypt($string)
    {

        $key = hash('sha256', $this->token);
        list($encrypted_data, $iv) = explode('::', base64_decode($string), 2);
        return openssl_decrypt($encrypted_data, $this->algorithm, $key, 0, $iv);
    }

    public function encrypt($string)
    {

        $output = false;
        $iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length($this->algorithm));
        // hash
        $key = hash('sha256', $this->token);
        $output = openssl_encrypt($string, $this->algorithm, $key, 0, $iv);
        return base64_encode($output . '::' . $iv);
    }

И код в nodejs , я сделал дешифратор работал правильно, но шифр не работает

    const crypto = require('crypto');

    const decipher = async (alg, key, value) => {
            const hash = crypto.createHash('sha256');
            hash.update(key);
            let token = hash.digest('hex');

            let buff = new Buffer.from(value, 'base64');
            let [encrypted, iv] = buff.toString('ascii').split('::', 2);
            iv = new Buffer.from(iv);

            const decipher = crypto.createDecipheriv(alg, token, iv);
            let decrypted = await decipher.update(encrypted, 'base64', 'ascii');
            decrypted += decipher.final('ascii');
            return decrypted;
    }

   /* this one is not working */
   const cipher = async (alg, key, value) => {


        let iv = crypto.randomBytes(8);

        var sha256 = crypto.createHash('sha256');
        sha256.update(key);
        var newkey = sha256.digest('base64');

        var encryptor = await crypto.createCipheriv(alg, newkey, iv);

        encrypted = encryptor.update(value, 'utf8', 'base64') + encryptor.final('base64');

        var final = encrypted + "::" +iv;

        let buf = Buffer.from(final);
        let encodedData = buf.toString('base64');

        return encodedData;

}

любая помощь, чтобы помочь мне сделать свою работу, я ценю

1 Ответ

2 голосов
/ 18 апреля 2020

Следующие изменения должны быть сделаны в методе cipher кода NodeJS:

  • Ключ должен быть закодирован шестнадцатеричным:

    var newkey = sha256.digest('hex'); 
    
  • IV должен быть добавлен в виде двоичной строки:

    var final = encrypted + "::" + iv.toString('binary');
    
  • И данные должны быть проанализированы в виде двоичной строки:

    let buf = Buffer.from(final, 'binary');
    

С этими изменениями метод cipher в коде NodeJS совместим с методом encrypt в коде PHP.

Метод cipher использует кодировку UTF8, метод decipher использует кодировку ASCII, так что только кодированные в ASCII тексты могут быть правильно расшифрованы. Чтобы снять ограничение на кодировку ASCII, в методе decipher необходимы следующие изменения:

  • Кодирование в двоичную строку должно выполняться с binary, а не с ascii:

    let [encrypted, iv] = buff.toString('binary').split('::', 2);
    iv = new Buffer.from(iv, 'binary');
    
  • И выходная кодировка должна быть utf8 вместо ascii:

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

С этими Изменения NodeJS и PHP код совместимы. Также обратите внимание:

  • На самом деле ни одна из примененных NodeJS -функций не является асинхронной, поэтому использование async / await не является действительно необходимым.
  • new перед Buffer.from можно опустить.
  • Алгоритм задается с помощью blowfish, что соответствует bf-cbc и означает Blowfi sh в CB C mode.
  • 32-байтовый ключ генерируется с помощью SHA256 и возвращается в виде шестнадцатеричной строки (с 64 байтами / символами), поэтому используется 64-байтовый ключ. Для Blowfi sh определена максимальная длина ключа 56 байтов, здесь .
  • SHA256 используется в качестве функции получения ключа, более безопасной является, например, PBKDF2 (по крайней мере, для слабых паролей), здесь .
  • IV, разделенный разделителем, добавляется к зашифрованному тексту с кодировкой Base64, а результирующие данные кодируются с помощью Base64 (т.е. зашифрованный текст, следовательно, кодируется с помощью Base64 дважды). Обычно IV и зашифрованный текст (в этом порядке) объединяются на двоичном уровне, а полученные данные кодируются в Base64. Разделитель не требуется, так как длина IV соответствует размеру блока и поэтому известна.
...