Не удается расшифровать зашифрованный файл с помощью libsodium

Я работаю над шифрованием с помощью libsodium, моя проблема заключается в части расшифровки, она не проходит и отображает ошибку.

Неустранимая ошибка: Uncaught SodiumException: лимит операций должен быть больше 0 в C:\xampp\htdocs\encrypter\decrypt.php:18 Трассировка стека: #0 C:\xampp\htdocs\encrypter\decrypt.php(18): натрия_крипто_pwhash () #1 {main} добавлено в C:\xampp\htdocs\encrypter\decrypt.php в строке 18

Я попытался скопировать некоторые строки в коде шифрования, но это не сработало.

Я также получаю предупреждение.

Но я не знаю, является ли это причиной. Я также получаю это по шифрованию.

Предупреждение: unpack(): коды 64-битного формата недоступны для 32-битных версий PHP в C:\xampp\htdocs\encrypter\decrypt.php в строке 11.

Предупреждение: unpack(): коды 64-битного формата недоступны для 32-битных версий PHP в C:\xampp\htdocs\encrypter\decrypt.php в строке 12.

ОБНОВЛЕНИЕ

  • Предупреждение исправлено изменением кода 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.


person Mark Gerryl Mirandilla    schedule 08.02.2019    source источник
comment
Предупреждение для unpack, вероятно, является подсказкой. Вы должны попробовать запустить его на 64-битной системе. Таким образом, проблема больше связана с попыткой распаковать 64-битное значение в 32-битной системе, чем с libsodium.   -  person Furgas    schedule 08.02.2019
comment
@Furgas, они не подключены отсюда php.net/manual/en/function .pack.php Я изменил его на 32-битный, ошибка все еще там.   -  person Mark Gerryl Mirandilla    schedule 08.02.2019
comment
Попробуйте отладить байты fread($fd_in, 8) - возможно, они все нули.   -  person Furgas    schedule 08.02.2019
comment
@Furgas значение зашифровано примерно так �QO����   -  person Mark Gerryl Mirandilla    schedule 08.02.2019
comment
Он не зашифрован, он в двоичной форме. Вместо строки с $opslimit =... попробуйте var_dump(bin2hex(fread($fd_in, 8)));   -  person Furgas    schedule 08.02.2019
comment
@Furgas string(16) "e9514ff1bfc9dcc8" $opslimit не имеет значения.   -  person Mark Gerryl Mirandilla    schedule 08.02.2019
comment
@Furgas Я меняю все на «V», теперь отображаются числа 2:alg -- 1957082864:ops--375774878:mem , но ошибка остается той же.   -  person Mark Gerryl Mirandilla    schedule 08.02.2019
comment
Так что это большое число. Вам придется протестировать его на 64-битной системе.   -  person Furgas    schedule 08.02.2019


Ответы (1)


Код действительно не был разработан для 32-битных версий PHP.

Если вы измените P на V, вам необходимо:

  • Делайте это как при вызовах unpack(), так и при вызовах pack()
  • Изменить количество считываемых/записываемых байтов с 8 до 4.

Но лучше всего было бы попытаться понять, что делает код.

Он сохраняет лимит памяти и итерации в начале файла, чтобы эти параметры можно было восстановить позже при чтении файла без необходимости их жесткого кодирования.

pack() кодирует значение в фиксированном количестве байтов. unpack() делает наоборот. pack('P') кодирует 64-битное значение в 8 байтов. unpack('P') читает 8 байтов и преобразует их в значение.

Если ваша среда не поддерживает 64-битные значения, упаковывайте/распаковывайте в 4 байта, но тогда вам нужно писать 4 байта, а не 8. И читать также 4 байта, а не 8.

person Frank Denis    schedule 08.02.2019