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

phpseclib生成RSA签名后在C#端验证失败问题求助

问题根因

PHP侧签名逻辑存在重复哈希的问题:
phpseclib的RSA::sign()方法在你已通过withHash("sha256")指定哈希算法的前提下,会自动对传入的原始内容做一次SHA256哈希计算,再基于结果生成PKCS1签名。但你的代码里提前对原始字符串test做了一次SHA256哈希,将得到的32字节哈希值传入sign()方法,相当于最终签名的是原始数据哈希的哈希,和C#侧验证时用的原始数据哈希不匹配,因此验证失败。


解决方案

提供两种可选修改方案,按需选择即可:

方案1:修改PHP代码(推荐,逻辑更规范)

直接传原始数据给sign()方法,不需要提前算哈希,phpseclib会自动完成哈希计算:

//Load private key
$rsa = PublicKeyLoader::load("... private key ...", false);

//Set PKCS1 signature mode + SHA256 hash
$rsa = $rsa->withPadding(RSA::SIGNATURE_PKCS1)->withHash("sha256");

// 直接传原始内容签名,无需提前计算哈希
$raw_data = "test";
$signed_hash = base64_encode($rsa->sign($raw_data));

// 计算原始内容的哈希给C#侧
$hash = base64_encode(pack("H*", hash("sha256", $raw_data)));

方案2:修改C#代码(适配现有PHP逻辑)

如果不能修改PHP侧代码,就在C#侧把拿到的哈希值再做一次SHA256计算,再执行验证:

static void Main()
{
    using (RSA rsa = RSA.Create())
    {
        //Load public key from XML string
        rsa.FromXmlString("... public key ...");

        RSAPKCS1SignatureDeformatter RSADeformatter = new RSAPKCS1SignatureDeformatter(rsa);
        RSADeformatter.SetHashAlgorithm("SHA256");

        byte[] phpHash = Convert.FromBase64String("SHA256 Hash As Base64");
        byte[] signedHash = Convert.FromBase64String("SHA256 Hash Signature As Base64");
        
        // 对PHP传过来的哈希再做一次SHA256计算,匹配PHP侧两次哈希的逻辑
        using (SHA256 sha256 = SHA256.Create())
        {
            byte[] actualHashToVerify = sha256.ComputeHash(phpHash);
            if (RSADeformatter.VerifySignature(actualHashToVerify, signedHash))
            {
                Console.WriteLine("True");
            }
            else
            {
                Console.WriteLine("False");
            }
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 19:54:01