本文目录导读:

在 PHP 中加密存储敏感数据(如密码、API密钥、个人信息等)是一个重要的安全实践,以下是几种常见且安全的加密存储方案:
密码加密(最常用)
使用 password_hash() 和 password_verify()(推荐)
// 加密(存储时)
$password = 'user_password_123';
$hashedPassword = password_hash($password, PASSWORD_DEFAULT);
// 输出类似:$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi
// 存入数据库
$stmt = $pdo->prepare("INSERT INTO users (username, password) VALUES (?, ?)");
$stmt->execute([$username, $hashedPassword]);
// 验证(登录时)
$inputPassword = 'user_input_password';
$storedHash = $row['password'];
if (password_verify($inputPassword, $storedHash)) {
echo "密码正确";
} else {
echo "密码错误";
}
// 检查是否需要重新哈希
if (password_needs_rehash($storedHash, PASSWORD_DEFAULT)) {
$newHash = password_hash($inputPassword, PASSWORD_DEFAULT);
// 更新数据库
}
对称加密(AES-256)
适用于需要解密的数据(如身份证号、银行卡等)。
// 定义加密类
class Crypto {
private $key;
private $cipher = 'aes-256-gcm';
public function __construct(string $encryptionKey) {
$this->key = hash('sha256', $encryptionKey, true);
}
// 加密
public function encrypt(string $plaintext): string {
$ivlen = openssl_cipher_iv_length($this->cipher);
$iv = openssl_random_pseudo_bytes($ivlen);
$tag = '';
$ciphertext = openssl_encrypt(
$plaintext,
$this->cipher,
$this->key,
OPENSSL_RAW_DATA,
$iv,
$tag
);
if ($ciphertext === false) {
throw new Exception('加密失败: ' . openssl_error_string());
}
// 将 IV 和 tag 一起存储
return base64_encode($iv . $tag . $ciphertext);
}
// 解密
public function decrypt(string $encryptedData): string {
$data = base64_decode($encryptedData);
$ivlen = openssl_cipher_iv_length($this->cipher);
$iv = substr($data, 0, $ivlen);
$tag = substr($data, $ivlen, 16); // GCM tag 是 16 字节
$ciphertext = substr($data, $ivlen + 16);
$plaintext = openssl_decrypt(
$ciphertext,
$this->cipher,
$this->key,
OPENSSL_RAW_DATA,
$iv,
$tag
);
if ($plaintext === false) {
throw new Exception('解密失败');
}
return $plaintext;
}
}
// 使用示例
$crypto = new Crypto('secret_key_here');
$encrypted = $crypto->encrypt('1234567890');
echo "加密后: " . $encrypted . "\n";
echo "解密后: " . $crypto->decrypt($encrypted);
非对称加密(RSA)
适用于双向通信或多方共享数据。
// 生成密钥对
$config = [
'private_key_bits' => 2048,
'private_key_type' => OPENSSL_KEYTYPE_RSA,
];
$keyPair = openssl_pkey_new($config);
// 提取公钥和私钥
openssl_pkey_export($keyPair, $privateKey);
$publicKey = openssl_pkey_get_details($keyPair)['key'];
// 加密(使用公钥)
function rsaEncrypt(string $data, string $publicKey): string {
$encrypted = '';
// 分段加密(因为 RSA 有长度限制)
$chunkSize = 245; // 2048位RSA最大加密长度
$dataChunks = str_split($data, $chunkSize);
foreach ($dataChunks as $chunk) {
$encryptedChunk = '';
openssl_public_encrypt($chunk, $encryptedChunk, $publicKey);
$encrypted .= $encryptedChunk;
}
return base64_encode($encrypted);
}
// 解密(使用私钥)
function rsaDecrypt(string $encryptedData, string $privateKey): string {
$data = base64_decode($encryptedData);
$decrypted = '';
$chunkSize = 256; // 2048位RSA最大解密长度
$dataChunks = str_split($data, $chunkSize);
foreach ($dataChunks as $chunk) {
$decryptedChunk = '';
openssl_private_decrypt($chunk, $decryptedChunk, $privateKey);
$decrypted .= $decryptedChunk;
}
return $decrypted;
}
// 使用示例
$data = "敏感数据";
$encrypted = rsaEncrypt($data, $publicKey);
$decrypted = rsaDecrypt($encrypted, $privateKey);
echo "解密结果: " . $decrypted;
哈希(单向加密)
适用于无需解密的场景(如验证数据完整性)。
// SHA-256 哈希
$hash = hash('sha256', $data);
// HMAC(带密钥的哈希)
$key = 'secret_key';
$hmac = hash_hmac('sha256', $data, $key);
// 加盐哈希
$salt = bin2hex(random_bytes(16));
$saltedHash = hash('sha256', $salt . $data);
// Bcrypt
$bcryptHash = password_hash($data, PASSWORD_BCRYPT, ['cost' => 12]);
// Argon2id(最安全)
$argon2Hash = password_hash($data, PASSWORD_ARGON2ID, [
'memory_cost' => 65536, // 64MB
'time_cost' => 4,
'threads' => 1
]);
数据库层面的加密
// MySQL AES 加密/解密 $query = "INSERT INTO users (name, ssn) VALUES (?, AES_ENCRYPT(?, ?))"; $stmt = $pdo->prepare($query); $stmt->execute([$name, $ssn, $encryptionKey]); $query = "SELECT AES_DECRYPT(ssn, ?) as ssn_decrypted FROM users WHERE id = ?"; $stmt = $pdo->prepare($query); $stmt->execute([$encryptionKey, $userId]); $row = $stmt->fetch(); echo $row['ssn_decrypted'];
完整的安全实践建议
class SecureData {
private $pdo;
private $encryptionKey;
public function __construct(\PDO $pdo, string $key) {
$this->pdo = $pdo;
$this->encryptionKey = $key;
}
// 安全存储密码
public function storePassword(int $userId, string $password): bool {
$hashed = password_hash($password, PASSWORD_DEFAULT);
$stmt = $this->pdo->prepare(
"UPDATE users SET password_hash = ? WHERE id = ?"
);
return $stmt->execute([$hashed, $userId]);
}
// 安全存储敏感数据
public function storeSensitiveData(int $userId, string $type, string $data): bool {
// 生成唯一的 IV
$iv = random_bytes(16);
$ciphertext = openssl_encrypt(
$data,
'aes-256-cbc',
$this->encryptionKey,
0,
$iv
);
$stmt = $this->pdo->prepare(
"INSERT INTO encrypted_data (user_id, data_type, iv, ciphertext)
VALUES (?, ?, ?, ?)"
);
return $stmt->execute([
$userId,
$type,
base64_encode($iv),
$ciphertext
]);
}
// 环境变量中的密钥(推荐)
// 不要硬编码密钥在代码中
public function getKey(): string {
return getenv('APP_ENCRYPTION_KEY') ?:
parse_ini_file('/secure/config.ini')['encryption_key'];
}
}
安全最佳实践总结
- 密码永远使用单向哈希:
password_hash()+password_verify() - 敏感数据使用 AES-256-GCM:带有认证标签,防篡改
- 密钥管理:
- 存储在环境变量或安全的密钥管理服务中
- 定期轮换密钥
- 不同用途使用不同密钥
- 使用 HTTPS:传输层加密
- 日志清理:不要记录敏感数据
- 备份安全:加密备份文件
选择哪种方案取决于你的需求:
- 无需解密 → 哈希(password_hash)
- 需要解密 → AES 对称加密
- 多方共享 → RSA 非对称加密
- 数据完整性验证 → HMAC
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播