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

libfido2与WebAuthn跨平台FIDO2认证互兼容问题求助

解决Windows libfido2与Web端WebAuthn跨平台互认兼容问题

问题背景

我用C#开发的Windows应用集成了libfido2发布版DLL,实现FIDO设备的注册与认证,单独运行完全正常;Web端基于WebAuthn实现FIDO2功能,单独运行也没问题。但跨端互认时出现两个核心问题:

  • Windows端使用WebAuthn生成的publicKey和CredentialId认证时,报错「FIDO2 operation failed (InvalidSignature)」
  • Web端使用libfido2生成的publicKey和CredentialId认证时,抛出「PeterO.Cbor.CBORException Message: Too many bytes」错误

问题根源

这俩问题本质是libfido2和WebAuthn在COSE公钥格式、CBOR编解码、数据序列化细节上的差异:

  1. InvalidSignature:WebAuthn返回的公钥是完整COSE CBOR对象,Windows端直接转字节传入Verify方法,没有正确提取公钥核心材料;或者ClientData哈希、AuthData的处理逻辑和WebAuthn不匹配。
  2. Too many bytes:libfido2生成的publicKey可能带有非标准CBOR包装或额外元数据,Web端的PeterO.Cbor解析器无法处理多余字节。

修复方案

一、解决Windows端InvalidSignature错误

  1. 正确解析WebAuthn的COSE公钥
    WebAuthn的publicKey是标准COSE CBOR结构,不能直接转字节传入libfido2的Verify方法,需要先解析CBOR提取公钥的x、y坐标(ES256算法为例),再拼接成libfido2要求的64字节原始格式。
  2. 统一ClientData哈希计算逻辑
    WebAuthn用UTF-8编码的clientDataJSON计算SHA-256哈希,Windows端要确保传入SetClientDataHash的是该哈希值,而非原始字符串。
  3. 确保AuthData完整性
    确认Windows端接收的AuthData是WebAuthn返回的完整原始字节,没有被截断或修改。

二、解决Web端Too many bytes错误

  1. 规范libfido2公钥存储格式
    注册时从FidoCredential获取公钥后,解析CBOR并重新序列化为标准COSE结构,再转Base64存入数据库,避免libfido2的非标准包装干扰Web端解析。
  2. 统一Base64编码方式
    WebAuthn常用Base64URL,libfido2可能用标准Base64,跨端传递时要做格式转换(替换-/_为+/=,补全=符号)。

调整后的代码示例

Windows端认证完成方法(适配WebAuthn公钥)

private void CompleteAuthentication(string rpId, ReadOnlySpan<byte> authData, ReadOnlySpan<byte> signature, FidoExtensions extensions, string publicKey)
{
    // 解析WebAuthn返回的COSE公钥CBOR对象
    var coseKey = PeterO.Cbor.CBORObject.DecodeFromBytes(Convert.FromBase64String(publicKey));
    
    // 提取ES256公钥的x、y坐标(算法不同需调整,如RS256取模和指数)
    byte[] x = coseKey["-2"].GetByteString();
    byte[] y = coseKey["-3"].GetByteString();
    
    // 构造libfido2要求的64字节原始公钥格式
    byte[] keyBytes = new byte[64];
    Buffer.BlockCopy(x, 0, keyBytes, 0, 32);
    Buffer.BlockCopy(y, 0, keyBytes, 32, 32);
    
    using (var assert = new FidoAssertion())
    {
        // 计算ClientData的SHA-256哈希(确保和WebAuthn逻辑一致)
        byte[] clientDataHash = SHA256.HashData(Encoding.UTF8.GetBytes(Cd));
        assert.SetClientDataHash(clientDataHash);
        
        assert.Rp = rpId;
        assert.Count = 1;
        assert.SetAuthData(authData, 0);
        assert.SetExtensions(extensions);
        assert.SetSignature(signature, 0);
        // 用处理后的公钥验证签名
        assert.Verify(0, FidoCose.ES256, keyBytes);
    }
}

Windows端注册时适配Web端的公钥存储逻辑

// 注册成功后获取libfido2生成的公钥
byte[] rawPublicKey = credential.PublicKey;
// 解析为标准COSE CBOR对象
var coseKey = PeterO.Cbor.CBORObject.DecodeFromBytes(rawPublicKey);
// 重新序列化为标准CBOR字节,转Base64存入数据库
string standardPublicKey = Convert.ToBase64String(coseKey.EncodeToBytes());
// 将standardPublicKey和CredentialId(转Base64URL)存入数据库

Base64与Base64URL转换工具

// 标准Base64转Base64URL(适配WebAuthn)
public static string Base64ToBase64Url(string base64)
{
    return base64.Replace('+', '-').Replace('/', '_').TrimEnd('=');
}

// Base64URL转标准Base64(适配libfido2)
public static string Base64UrlToBase64(string base64Url)
{
    base64Url = base64Url.Replace('-', '+').Replace('_', '/');
    return base64Url.PadRight(base64Url.Length + (4 - base64Url.Length % 4) % 4, '=');
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 16:45:32