使用PHP OpenSSL结合RSA SHA1验证签名数据遇阻求助
PHP OpenSSL签名验证失败排查方案
问题场景
尝试用PHP OpenSSL验证响应数据签名,确认签名有效但openssl_verify始终验证失败,代码如下:
<?php $data='BE10000202|20240226154030|405700076188|20240226155800|06||AC|561708940418|BNBL||90.0|BTN'; $signed='4732D17334BE2DECC4136C2FAF4E9A43778EBA277D41E4B32E668B91D3C99B73014914E0FDB045D135B924E56D18F812C504089DE2A1CF4FDB8754A9E2B8517566180CAE16E946AF40E3B4C5AFD4130B2E6E5FC536F353219FD231259C69C2494502A0E4566CE410F28205A636A06C49BA2DA8409A0969F57494E28E25127789016C781A7433B1F51F4FC4BF3DBBF5971AB5A1431E8046E1FCE72D110E442FFEE536F751A358E15FB4DFC183EBF4618BC791B46DE2DCC63132F7E314FBD8A4D2AC6058E7BF4395EDA9762585CCC4113BA6D450F0F82E4B826E38A8AA85D3033931EADFC2E8AE96C66E63F78A5E2AE500268C0012E6176255EFA6FB7D67D6A2A3'; $public_key="-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFxkd8seAAOCAQ8AMIIBCgKCAQEAw5jrOBbKzur2ED\nI/6zKwjFa2NKV7mgQH0N1lNw74bq+ce4qY7nTmUBz5SKIXtjENDtguAfHl9qX2ZW\n52plZIaDthwa9YgdOu5+pJNKcO8AeCFbF9AURkQgie9lCBmZWCiLtDyCczIsRTPj\nTztlpqUveypJCOp3jCHLpE8PGJ2LUHgQyGx1Pc+s/PQs4Z3qyVtxWvFy5ugjXgCL\n0IqXWQ4cLCUHA6+FAEBqIRZGATWBhKOafxbSiTpRQiXrLq5kVea/KXYFG9Mva0QL\nQyjVJZsKNC6VK1VGRArMr2KQK69pBNiy+yQqCJw6A2LBAkcERAREHoZITUcA/Ycx\nAQIDAQAB\n-----END PUBLIC KEY-----"; $verified = openssl_verify($data, $signed, $public_key, OPENSSL_ALGO_SHA1); echo $verified; ?>
排查与解决
1. 签名数据格式错误
openssl_verify要求签名参数是原始二进制数据,但你的signed是十六进制字符串,必须先转换为二进制:
$signed_bin = hex2bin($signed);
2. 哈希算法匹配检查
确认签名生成时使用的哈希算法是否为SHA1。如果对方用的是SHA256等其他算法,需替换对应的常量,比如OPENSSL_ALGO_SHA256。
3. 修正后的完整代码
<?php $data='BE10000202|20240226154030|405700076188|20240226155800|06||AC|561708940418|BNBL||90.0|BTN'; $signed='4732D17334BE2DECC4136C2FAF4E9A43778EBA277D41E4B32E668B91D3C99B73014914E0FDB045D135B924E56D18F812C504089DE2A1CF4FDB8754A9E2B8517566180CAE16E946AF40E3B4C5AFD4130B2E6E5FC536F353219FD231259C69C2494502A0E4566CE410F28205A636A06C49BA2DA8409A0969F57494E28E25127789016C781A7433B1F51F4FC4BF3DBBF5971AB5A1431E8046E1FCE72D110E442FFEE536F751A358E15FB4DFC183EBF4618BC791B46DE2DCC63132F7E314FBD8A4D2AC6058E7BF4395EDA9762585CCC4113BA6D450F0F82E4B826E38A8AA85D3033931EADFC2E8AE96C66E63F78A5E2AE500268C0012E6176255EFA6FB7D67D6A2A3'; $public_key="-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFxkd8seAAOCAQ8AMIIBCgKCAQEAw5jrOBbKzur2ED\nI/6zKwjFa2NKV7mgQH0N1lNw74bq+ce4qY7nTmUBz5SKIXtjENDtguAfHl9qX2ZW\n52plZIaDthwa9YgdOu5+pJNKcO8AeCFbF9AURkQgie9lCBmZWCiLtDyCczIsRTPj\nTztlpqUveypJCOp3jCHLpE8PGJ2LUHgQyGx1Pc+s/PQs4Z3qyVtxWvFy5ugjXgCL\n0IqXWQ4cLCUHA6+FAEBqIRZGATWBhKOafxbSiTpRQiXrLq5kVea/KXYFG9Mva0QL\nQyjVJZsKNC6VK1VGRArMr2KQK69pBNiy+yQqCJw6A2LBAkcERAREHoZITUcA/Ycx\nAQIDAQAB\n-----END PUBLIC KEY-----"; // 转换十六进制签名为二进制 $signed_bin = hex2bin($signed); // 执行验证 $verified = openssl_verify($data, $signed_bin, $public_key, OPENSSL_ALGO_SHA1); echo $verified; // 1表示验证成功,0失败,-1表示出错 ?>
额外检查点
- 确保公钥格式正确,PEM格式的公钥必须包含
-----BEGIN PUBLIC KEY-----和-----END PUBLIC KEY-----标记,且换行符正确。 - 验证
$data是否与签名生成时的原始数据完全一致,包括分隔符、空格、大小写等,任何差异都会导致验证失败。
内容的提问来源于stack exchange,提问作者Toki
相关产品推荐
相关产品推荐

