當前位置: 首頁> 最新文章列表> hash_final 如何與openssl_sign 一起完成數字簽名?

hash_final 如何與openssl_sign 一起完成數字簽名?

gitbox 2025-05-26

在PHP 中,數字簽名是保障數據完整性與身份認證的重要手段。通過對數據進行摘要(哈希處理)並使用私鑰加密摘要,發送方可以證明數據確實由自己發出,且在傳輸過程中未被篡改。本文將詳細講解如何結合hash_finalopenssl_sign函數,實現一個完整的數字簽名過程。

一、基本概念回顧

1. hash 系列函數

PHP 提供了一系列用於生成哈希摘要的函數,包括hash_inithash_updatehash_final 。這些函數支持流式操作,適合處理大文件或分段傳輸的數據。

2. openssl_sign 函數

openssl_sign使用私鑰對數據進行簽名,生成不可逆的加密摘要。簽名後的數據可以使用公鑰進行驗證。

二、簽名過程步驟

我們將以一個簡單的場景來演示,假設我們需要對一段較大的字符串內容進行數字簽名。

1. 初始化哈希上下文

$context = hash_init('sha256');

這裡我們使用SHA-256 算法。你也可以根據實際需求選擇其他算法。

2. 分段更新數據(模擬大數據處理)

 $dataParts = [
    '第一段內容,可能來自上傳文件的一部分。',
    '第二段內容,可能是流媒體或日誌的一部分。',
    '最後一段內容,構成完整的數據塊。'
];

foreach ($dataParts as $part) {
    hash_update($context, $part);
}

這段代碼模擬了大數據的處理方式,通過hash_update分段添加數據,適合不能一次性讀入內存的場景。

3. 生成最終摘要

$finalDigest = hash_final($context, true); // 使用原始二進制格式

注意我們將第二個參數設為true ,以便獲取原始的二進制數據用於簽名,而不是十六進製字符串。

4. 使用私鑰進行簽名

$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)。

5. 將簽名進行安全傳輸或保存

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