PHP Conference Japan 2024

openssl_open

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

openssl_open開啟密封的資料

說明

openssl_open(
    string $data,
    #[\SensitiveParameter] string &$output,
    string $encrypted_key,
    #[\SensitiveParameter] OpenSSLAsymmetricKey|OpenSSLCertificate|array|string $private_key,
    string $cipher_algo,
    ?string $iv = null
): bool

openssl_open() 使用從 encrypted_key 解密的封裝金鑰,並使用 private_key 開啟(解密)data。解密是使用 cipher_algoiv 完成的。只有當加密方法需要時才需要 IV。該函式會將解密後的資料填入 output。封裝金鑰通常是在使用與私鑰相關聯的公鑰密封資料時產生的。有關詳細資訊,請參閱 openssl_seal()

參數

data

密封的資料。

output

如果呼叫成功,開啟的資料會在此參數中傳回。

encrypted_key

可以使用 private_key 解密的加密對稱金鑰。

private_key

用於解密 encrypted_key 的私鑰。

cipher_algo

用於解密 data 的加密方法。

注意

PHP 8.0 之前的版本預設值是 ('RC4'),這被認為是不安全的。強烈建議明確指定安全的加密方法。

iv

用於解密 data 的初始化向量。如果加密方法需要 IV,則需要它。可以透過使用 cipher_algo 呼叫 openssl_cipher_iv_length() 來找出此值。

傳回值

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

更新日誌

版本 說明
8.0.0 private_key 現在接受 OpenSSLAsymmetricKeyOpenSSLCertificate 實例;先前接受 resource 型別為 OpenSSL keyOpenSSL X.509 CSR
8.0.0 cipher_algo 不再是可選參數。

範例

範例 1 openssl_open() 範例

<?php

// 假設 $sealed、$env_key 和 $iv 包含密封的資料、我們的
// 封裝金鑰和 IV。這些都是由密封者給我們的。

// 從 private_key.pem 檔案中提取私鑰
$pkey = openssl_get_privatekey("file://private_key.pem");

// 解密資料並將其儲存在 $open 中
if (openssl_open($sealed, $open, $env_key, $pkey, 'AES256', $iv)) {
echo
"這是開啟的資料:", $open;
} else {
echo
"開啟資料失敗";
}

?>

參見

新增註解

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

sdc
13 年前
PHP 編譯時未包含 OpenSSL 支援?以下是如何呼叫 openssl 命令列工具以達成相同目標的方法

<?php
// 假設 $sealed 和 $env_key 變數已包含密封的資料和我們的封裝金鑰,兩者皆由密封器提供。

// 指定私鑰檔案和密碼
$pkey_file='key.pem';
$pkey_pp='netsvc';

// 呼叫 openssl 來解密封裝金鑰
$ph=proc_open('openssl rsautl -decrypt -inkey '.
escapeshellarg($pkey_file).' -passin fd:3',array(
0 => array('pipe','r'), // stdin < 封裝金鑰
1 => array('pipe','w'), // stdout > 解碼後的封裝金鑰
2 => STDERR,
3 => array('pipe','r'), // < 密碼
),$pipes);
// 寫入封裝金鑰
fwrite($pipes[0],$env_key);
fclose($pipes[0]);
// 寫入私鑰密碼
fwrite($pipes[3],$pkey_pp);
fclose($pipes[3]);
// 讀取解碼後的金鑰,並轉換為十六進位制
$env_key='';
while(!
feof($pipes[1])){
$env_key.=sprintf("%02x",ord(fgetc($pipes[1])));
}
fclose($pipes[1]);
if(
$xc=proc_close($ph)){
echo
"結束代碼: $xc\n";
}

// 呼叫 openssl 來解密
$ph=proc_open('openssl rc4 -d -iv 0 -K '.$env_key,array(
0 => array('pipe','r'), // stdin < 密封的資料
1 => array('pipe','w'), // stdout > 解開的資料
2 => STDERR,
),
$pipes);
// 寫入密封的資料
fwrite($pipes[0],$sealed);
fclose($pipes[0]);
// 讀取解開的資料
//$open=stream_get_contents($pipes[1]);
$open='';
while(!
feof($pipes[1])){
$open.=fgets($pipes[1]);
}
fclose($pipes[1]);
if(
$xc=proc_close($ph)){
echo
"結束代碼: $xc\n";
}

// 顯示解密後的資料
echo $open;

?>
Gareth Owen
15 年前
範例程式碼,假設 mycert.pem 是一個包含私鑰和公鑰的憑證。

$cert = file_get_contents("mycert.pem");

$public = openssl_get_publickey($cert);
$private = openssl_get_privatekey($cert);

$data = "我是個伐木工人,我很好。";

echo "資料之前:{$data}\n";
openssl_seal($data, $cipher, $e, array($public));

echo "密文:{$cipher}\n";

openssl_open($cipher, $open, $e[0], $private);
echo "解密後:{$open}\n";
To Top