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
相关产品推荐
相关产品推荐

