首页 > 解决方案 > 我怎样才能使有效的签名 php openssl

问题描述

我如何生成有效签名以及如何使用我的私钥签署请求正文我已经尝试过这样的代码,但结果总是签名无效还有其他方法吗?在问我已经在谷歌搜索解决问题但我还没有正确答案之前

function mgAccount(){

    $url = "http://aaaa.com";

    $getFields = [
        "oaa_id" => 838,
    ];

    $data_string = json_encode($getFields);

    $sign = createPrivateAndPublicKey($data_string);

    $header = array();
    $header[] = "Content-Type: application/json";
    $header[] = "Accept: application/json";
    $header[] = "Signature: $sign";

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $header);                                      
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string);
    $output = curl_exec($ch);

    curl_close($ch);
    return json_decode($output,true);
}
function createPrivateAndPublicKey($data)
{
    // import your private key
    $privateKeyId = openssl_pkey_get_private(file_get_contents('private.pem'));
    // sign date with your private key
    openssl_sign($data, $signature, $privateKeyId, 'RSA-SHA256');
    // encode into base64
    $sign = base64_encode($signature);
    // you may free up memory after, but I wouldn't recommend, since you are going to make many requests 
    and sign each of them.
   // importing key from file each time isn't brightest idea
    openssl_free_key($privateKeyId);
    // importing public key
    $pub_key = openssl_pkey_get_public(file_get_contents('public.pem'));
    // verifying signature for $data and imported public key
    // note that signature firstly was decoded from base64
    $valid = openssl_verify($data, base64_decode($sign), $pub_key, 'RSA-SHA256');

    if ($valid == 1){
      echo "signature is valid \n";
    } else {
      echo "signature is NOT valid \n";
    }
    // same thing about freeing of key
    openssl_free_key($pub_key);
}

标签: phpcurlopenssl

解决方案


我最好的猜测:您的私钥与您的公钥不匹配。

当我运行此特定代码时:

$private_key = <<<'EOD'
-----BEGIN RSA PRIVATE KEY-----
MIIBOgIBAAJBANDiE2+Xi/WnO+s120NiiJhNyIButVu6zxqlVzz0wy2j4kQVUC4Z
RZD80IY+4wIiX2YxKBZKGnd2TtPkcJ/ljkUCAwEAAQJAL151ZeMKHEU2c1qdRKS9
sTxCcc2pVwoAGVzRccNX16tfmCf8FjxuM3WmLdsPxYoHrwb1LFNxiNk1MXrxjH3R
6QIhAPB7edmcjH4bhMaJBztcbNE1VRCEi/bisAwiPPMq9/2nAiEA3lyc5+f6DEIJ
h1y6BWkdVULDSM+jpi1XiV/DevxuijMCIQCAEPGqHsF+4v7Jj+3HAgh9PU6otj2n
Y79nJtCYmvhoHwIgNDePaS4inApN7omp7WdXyhPZhBmulnGDYvEoGJN66d0CIHra
I2SvDkQ5CmrzkW5qPaE2oO7BSqAhRZxiYpZFb5CI
-----END RSA PRIVATE KEY-----
EOD;
$public_key = <<<'EOD'
-----BEGIN PUBLIC KEY-----
MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANDiE2+Xi/WnO+s120NiiJhNyIButVu6
zxqlVzz0wy2j4kQVUC4ZRZD80IY+4wIiX2YxKBZKGnd2TtPkcJ/ljkUCAwEAAQ==
-----END PUBLIC KEY-----
EOD;
$data="test";
$privateKeyId = openssl_pkey_get_private($private_key);
// sign date with your private key
openssl_sign($data, $signature, $privateKeyId, 'RSA-SHA256');
// encode into base64
$sign = base64_encode($signature);
// you may free up memory after, but I wouldn't recommend, since you are going to make many requests and sign each of them.
  // importing key from file each time isn't brightest idea
openssl_free_key($privateKeyId);
// importing public key
$pub_key = openssl_pkey_get_public($public_key);
// verifying signature for $data and imported public key
// note that signature firstly was decoded from base64
$valid = openssl_verify($data, base64_decode($sign), $pub_key, 'RSA-SHA256');

if ($valid == 1){
  echo "signature is valid \n";
} else {
  echo "signature is NOT valid \n";
}
// same thing about freeing of key
openssl_free_key($pub_key);

它输出signature is valid所以问题可能是你的密钥对。(PScreatePrivateAndPublicKey是一个不创建任何东西的函数的愚蠢名称......)

你的 curl 代码也很混乱,就像createPrivateAndPublicKey一个 void 函数一样,它不返回任何东西,所以当你这样做时

$sign = createPrivateAndPublicKey($data_string);
$header[] = "Signature: $sign";

您分配$sign给 NULL 并且当您将 NULL 添加到字符串时,没有任何反应,所以您设置的标题只是Signature: (blank)


推荐阅读