【问题标题】:Decrypt a signature using openssl_public_decrypt使用 openssl_public_decrypt 解密签名
【发布时间】:2020-08-23 05:36:15
【问题描述】:

我正在尝试验证对我们其中一个端点的外部调用,该端点由第三方触发,我们收到交易数据和基于该交易信息的签名,因此,我们需要解密签名并比较结果以验证真实性。

我正在尝试使用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 应用于 结果。结果值必须与解密签名的结果进行比较 与我们的公钥参数。

任何提示将不胜感激。

【问题讨论】:

  • 请注意,您可能使用了错误的签名填充。签名生成与使用私钥加密不同。只需创建一个签名而不是加密。

标签: php encryption php-openssl


【解决方案1】:

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

无论如何,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) )

【讨论】:

  • 宾果游戏,问题是我使用您的 IF 进行验证的方式进行了验证并且成功。谢谢!
猜你喜欢
  • 2021-12-21
  • 1970-01-01
  • 2016-10-20
  • 2018-09-02
  • 2016-03-27
  • 2012-02-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多