International PHP Conference Berlin 2025

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配置文件选项。参见 openssl_csr_new() 获取更多关于 options 的信息。

返回值

成功时返回 true, 或者在失败时返回 false

更新日志

版本 说明
8.0.0 key 现在接受 OpenSSLAsymmetricKeyOpenSSLCertificate 实例;之前接受类型 OpenSSL keyOpenSSL X.509resource
添加备注

用户贡献的备注 6 notes

up
4
chris dot kistner at gmail dot com
13 years ago
Please take note that older versions of PHP/OpenSSL exports the RSA private key with '-----BEGIN RSA PRIVATE KEY-----' PEM tag, which includes just the privateKey field, thus omitting the version and privateKeyAlgorithm fields.

The effect of that would be that if you're converting it to DER, and then back to PEM, but using '-----BEGIN PRIVATE KEY-----' PEM tag, that the openssl_pkey_get_privatekey() function will fail!

Senthryl's code can be used to prefix the PEM encoded data with the version and privateKeyAlgorithm fields again.

The newer PHP/OpenSSL versions exports the RSA private key with '-----BEGIN PRIVATE KEY-----' PEM tag, which includes the version and privateKeyAlgorithm fields.

I noticed these differences between my two servers:
PHP Version 5.3.3 (OpenSSL 1.0.0a-fips 1 Jun 2010) on Fedora Core 12 x64
PHP Version 5.2.9 (OpenSSL 0.9.8g 19 Oct 2007) on Fedora Core 10 x64
up
3
eric at ericseastrand dot com
12 years ago
I kept banging my head against the wall today trying to figure out why the RSA keys I was generating were encrypted (they have this stuff in them)
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,BEA1180EADE1524F

I finally realized that the issue was that I was passing a password into the "openssl_pkey_export" method inadvertently.

So the moral of the story is: you have to use NULL as the password. using an empty string will still cause the key to be encrypted.
up
2
robbat2 at gentoo dot org
20 years ago
Warning, this function is NOT capable of exporting PEM-encoded public keys. It can only export private keys.
up
2
Senthryl
14 years ago
This function can be used to create a private key for use by JCE in Java. For example, a private key could be generated by a PHP script and the result could be used in a Java client application.

Java requires the private key in DER format with some extra ASN.1 wrapping. The function below can be used to convert the output of openssl_pkey_export into a format suitable for input into 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;
}
?>

Example use:
<?php
$keys
= openssl_pkey_new(array('digest_alg' => 'sha1', 'private_key_type' => OPENSSL_KEYTYPE_RSA, 'private_key_bits' => 2048));
if (
$keys === false) die('Failed to generate key pair.'."\n");
if (!
openssl_pkey_export($keys, $privateKey)) die('Failed to retrieve private key.'."\n");
$javaKey = convertPemToDer($privateKey);

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

Exporting a public key for use with JCE is trickier, since the Java libraries require the key to be input as a byte array. In effect, the public key outputted by openssl_pkey_get_details() must be base64 decoded as above, and then parsed as ASN.1 to receive the actual key bytes (this can be done either on the PHP side or the Java side).

The following link is an invaluable resource to understanding the output from these functions:
"A Layman's Guide to a Subset of ASN.1, BER, and DER"
http://luca.ntop.org/Teaching/Appunti/asn1.html
up
3
Tk at phpRocks dot net
15 years ago
Complete example to encrypt data...
=)
<pre>
<?php
// Create the keypair
$res=openssl_pkey_new();

// Get private key
openssl_pkey_export($res, $privkey, "PassPhrase number 1" );

// Get public key
$pubkey=openssl_pkey_get_details($res);
$pubkey=$pubkey["key"];
//var_dump($privkey);
//var_dump($pubkey);

// Create the keypair
$res2=openssl_pkey_new();

// Get private key
openssl_pkey_export($res2, $privkey2, "This is a passPhrase *µà" );

// Get public key
$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]));

// decrypt the data and store it in $open
if (openssl_open($sealed, $open, $ekeys[1], openssl_pkey_get_private ($privkey2 ,"This is a passPhrase *µà" ) ) ) {
echo
"here is the opened data: ", $open;
} else {
echo
"failed to open data";
}

?>
</pre>

Outputs :
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="
here is the opened data: Only I know the purple fox. Trala la !
up
-3
Anonymous
17 years ago
you can get public key using openssl_pkey_get_details(resource $key ) function:

<?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