【问题标题】:Can't decrypt encrypted file using libsodium无法使用 libsodium 解密加密文件
【发布时间】:2019-02-08 07:08:16
【问题描述】:

我正在使用 libsodium 进行加密,我的问题是解密部分,它没有通过并显示错误。

致命错误:未捕获的 SodiumException:操作限制必须大于 0 在 C:\xampp\htdocs\encrypter\decrypt.php:18 堆栈跟踪:#0 C:\xampp\htdocs\encrypter\decrypt.php(18): sodium_crypto_pwhash() #1 {main} 在第 18 行的 C:\xampp\htdocs\encrypter\decrypt.php 中抛出

我试图复制加密代码中的一些行但没有成功。

我也收到警告。

但我不知道这是否是原因。我也收到了这个关于加密的信息。

警告:unpack():64 位格式代码不适用于 32 位 第 11 行 C:\xampp\htdocs\encrypter\decrypt.php 中的 PHP 版本

警告:unpack():64 位格式代码不适用于 32 位 第 12 行 C:\xampp\htdocs\encrypter\decrypt.php 中的 PHP 版本

更新

  • 通过将 pack() 代码从 P 更改为 V 来修复警告。

  • 更改代码后,$opslimit 的值大于 0。

解密代码

$password = 'password';
$encrypted_file = 'tmp/inc.php';
$decrypted_file = 'tmp/inc.dec';

$fd_in = fopen($encrypted_file, 'rb');
$fd_out = fopen($decrypted_file, 'wb');

$alg = unpack('C', fread($fd_in, 1))[1];
$opslimit = unpack('V', fread($fd_in, 8))[1];
$memlimit = unpack('V', fread($fd_in, 8))[1];
$salt = fread($fd_in, SODIUM_CRYPTO_PWHASH_SALTBYTES);

$header = fread($fd_in, SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_HEADERBYTES);

$secret_key = sodium_crypto_pwhash(SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_KEYBYTES,
                                   $password, $salt, $opslimit, $memlimit, $alg);

$stream = sodium_crypto_secretstream_xchacha20poly1305_init_pull($header, $secret_key);
do {
    $chunk = fread($fd_in, $chunk_size + SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_ABYTES);
    $res = sodium_crypto_secretstream_xchacha20poly1305_pull($stream, $chunk);
    if ($res === FALSE) {
       break;
    }
    list($decrypted_chunk, $tag) = $res;
    fwrite($fd_out, $decrypted_chunk);
} while (!feof($fd_in) && $tag !== SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_FINAL);
$ok = feof($fd_in);

fclose($fd_out);
fclose($fd_in);

if (!$ok) {
    die('Invalid/corrupted input');
}

这是我使用的来自libsodium example的源代码。

【问题讨论】:

  • unpack 的警告可能是提示。您应该尝试在 64 位系统上运行它。所以问题更多在于尝试在 32 位系统上解压 64 位值,而不是使用 libsodium。
  • @Furgas,他们没有从这里连接基地php.net/manual/en/function.pack.php我把它改成32位错误仍然存​​在。
  • 尝试调试 fread($fd_in, 8) 的字节 - 也许它们都是零。
  • @Furgas 该值已加密,类似于 �QO����
  • 它没有加密,它是二进制形式。而不是$opslimit =... 尝试var_dump(bin2hex(fread($fd_in, 8)));

标签: php encryption cryptography libsodium


【解决方案1】:

代码确实不是为 32 位版本的 PHP 设计的。

如果您将P 更改为V,您需要:

  • 在调用unpack() 和调用pack() 时都这样做
  • 将读取/写入的字节数从 8 更改为 4。

但实际上最好的办法是尝试理解代码的作用。

它将内存限制和迭代存储在文件的开头,以便以后读取文件时可以恢复这些参数,而不必对其进行硬编码。

pack() 将值编码为固定字节数。 unpack() 则相反。 pack('P') 将 64 位值编码为 8 个字节。 unpack('P') 读取 8 个字节并将其转换为一个值。

如果您的环境不支持 64 位值,请打包/解压缩为 4 个字节,但您需要写入 4 个字节,而不是 8 个字节。并且还要读取 4 个字节,而不是 8 个字节。

【讨论】:

    猜你喜欢
    • 2022-08-14
    • 1970-01-01
    • 2022-06-16
    • 2017-10-23
    • 2015-02-25
    • 1970-01-01
    • 2016-09-10
    • 1970-01-01
    • 2014-04-22
    相关资源
    最近更新 更多