You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP Sodium加密解密失败:配置与密钥一致仍无法解密

问题:PHP Sodium跨环境解密失败,密钥配置一致仍报错

使用PHP 8.2的Sodium扩展进行加密解密,已确认本地与服务器的密钥、PHP版本、扩展配置一致,但服务器加密后的数据在本地解密失败,此前用OpenSSL也遇到同类问题。服务器FPM启用了Sodium和OpenSSL,CLI的php.ini中这两项被注释。

加密脚本

<?php
$config = parse_ini_file('/home/mysite/config.ini', true);
$encryptionKey = base64_decode($config['encryption_sodium']['encryption_key']);

function secured_encrypt($data, $key)
{
    if (strlen($key) !== SODIUM_CRYPTO_AEAD_XCHACHA20POLY1305_IETF_KEYBYTES) {
        throw new Exception('Invalid key length: ' . strlen($key) . ' bytes');
    }

    $nonce = random_bytes(SODIUM_CRYPTO_AEAD_XCHACHA20POLY1305_IETF_NPUBBYTES);
    $encrypted = sodium_crypto_aead_xchacha20poly1305_ietf_encrypt($data, '', $nonce, $key);
    $output = base64_encode($nonce . $encrypted);

    error_log("Encryption Key (hex): " . bin2hex($key));
    error_log("Nonce (hex): " . bin2hex($nonce));
    error_log("Encrypted Data (hex): " . bin2hex($encrypted));
    error_log("Base64 Encoded: " . $output);

    return $output;
}

$data = "Sensitive data to encrypt";
$encryptedData = secured_encrypt($data, $encryptionKey);
echo "Base64 Encoded: " . $encryptedData . PHP_EOL;
?>

解密脚本

<?php
$config = parse_ini_file('/home/mysite/config.ini', true);
$encryptionKey = base64_decode($config['encryption_sodium']['encryption_key']);

function secured_decrypt($encrypted, $key)
{
    if (strlen($key) !== SODIUM_CRYPTO_AEAD_XCHACHA20POLY1305_IETF_KEYBYTES) {
        throw new Exception('Invalid key length: ' . strlen($key) . ' bytes');
    }

    $decoded = base64_decode($encrypted);
    if ($decoded === false) {
        throw new Exception('Base64 decode failed');
    }

    $nonce_length = SODIUM_CRYPTO_AEAD_XCHACHA20POLY1305_IETF_NPUBBYTES;
    $nonce = substr($decoded, 0, $nonce_length);
    $ciphertext = substr($decoded, $nonce_length);

    error_log("Decryption Key (hex): " . bin2hex($key));
    error_log("Nonce (hex): " . bin2hex($nonce));
    error_log("Ciphertext (hex): " . bin2hex($ciphertext));

    $decrypted = sodium_crypto_aead_xchacha20poly1305_ietf_decrypt($ciphertext, '', $nonce, $key);
    if ($decrypted === false) {
        error_log("Decryption failed. Nonce (hex): " . bin2hex($nonce));
        error_log("Ciphertext (hex): " . bin2hex($ciphertext));
        error_log("Key (hex): " . bin2hex($key));
        throw new Exception('Decryption failed. Check logs for details.');
    }

    return $decrypted;
}

try {
    $encryptedData = '96f7TzDaKvYMqCiiM9JsSrkImFDg1f88Iyb+abD6ag4Wwe0SYIGMAnxRYuF/dMZbPTw0kMNluJ9OyrNALwHak=';
    error_log("Encrypted Data: " . $encryptedData);
    $decryptedData = secured_decrypt($encryptedData, $encryptionKey);
    echo "Decrypted Data: " . $decryptedData . PHP_EOL;
} catch (Exception $e) {
    error_log($e->getMessage());
    echo 'An error occurred: ' . $e->getMessage();
}
?>

日志输出

加密日志

Original Data: Sensitive data to encrypt
Encryption Key (hex): cfb142f01779e3e6565518cd4955a03ce5474cd98e469447841ea0a71d28b10d
Nonce (hex): f7a7ebed9a063d4b0832da2022dc231b42e422613320995f
Encrypted Data (hex): f3c972f94a9c5e3a9838a5af7bd1268818c027c5162e1f74c65b3d3c3490c365b89f74cab3402f01da9
Base64 Encoded: 96f7TzDaKvYMqCiiM9JsSrkImFDg1f88Iyb+abD6ag4Wwe0SYIGMAnxRYuF/dMZbPTw0kMNluJ9OyrNALwHak=

解密日志

Encrypted Data: 96f7TzDaKvYMqCiiM9JsSrkImFDg1f88Iyb+abD6ag4Wwe0SYIGMAnxRYuF/dMZbPTw0kMNluJ9OyrNALwHak=
Decryption Key (hex): cfb142f01779e3e6565518cd4955a03ce5474cd98e469447841ea0a71d28b10d
Nonce (hex): f7a7ebed9a063d4b0832da2022dc231b42e422613320995f
Ciphertext (hex): f3c972f94a9c5e3a9838a5af7bd1268818c027c5162e1f74c65b3d3c3490c365b89f74cab3402f01da9
Decryption failed. Check logs for details.

排查建议

  • 检查parse_ini_file读取一致性:本地和服务器的config.ini中,encryption_key的base64字符串需完全一致,重点排查是否存在空格、换行或引号包裹导致的解析差异。
  • 验证base64解码结果:在本地和服务器分别执行echo bin2hex(base64_decode('你的密钥base64值'));,确认输出的十六进制字符串与日志中的密钥完全匹配。
  • 核对加密输出完整性:确保服务器输出的base64字符串未被URL编码、转义或截断,对比解密时传入的字符串与服务器输出是否完全一致(包括末尾的=符号)。
  • 验证Sodium常量一致性:在本地和服务器执行php -r "echo SODIUM_CRYPTO_AEAD_XCHACHA20POLY1305_IETF_KEYBYTES . PHP_EOL; echo SODIUM_CRYPTO_AEAD_XCHACHA20POLY1305_IETF_NPUBBYTES . PHP_EOL;",确认常量值为32和24。
  • 检查CLI扩展状态:执行php -m | grep sodium,确认CLI环境实际加载了Sodium扩展(PHP 7.2+默认内置,注释php.ini配置不代表未加载)。
  • 硬编码密钥测试:暂时跳过配置文件读取,在加密和解密脚本中直接硬编码相同的二进制密钥(由十六进制转换而来),测试解密是否正常,排除配置读取问题。

内容的提问来源于stack exchange,提问作者mybackhurtstoomuch12

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 03:02:06