带有openSSL的PHP​​ - 提供的密钥参数不能强制转换为私钥

时间:2017-12-27 11:06:14

标签: php pyopenssl

我尝试使用openssl_sign()功能对文件进行签名。我有以下私钥: -----BEGIN EC PRIVATE KEY----- MHQCAQEEIDzQVg9bJ1kZFsZDoLeqadA4OTgKc40ukSmQ3MVzcV0soAcGBSuBBAAK oUQDQgAEvzUNKCE3UVimCLUePomOUH/kfy0ujHdN5Kmn7ez3TtokJDy5ksVnOgf6 WzpmzY46zvKAnQ44Cgx5Kdqx5dVDiw== -----END EC PRIVATE KEY-----

我使用以下功能:openssl_sign("test", $signature, $private_key, OPENSSL_ALGO_SHA256);

我有一台能够使用给定密钥签名的服务器和一台不能签名的服务器。有一个PHP 5.6和一个没有PHP 7.1。为什么一台服务器能够使用密钥而另一台服务器不能?

5 个答案:

答案 0 :(得分:1)

记住:

$key="-----BEGIN RSA PRIVATE KEY-----
        ONp+TMNeWOkyAnfdRjXJnZisrkvk8kYaSCdFpE//Who4PZLvup8TBXV+aHUN5aNb
        qV8KP+r+yjsnAguLM1ZGuP1JJ+MRETk7pUX5QwIDAQABAoIBAAXCozlhkTCLo34V
        k7Ql3Y1tLiYnRIQqA1VYiJLmn4nZhUZkMQzyAWhp56ne38V7it2LVggENmZyyfzf
        BXLZCZLD2vXdvaIRM2BEZd4xouAVtrVozi8HP1UC+OfQpbAH+ez+Ek+XArSNUXiQ
        MIIEowIBAAKCAQEAk8uKqR2c7kDZIsEb2DAyhYz2HxIjKVXALHxZTWHKqyWgUXKw
        htiJlpi6T/jJw9FALnvQMFT9q8BXhVkKTMJvXkNDJtOZ35dZ7+GqfSEHzKojXv4v
        -----END RSA PRIVATE KEY-----";

无效且与

不同
$key="-----BEGIN RSA PRIVATE KEY-----
ONp+TMNeWOkyAnfdRjXJnZisrkvk8kYaSCdFpE//Who4PZLvup8TBXV+aHUN5aNb
qV8KP+r+yjsnAguLM1ZGuP1JJ+MRETk7pUX5QwIDAQABAoIBAAXCozlhkTCLo34V
k7Ql3Y1tLiYnRIQqA1VYiJLmn4nZhUZkMQzyAWhp56ne38V7it2LVggENmZyyfzf
BXLZCZLD2vXdvaIRM2BEZd4xouAVtrVozi8HP1UC+OfQpbAH+ez+Ek+XArSNUXiQ
MIIEowIBAAKCAQEAk8uKqR2c7kDZIsEb2DAyhYz2HxIjKVXALHxZTWHKqyWgUXKw
htiJlpi6T/jJw9FALnvQMFT9q8BXhVkKTMJvXkNDJtOZ35dZ7+GqfSEHzKojXv4v
-----END RSA PRIVATE KEY-----";

这是有效的。

如果您使用拳头或类似拳头,则可能会出现该异常。在我的情况下,密钥在一行中传递,因此引发异常,与phpversión或SO无关。

答案 1 :(得分:0)

也许您需要使用openssl_get_privatekey来创建私钥资源,而不是简单地使用字符串

$str_priv_key='-----BEGIN EC PRIVATE KEY-----
MHQCAQEEIDzQVg9bJ1kZFsZDoLeqadA4OTgKc40ukSmQ3MVzcV0soAcGBSuBBAAK
oUQDQgAEvzUNKCE3UVimCLUePomOUH/kfy0ujHdN5Kmn7ez3TtokJDy5ksVnOgf6
WzpmzY46zvKAnQ44Cgx5Kdqx5dVDiw==
-----END EC PRIVATE KEY-----';

$pkey=openssl_get_privatekey( $str_priv_key );
openssl_sign( "test", $signature, $pkey );
openssl_free_key( $pkey );

根据PHP manual,私钥参数必须是资源

> priv_key_id
> resource - a key, returned by openssl_get_privatekey()

答案 2 :(得分:0)

首先,您应该检查是否启用了OpenSSL。您可以通过输出

来完成此操作

的phpinfo();

并检查:“启用了OpenSSL支持”。在这种情况下它是。

为了进一步排除故障,有两个功能有很大帮助:

error_get_last()
Usage: print_r(error_get_last());

openssl_error_string()
Usage: echo openssl_error_string();

在这种情况下,“error_get_last()”返回:

  

openssl_sign():提供的密钥param不能被强制转换为私有   键

并返回“openssl_error_string()”:

  

错误:100AE081:椭圆曲线   例程:EC_GROUP_new_by_curve_name:未知组

此消息表示使用的OpenSSL版本没有代码来处理使用的EC曲线。 “EC_GROUP_new_by_curve_name”搜索“static const ec_list_element curve_list []”并找不到。结果它返回“未知”。

现在你有3个选择:

  • 升级您的OpenSSL以支持此曲线。
  • 选择两台服务器上支持的另一条曲线。
  • 使用非EC加密。

从PHP 7.1.0起,您可以使用:

openssl_get_curve_names()

获取支持的曲线列表。我不知道PHP 5.6的类似功能,因此在获得两台主机上可用的功能之前,您可能需要尝试一些功能。

如旁注: 一些Linux发行版,如RedHat和CentOS,使用比其他发行版更严格的OpenSSL版本。该错误表明在这种情况下,OpenSSL是在旧的(5.8)CentOS版本上手动更新的。有一些在线手册(如https://syslint.com/blog/tutorial/how-to-upgrade-openssl-on-centos-7-or-rhel-7/)只能升级OpenSSL可执行文件。如果使用这个或类似的技术,PHP仍然会使用'旧的'OpenSSL,因此从命令行运行OpenSSL会产生与PHP调用不同的结果。

答案 3 :(得分:0)

只需使用HS256编码。这是最好的答案。

答案 4 :(得分:0)

可能是权限问题?确保您的 php 脚本可以读取您的 private_key.pem。还要记住,私钥参数必须是资源。

// fetch private key from file and ready it
$private_key = openssl_pkey_get_private("file:///path/to/your/private_key.pem");
// compute signature
openssl_sign("test", $signature, $private_key, OPENSSL_ALGO_SHA256);

然后为您的密钥添加读取权限:chmod a+r /path/to/your/private_key.pem