C#中SHA256加密+私钥签名+Base64转换问题求助
签名生成问题排查
问题描述
需实现的加密签名流程:
- 使用SHA256算法加密普通字符串
- 用自有私钥对加密后的文本进行签名
- 将结果字节数组转为Base64字符串作为API请求头传递
现有代码无法生成正确签名串,传入原始数据为message,验证结果不正确:
byte[] signedBytes, originalData; string temp_inBase64; using (SHA256 hash = SHA256Managed.Create()) { Encoding enc = Encoding.UTF8; originalData = hash.ComputeHash(enc.GetBytes(message)); } using (var rsa = new RSACryptoServiceProvider()) { rsa.FromXmlString("xxxxxx"); //Final try { signedBytes = rsa.SignData(originalData, new SHA256CryptoServiceProvider()); temp_inBase64 = Convert.ToBase64String(signedBytes); } catch (CryptographicException e) { Console.WriteLine(e.Message); return null; } finally { rsa.PersistKeyInCsp = false; } } return temp_inBase64;
排查与修复方案
1. 核心错误:重复哈希
你的代码存在关键逻辑错误:先手动对原始字符串做了SHA256哈希,随后调用SignData方法时,该方法会再次对输入的哈希值执行SHA256哈希,相当于对原始数据做了两次SHA256哈希后再签名,完全不符合预期流程。
修复方案二选一:
方案A:用SignData直接处理原始字符串(推荐)
移除手动哈希步骤,让SignData内部自动完成哈希操作:
byte[] signedBytes; string temp_inBase64; Encoding enc = Encoding.UTF8; byte[] originalData = enc.GetBytes(message); using (var rsa = new RSACryptoServiceProvider()) { rsa.FromXmlString("xxxxxx"); try { // SignData会自动对原始字节数据做SHA256哈希后签名 signedBytes = rsa.SignData(originalData, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); temp_inBase64 = Convert.ToBase64String(signedBytes); } catch (CryptographicException e) { Console.WriteLine(e.Message); return null; } finally { rsa.PersistKeyInCsp = false; } } return temp_inBase64;
方案B:手动哈希后用SignHash签名
若必须先手动执行SHA256哈希,需改用SignHash方法直接对哈希值签名:
byte[] signedBytes, hashBytes; string temp_inBase64; Encoding enc = Encoding.UTF8; using (SHA256 hash = SHA256.Create()) { hashBytes = hash.ComputeHash(enc.GetBytes(message)); } using (var rsa = new RSACryptoServiceProvider()) { rsa.FromXmlString("xxxxxx"); try { // 直接对已哈希的值签名,避免重复哈希 signedBytes = rsa.SignHash(hashBytes, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); temp_inBase64 = Convert.ToBase64String(signedBytes); } catch (CryptographicException e) { Console.WriteLine(e.Message); return null; } finally { rsa.PersistKeyInCsp = false; } } return temp_inBase64;
2. 其他需验证的点
- 私钥合法性:确认
rsa.FromXmlString传入的XML私钥是完整的合法RSA私钥,包含<RSAKeyValue>节点。 - 编码一致性:确保API验证方同样使用UTF-8编码处理原始字符串,和你的代码保持一致。
- 签名填充方式:默认
RSACryptoServiceProvider使用PKCS#1填充,需确认验证方使用相同的填充规则,否则会验证失败。
内容的提问来源于stack exchange,提问作者transport company
相关产品推荐
相关产品推荐

