Bouncy Castle实现SHA-384withECDSA签名验证抛出ArgumentException如何解决
问题根因与修复方案
- 错误1:公钥格式识别错误
你当前使用的pub384是X.509 SubjectPublicKeyInfo(SPKI)标准的DER编码格式,并非P-384公钥的原始x/y坐标拼接格式,直接按长度切分取前62字节作为x坐标完全不符合格式规范,因此抛出坐标不在椭圆曲线有限域内的异常。
P-384曲线的x、y坐标均为固定384位(即48字节),未压缩格式的原始公钥结构为1字节标识(固定0x04) + 48字节x + 48字节y,总长度97字节。你提供的124字节公钥前27字节为SPKI格式头,剩余97字节才是原始公钥内容。 - 错误2:签名格式重复编码
你当前使用的sig384本身已经是SEQUENCE {INTEGER r, INTEGER s}结构的DER编码格式签名,无需再次拆分拼接生成derSignature,否则会导致签名格式错误验签失败。你之前SHA256场景的签名是原始r+s拼接的plain格式,才需要手动转DER,两类场景输入的签名格式不同。
修复后的代码
public static void VerifySHA384Bouncy(byte[] message, byte[] signature, byte[] pubkey) { // 直接解析SPKI格式公钥,无需手动切分坐标(推荐,兼容性更高) var pubKeyParam = (ECPublicKeyParameters)PublicKeyFactory.CreateKey(pubkey); // 若需手动切分坐标,可使用以下代码替换上一行 // X9ECParameters ecParams = NistNamedCurves.GetByName("P-384"); // ECDomainParameters domainParameters = new ECDomainParameters(ecParams.Curve, ecParams.G, ecParams.N, ecParams.H); // // 跳过前27字节SPKI头+1字节未压缩标识0x04 // var rawPubKey = pubkey.Skip(28).ToArray(); // BigInteger x = new BigInteger(1, rawPubKey.Take(48).ToArray()); // BigInteger y = new BigInteger(1, rawPubKey.Skip(48).Take(48).ToArray()); // ECPoint q = ecParams.Curve.CreatePoint(x, y); // var pubKeyParam = new ECPublicKeyParameters(q, domainParameters); var verifier = SignerUtilities.GetSigner("SHA-384withECDSA"); verifier.Init(false, pubKeyParam); verifier.BlockUpdate(message, 0, message.Length); // 直接使用输入的签名即可,无需二次编码 bool result = verifier.VerifySignature(signature); Console.WriteLine("result: " + result); }
后续对接不同场景时优先确认输入的公钥、签名是裸拼接格式还是标准编码格式,不要直接照搬原有逻辑即可。
内容的提问来源于stack exchange,提问作者One-One
相关产品推荐
相关产品推荐

