簡體   English   中英

帶有 openSSL 的 PHP - 提供的密鑰參數不能被強制轉換為私鑰

[英]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 個選項:

  • 升級您的 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 調用不同的結果。

也許您需要使用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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM