dousigan0499 2019-02-02 14:40
浏览 439
已采纳

在Nodejs中加密并在PHP中解密

I'm trying to decrypt a string in PHP which was originally encrypted in NodeJS.

PHP:

openssl_decrypt($raw_id, "aes-128-cbc", "s7UbmJpfm56r6CAC6mz7KVZdRc3Fxc4m", 0, null)

This seems to always returnfalse.

Encryption in Nodejs:

function encrypt(text) {
    var cipher = crypto.createCipher('aes-128-cbc', 's7UbmJpfm56r6CAC6mz7KVZdRc3Fxc4m');
    var encrypted = cipher.update(text, 'utf8', 'hex')
    encrypted  += cipher.final('hex')

    return encrypted; 
}

function decrypt(text) {
    var cipher = crypto.createDecipher('aes-128-cbc', 's7UbmJpfm56r6CAC6mz7KVZdRc3Fxc4m');
    var decrypted = cipher.update(text, 'hex', 'utf8')
    decrypted += cipher.final('utf8');

    return decrypted;
}

I basically want to encrypt, for example, encrypt("Pizza") in Nodejs, send it to the PHP page (3879f91a59e9a458db62f905b0a488a1), and decrypt it from there (openssl_decrypt: return Pizza).

I know this code is not safe, since I'm not using an IV but I'm not sure how to add one.

  • 写回答

1条回答

  • doxqszx09742 2019-02-02 16:51
    关注

    Your method is not secure and can also be victim to man in the middle attacks, you should always use a IV and a HMAC
    You can encrypt in php like this

    $key = substr('encyptionsec123342',0,32)
    function encrypt ($message, $method, $secret, &$hmac) {
        $iv = substr(bin2hex(openssl_random_pseudo_bytes(16)),0,16);
        $encrypted = base64_encode($iv) . openssl_encrypt($message, $method, $secret, 0, $iv);
        $hmac = hash_hmac('md5', $encrypted, $secret);
        return $encrypted;
    }
    
    function decrypt ($encrypted, $method, $secret, $hmac) {
        if (hash_hmac('md5', $encrypted, $secret) == $hmac) {
            $iv = base64_decode(substr($encrypted, 0, 24));
            return openssl_decrypt(substr($encrypted, 24), $method, $secret, 0, $iv);
        }
    }
    
    function encryptWithTSValidation ($message, $method, $secret, &$hmac) {
        date_default_timezone_set('UTC');
        $message = substr(date('c'),0,19) . "$message";
        return encrypt($message, $method, $secret, $hmac);
    }
    
    function decryptWithTSValidation ($encrypted, $method, $secret, $hmac, $intervalThreshold) {
        $decrypted = decrypt($encrypted, $method, $secret, $hmac);
        $now = new DateTime();
        $msgDate = new DateTime(str_replace("T"," ",substr($decrypted,0,19)));
        if (($now->getTimestamp() - $msgDate->getTimestamp()) <= $intervalThreshold) {
            return substr($decrypted,19);
        }
    }
    

    This is a secure AES-256-CBC method and with HMAC to stop man in the middle attacks.
    Node.js

    var secret = "encyptionsec123342";
    secret = secret.substr(0, 32);
    var method = 'AES-256-CBC';
    var encrypt = function(message, method, secret, hmac) {
        var iv = crypto.randomBytes(16).toString('hex').substr(0, 16);
        var encryptor = crypto.createCipheriv(method, secret, iv);
        var encrypted = new Buffer.alloc(iv).toString('base64') + encryptor.update(message, 'utf8', 'base64') + encryptor.final('base64');
        hmac = crypto.createHmac('md5', secret).update(encrypted).digest('hex');
        return encrypted;
    };
    var decrypt = function(encrypted, method, secret, hmac) {
        if (crypto.createHmac('md5', secret).update(encrypted).digest('hex') == hmac) {
            var iv = new Buffer.from(encrypted.substr(0, 24), 'base64').toString();
            var decryptor = crypto.createDecipheriv(method, secret, iv);
            return decryptor.update(encrypted.substr(24), 'base64', 'utf8') + decryptor.final('utf8');
        }
    };
    var encryptWithTSValidation = function(message, method, secret, hmac) {
        var messageTS = new Date().toISOString().substr(0, 19) + message;
        return encrypt(messageTS, method, secret, hmac);
    }
    var decryptWithTSValidation = function(encrypted, method, secret, hmac, intervalThreshold) {
        var decrypted = decrypt(encrypted, method, secret, hmac);
        var now = new Date();
        var year = parseInt(decrypted.substr(0, 4)),
            month = parseInt(decrypted.substr(5, 2)) - 1,
            day = parseInt(decrypted.substr(8, 2)),
            hour = parseInt(decrypted.substr(11, 2)),
            minute = parseInt(decrypted.substr(14, 2)),
            second = parseInt(decrypted.substr(17, 2));
        var msgDate = new Date(Date.UTC(year, month, day, hour, minute, second))
        if (Math.round((now - msgDate) / 1000) <= intervalThreshold) {
            return decrypted.substr(19);
        }
    }
    

    To perform encryption and decryption in php,

    $encrypted = encryptWithTSValidation($recipent, $method, $key, $hmac);
    $decrypted = decryptWithTSValidation($encrypted,$method,$key, $hmac, 60*60*12)//this is 12 hours 
    

    to generate a hmac, you can use simple md5 hashing

    $hmac = hash_hmac('md5', $recipent, $key);
    

    and in node.js

    var decrypted = decryptWithTSValidation(encString, method, secret, hmac, 60 * 60);
    var encrypted = decryptWithTSValidation(string, method, secret, hmac);
    

    NOTE: Make sure to make a unique key that is of 32 bit and is same while encryption and decryption in nodejs and php. Also keep it safe and never store it in a database.
    Code Reference : Encrypt string in PHP and decrypt in Node.js

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 用visual studi code完成html页面
  • ¥15 聚类分析或者python进行数据分析
  • ¥15 逻辑谓词和消解原理的运用
  • ¥15 三菱伺服电机按启动按钮有使能但不动作
  • ¥15 js,页面2返回页面1时定位进入的设备
  • ¥50 导入文件到网吧的电脑并且在重启之后不会被恢复
  • ¥15 (希望可以解决问题)ma和mb文件无法正常打开,打开后是空白,但是有正常内存占用,但可以在打开Maya应用程序后打开场景ma和mb格式。
  • ¥20 ML307A在使用AT命令连接EMQX平台的MQTT时被拒绝
  • ¥20 腾讯企业邮箱邮件可以恢复么
  • ¥15 有人知道怎么将自己的迁移策略布到edgecloudsim上使用吗?