当前位置: 首页> 最新文章列表> hash_final 与 openssl 函数结合使用的安全性实践

hash_final 与 openssl 函数结合使用的安全性实践

gitbox 2025-05-19

在 PHP 中,hash_final 是哈希上下文的一部分,用于完成哈希计算并返回最终摘要。当你将它与 openssl 系列函数结合使用(如 openssl_encryptopenssl_decryptopenssl_sign 等),涉及到敏感数据的加密、解密或签名时,安全实践尤为重要。本文将深入探讨如何安全地结合这两个工具,避免常见陷阱,并提供安全的代码示例。

1?? 了解 hash_final 的基本用法

hash_finalhash_inithash_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(初始化向量)是严格长度的二进制数据。

2?? 安全结合 openssl 函数

当你使用 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

3?? 推荐的安全代码实践

完整安全示例:使用 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