用PHP加密,用Javascript解密(cryptojs)

 高飘琼里15 发布于 2023-01-08 12:06

我在基本加密/解密方面遇到了麻烦.我一直在寻找一个有效的例子,但还没有找到一个有效的例子.

- 我将在php中进行加密,使用cryptoj解密以获得一小部分安全性


我错过了哪一步?

2 个回答
  • 我需要同样的东西,我写了一个简短的库,适用于CryptoJS 3.x和PHP,支持openssl.希望这有帮助,源代码和示例文件在这里https://github.com/brainfoolong/cryptojs-aes-php

    PHP Lib

    /**
    * Decrypt data from a CryptoJS json encoding string
    *
    * @param mixed $passphrase
    * @param mixed $jsonString
    * @return mixed
    */
    function cryptoJsAesDecrypt($passphrase, $jsonString){
        $jsondata = json_decode($jsonString, true);
        $salt = hex2bin($jsondata["s"]);
        $ct = base64_decode($jsondata["ct"]);
        $iv  = hex2bin($jsondata["iv"]);
        $concatedPassphrase = $passphrase.$salt;
        $md5 = array();
        $md5[0] = md5($concatedPassphrase, true);
        $result = $md5[0];
        for ($i = 1; $i < 3; $i++) {
            $md5[$i] = md5($md5[$i - 1].$concatedPassphrase, true);
            $result .= $md5[$i];
        }
        $key = substr($result, 0, 32);
        $data = openssl_decrypt($ct, 'aes-256-cbc', $key, true, $iv);
        return json_decode($data, true);
    }
    
    /**
    * Encrypt value to a cryptojs compatiable json encoding string
    *
    * @param mixed $passphrase
    * @param mixed $value
    * @return string
    */
    function cryptoJsAesEncrypt($passphrase, $value){
        $salt = openssl_random_pseudo_bytes(8);
        $salted = '';
        $dx = '';
        while (strlen($salted) < 48) {
            $dx = md5($dx.$passphrase.$salt, true);
            $salted .= $dx;
        }
        $key = substr($salted, 0, 32);
        $iv  = substr($salted, 32,16);
        $encrypted_data = openssl_encrypt(json_encode($value), 'aes-256-cbc', $key, true, $iv);
        $data = array("ct" => base64_encode($encrypted_data), "iv" => bin2hex($iv), "s" => bin2hex($salt));
        return json_encode($data);
    }
    

    Javascript Lib

    var CryptoJSAesJson = {
        stringify: function (cipherParams) {
            var j = {ct: cipherParams.ciphertext.toString(CryptoJS.enc.Base64)};
            if (cipherParams.iv) j.iv = cipherParams.iv.toString();
            if (cipherParams.salt) j.s = cipherParams.salt.toString();
            return JSON.stringify(j);
        },
        parse: function (jsonStr) {
            var j = JSON.parse(jsonStr);
            var cipherParams = CryptoJS.lib.CipherParams.create({ciphertext: CryptoJS.enc.Base64.parse(j.ct)});
            if (j.iv) cipherParams.iv = CryptoJS.enc.Hex.parse(j.iv)
            if (j.s) cipherParams.salt = CryptoJS.enc.Hex.parse(j.s)
            return cipherParams;
        }
    }
    

    示例Javascript

    var encrypted = CryptoJS.AES.encrypt(JSON.stringify("value to encrypt"), "my passphrase", {format: CryptoJSAesJson}).toString();
    var decrypted = JSON.parse(CryptoJS.AES.decrypt(encrypted, "my passphrase", {format: CryptoJSAesJson}).toString(CryptoJS.enc.Utf8));
    

    示例PHP

    $encrypted = cryptoJsAesEncrypt("my passphrase", "value to encrypt");
    $decrypted = cryptoJsAesDecrypt("my passphrase", $encrypted);
    

    2023-01-08 12:09 回答
  • Scott Arciszewski 安全声明:此答案的代码容易受到选择密文攻击.请参阅此答案以获取安全加密.

    这是一个用PHP加密字符串并使用CryptoJS解密它的工作示例.

    在PHP方面:

    使用MCRYPT_RIJNDAEL_128(不是256)与AES配对.这里的128是块大小,而不是密钥大小.

    也发送IV.您需要IV才能解密.

    $text = "this is the text here";
    $key = "encryptionkey";
    
    // Note: MCRYPT_RIJNDAEL_128 is compatible with AES (all key sizes)
    $iv = random_bytes(16);
    
    $ciphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $text, MCRYPT_MODE_CBC, $iv);
    
    echo "iv:".base64_encode($iv)."\n";
    echo "ciphertext:".base64_encode($ciphertext)."\n";
    

    以下是测试运行的示例输出:

    iv:BMcOODpuQurUYGICmOqqbQ==
    ciphertext:ZJAab8YtkRq5TL7uyIR7frM2b3krftJzn1pTqRTAda4=
    

    Scott Arciszewski 重要提示:因为我们没有对我们的密文进行身份验证,所以解密变得容易受到填充oracle攻击.另请参见:PHP中的身份验证加密.

    在CryptoJS方面:

    你的密钥只有13个ASCII可打印字符,非常弱.Mcrypt 使用ZERO字节将密钥填充到有效的密钥大小.

    密钥IV转换为字阵列.

    我没有太多运气用密文作为字数组解密,所以我把它保留为Base64格式.

    CryptoJS = require("crypto-js")
    
    // Mcrypt pads a short key with zero bytes
    key = CryptoJS.enc.Utf8.parse('encryptionkey\u0000\u0000\u0000')
    
    iv = CryptoJS.enc.Base64.parse('BMcOODpuQurUYGICmOqqbQ==')
    
    // Keep the ciphertext in Base64 form
    ciphertext = 'ZJAab8YtkRq5TL7uyIR7frM2b3krftJzn1pTqRTAda4='
    
    /**
     * DANGER DANGER WILL ROBINSON! <== Stop editing my answer or I will delete it.
     *
     * This example code doesn't demonstrate AUTHENTICATED ENCRYPTION
     * and is therefore vulnerable to chosen-ciphertext attacks.
     *
     * NEVER USE THIS CODE TO PROTECT SENSITIVE DATA!
     */
    
    // Mcrypt uses ZERO padding
    plaintext = CryptoJS.AES.decrypt(ciphertext, key, { iv: iv, padding: CryptoJS.pad.ZeroPadding })
    
    // I ran this in nodejs
    process.stdout.write(CryptoJS.enc.Utf8.stringify(plaintext))
    

    2023-01-08 12:09 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有