【问题标题】:How to encrypt JSON object with JS-NaCl and decrypt with php Libsodium如何使用 JS-NaCl 加密 JSON 对象并使用 php Libsodium 解密
【发布时间】:2019-12-26 15:21:19
【问题描述】:

我设法找到了一个用于前端加密的 Libsodium js 库 (JS-NaCl),并且还为 Libsodium 加密/解密设置了我的 PHP 后端。当我像下面这样加密 JSON 对象时


const key = "827ccb0eea8a706c4c34a16891f84e7b";
const nonce = "0123456789abcdefghijvbnm";

var credentials = {
       "zip":"265",
       "account_number":"10028979739",
       "passcode":"1234",
       "account_type":"personal",
       "request":"login",
       "device":"iPhone 11"
   };


function encrypt(data){
 return sodium.crypto_secretbox(sodium.encode_utf8(data),nonce,key);
};

function decrypt(data){
 return sodium.decode_utf8(sodium.crypto_secretbox_open(data, nonce, key));
}

function login(data){
$.ajax({
       url:baseURL+"account/account.php",
       method:"POST",
       contentType:"application/x-www-form-urlencoded",
       dataType:"json",
       data:"datax="+JSON.stringify(encrypt(credentials)),
       beforeSend:()=>{
           console.log(credentials);
       },success:(response)=>{
          console.log(response);
       },error:(e)=>{
           swal("Connection Error","Failed to connect to the server!","error");
       }
   });

}

当我使用它触发登录方法时,它会使用 encrypt 方法加密 JSON 对象,因此我发送如下内容:

datax: {"0":191,"1":118,"2":248,"3":134,"4":45,"5":163,"6":3,"7":157,"8":78,"9":73,"10":157,"11":137,"12":178,"13":6,"14":68,"15":91,"16":217,"17":219,"18":50,"19":11,"20":127,"21":177,"22":130,"23":25,"24":209,"25":254,"26":210,"27":44,"28":119,"29":13,"30":144}

在 php 后端代码中我正在这样做:


<?php
function decrypt($data){
        $key = "e9897cea109576c2f8088c277125d553e4f83afbc0abbb92cfb1f7b776b4fee0";
        $nonce = "0123456789abcdefghijvbnm";
        return sodium_crypto_secretbox_open($data,$nonce,$key);
    }

    function encrypt($data){
        $data = utf8_encode($data);
        $key = "e9897cea109576c2f8088c277125d553e4f83afbc0abbb92cfb1f7b776b4fee0";
        $nonce = "0123456789abcdefghijvbnm";
        return sodium_crypto_secretbox($data,$nonce,$key);
    }


    $credentials = $_POST["datax"];
    echo decrypt($credentials);

    ?>

相同的密钥,相同的随机数,但它不会回显任何内容。这个怎么解密??

【问题讨论】:

    标签: javascript php libsodium nacl-cryptography


    【解决方案1】:

    代码需要一些更改。在 JavaScript 端(前端):

    • JavaScript 对象必须转换成字符串。

    • 除了数据,nonce 和 key 也必须使用 Utf8 编码。尽管密钥也可以十六进制编码为 16 字节密钥,但在这种情况下,它必须是 Utf8 编码为 32 字节密钥,因为sodium.crypto_secretbox 需要 32 字节密钥。预期的 nonce 大小必须为 24 字节。

    • 现在可以加密数据了。

    • sodium.crypto_secretbox 将数据返回为Uint8Array,因此必须对其进行编码以传输为合适的格式,例如十六进制。

    对应的代码是:

    nacl_factory.instantiate(function (sodium) {
    
        var credentials = {
            "zip":"265",
            "account_number":"10028979739",
            "passcode":"1234",
            "account_type":"personal",
            "request":"login",
            "device":"iPhone 11"
        };
    
        // Convert JavaScript object to string
        var data = JSON.stringify(credentials);
    
        // Utf8 encode key, nonce and data
        var keyUtf8 = sodium.encode_utf8("827ccb0eea8a706c4c34a16891f84e7b");
        var nonceUtf8 = sodium.encode_utf8("0123456789abcdefghijvbnm");
        var dataUtf8 = sodium.encode_utf8(data);
       
        // Encrypt
        var encrypted = sodium.crypto_secretbox(dataUtf8, nonceUtf8, keyUtf8);
    
        // Hex encode encrypted data for transfer 
        var encryptedHex = sodium.to_hex(encrypted);
    
        console.log("Ciphertext (hex):\n" + encryptedHex.replace(/(.{64})/g, "$1\n"));
    });
    &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/js-nacl/1.3.2/nacl_factory.js"&gt;&lt;/script&gt;

    在 PHP 端(后端):

    • 必须解码十六进制字符串$encryptedHex

    • 解码后的数据将被解密。为此,必须使用加密的密钥和随机数。在发布的代码中使用了不同的密钥,这在crypto_secretbox(对称加密)的上下文中是不可能的,即双方使用相同的密钥。对于非对称加密,有crypto_box

    • 可以将结果解码为 JavaScript 对象,其对象可以照常访问。

    对应的代码是:

    // Hex decode
    $encrypted = sodium_hex2bin($encryptedHex);
    
    // Decrypt
    $nonce = "0123456789abcdefghijvbnm";
    $key = "827ccb0eea8a706c4c34a16891f84e7b";
    $decrypted = sodium_crypto_secretbox_open($encrypted, $nonce, $key);
    
    // Convert to JavaScript object
    $decryptedJSON = json_decode($decrypted);
    echo "Zip:            " . $decryptedJSON->zip . "\n";
    echo "Account number: " . $decryptedJSON->account_number . "\n";
    echo "Passcode:       " . $decryptedJSON->passcode . "\n";
    echo "Account type:   " . $decryptedJSON->account_type . "\n";
    echo "Request:        " . $decryptedJSON->request . "\n";
    echo "Device:         " . $decryptedJSON->device . "\n";
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-10-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-22
      • 1970-01-01
      相关资源
      最近更新 更多