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

WebAuthn断言ECDSA签名验证失败排查求助

排查WebAuthn断言签名验证失败的核心方向

1. 重点核查ASN.1转换逻辑

WebAuthn返回的ECDSA签名是IEEE P1363格式(直接拼接r+s字节),而.NET的ECDsa.VerifyData()默认要求ASN.1/DER格式,转换错误是最常见的失效原因:

  • 确认转换时的字节处理逻辑:
    public static byte[] ConvertP1363ToDer(byte[] p1363Signature)
    {
        if (p1363Signature.Length != 64) throw new ArgumentException("P-256签名必须为64字节");
        
        byte[] r = p1363Signature.Take(32).ToArray();
        byte[] s = p1363Signature.Skip(32).ToArray();
        
        // 修正DER整数格式:移除前导零,最高位为1时补0x00前缀
        r = FixDerInteger(r);
        s = FixDerInteger(s);
        
        // 组装DER结构:0x30(SEQUENCE) + 总长度 + 0x02(INTEGER) + r长度 + r + 0x02 + s长度 + s
        int totalLength = 2 + r.Length + 2 + s.Length;
        var derBytes = new List<byte>
        {
            0x30, (byte)totalLength,
            0x02, (byte)r.Length
        };
        derBytes.AddRange(r);
        derBytes.AddRange(new byte[] { 0x02, (byte)s.Length });
        derBytes.AddRange(s);
        
        return derBytes.ToArray();
    }
    
    private static byte[] FixDerInteger(byte[] value)
    {
        // 移除无效前导零
        int startIdx = 0;
        while (startIdx < value.Length - 1 && value[startIdx] == 0)
            startIdx++;
        var trimmed = value.Skip(startIdx).ToArray();
        
        // 最高位为1时补0x00,避免被解析为负数
        if ((trimmed[0] & 0x80) != 0)
            return new byte[] { 0x00 }.Concat(trimmed).ToArray();
        
        return trimmed;
    }
    
  • 直接对比成功/失败案例的转换后DER字节,确认是否存在差异。

2. 验证核心参数的正确性

  • 待验证数据完整性:WebAuthn的验证数据必须是clientDataHash + authenticatorData的拼接字节,确认这两部分的哈希值、原始数据与认证流程完全一致,尤其是authenticatorData中的rpIdHash、标志位(userPresent/userVerified)不能有变动。
  • 哈希算法匹配:WebAuthn公钥的alg字段对应哈希算法(如ES256对应SHA256),必须确保VerifyData()传入的HashAlgorithmName与之一致。

3. 公钥加载逻辑检查

WebAuthn公钥为COSE格式,解析错误会直接导致验证失败:

public static ECDsa LoadCosePublicKey(byte[] cosePublicKey)
{
    // COSE公钥结构:{ 1: 2(EC2), 3: -7(ES256), -1: 1(P-256), -2: x字节, -3: y字节 }
    var coseDict = CBOR.Decode(cosePublicKey) as Dictionary<object, object>;
    byte[] x = (byte[])coseDict[-2];
    byte[] y = (byte[])coseDict[-3];
    
    var ecParams = new ECParameters
    {
        Curve = ECCurve.NamedCurves.nistP256,
        Q = new ECPoint { X = x, Y = y }
    };
    return ECDsa.Create(ecParams);
}
  • 对比成功/失败案例的公钥X、Y坐标,确认解析后的参数完全一致,避免Base64URL解码错误、字节序颠倒等问题。

4. 其他排查点

  • 确认.NET版本:部分旧版本的ECDsa对DER格式的容错性较低,需确保使用的框架版本支持规范的ASN.1解析。
  • 检查签名的Base64URL解码:WebAuthn返回的签名是Base64URL编码,必须先转换为标准Base64再解码为字节数组,避免字符替换错误(如-→+、_→/,补全=)。

内容的提问来源于stack exchange,提问作者McMurphy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 16:45:53