为了账号安全,请及时绑定邮箱和手机立即绑定

使用 openssl_public_decrypt 解密签名

使用 openssl_public_decrypt 解密签名

PHP
开心每一天1111 2023-10-22 21:27:42
我正在尝试验证对我们的一个端点的外部调用,该端点是由第三方触发的,我们收到交易数据和基于该交易信息的签名,因此,我们需要解密签名并比较结果验证真伪。我正在尝试openssl_public_decrypt使用提供商的公钥来解密签名。这就是我正在尝试的方式:$signature = 'GcTtinhU0YgwGbZPtBwLdh+zdEe0w0W95TFPggeHMCjeDUBWgZfCZ6ZDRUk7DfT5BkKsbAi8/4o60Krcwz1JMdRjmsPf7vj33heVIB2PZJaf8eFR1jijLIsyl4vgH7BbbQ2I6kk6IcYXYWPVAHYRWxl1pJwOyNxZPr49fdW+hcw2zbpkEmj2114QBSiV6eHLowVYKLvpuiT8zLc6DN/wVzCYBuR/cg+CPHgYMeWFsuvu9J46hm6Hij00E68ldYAqVwImlmHPqfqvdEItg3Oi0ac4tXH2nCNgLPHcyU/H32NzTYC9iT1YZkoInqsU6Qv64vbU9lSMS91EQBEa5UQkUg==';$pubKey = openssl_pkey_get_public('file://path/to/public.pem');if( openssl_public_decrypt(base64_decode($signature), $data, $pubKey)){  echo $data;}else{  echo 'Error';}我没有收到任何错误,但该$data值不是我所期望的,是这样的v_~�@&�W� �q�&Ș�uQ���֔�我确信我丢失了一些东西,但我无法找出它是什么,因为该$data值看起来像是加密的。我期望解密的结果是167619085f7ed94026e357930b18dc011971f226c898ef7551cdf6ec9ad694cf以下代码的结果$canonical = 'c328e942-8be8-4104-abbe-048254f893dc|9687|2874.30|52409|BP1381|550bd8439cd1f41691671cdd4e8c6ae6';$hashed = hash('sha256', $canonical);最后一部分是提供者如何生成签名。对于给定的示例,规范形式如下: cec4b9bf-5a39-4bd7-bc8b826ebc18208d|Internal_0005|12|39679|BP7610|947d589a40dece13c28f2b63c41ae451我们通过使用 SHA-256 对规范形式进行哈希处理并使用我们的私钥对结果字节进行加密来对响应进行签名。RSA_ENCRYPT(SHA256(canonicForm), privkey.key)要验证有效负载,您必须重新计算规范形式并对结果应用 SHA-256。结果值必须与用我们的公钥解密签名参数的结果进行比较。任何提示将不胜感激。
查看完整描述

1 回答

?
神不在的星期二

TA贡献1963条经验 获得超6个赞

也许发布公钥和一些有效的测试数据以便我们可以测试自己?

无论如何,v_~�@&�W��q�&Ș�uQ���֔�这可能是一个有效的签名,请记住 SHA256 是 256 个随机位,它是二进制数据,不是 ASCII 数据,不是十六进制,并且不可打印。SHA256 也恰好是 32 个字节长(256 位,1 个字节是 8 位,256/8 是 32 个字节),因此如果您在解密后运行 var_dump(strlen($data)) ,它应该打印 32,如果是话不打印 32,这意味着他们正在使用填充方案,尝试检查 OPENSSL_PKCS1_PADDING 和 OPENSSL_NO_PADDING 的 strlen ,当您获得正确的填充方案时,解密后的 strlen($data) 应该是 int(32)

但我最好的猜测是:

$signature = 'GcTtinhU0YgwGbZPtBwLdh+zdEe0w0W95TFPggeHMCjeDUBWgZfCZ6ZDRUk7DfT5BkKsbAi8/4o60Krcwz1JMdRjmsPf7vj33heVIB2PZJaf8eFR1jijLIsyl4vgH7BbbQ2I6kk6IcYXYWPVAHYRWxl1pJwOyNxZPr49fdW+hcw2zbpkEmj2114QBSiV6eHLowVYKLvpuiT8zLc6DN/wVzCYBuR/cg+CPHgYMeWFsuvu9J46hm6Hij00E68ldYAqVwImlmHPqfqvdEItg3Oi0ac4tXH2nCNgLPHcyU/H32NzTYC9iT1YZkoInqsU6Qv64vbU9lSMS91EQBEa5UQkUg==';


$canonical = 'c328e942-8be8-4104-abbe-048254f893dc|9687|2874.30|52409|BP1381|550bd8439cd1f41691671cdd4e8c6ae6';

$pubKey = openssl_pkey_get_public('file://path/to/public.pem');


if( openssl_public_decrypt(base64_decode($signature), $data, $pubKey)){

  echo "signature decryption success! ";

  if(hash_equals(hash("sha256",$canonical,true),$data)){

    echo "checksum verification success!";

  } else{

    echo "checksum verification failed (after decryption was successful..)";

  }

}else{

  echo 'checksum decryption error';

}

但再次尝试两者


if( openssl_public_decrypt(base64_decode($signature), $data, $pubKey, OPENSSL_PKCS1_PADDING)){


if( openssl_public_decrypt(base64_decode($signature), $data, $pubKey, OPENSSL_NO_PADDING)){

其中 1 个可能是正确的(当正确时, var_dump(strlen($data)) 应该打印 int(32) )


查看完整回答
反对 回复 2023-10-22
  • 1 回答
  • 0 关注
  • 79 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信