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

options 可用于通过指定和/或覆盖 openssl 配置文件选项来微调导出过程。有关 options 的更多信息,请参阅 openssl_csr_new()

返回值

成功时返回 true,失败时返回 false

变更日志

版本 说明
8.0.0 key 现在可以接受 OpenSSLAsymmetricKeyOpenSSLCertificate 实例;以前接受的是类型为 OpenSSL keyOpenSSL X.509资源
添加说明

用户贡献说明 6 说明

4
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 的代码可用于再次在 PEM 编码数据前面添加 version 和 privateKeyAlgorithm 字段。

较新的 PHP/OpenSSL 版本导出带有 '-----BEGIN PRIVATE KEY-----' PEM 标签的 RSA 私钥,该标签包含 version 和 privateKeyAlgorithm 字段。

我在我的两个服务器之间发现了这些差异
PHP 版本 5.3.3 (OpenSSL 1.0.0a-fips 1 Jun 2010) 在 Fedora Core 12 x64 上
PHP 版本 5.2.9 (OpenSSL 0.9.8g 19 Oct 2007) 在 Fedora Core 10 x64 上
3
eric at ericseastrand dot com
12 年前
今天我一直在撞墙,试图弄清楚为什么我生成的 RSA 密钥被加密了(它们包含这些内容)
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,BEA1180EADE1524F

我终于意识到问题是我无意中将密码传递给了 "openssl_pkey_export" 方法。

所以故事的寓意是:您必须使用 NULL 作为密码。使用空字符串仍然会导致密钥被加密。
2
robbat2 at gentoo dot org
20 年前
警告,此函数不能导出 PEM 编码的公钥。它只能导出私钥。
2
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(
'Invalid PEM format encountered.'."\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
3
Tk at phpRocks dot net
15 年前
加密数据的完整示例...
=)
<pre>
<?php
// 创建密钥对
$res=openssl_pkey_new();

// 获取私钥
openssl_pkey_export($res, $privkey, "PassPhrase number 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, "This is a passPhrase *µà" );

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

$data = "Only I know the purple fox. Trala la !";

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

var_dump("sealed");
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 ,"This is a passPhrase *µà" ) ) ) {
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) "sealed"
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="
以下是已打开的数据:Only I know the purple fox. Trala la !
-3
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