【问题标题】:Need Help to convert Encryption Blowfish php to Nodejs using crypto需要帮助使用加密将加密 Blowfish php 转换为 Nodejs
【发布时间】:2020-07-31 12:10:21
【问题描述】:

您好,我需要帮助来使用加密模块将我的 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 中的代码,我让 decipher 正常工作,但是 cipher 不工作

    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;

}

任何帮助我完成工作的帮助我都感激不尽

【问题讨论】:

    标签: php node.js encryption cryptojs


    【解决方案1】:

    必须在NodeJS代码的cipher方法中做如下改动:

    • 密钥必须是十六进制编码:

      var newkey = sha256.digest('hex'); 
      
    • IV 必须附加为二进制字符串:

      var final = encrypted + "::" + iv.toString('binary');
      
    • 并且数据必须被解析为二进制字符串:

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

    通过这些更改,NodeJS 代码中的 cipher 方法与 PHP 代码中的 encrypt 方法兼容。

    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 并不是真正必要的。
    • Buffer.from 之前的new 可以省略。
    • 算法用blowfish指定,对应bf-cbc,表示CBC模式下的Blowfish。
    • 使用 SHA256 生成 32 字节密钥,并以十六进制字符串(64 字节/字符)形式返回,因此使用 64 字节密钥。对于 Blowfish,最大密钥长度定义为 56 个字节,here
    • SHA256 用作密钥派生函数,更安全的是例如PBKDF2(至少对于弱密码),here
    • IV 由定界符分隔,附加到 Base64 编码的密文中,结果数据经过 Base64 编码(即密文因此经过两次 Base64 编码)。通常 IV 和密文(按此顺序)在二进制级别上连接,并且生成的数据是 Base64 编码的。分隔符不是必需的,因为 IV 的长度对应于块大小,因此是已知的。

    【讨论】:

    • 多么完整的答案,非常感谢您的帮助,几个小时后我会做出改变。 =D
    猜你喜欢
    • 2021-05-08
    • 2021-01-30
    • 2022-01-12
    • 2017-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多