如何用RSA签名SHAKE256哈希?RSACryptoServiceProvider不支持SHA3的解决办法
解决RSACryptoServiceProvider不支持SHAKE256哈希的RSA签名问题
方案一:手动构建PKCS#1 v1.5签名格式(适用于.NET Framework)
由于RSACryptoServiceProvider的SignHash不支持SHAKE256,可手动实现RSA签名的底层逻辑——对符合PKCS#1 v1.5格式的哈希数据块进行私钥加密:
生成SHAKE256哈希
用已有的SeriesOne.CORE包生成输入数据的SHAKE256哈希,得到字节数组shakeHash。构建PKCS#1 v1.5签名块
RSA签名需将哈希值包装为指定结构,以2048位RSA密钥(模数长度256字节)为例:// 自定义SHAKE256的OID(若仅用于内部验证,可省略OID部分) var oidBytes = Encoding.ASCII.GetBytes("1.3.6.1.4.1.11591.15.2"); int keySizeBytes = 256; // 2048位密钥对应256字节 int paddingLength = keySizeBytes - 3 - oidBytes.Length - shakeHash.Length; var paddingBytes = new byte[paddingLength]; Array.Fill(paddingBytes, (byte)0xFF); // 组装签名块:0x00 0x01 + 全0xFF填充 + 0x00 + OID + 哈希值 var signatureBlock = new byte[] { 0x00, 0x01 } .Concat(paddingBytes) .Concat(new byte[] { 0x00 }) .Concat(oidBytes) .Concat(shakeHash) .ToArray();生成签名
使用私钥加密签名块,采用PKCS#1填充:byte[] signature; using (var rsa = new RSACryptoServiceProvider(2048)) { rsa.FromXmlString(私钥XML字符串); signature = rsa.Encrypt(signatureBlock, RSAEncryptionPadding.Pkcs1); }验证签名
用公钥解密签名,提取哈希值并对比:bool isValid = false; using (var rsa = new RSACryptoServiceProvider(2048)) { rsa.FromXmlString(公钥XML字符串); var decryptedBlock = rsa.Decrypt(signature, RSAEncryptionPadding.Pkcs1); var extractedHash = decryptedBlock.Skip(decryptedBlock.Length - shakeHash.Length).ToArray(); isValid = extractedHash.SequenceEqual(shakeHash); }
方案二:使用RSACng(.NET Framework 4.6+ 或 .NET Core/5+)
替换旧的RSACryptoServiceProvider为RSACng,它支持更灵活的签名操作,可直接对SHAKE256哈希进行签名:
// 生成SHAKE256哈希 byte[] shakeHash = SeriesOne.CORE.Hash.SHAKE256(输入数据字节数组, 哈希输出长度); // 签名哈希 byte[] signature; using (var rsa = new RSACng()) { rsa.ImportParameters(私钥参数); signature = rsa.SignHash(shakeHash, new HashAlgorithmName("SHAKE256"), RSASignaturePadding.Pkcs1); } // 验证签名 bool isValid; using (var rsa = new RSACng()) { rsa.ImportParameters(公钥参数); isValid = rsa.VerifyHash(shakeHash, signature, new HashAlgorithmName("SHAKE256"), RSASignaturePadding.Pkcs1); }
方案三:使用第三方加密库(如BouncyCastle)
直接使用支持SHA3系列的加密库,无需手动处理格式:
// 生成SHAKE256哈希 var shakeDigest = new ShakeDigest(256); shakeDigest.BlockUpdate(输入数据字节数组, 0, 输入数据字节数组.Length); byte[] shakeHash = new byte[32]; // 自定义输出长度 shakeDigest.DoFinal(shakeHash, 0); // RSA签名 var privateKey = AsymmetricKeyParameterConverter.FromXmlString(私钥XML字符串); var signer = SignerUtilities.GetSigner("SHAKE256withRSA"); signer.Init(true, privateKey); signer.BlockUpdate(shakeHash, 0, shakeHash.Length); byte[] signature = signer.GenerateSignature(); // 验证签名 var publicKey = AsymmetricKeyParameterConverter.FromXmlString(公钥XML字符串); var verifier = SignerUtilities.GetSigner("SHAKE256withRSA"); verifier.Init(false, publicKey); verifier.BlockUpdate(shakeHash, 0, shakeHash.Length); bool isValid = verifier.VerifySignature(signature);
内容的提问来源于stack exchange,提问作者tokechu
相关产品推荐
相关产品推荐

