2017-12-27 468 views
4

我試圖使用openssl_sign()函數簽署文件。我有以下私鑰: -----BEGIN EC PRIVATE KEY----- MHQCAQEEIDzQVg9bJ1kZFsZDoLeqadA4OTgKc40ukSmQ3MVzcV0soAcGBSuBBAAK oUQDQgAEvzUNKCE3UVimCLUePomOUH/kfy0ujHdN5Kmn7ez3TtokJDy5ksVnOgf6 WzpmzY46zvKAnQ44Cgx5Kdqx5dVDiw== -----END EC PRIVATE KEY----- PHP與openSSL - 提供的密鑰參數不能被強制爲私鑰

我正在使用以下函數:openssl_sign("test", $signature, $private_key, OPENSSL_ALGO_SHA256);

我有一臺服務器可以使用給定的密鑰進行簽名,而另一臺則不能。一個是PHP 5.6,另一個沒有PHP 7.1。一臺服務器怎麼能夠使用這個密鑰而另一臺卻不能?

+0

https://stackoverflow.com/questions/21149200/supplied-key-param-cannot-be-coerced-into-a-private-key-with-google-apis – RamRaider

+0

出於安全考慮,我希望這不是你的您在此發佈的實際私鑰。如果是這樣,我建議你立即更換它。 – Kaii

+0

啊不,這只是一些隨機字節.. – user2298995

回答

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() 
+0

感謝評論,似乎我得到了同樣的錯誤。 'openssl_get_privatekey'沒有什麼區別:'PHP警告:openssl_sign():提供的密鑰參數不能被強制轉換爲' – user2298995

+0

'中的私鑰,這大概是問題中的私鑰字符串不是完整的字符串?也許值得注意的是我有PHP 5.3.2 – RamRaider

+0

它應該是,因爲它可以在不同的服務器上工作,並且在使用OpenSSL使用命令行進行簽名時它可以工作:'openssl dgst -sha256 -hex -sign key.pem hash.txt' – user2298995

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(): supplied key param cannot be coerced into a private key

和返回的「openssl_error_string()」:

error:100AE081:elliptic curve routines:EC_GROUP_new_by_curve_name:unknown group

此消息表示使用的OpenSSL版本沒有代碼來處理使用的EC曲線。 「EC_GROUP_new_by_curve_name」搜索「靜態常量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調用不同的結果。

+0

同樣的錯誤是我得到的:'openssl_sign():提供的鍵參數不能強制成私鑰「 – user2298995

+0

嘗試了第二條評論。收到:'錯誤:100AE081:橢圓曲線例程:EC_GROUP_new_by_curve_name:未知組' – user2298995

+0

工作的服務器:PHP 5.6,OpenSSL:1.0.1f 2014年1月6日;不支持的服務器:PHP 7.1,OpenSSL:1.0.2n 2017年12月7日(最新版)。 – user2298995