PHP Conference Japan 2024

openssl_pkey_export

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

openssl_pkey_export將金鑰的可匯出表示式取得為字串

說明

openssl_pkey_export(
    #[\SensitiveParameter] OpenSSLAsymmetricKey|OpenSSLCertificate|array|string $key,
    string &$output,
    #[\SensitiveParameter] ?string $passphrase = null,
    ?array $options = null
): bool

openssl_pkey_export()key 匯出為 PEM 編碼字串,並將其儲存至 output (以傳址方式傳遞)。

注意 您需要安裝有效的 openssl.cnf 才能使此函式正常運作。請參閱安裝章節中的註解以取得更多資訊。

參數

key

output

passphrase

金鑰可選擇性地受到 passphrase 的保護。

options

透過指定及/或覆寫 openssl 組態檔的選項,可以使用 options 來微調匯出程序。請參閱 openssl_csr_new() 以取得有關 options 的更多資訊。

傳回值

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

變更記錄

版本 說明
8.0.0 key 現在接受 OpenSSLAsymmetricKeyOpenSSLCertificate 實例;先前,接受類型為 OpenSSL keyOpenSSL X.509資源
新增註解

使用者提供的註解 6 個註解

chris dot kistner at gmail dot com
13 年前
請注意,舊版的 PHP/OpenSSL 會以 '-----BEGIN RSA PRIVATE KEY-----' PEM 標籤匯出 RSA 私鑰,其中僅包含 privateKey 欄位,因此省略了 version 和 privateKeyAlgorithm 欄位。

這會導致如果您將其轉換為 DER,然後再轉換回 PEM,但使用 '-----BEGIN PRIVATE KEY-----' PEM 標籤,則 openssl_pkey_get_privatekey() 函式將會失敗!

可以使用 Senthryl 的程式碼再次以 version 和 privateKeyAlgorithm 欄位為 PEM 編碼資料加上前綴。

較新的 PHP/OpenSSL 版本會以 '-----BEGIN PRIVATE KEY-----' PEM 標籤匯出 RSA 私鑰,其中包含 version 和 privateKeyAlgorithm 欄位。

我注意到我的兩台伺服器之間存在這些差異
PHP 版本 5.3.3 (OpenSSL 1.0.0a-fips 2010 年 6 月 1 日) 在 Fedora Core 12 x64 上
PHP 版本 5.2.9 (OpenSSL 0.9.8g 2007 年 10 月 19 日) 在 Fedora Core 10 x64 上
eric at ericseastrand dot com
12 年前
今天我一直碰壁,試圖弄清楚為什麼我產生的 RSA 金鑰被加密了 (它們裡面有這些東西)
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,BEA1180EADE1524F

我終於意識到問題是我不小心將密碼傳遞到「openssl_pkey_export」方法中。

所以重點是:您必須使用 NULL 作為密碼。使用空字串仍然會導致金鑰被加密。
robbat2 at gentoo dot org
20 年前
警告,此函式無法匯出 PEM 編碼的公鑰。它只能匯出私鑰。
Senthryl
14 年前
此函式可用於建立 Java 中 JCE 使用的私鑰。例如,可以使用 PHP 腳本產生私鑰,並在 Java 用戶端應用程式中使用該結果。

Java 需要 DER 格式的私鑰,並帶有一些額外的 ASN.1 包裝。以下函式可用於將 openssl_pkey_export 的輸出轉換為適合輸入 JCE 的格式

<?php
function derLength($length) {
if (
$length < 128) return str_pad(dechex($length), 2, '0', STR_PAD_LEFT);
$output = dechex($length);
if (
strlen($output) % 2 != 0) $output = '0'.$output;
return
dechex(128 + strlen($output)/2) . $output;
}
function
convertPemToDer($pem) {
$matches = array();
if (!
preg_match('~^-----BEGIN ([A-Z ]+)-----\s*?([A-Za-z0-9+=/\r\n]+)\s*?-----END \1-----\s*$~D', $pem, $matches)) {
die(
'遇到無效的 PEM 格式。'."\n");
}
$derData = base64_decode(str_replace(array("\r", "\n"), array('', ''), $matches[2]));
$derData = pack('H*', '020100300d06092a864886f70d010101050004'.derLength(strlen($derData))) . $derData;
$derData = pack('H*', '30'.derLength(strlen($derData))) . $derData;
return
$derData;
}
?>

使用範例
<?php
$keys
= openssl_pkey_new(array('digest_alg' => 'sha1', 'private_key_type' => OPENSSL_KEYTYPE_RSA, 'private_key_bits' => 2048));
if (
$keys === false) die('產生金鑰對失敗。'."\n");
if (!
openssl_pkey_export($keys, $privateKey)) die('擷取私鑰失敗。'."\n");
$javaKey = convertPemToDer($privateKey);

file_put_contents('key_for_java.der', $javaKey);
?>

匯出用於 JCE 的公鑰比較棘手,因為 Java 函式庫要求金鑰以位元組陣列的形式輸入。實際上,由 openssl_pkey_get_details() 輸出的公鑰必須如上所述進行 base64 解碼,然後解析為 ASN.1 以接收實際的金鑰位元組(這可以在 PHP 端或 Java 端完成)。

以下連結是了解這些函式輸出的寶貴資源
「ASN.1、BER 和 DER 子集的通俗指南」
http://luca.ntop.org/Teaching/Appunti/asn1.html
Tk at phpRocks dot net
15 年前
完整的資料加密範例...
=)
<pre>
<?php
// 建立金鑰對
$res=openssl_pkey_new();

// 取得私鑰
openssl_pkey_export($res, $privkey, "密碼短語 1 號" );

// 取得公鑰
$pubkey=openssl_pkey_get_details($res);
$pubkey=$pubkey["key"];
//var_dump($privkey);
//var_dump($pubkey);

// 建立金鑰對
$res2=openssl_pkey_new();

// 取得私鑰
openssl_pkey_export($res2, $privkey2, "這是一個密碼短語 *µà" );

// 取得公鑰
$pubkey2=openssl_pkey_get_details($res2);
$pubkey2=$pubkey2["key"];
var_dump($privkey2);
var_dump($pubkey2);

$data = "只有我知道紫狐。Trala la !";

openssl_seal($data, $sealed, $ekeys, array($pubkey, $pubkey2));

var_dump("已封裝");
var_dump(base64_encode($sealed));
var_dump(base64_encode($ekeys[0]));
var_dump(base64_encode($ekeys[1]));

// 解密資料並將其儲存在 $open 中
if (openssl_open($sealed, $open, $ekeys[1], openssl_pkey_get_private ($privkey2 ,"這是一個密碼短語 *µà" ) ) ) {
echo
"這是開啟的資料:", $open;
} else {
echo
"開啟資料失敗";
}

?>
</pre>

輸出
string(963) "-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,DA1943487C9C83B2

1/j65PJgfYqYMJSWRBk9UzXaa3USMdpkq4ztzL7IPMTPgTwVKxZbvBxzsGUXUmh6
dkWpF1jzi3B44o06mw55t2LHNkGAph/iKVP4Zvnyp/KWaZJSF+pNkvukle1u2/40
WpbNy1f8LA+ZDr7ICOCY1jy/bz/xzOCrVjqY/F4ukQik9M6bL9ZwI5fyhrcHq6EG
KsUX49XKtP/a+kQhluejzIw1aDBqmHpJTCzkL7teCk6l8x8r8mMmss1D9XqggjFm
TQncqR6IU5DClklO53JdWSFC5zTcFYMgq9lMwCQ5o4bs8iBKiE+TOFEKiggtn5zA
v189tlPtM6YePcXAm5Ymgy90Ovq3lGS4k+JkCB2Hm3HgUAB3pd9v3fOeyuFMeing
XHBuLR5nmWITzcfRuAsh0p9xe2puTVFdrLkrQFnh5Xkerm+YUQ6oTecTKRFq7S3l
hLlFIg7KbXxDjg3H5f87DCEp/isV70Rc7flvIBP6u5GX+GrmCFWjQxmGefEJQ5fZ
P7sOzHEdkOHZV7yYn+5MwQ4vDHLKQxvMqUolgvuEAzcL1o976KHAQP0accmwApXz
jry3zVqRnGvyPHo+nGwRiATJj0lAgX/j8cghJg+oo+TiXD2cM5i+Hut4dmImZNDL
3Fn2uLzklQHPlaoaz2dACyaN/sUtmVLtdnn00nuwIy2xDfHDl9MOQ6WHocU78DWo
Mw+x8B+SBsALm3Ah6JzqA8l3OAYSRxjp7YQXLQLkdCi7jEjjTl/0NVTnqU+W89XB
GBH3r8ZgIpifl3M7ZYTKLnToNL7Y/AehPs+tKgFHkXtGMKu4cIt9Ag==
-----END RSA PRIVATE KEY-----
"
string(272) "-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDH82E/Dn37torKz/vhAkpji9ZS
HCyfM7JuXCbh70F75Zh2/rEVvz38yNf6f01DNXiSpzO5eTmoXD7Blsb635AOjYbl
X/WljpFbwQ2QUUDlNDAslrqXYlMzht2MCq/pjtGgk0zJx6i+HjFyV7mebeePQY/x
NOzMpmy/Ke3u+SSHRwIDAQAB
-----END PUBLIC KEY-----
"
string(6) "已封裝"
string(52) "y4L3+SDVJwTfa9Em61R3X2p/LElr8N/xPCXw8kqm0co4bn3V1Tw="
string(172) "ezUo2rWLGHPv9bHE5gG8fe5qy8erGlITsSs+qGr2o8aoi98SLnyIFm4N
EQWJrmU43Ehlw72NujJ
B8chYNw2NkIDfaLChvLH54CBuCfyuF+1lWEAUwL8
FU1LftqIIt1ikjSu/8qFU6S6wikJx1pFf1IbXfOeeJVvZ1UJM2rBbudI="
string(172) "RPYLXGBXDnXDIUrFy1/GOM+//Ew/mn2syKDbhIegOJJPnpd
X6ffwXkWH5Bp8kOdz0aO9gK3whG+c
/QF+9eqcTw9SvvlrDqsP0gkRGNIOgMUiBFLoMT92JQWSI7ZesDAU0
JPRWpXsKaIOEkBGmxOMYfEd6OJWp0Mwe4COL3lP2PQ="
這是開啟的資料:只有我知道紫狐。Trala la !
Anonymous
17 年前
您可以使用 openssl_pkey_get_details(resource $key) 函數取得公鑰

<?php

$pub_key
= openssl_pkey_get_public(file_get_contents('./cert.crt'));
$keyData = openssl_pkey_get_details($pub_key);
fule_put_contents('./key.pub', $keyData['key']);

?>
To Top