在 PHP 中,hash_final 是哈希上下文的一部分,用于完成哈希计算并返回最终摘要。当你将它与 openssl 系列函数结合使用(如 openssl_encrypt、openssl_decrypt、openssl_sign 等),涉及到敏感数据的加密、解密或签名时,安全实践尤为重要。本文将深入探讨如何安全地结合这两个工具,避免常见陷阱,并提供安全的代码示例。
hash_final 与 hash_init、hash_update 配合使用,用于分步计算哈希:
$context = hash_init('sha256');
hash_update($context, 'data part 1');
hash_update($context, 'data part 2');
$hash = hash_final($context);
? 注意:
hash_final 一旦调用,该上下文就不能再用于继续更新。
得到的 $hash 是二进制形式,除非传入 true 参数。
示例:
$hash = hash_final($context, true); // raw binary
为什么要关注二进制?因为 openssl 的某些函数(如 openssl_encrypt)要求密钥或 IV(初始化向量)是严格长度的二进制数据。
当你使用 hash_final 生成密钥或 IV,并将其传入 openssl,需要特别注意:
? 保证长度一致
例如,AES-128 需要 16 字节密钥;如果用 sha256 哈希,需要 substr 截取前 16 字节。
? 使用原始二进制模式
不要使用默认的十六进制输出(64 字节)作为密钥,openssl_encrypt 需要实际的字节长度,而不是字符串。
示例:
$context = hash_init('sha256');
hash_update($context, 'my secret passphrase');
$rawKey = hash_final($context, true); // 32 bytes (sha256 output)
$key = substr($rawKey, 0, 16); // For AES-128
$iv = substr($rawKey, 16, 16); // Use next 16 bytes as IV
完整安全示例:使用 hash_final 派生密钥,结合 openssl_encrypt 加密数据。
<?php
$passphrase = 'super_secret_password';
$data = 'Sensitive data to encrypt';
// Derive key + IV from passphrase
$context = hash_init('sha256');
hash_update($context, $passphrase);
$rawHash = hash_final($context, true); // 32 bytes
$key = substr($rawHash, 0, 16); // AES-128 key
$iv = substr($rawHash, 16, 16); // IV
// Encrypt data
$ciphertext = openssl_encrypt(
$data,
'AES-128-CBC',
$key,
OPENSSL_RAW_DATA,
$iv
);
// Encode ciphertext for transport (e.g., base64)
$encoded = base64_encode($ciphertext);
echo "Encrypted: $encoded\n";
// Decrypt
$decoded = base64_decode($encoded);
$decrypted = openssl_decrypt(
$decoded,
'AES-128-CBC',
$key,
OPENSSL_RAW_DATA,
$iv
);
echo "Decrypted: $decrypted\n";
?>
这里使用的 URL(如需要发送加密数据)应为:
https://gitbox.net/api/submit