PHP RSA密钥创建 [英] PHP RSA key creation

查看:408
本文介绍了PHP RSA密钥创建的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在创建/使用PHP中创建和使用的RSA密钥时遇到问题.问题是,(公共和私有)密钥应该在不同的服务器之间交换(例如,移动用户帐户时).

I have an issue with creating/using RSA keys created and used in PHP. Problem is, that the (public AND private) keys should be exchanged between different servers (e.g. when a user account is moved).

现在,PHP的openssl-lib没有提供有关创建密钥的格式的任何详细信息.最新文档位于 http://php.net/manual/zh/function .openssl-pkey-export.php 仅声明它是"PEM格式",但没有说明它是PKCS#1还是PKCS#8

Now, the openssl-lib of PHP does not provide any detailed info on in what format the keys are created. The latest documentation at http://php.net/manual/en/function.openssl-pkey-export.php just states, that it is "in PEM format", but it does not say whether it is in PKCS#1 or PKCS#8

此外,私钥PEM的头和尾在PHP版本之间也不同,如以下代码所示:

Additionally, the headers and trailers of the private key PEM differ between PHP versions as the following code demonstrates:

<?php
$config = array(
    "digest_alg" => 'sha512',
        "private_key_bits" => 4096,
    "private_key_type" => OPENSSL_KEYTYPE_RSA
);
$keyPair = openssl_pkey_new($config);
$privateKey = NULL;
openssl_pkey_export($keyPair, $privateKey);
var_dump($privateKey);
$keyDetails = openssl_pkey_get_details($keyPair);
$publicKey = $keyDetails['key'];
var_dump($publicKey);
die();
?>

将输出不同的内容:

PHP v 5.4:

PHP v 5.4:

string(3272) "-----BEGIN PRIVATE KEY-----
MIIJRAIBADANBgkqhkiG9w0BAQEFAASCCS4wggkqA//...
-----END PRIVATE KEY-----
"

string(800) "-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAO//...
-----END PUBLIC KEY-----
"

PHP v 5.5:

PHP v 5.5:

string(3272) "-----BEGIN RSA PRIVATE KEY-----
MIIJRAIBADANBgkqhkiG9w0BAQEFAASCCS4wggkqA//...
-----END RSA PRIVATE KEY-----
"

string(800) "-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAO//...
-----END PUBLIC KEY-----
"

PHP v 5.6:

PHP v 5.6:

string(3272) "-----BEGIN PRIVATE KEY----- 
MIIJQgIBADANBggsdisdVUCJDSQCjqgl2XqzR+bSv//...
-----END PRIVATE KEY-----
"

string(800) "-----BEGIN PUBLIC KEY----- 
MIICIjANBgkqhkiG9w0BsdvQEFAAOdfAg8AMIICFAgEAo6oJdl6s0fm0r7QlaN/U//...
-----END PUBLIC KEY----- 
"

因此,私钥头/尾随您使用的PHP版本而变化.这不是一个真正的问题,但事实证明,使用"RSA"创建密钥头的系统将无法使用没有"RSA"的用户密钥,例如openssl_sign():您将获得一个错误,指出无法将提供的密钥强制转换为私钥" ...这就是混乱的地方.

So the private key header/trailer changes based on what PHP version you use. This wouldn't be a real problem, but as it turns out, a system which would create a key header WITH "RSA" will not be able to user key WITHOUT "RSA" for e.g., openssl_sign(): You'll get an error stating that the "provided key couldn't be coerced into a private key"... And this is where it gets messy.

根据 https://tls. mbed.org/kb/cryptography/asn1-key-structures-in-der-pem ,应在标头中带有"RSA"的私钥PEM格式与不包含PKCS的私钥PEM格式之间进行区分#1和PKCS#8,即是否包含有关算法等的附加信息.

According to https://tls.mbed.org/kb/cryptography/asn1-key-structures-in-der-and-pem, there should be a distinction between Private key PEM formats with the "RSA" in the header an those without, being PKCS#1 and PKCS#8, i.e. with additinal info about the algorithm etc. or not.

由于这个原因,我遇到了严重的问题.为PHP5.6编写的同一软件不能在PHP5.5上运行.可以通过手动将5.5标头替换为5.6兼容标头来使用变通办法,但这只是肮脏的破解".有没有一种好的"方式来解决这个问题?

I am running into serious problems due to this. The same software written for PHP5.6 cannot run on PHP5.5. On could use a workaround by replacing the 5.5-headers with 5.6-compatible ones manually, but this would just be a "dirty hack". Is there a "good" way how to deal with this?

在安装时,此替换代码将尝试创建私钥,提取标头并记住".然后将检查运行时使用的所有键.如果找到的标头不适合本地"标头,则需要进行交换.

At setup, this replacement-code would attempt to create a private key, extract the header and "remember it". All keys used at runtime would then be checked. If the headers found would not fit to the "local" ones, they would need to be exchanged.

但是我想这里有某种配置选项(我还没有找到),可以配置使用哪种格式?

But I guess there is some kind of configuration option (which I haven't managed to find yet) where I can configure which format is used?

接下来,一个更有趣的问题:openssl究竟创建了哪种格式? PKCS#1? PKCS#8?这也是可配置的吗?

Next, more interesting question: What format is created exactly by openssl? PKCS#1? PKCS#8? Is this also configurable?

推荐答案

无配置(很遗憾).只是PHP + OpenSSL版本问题. BEGIN RSA PRIVATE KEY表示PKCS#1格式.如果没有RSA,则为PKCS#8.

No configuration (unfortunatelly). Just PHP + OpenSSL version issue. BEGIN RSA PRIVATE KEY indicates PKCS#1 format. Without RSA it's PKCS#8.

使用PKCS1生成私钥RSA (我的年龄较大发布到相同的问题)

Generate private key RSA with PKCS1 (my older post to the same problem)

什么是"BEGIN RSA PRIVATE KEY"之间的区别和"BEGIN PRIVATE KEY" .

您可以尝试phpsec库或从命令行(exec())调用openssl.我知道这对您没有帮助,但是似乎还没有很好的解决方案.

You can try phpsec library or call openssl from command line (exec()). I know it does not help you but it seems there is not good solution yet.

修改

我对您的测试脚本做了一些改动,并在Windows 7上测试了私钥格式.

I altered your test script a little bit and tested private key format on my windows 7.

<?php

$keyPair = openssl_pkey_new(array(
    "digest_alg" => 'sha512',
    "private_key_bits" => 4096,
    "private_key_type" => OPENSSL_KEYTYPE_RSA
));
$privateKey = null;

openssl_pkey_export($keyPair, $privateKey);

echo sprintf("PHP: %s\n", phpversion());
echo sprintf("OpenSSL: %s\n", OPENSSL_VERSION_TEXT);
echo sprintf("Private key header: %s\n", current(explode("\n", $privateKey)));

PHP: 5.4.44
OpenSSL: OpenSSL 0.9.8zf 19 Mar 2015
Private key header: -----BEGIN RSA PRIVATE KEY-----

PHP: 5.5.28
OpenSSL: OpenSSL 1.0.1p 9 Jul 2015
Private key header: -----BEGIN PRIVATE KEY-----

PHP: 5.6.12
OpenSSL: OpenSSL 1.0.1p 9 Jul 2015
Private key header: -----BEGIN PRIVATE KEY-----

这些结果根据opensl的​​更改日志重现了opensl的​​默认行为.

These results reproduce default behaviour of openssl according to its changelog.

在0.9.8n和1.0.0之间更改(2010年3月29日)

Changes between 0.9.8n and 1.0.0 [29 Mar 2010]

将PKCS#8设置为私钥的默认写格式,替换为 传统格式.此表格是标准化的,更加安全,而且不会 包含隐式MD5依赖关系. [史蒂夫·汉森]

Make PKCS#8 the default write format for private keys, replacing the traditional format. This form is standardised, more secure and doesn't include an implicit MD5 dependency. [Steve Henson]

这篇关于PHP RSA密钥创建的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆