在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 ,我們可以實現靈活且安全的數字簽名機制。這種方式特別適用於需要分段處理大數據的場景。不要忘記在傳輸過程中保護私鑰與簽名數據的安全,確保系統整體的信任鏈不被破壞。