[英]PHP with openSSL - supplied key param cannot be coerced into a private key
我正在嘗試使用openssl_sign()
函數對文件進行簽名。 I have the following private key: -----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 。 為什么一台服務器可以使用密鑰而一台不能?
記住:
$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-----";
這是有效的。
如果你使用第一個或任何類似的,你可能會得到那個例外。 在我的情況下,密鑰是在一行中傳遞的,因此會引發異常,並且與 php 版本或 SO 無關。
首先,您應該檢查是否啟用了 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():提供的密鑰參數不能被強制轉換為私鑰
並返回“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 個選項:
從 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 調用不同的結果。
也許您需要使用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 手冊,私鑰參數必須是資源
> priv_key_id
> resource - a key, returned by openssl_get_privatekey()
可能是權限問題? 確保您的 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
一旦我因為密鑰文件末尾的空行而收到此錯誤。 我認為值得一看。
在密鑰中找到 /n 並手動替換為回車鍵,就可以了。
只需使用 HS256 編碼。 這是最好的答案。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.