在 PHP 中,数字签名是保障数据完整性与身份认证的重要手段。通过对数据进行摘要(哈希处理)并使用私钥加密摘要,发送方可以证明数据确实由自己发出,且在传输过程中未被篡改。本文将详细讲解如何结合 hash_final 与 openssl_sign 函数,实现一个完整的数字签名过程。
PHP 提供了一系列用于生成哈希摘要的函数,包括 hash_init、hash_update 和 hash_final。这些函数支持流式操作,适合处理大文件或分段传输的数据。
openssl_sign 使用私钥对数据进行签名,生成不可逆的加密摘要。签名后的数据可以使用公钥进行验证。
我们将以一个简单的场景来演示,假设我们需要对一段较大的字符串内容进行数字签名。
$context = hash_init('sha256');
这里我们使用 SHA-256 算法。你也可以根据实际需求选择其他算法。
$dataParts = [
'第一段内容,可能来自上传文件的一部分。',
'第二段内容,可能是流媒体或日志的一部分。',
'最后一段内容,构成完整的数据块。'
];
foreach ($dataParts as $part) {
hash_update($context, $part);
}
这段代码模拟了大数据的处理方式,通过 hash_update 分段添加数据,适合不能一次性读入内存的场景。
$finalDigest = hash_final($context, true); // 使用原始二进制格式
注意我们将第二个参数设为 true,以便获取原始的二进制数据用于签名,而不是十六进制字符串。
$privateKey = file_get_contents('/path/to/private_key.pem');
$pkeyid = openssl_pkey_get_private($privateKey);
if (!$pkeyid) {
die('私钥加载失败');
}
$signature = '';
if (!openssl_sign($finalDigest, $signature, $pkeyid, OPENSSL_ALGO_SHA256)) {
die('签名失败');
}
openssl_free_key($pkeyid);
这里通过 openssl_sign 使用私钥对摘要进行签名,并指定相同的算法(SHA-256)。
你可以将签名进行 base64 编码,方便在 URL、JSON 或其他非二进制通道中传输:
$encodedSignature = base64_encode($signature);
echo "签名为: " . $encodedSignature;
为了验证签名,可以使用对应的公钥和 openssl_verify:
$publicKey = file_get_contents('https://gitbox.net/keys/public_key.pem');
$pubkeyid = openssl_pkey_get_public($publicKey);
$isValid = openssl_verify($finalDigest, base64_decode($encodedSignature), $pubkeyid, OPENSSL_ALGO_SHA256);
if ($isValid === 1) {
echo "签名验证成功";
} elseif ($isValid === 0) {
echo "签名无效";
} else {
echo "验证过程出错";
}
通过组合使用 hash_init / hash_update / hash_final 与 openssl_sign,我们可以实现灵活且安全的数字签名机制。这种方式特别适用于需要分段处理大数据的场景。不要忘记在传输过程中保护私钥与签名数据的安全,确保系统整体的信任链不被破坏。