【问题标题】:Using the Sodium Lib in PHP functions在 PHP 函数中使用 Sodium Lib
【发布时间】:2020-03-06 16:50:46
【问题描述】:

我将再次尝试在此网站上发帖。我之前的问题被忽略或批评了,因为我猜人们认为我没有花太多精力来试图找出问题,而只是寻找一些简单的代码来复制!

我的目标是编写可以调用的 PHP 函数来加密和解密要存储在服务器上的数据,而加密密钥存储在 USB 加密狗上。我一直在玩 Sodium,但网上似乎没有很多关于它的信息。我也不是一个受过高等教育的程序员,因为我自学了我所知道的一切。

这里是示例测试代码:

<?php

//set variables
$key="";
$passedkey="";
$name="";
$nonce="";
$ciphertext="";
$encoded="";
$encodeddata="";
$datatoencode="";
$decodeddata="";
$decodedkey="";

function encodedata($passedkey, $datatoencode){
    $decodedkey = base64_decode($passedkey);    
    $nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
    $ciphertext = sodium_crypto_secretbox($datatoencode, $nonce, $decodedkey);
    $encodeddata = base64_encode($nonce . $ciphertext);
}

function decodedata($passedkey, $datatodecode, $decodeddata){
    $decodedkey = base64_decode($passedkey);
    $nonce = mb_substr($datatodecode, 0, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, '8bit');
    $ciphertext = mb_substr($datatodecode, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, null, '8bit');
    $decodeddata = sodium_crypto_secretbox_open($ciphertext, $nonce, $decodedkey);
}

if ($_SERVER["REQUEST_METHOD"] == "POST") {
    // collect value of input field
    $encodedata = $_POST['encodedata'];
    $passedkey = base64_decode($_POST['skey']);
    echo $encodeddata . "<br>";

    //call function to encode the data
    encodedata($passedkey, $datatoencode);

    // now decode the data
    decodedata($passedkey, $encodeddata, $decodeddata);
    echo $decodeddata;
}

?>




<html>
<body>

<form method="post" action="<?php echo $_SERVER['PHP_SELF'];?>">
  Data to encode: <input type="text" name="encodedata">
  Key: <input type="text" name="skey">
  <input type="submit">
</form>


</body>
</html>

我在服务器错误日志中收到此错误消息:

[06-Mar-2020 16:16:11 UTC] PHP Fatal error:  Uncaught SodiumException: key size should be SODIUM_CRYPTO_SECRETBOX_KEYBYTES bytes in /home/.../test/keytest.php:17
Stack trace:
#0 /home/.../test/keytest.php(17): sodium_crypto_secretbox()
#1 /home/.../test/keytest.php(35): encodedata()
#2 {main}
  thrown in /home/.../test/keytest.php on line 17
[06-Mar-2020 16:16:24 UTC] PHP Fatal error:  Uncaught SodiumException: key size should be SODIUM_CRYPTO_SECRETBOX_KEYBYTES bytes in /home/.../test/keytest.php:17
Stack trace:
#0 /home/.../test/keytest.php(17): sodium_crypto_secretbox()
#1 /home/.../test/keytest.php(35): encodedata()
#2 {main}
  thrown in /home/.../test/keytest.php on line 17
[06-Mar-2020 16:30:38 UTC] PHP Fatal error:  Uncaught SodiumException: key size should be SODIUM_CRYPTO_SECRETBOX_KEYBYTES bytes in /home/.../test/keytest.php:18
Stack trace:
#0 /home/.../test/keytest.php(18): sodium_crypto_secretbox()
#1 /home/.../test/keytest.php(36): encodedata()
#2 {main}
  thrown in /home/.../test/keytest.php on line 18

任何有助于调试代码的提示将不胜感激!

【问题讨论】:

  • 您使用的是 SODIUM_CRYPTO_SECRETBOX_NONCEBYTES,而不是 KEY 字节,请尝试将其替换为错误消息建议的内容
  • 你传递的skey是什么?不管它是什么,一旦它通过base64_decode,它就不是 32 字节长了。错误消息试图在这里为您提供帮助。
  • 我使用 random_bytes(SODIUM_CRYPTO_SECRETBOX_KEYBYTES) 创建密钥。然后,我使用 base64_encode 函数对密钥进行编码,以便将其保存在 USB 加密狗上的文件中。将其粘贴到测试字段中,然后 base64_decoded 得到原始密钥。

标签: php sodium


【解决方案1】:

你的变量很遥远。这段代码中有几处是关闭的,老实说,我花了几分钟才注意到你的$encodedata 没有设置为function encodedata()。无论如何,我相信您的变量已经设置是我的错。请耐心等待,因为这是一个很长的解释。

我注意到的第一件事是您将$passedkey 解码了两次(或三次,如果两个函数都计算在内)。当您调用函数/s 时,在if($_SERVER("REQUEST_METHOD") == "POST") 中,$passedkey 已经通过base64_decode 解码并放置在变量$passedkey 中。在encodedatadecodedata 这两个函数中,您再次对其进行了解码,因此当您尝试调用这些函数时出现错误。由于参数$passedkey的值是到达函数之前已经解码的值,所以不需要再次解码。和我一样是多余的。因此,$decodedkey = base64_decode($passedkey); 不再需要,$decodedkey 变量应在两个function 上更改为$passedkey

第二个是你的$encodedata没有被调用。在if($_SERVER("REQUEST_METHOD") == "POST") 中,$encodedata 的值为$_POST['encodedata'],因此input 的值是要编码的数据。然而,当你调用该函数时,却找不到encodedata$encodedata

第三个问题是你的函数没有“返回”任何东西。你不能指望echo $encodeddata;echo $decodeddata; 从函数的“内部”返回一个值。嗯,我不知道你是否使用了一个可以的平台,但你去吧。

基本上,示例代码的问题是变量放置错误,没有注意值和参数。无论如何,我的建议是 USB 加密狗中保存的 skey 应该在 base64_encode() 中,并且是正确的钠键值,否则,这将不起作用。

这是一个编辑过的代码,我不知道这是否适用于你,但它适用于我的。

<?php

//set variables
$key="";
$passedkey="";
$name="";
$nonce="";
$ciphertext="";
$encoded="";
$encodeddata="";
$datatoencode="";
$decodeddata="";
$decodedkey="";

function encodedata($passedkey, $datatoencode){
    //no need to decode $passedkey since it is already decoded before calling the function
        //you can still retain $decodedkey = base64_decode($passedkey) but should REPLACE $passedkey = base64_decode($_POST['skey']); WITH $passedkey = $_POST['skey']; below
    $nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
    //change $decodedkey to $passedkey
    $ciphertext = sodium_crypto_secretbox($datatoencode, $nonce, $passedkey);
    $encodeddata = base64_encode($nonce . $ciphertext);
    //return the encrypted data when the function is called
    return $encodeddata;
}

function decodedata($passedkey, $datatodecode){
    //decode the encrypted data since it is stored as base64_encode()
        //you can still retain $decodedkey = base64_decode($passedkey) but should REPLACE $passedkey = base64_decode($_POST['skey']); WITH $passedkey = $_POST['skey']; below
    $datatodecode = base64_decode($datatodecode);
    $nonce = mb_substr($datatodecode, 0, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, '8bit');
    $ciphertext = mb_substr($datatodecode, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, null, '8bit');
    //change $decodedkey to $passedkey
    $decodeddata = sodium_crypto_secretbox_open($ciphertext, $nonce, $passedkey);
    //return the plaintext when the function is called
    return $decodeddata;
}

if ($_SERVER["REQUEST_METHOD"] == "POST") {
    // collect value of input field
    $encodedata = $_POST['encodedata'];
    $passedkey = base64_decode($_POST['skey']);

    //call function to encode the data
        //you can't fetch the value of a variable from outside of the function hence we will make the function itself a variable.
        //the returned data from the function is now the value of the variabl
    $encrypted = encodedata($passedkey, $encodedata);
    echo $encrypted.'<br />';
    

    // now decode the data
    $decypted = decodedata($passedkey, $encrypted);
    echo $decypted.'<br />';
}

?>




<html>
<body>

<form method="post" action="<?php echo $_SERVER['PHP_SELF'];?>">
  Data to encode: <input type="text" name="encodedata">
  Key: <input type="text" name="skey">
  <input type="submit">
</form>


</body>
</html>

我不知道你的意思或你到底想做什么,但这是让你给定的代码工作的方法。

【讨论】:

  • 感谢您的回复。我早就忘记了这篇文章,如果我决定再次尝试使用它,我感谢你的帮助!
猜你喜欢
  • 2014-01-26
  • 2019-09-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-03
  • 2019-08-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多