PHP Conference Japan 2024

openssl_public_decrypt

(PHP 4 >= 4.0.6, PHP 5, PHP 7, PHP 8)

openssl_public_decrypt使用公開金鑰解密資料

描述

openssl_public_decrypt(
    string $data,
    #[\SensitiveParameter] string &$decrypted_data,
    OpenSSLAsymmetricKey|OpenSSLCertificate|array|string $public_key,
    int $padding = OPENSSL_PKCS1_PADDING
): bool

openssl_public_decrypt() 解密先前透過 openssl_private_encrypt() 加密的 data,並將結果儲存到 decrypted_data 中。

您可以利用此函式來檢查訊息是否由私密金鑰的擁有者所寫。

參數

data

decrypted_data

public_key

public_key 必須是與用於加密資料的私密金鑰相對應的公開金鑰。

padding

padding 可以是 OPENSSL_PKCS1_PADDINGOPENSSL_NO_PADDING 其中之一。

回傳值

成功時回傳 true,失敗時回傳 false

變更日誌

版本 描述
8.0.0 public_key 現在接受 OpenSSLAsymmetricKeyOpenSSLCertificate 實例;先前則接受 resource 類型為 OpenSSL keyOpenSSL X.509

參見

新增註解

使用者貢獻的註解 1 則註解

5
Hernanibus
8 年前
關於手冊中 openssl_private_encrypt 中 [P.Peyremorte] 的註解的一點小註解。

「- openssl_private_encrypt 一次最多可加密 117 個字元。」

這取決於 $key 的長度

– 對於 1024 位元金鑰長度 => 要加密的最大字元數 (位元組) = 1024/8 - 11 (當使用填充時) = 117 個字元 (位元組)。
– 對於 2048 位元金鑰長度 => 要加密的最大字元數 (位元組) = 2048/8 - 11 (當使用填充時) = 245 個字元 (位元組)。
... 等等

順帶一提,如果 openssl_private_encrypt 因為資料大小而失敗,您只會得到 false 作為回傳值,openssl_public_decrypt() 在解密時也是如此。

「- 加密輸出字串的長度始終為 129 個字元。如果您在加密輸出上使用 base64_encode,則將始終給出 172 個字元,最後一個始終為 "=" (填充物)」

這再次取決於 $key 的長度

– 對於 1024 位元金鑰長度 => 原始位元組的加密數始終是 RSA 設計的 128 位元組 (1024 位元) 區塊。
– 對於 2048 位元金鑰長度 => 原始位元組的加密數始終是 RSA 設計的 256 位元組 (2048 位元) 區塊。
... 等等

關於 base64_encode 輸出長度,它取決於您編碼的內容 (這表示它取決於加密後的位元組),但通常產生的編碼字串會大約大 33% (對於 128 位元組大約 170 位元組,對於 256 位元組大約 340 位元組)。

我會將 [P.Peyremorte] 的註解稍微概括一下:
<?php
// 給定變數作為常數:

//用於加密區塊密碼的區塊大小
private $ENCRYPT_BLOCK_SIZE = 200;// 例如,對於 2048 位元金鑰,留下一些空間

//用於解密區塊密碼的區塊大小
private $DECRYPT_BLOCK_SIZE = 256;// 這也是 2048 位元金鑰

//對於加密,我們將使用:
function encrypt_RSA($plainData, $privatePEMKey)
{
$encrypted = '';
$plainData = str_split($plainData, $this->ENCRYPT_BLOCK_SIZE);
foreach(
$plainData as $chunk)
{
$partialEncrypted = '';

//例如使用 OPENSSL_PKCS1_PADDING 作為填充
$encryptionOk = openssl_private_encrypt($chunk, $partialEncrypted, $privatePEMKey, OPENSSL_PKCS1_PADDING);

if(
$encryptionOk === false){return false;}//您也可以回傳錯誤。如果太大,這將為 false
$encrypted .= $partialEncrypted;
}
return
base64_encode($encrypted);//將整個二進位字串編碼為 MIME base 64
}

//對於解密,我們將使用:
protected function decrypt_RSA($publicPEMKey, $data)
{
$decrypted = '';

//在分割前必須完成解碼,以取得二進位字串
$data = str_split(base64_decode($data), $this->DECRYPT_BLOCK_SIZE);

foreach(
$data as $chunk)
{
$partial = '';

//確保填充匹配
$decryptionOK = openssl_public_decrypt($chunk, $partial, $publicPEMKey, OPENSSL_PKCS1_PADDING);

if(
$decryptionOK === false){return false;}//這裡也處理解密中的錯誤。如果太大,這將為 false
$decrypted .= $partial;
}
return
$decrypted;
}
?>
To Top