如何用phpseclib验证RSA 2048密钥对的PKCS#1v1.5 SHA256签名
RSA签名验证失败排查(PHP + phpseclib)
问题场景
在API端点验证Android端通过ReactNativeBiometrics生成的RSA签名时,多次尝试均失败,但使用在线签名验证工具可以成功通过。
移动端实现
密钥对与签名均通过ReactNativeBiometrics库生成:
- 密钥对生成:调用
createKeys方法 - 签名生成:调用
createSignature方法
PHP环境依赖
composer.json配置:
{ "require": { "phpseclib/phpseclib": "^3.0", "kint-php/kint": "^4.2" } }
验证代码(index.php)
<?php require "vendor/autoload.php"; use phpseclib3\Crypt\PublicKeyLoader; use phpseclib3\Crypt\RSA; $message = "CIAO"; $signature = "nu92wNMUDDUgZJbrKOIJt09FOfvMvQ6fWlNCfvkxqhUuGIT7hCnikQCM4KfXJN/X7D3+ISQvu1+BbVYug2uvxDwtDt7mHRr7lo7SRN6/yFq237LJ9iHZNZWXz1Ict1ez92Aa1oeDZtMpO84VOrVE372UNOETFvz+AaeTJ3lO/3WV+xu+uQ36FiOhLtAi7CXFhCki3+P6oO0Va1PtB2rmdiMcbHSkn3y5IZG5UTxLtRYr0dkTbbq+ySNMdYY01Yd1aOHl7phgoR+sRHQwOaq2/IHAahBOTZShrjLy5b/DmDaYwjjAs76FSQFiWtPjtm0WdiroGbzdwsHjWgBXKyHzHA=="; $hash = hash('sha256', $message, true); $publicKey = " -----BEGIN RSA PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu4sNG1i5Tiqc2nz5nFU8 Q7UaKbOqV2jTCB0Alg2hwT6GQX/GhPTHiPicoLPX1yubPbDxn9e/4ZPCwdfW20JG 4oaGNUnT6VSfH9Tx5ckBGIYzsHbRU7llKgMFK91RVrTCb/3v1sSEHBthby2C4c2V N1zDCZxaTGfY3zgsEhUIYHhagam1c/WHR9mVCu+9a9QwsMgJ9ppKwikzLyetNkla MvIKzTxsFHrtZrmBhlbmRHFXGKqqwvnwxkER14YpldiXBFUJ1/p4JHE09byfxmC/ 9kRjFxqOxU3hwvO2YlRbk9/T8+6mtyyUxHLLK37vBYOuvKEaPIKM/ASm8UiZLwqq swIDAQAB -----END RSA PUBLIC KEY----- "; $key = PublicKeyLoader::loadPublicKey($publicKey, $password = false); \Kint::dump( $publicKey, $key::getSupportedKeyFormats(), $key->getLoadedFormat(), $key->getPadding(), (string) $key->getHash(), $key, $key instanceof \phpseclib3\Crypt\Common\PublicKey, $key->verify(base64_decode($message, true), base64_decode($signature, true)), $key->verify(base64_decode($message, true), $signature), $key->verify($message, base64_decode($signature, true)), $key->verify($message, $signature), $key->verify($hash, base64_decode($signature, true)) );
问题现象
- 上述代码中所有
verify调用均返回false - 使用在线签名验证工具可成功验证该签名与公钥的匹配性
解决方案
问题出在phpseclib3的默认配置与ReactNativeBiometrics的签名算法不匹配:
ReactNativeBiometrics在Android端生成签名时,默认使用SHA256withRSA(即PKCS#1 v1.5填充 + SHA-256哈希),而phpseclib3加载公钥后默认可能使用PSS填充或不匹配的哈希算法。
修改公钥加载代码,显式指定哈希算法与填充方式:
$key = PublicKeyLoader::loadPublicKey($publicKey) ->withHash('sha256') ->withPadding(RSA::SIGNATURE_PKCS1);
然后使用正确的验证方式:
// 直接传入原始消息和Base64解码后的签名,verify方法会自动处理哈希 $isValid = $key->verify($message, base64_decode($signature, true));
原因说明
- ReactNativeBiometrics的
createSignature方法在Android端使用的是Signature.getInstance("SHA256withRSA"),对应PKCS#1 v1.5填充 - phpseclib3默认情况下,对于RSA公钥可能会采用更安全的PSS填充,导致与移动端签名不兼容
- 无需手动计算消息哈希,
verify方法会根据指定的哈希算法自动处理
内容的提问来源于stack exchange,提问作者theex
相关产品推荐
相关产品推荐

