【问题标题】:PHP RSA key creationPHP RSA 密钥创建
【发布时间】:2015-08-18 23:28:31
【问题描述】:

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

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

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

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

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

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

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:

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():你会得到一个错误指出“提供的密钥不能被强制转换为私钥”......这就是它变得混乱的地方。

根据https://tls.mbed.org/kb/cryptography/asn1-key-structures-in-der-and-pem,在标头中带有“RSA”的私钥 PEM 格式和没有标头中的 PKCS#1 和 PKCS#8 的私钥 PEM 格式之间应该有区别,即带有关于算法等的附加信息或不是。

因此,我遇到了严重的问题。为 PHP5.6 编写的相同软件无法在 PHP5.5 上运行。 On 可以通过手动将 5.5 标题替换为 5.6 兼容的标题来使用解决方法,但这只是一个“肮脏的黑客”。有没有“好”的方法来处理这个问题?

在设置时,这个替换代码会尝试创建一个私钥,提取标题并“记住它”。然后将检查运行时使用的所有密钥。如果找到的标头不适合“本地”标头,则需要交换它们。

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

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

【问题讨论】:

  • 不幸的是,我刚刚使用 PHP v5.6.9 进行了测试,在这种情况下,它还输出包含“RSA”的标题和尾声

标签: php pki php-openssl


【解决方案1】:

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

Generate private key RSA with PKCS1(我以前发过同样问题的帖子)

what is the differences between "BEGIN RSA PRIVATE KEY" and "BEGIN PRIVATE KEY".

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

编辑

我稍微修改了你的测试脚本,并在我的 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-----

这些结果根据其变更日志重现了 openssl 的默认行为。

0.9.8n 和 1.0.0 [2010 年 3 月 29 日] 之间的变化

使 PKCS#8 成为私钥的默认写入格式,替换 传统格式。这种形式是标准化的,更安全的,不 包括一个隐式的 MD5 依赖项。 [史蒂夫汉森]

【讨论】:

  • 但为什么有时相同版本的 PHP(例如 5.6)在不同的安装中使用不同的标头?这是在哪里指定的?
  • 很难说。你使用什么操作系统?你是使用默认的 PHP 还是自编译的?你在 phpinfo 中看到了什么版本的 OpenSSL 库?例如,我在我的 Windows 机器上使用 PHP 5.5.18 (OpenSSL 1.0.1i) 获得 PKCS#8 (BEGIN PRIVATE KEY)。
  • 检查了这个:PHP 5.4 (Debian wheezy), PHP 5.6 (Debian wheezy with PHP 5.6 from "packages.dotdeb.org"), PHP 5.6 (MacOS X 10.10, PHP install via brew), PHP 5.5 ( MacOS X 10.10,来源未知),PHP 5.5(Ubuntu)
  • 和 PHP 使用的 openssl 版本? If you look to openssl changelog you can see they changed default private key format from PKCS#1 to PKCS#8 in 1.0.0。我认为这是 PHP 行为问题的根源。但是 PHP 5.6 应该使用 openssl 1.0+ :-/。我会在家里稍微测试一下。
  • 好的,我们可能已经解决了问题的核心 :) 然而在我的 MacOS X 10.10 上,openssl 0.9.8zf 和 PHP 5.6 我得到了 -----BEGIN PRIVATE KEY---- - 标题......让我猜猜 - 那是苹果的问题? ;) 我试过这个:apple.stackexchange.com/questions/126830/… 现在得到了 1.0.2d_1 - 我会让你知道这会如何影响关键标题...
猜你喜欢
  • 2020-12-26
  • 2019-05-24
  • 1970-01-01
  • 1970-01-01
  • 2023-03-11
  • 1970-01-01
  • 2020-12-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多