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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 19:45:05