WebAuthn生成公钥的解码方法及格式适配技术咨询
关于WebAuthn公钥格式与CBOR解码的解决方案
1. 必须了解的WebAuthn公钥格式要点
- WebAuthn API返回的
credentialPublicKey是COSE Key结构,采用CBOR二进制编码,包含密钥类型、算法标识、核心参数(如RSA的模数/指数,EC的x/y坐标)等元数据。 - 你从WebAuthn Playground获取的公钥是PEM格式的SPKI公钥:它是将ASN.1 DER编码的公钥信息做Base64编码,再加上标准头脚生成的,属于传统PKI格式,和COSE Key完全不兼容——这就是直接传入CBOR解码函数报错的核心原因。
2. 适配CBOR解码代码的具体操作
你手里的PEM公钥无法直接用那段CBOR解码代码处理,有两种可行方案:
方案一:获取原生COSE Key(推荐)
回到WebAuthn Playground,找到生成密钥对时返回的credentialPublicKey原始二进制数据(通常是Uint8Array或ArrayBuffer类型),直接传入cbor.decodeAllSync即可正常解析,无需额外转换。
方案二:将PEM公钥转换为COSE Key格式
如果只能拿到当前的PEM公钥,可通过以下步骤转换为CBOR编码的COSE Key,再用你的代码解码:
import * as cbor from 'cbor'; import { createPublicKey } from 'crypto'; // 你的PEM公钥(已清理头脚和换行) const pemPublicKey = `MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA12_SHooAcAenEEhUaGH7woTdHC7sFYx9AjDbZWE3a6DakqFUFF6F7-AT-CGnD3I8_tdpDUkI8237YnvcFowgnuiZqCauigu7fOJOs5hVp5aHWMZW8Rz6YVMkOrFrrrey9DWnaCVmzxJwEEOTQUfjXP-wNsymuk-xzJM9WUOnDbDKMCuCppjFgrSGMSneyHw6cA4tqvpRC1oCi0Pdk2746dPZlWocL1MU8dt1p6dMKLw8jTyq1amkG37G5uW_81GuGaGsEAMtX5vBs_4rHzVH2p_oCe2mKRw2QtP2N9PhQMqyPb2D5RUD1Ye_T2gSrnCNcLXxDDzx3ftHy1cmOY8igQIDAQAB`; // 1. 清理PEM并转成DER二进制 const cleanPem = pemPublicKey.replace(/-----BEGIN PUBLIC KEY-----|-----END PUBLIC KEY-----|\n/g, ''); const derBuffer = Buffer.from(cleanPem, 'base64'); // 2. 解析RSA公钥的核心参数(模数n、公钥指数e) const rsaKey = createPublicKey({ key: derBuffer, format: 'der', type: 'spki' }); const jwk = rsaKey.export({ format: 'jwk' }) as JsonWebKey; const n = Buffer.from(jwk.n!, 'base64url'); const e = Buffer.from(jwk.e!, 'base64url'); // 3. 构造符合COSE标准的RSA密钥结构 const coseKey = { 1: 3, // kty: 标识为RSA密钥 3: -257, // alg: 标识为RS256签名算法 -1: n, // RSA模数 -2: e // RSA公钥指数 }; // 4. 编码为CBOR二进制后解码 const coseBuffer = cbor.encode(coseKey); const struct = cbor.decodeAllSync(coseBuffer)[0]; // 提取所需的公钥参数 console.log('模数n:', struct[-1].toString('hex')); console.log('公钥指数e:', struct[-2].toString('hex'));
说明:如果是EC密钥,COSE Key的参数会不同(比如kty为2,加上曲线标识、x/y坐标等),但核心转换逻辑一致。
内容的提问来源于stack exchange,提问作者failedprofundity
相关产品推荐
相关产品推荐

