PHP 数据库敏感数据加密存储方案
在用户注册、支付、身份认证等场景中,密码、身份证号、手机号、银行卡号等属于敏感数据,绝不可明文存储于数据库。本文介绍一种基于 PHP 的安全、可落地的加密存储实践方案。
✅ 核心原则
- 不自行实现加密算法 —— 使用 PHP 原生
openssl_encrypt()/openssl_decrypt() - 密钥严格管理 —— 密钥不硬编码,推荐使用环境变量或密钥管理服务(如 Vault)
- 加盐+随机 IV —— 每次加密使用唯一初始化向量(IV),防止相同明文生成相同密文
- 避免对称加密用于密码 —— 密码应使用
password_hash()单向哈希(本文聚焦「可逆加密」场景,如身份证号)
🔐 安全加密类示例
<?php
class SecureDataCryptor
{
private string $cipher = 'AES-256-CBC';
private string $key;
public function __construct(string $key)
{
// 使用 SHA-256 确保密钥长度合规(32字节)
$this->key = hash('sha256', $key, true);
}
public function encrypt(string $plaintext): string
{
$ivlen = openssl_cipher_iv_length($this->cipher);
$iv = openssl_random_pseudo_bytes($ivlen);
$encrypted = openssl_encrypt(
$plaintext,
$this->cipher,
$this->key,
OPENSSL_RAW_DATA,
$iv
);
// 将 IV 和密文 Base64 合并存储(IV 可公开,但必须唯一)
return base64_encode($iv . $encrypted);
}
public function decrypt(string $ciphertext): ?string
{
$data = base64_decode($ciphertext);
$ivlen = openssl_cipher_iv_length($this->cipher);
$iv = substr($data, 0, $ivlen);
$encrypted = substr($data, $ivlen);
return openssl_decrypt(
$encrypted,
$this->cipher,
$this->key,
OPENSSL_RAW_DATA,
$iv
);
}
}
// 使用示例(生产环境请从 $_ENV 或配置中心读取密钥)
$cryptor = new SecureDataCryptor($_ENV['APP_ENCRYPTION_KEY'] ?? 'your-32-byte-secret-key-here');
$idCard = '11010119900307271X';
$encrypted = $cryptor->encrypt($idCard);
echo "加密后: {$encrypted}\n"; // 存入数据库
$decrypted = $cryptor->decrypt($encrypted);
echo "解密后: {$decrypted}"; // 输出原始身份证号
?>
⚠️ 重要提醒
不要加密主键或索引字段:加密后数据不可检索、无法建立高效索引。如需模糊查询(如手机号前缀),可考虑「确定性加密」或「HMAC 摘要索引」,但需权衡安全性与功能。
最后,务必配合 最小权限数据库账户、HTTPS 强制传输、定期密钥轮换 及 审计日志记录,构建纵深防御体系。
安全无小事 —— 加密是手段,而非终点。持续关注 PHP OpenSSL 文档 与 OWASP 加密最佳实践,方能守护用户信任。
```