使用openssl_public_decrypt

问题描述

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

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

任何提示将不胜感激。

解决方法

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

无论如何,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),$pubKey,OPENSSL_PKCS1_PADDING)){

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

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

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...