PHP Libsodium 使用指南
Libsodium 是一个现代、易用的加密库,PHP 从 7.2 开始默认内置了对它的支持。

检查是否已安装
// 检查扩展是否可用
if (extension_loaded('sodium')) {
echo "Libsodium 扩展已加载";
}
// 查看版本
echo SODIUM_LIBRARY_VERSION;
基本加密/解密
对称加密 (SecretKey)
// 生成密钥 $key = sodium_crypto_secretbox_keygen(); // 加密 $message = "这是一条秘密消息"; $nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES); $ciphertext = sodium_crypto_secretbox($message, $nonce, $key); // 解密 $decrypted = sodium_crypto_secretbox_open($ciphertext, $nonce, $key); echo $decrypted; // 输出:这是一条秘密消息
非对称加密
生成密钥对
// Alice 生成密钥对 $alice_keypair = sodium_crypto_box_keypair(); $alice_secret = sodium_crypto_box_secretkey($alice_keypair); $alice_public = sodium_crypto_box_publickey($alice_keypair); // Bob 生成密钥对 $bob_keypair = sodium_crypto_box_keypair(); $bob_secret = sodium_crypto_box_secretkey($bob_keypair); $bob_public = sodium_crypto_box_publickey($bob_keypair);
加密消息
// Alice 给 Bob 发送加密消息
$message = "这是给Bob的私密消息";
$nonce = random_bytes(SODIUM_CRYPTO_BOX_NONCEBYTES);
// 使用Bob的公钥和Alice的私钥加密
$ciphertext = sodium_crypto_box(
$message,
$nonce,
$alice_secret . $bob_public
);
// Bob 解密(使用Bob的私钥和Alice的公钥)
$decrypted = sodium_crypto_box_open(
$ciphertext,
$nonce,
$bob_secret . $alice_public
);
密码哈希
// 哈希密码
$password = "用户密码123";
$hash = sodium_crypto_pwhash_str(
$password,
SODIUM_CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE,
SODIUM_CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE
);
// 验证密码
if (sodium_crypto_pwhash_str_verify($hash, $password)) {
echo "密码验证成功";
}
// 判断是否需要重新哈希
if (sodium_crypto_pwhash_str_needs_rehash(
$hash,
SODIUM_CRYPTO_PWHASH_OPSLIMIT_MODERATE,
SODIUM_CRYPTO_PWHASH_MEMLIMIT_MODERATE
)) {
// 重新哈希
$new_hash = sodium_crypto_pwhash_str(
$password,
SODIUM_CRYPTO_PWHASH_OPSLIMIT_MODERATE,
SODIUM_CRYPTO_PWHASH_MEMLIMIT_MODERATE
);
}
签名验证
// 生成签名密钥对
$sign_keypair = sodium_crypto_sign_keypair();
$secret_key = sodium_crypto_sign_secretkey($sign_keypair);
$public_key = sodium_crypto_sign_publickey($sign_keypair);
// 签名消息
$message = "这是需要签名的消息";
$signed_message = sodium_crypto_sign($message, $secret_key);
// 验证并提取原始消息
$original = sodium_crypto_sign_open($signed_message, $public_key);
if ($original !== false) {
echo "签名验证成功:" . $original;
}
安全随机数生成
// 生成随机字节 $random_bytes = random_bytes(32); // 生成随机整数 $random_int = random_int(1, 100); // 生成用于加密的随机数 $nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
完整示例:用户密码加密存储
class UserAuth {
public static function hashPassword(string $password): string {
return sodium_crypto_pwhash_str(
$password,
SODIUM_CRYPTO_PWHASH_OPSLIMIT_MODERATE,
SODIUM_CRYPTO_PWHASH_MEMLIMIT_MODERATE
);
}
public static function verifyPassword(string $password, string $hash): bool {
return sodium_crypto_pwhash_str_verify($hash, $password);
}
public static function needsRehash(string $hash): bool {
return sodium_crypto_pwhash_str_needs_rehash(
$hash,
SODIUM_CRYPTO_PWHASH_OPSLIMIT_MODERATE,
SODIUM_CRYPTO_PWHASH_MEMLIMIT_MODERATE
);
}
}
// 使用示例
$password = "secure_password_123";
$hash = UserAuth::hashPassword($password);
echo "哈希结果: " . $hash . "\n";
if (UserAuth::verifyPassword("wrong_password", $hash)) {
echo "密码正确";
} else {
echo "密码错误";
}
安全注意事项
// ✅ 正确:每次使用新的随机 nonce
$nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
// ❌ 错误:重复使用 nonce
$nonce = "fixed_nonce_12345678";
// ✅ 正确:使用常量比较
if (hash_equals($hash1, $hash2)) {
echo "相等";
}
// ❌ 错误:使用普通比较(易受时序攻击)
if ($hash1 === $hash2) {
echo "相等";
}
// ✅ 正确:使用后会销毁敏感数据
sodium_memzero($secret_key);
性能优化建议
// 使用不同的安全级别
$opslimit_interactive = SODIUM_CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE; // 用于交互式登录
$opslimit_moderate = SODIUM_CRYPTO_PWHASH_OPSLIMIT_MODERATE; // 中等安全
$opslimit_sensitive = SODIUM_CRYPTO_PWHASH_OPSLIMIT_SENSITIVE; // 高安全(慢)
// 密码哈希示例
$hash = sodium_crypto_pwhash_str(
$password,
$opslimit_moderate, // 根据场景选择合适的级别
SODIUM_CRYPTO_PWHASH_MEMLIMIT_MODERATE
);
常见错误处理
try {
// 验证输入长度
if (mb_strlen($key, '8bit') !== SODIUM_CRYPTO_SECRETBOX_KEYBYTES) {
throw new Exception("密钥长度不正确");
}
// 执行加密操作
$ciphertext = sodium_crypto_secretbox($message, $nonce, $key);
} catch (Exception $e) {
// 处理错误
error_log("加密失败: " . $e->getMessage());
// 不要暴露具体的错误信息给用户
echo "处理失败";
} finally {
// 清理敏感数据
sodium_memzero($key);
}
Libsodium 提供了现代、安全的加密功能,相比 mcrypt 等旧库更推荐使用。