You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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));

原因说明

  1. ReactNativeBiometrics的createSignature方法在Android端使用的是Signature.getInstance("SHA256withRSA"),对应PKCS#1 v1.5填充
  2. phpseclib3默认情况下,对于RSA公钥可能会采用更安全的PSS填充,导致与移动端签名不兼容
  3. 无需手动计算消息哈希,verify方法会根据指定的哈希算法自动处理

内容的提问来源于stack exchange,提问作者theex

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 09:35:38