用 sodium 的 sodium_crypto_secretbox() 对文本做带认证的对称加密。每次加密生成新 nonce,保存 nonce 和密文。解密时用同一把密钥,校验失败应拒绝读取。
生成演示密钥并封装密文
保存为 secretbox.php。这个示例在同一次运行里完成加解密,密钥不写入输出。
<?php $key = sodium_crypto_secretbox_keygen(); $nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES); $plain = 'demo message'; $cipher = sodium_crypto_secretbox($plain, $nonce, $key); $encoded = base64_encode($nonce . $cipher);

Base64 用于传输二进制结果。真实应用的密钥应由受控配置提供,同一把密钥下每次加密都要使用新 nonce。
解码后校验长度和完整性
把下列代码接到脚本后面,错误时直接拒绝数据。
立即学习“PHP免费学习笔记(深入)”;
function openMessage(string $encoded, string $key): string
{
$packet = base64_decode($encoded, true);
$size = SODIUM_CRYPTO_SECRETBOX_NONCEBYTES;
if ($packet === false || strlen($packet) < $size + SODIUM_CRYPTO_SECRETBOX_MACBYTES) {
throw new InvalidArgumentException('Invalid encrypted packet');
}
$result = sodium_crypto_secretbox_open(
substr($packet, $size), substr($packet, 0, $size), $key
);
if ($result === false) {
throw new RuntimeException('Authentication failed');
}
return $result;
}
echo openMessage($encoded, $key), PHP_EOL;执行前确认 PHP 已加载 Sodium,预期输出 demo message。
改动密文后验证拒绝解密
追加下面的测试,只修改密文字节,保持编码和长度有效。
$packet = $nonce . $cipher;
$last = strlen($packet) - 1;
$packet[$last] = chr(ord($packet[$last]) ^ 1);
try {
openMessage(base64_encode($packet), $key);
} catch (RuntimeException $error) {
echo $error->getMessage(), PHP_EOL;
}预期输出 Authentication failed。账户密码应使用 password_hash 一类的密码哈希方案。



















