深入Passkey通行密钥:抓包、手动解析公钥与验签完整实战

通行密钥(Passkey)基于WebAuthn/FIDO2协议,使用非对称密钥完成无密码身份认证。本文通过浏览器抓包真实流量,完整演示注册阶段提取COSE公钥、登录阶段重组签名原文、手动ECDSA SHA256验签全流程

前言

通行密钥分为两大核心流程:注册(create,生成密钥对,公钥上交服务器)、认证登录(get,设备用私钥签名,服务器拿公钥验签)。

  • 私钥:永远保存在认证器(手机、安全密钥)内部,不会通过网络传输。
  • 公钥:注册阶段通过attestationObject返回,服务器必须持久存储,用于后续登录验签。
  • 登录返回的JSON报文不会携带公钥,仅返回凭证ID、签名、认证器数据;服务器靠凭证ID查表取出公钥做校验。
    很多新手踩坑:把rawId(凭证ID)当成公钥;直接拿Base64字符串做哈希;混淆DER签名与raw R || S签名格式,导致验签持续失败。下面基于真实抓包流量一步步拆解。

1. 提取公钥

注册时抓包完整报文如下。

id:"ETO9WnmGSneO40QBN30PoQ"
rawId:"ETO9WnmGSneO40QBN30PoQ=="
{
    "clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIiwiY2hhbGxlbmdlIjoiY0dwT1VEUXpNVXBXZWxCV2NEVklORE5XYldKU1RYUlJiSGRsUkhwMU1WRXZaVUZrUkdsSWJDOUxORDAiLCJvcmlnaW4iOiJodHRwczovL2Rhc2guY2xvdWRmbGFyZS5jb20iLCJjcm9zc09yaWdpbiI6ZmFsc2V9",
    "attestationObject": "o2NmbXRkbm9uZWdhdHRTdG10oGhhdXRoRGF0YViUGYFcuaX7JdgF3r17MlN+1Xhjmz7RCOx8W7no8N+xaHNdAAAAANVIgm55tNtAo9gREW9+g0kAEBEzvVp5hkp3juNEATd9D6GlAQIDJiABIVggcxmO6BWUWvaSE96aEuS3dGZsmsfkeCKYT+c45ROhmfMiWCCfXEJ5Y41UpqusWuPe/HL3hXmeFrbXx8IXxv6Z2gIkqA=="
}

浏览器调用navigator.credentials.create()完成注册,HTTP POST请求载荷核心字段:clientDataJSON、attestationObject。
clientDataJSON解码后type="webauthn.create"代表注册行为;challenge:"cGpOUDQzMUpWe……"服务器提前下发的随机挑战值,防重放攻击;origin:"https://dash.cloudflare.com"当前网页域名;crossOrigin为是否跨域,一般为否。
image1
attestationObject是Base64编码的CBOR二进制对象,公钥就藏在这里,不是JSON,不能直接JSON解析。
image2
步骤一:通过网站https://www.codertools.net/tools/cbor.php?lang=zh 对attestationObject字段进行解码,解码后包括3个key:fmt、attStmt、authData,authData是认证器原始二进制数据,这是我们解析公钥的核心数据源。如下图所示。
image3
步骤二:切片解析authData字节流,头部固定长度:32+1+4 =37字节,偏移 offset=37开始进入attestedCredentialData,分析如图以及表格:

字段 字节长度 说明
rpIdHash 32 字节 依赖方域名sha256哈希,防域名篡改
flags 1 字节 用户存在、用户验证标记位
signCount 4 字节(大端) 签名计数器,检测密钥克隆
attestedCredentialData 变长 AAGUID + 凭证ID长度 + credentialId + COSE公钥

image4
步骤三:提取COSE公钥进行解码获取64字节公钥值。X、Y各32字节,拼接前缀04得到65字节未压缩椭圆公钥。数据库存储:需要保存rawId(凭证ID)、COSE 公钥二进制、初始signCount,登录时用rawId查询取出公钥。
image5

73198ee815945af69213de9a12e4b774666c9ac7e47822984fe738e513a199f39f5c4279638d54a6abac5ae3defc72f785799e16b6d7c7c217c6fe99da0224a8

2. 提取签名值

在登录的时候抓取签名值、原文值。登录抓包完整报文如下。

{
  "id": "ETO9WnmGSneO40QBN30PoQ",
  "type": "public-key",
  "rawId": "ETO9WnmGSneO40QBN30PoQ==",
  "response": {
    "authenticatorData": "GYFcuaX7JdgF3r17MlN+1Xhjmz7RCOx8W7no8N+xaHMdAAAAAA==",
    "clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uZ2V0IiwiY2hhbGxlbmdlIjoiZWpaQmFtZElWbEE1TlRZeVZHOXRXV05KVUVKTlpUWk9TR1ZoSzFWM2RtNXljVFoxVnpNdlRqa3ZjejAiLCJvcmlnaW4iOiJodHRwczovL2Rhc2guY2xvdWRmbGFyZS5jb20iLCJjcm9zc09yaWdpbiI6ZmFsc2V9",
    "signature": "MEUCIQCAkrz/scExG4apAxxjiX7Y7JSab84bKnvjtQX0thtpOgIgKZ2zYpjh9QqrVX8OiAE4GKrzTZho08VkkRdw5/vr+is=",
    "userHandle": "OTY4MGYxYTE0MzIxNWM0NDk4ZjMzMWE0YmVjOWNlMTM="
  }
}
序号 字段 字段说明
1 signature 认证器私钥生成的ASN.1‑DER格式ECDSA 签名,Base64编码
2 authenticatorData 认证器二进制数据(base64)
3 clientDataJSON 浏览器侧数据,包含 challenge、origin,防重放、防钓鱼

image6
signature(base64):MEUCIQCAkrz/scExG4apAxxjiX7Y7JSab84bKnvjtQX0thtpOgIgKZ2zYpjh9QqrVX8OiAE4GKrzTZho08VkkRdw5/vr+is=
解码Hex:30450221008092bcffb1c1311b86a9031c63897ed8ec949a6fce1b2a7be3b505f4b61b693a0220299db36298e1f50aab557f0e88013818aaf34d9868d3c564911770e7fbebfa2b

3. 提取原文值

签名原文(待验签数据)由两部分组成,authenticatorData值和SHA256(clientDataJSON)值,构造规则为:signed_data = authenticatorData(二进制) || SHA256(“clientDataJSON(二进制)”). digest()
(1)authenticatorData(base64):GYFcuaX7JdgF3r17MlN+1Xhjmz7RCOx8W7no8N+xaHMdAAAAAA==
解码hex:19815cb9a5fb25d805debd7b32537ed578639b3ed108ec7c5bb9e8f0dfb168731d00000000
(2)clientDataJSON(base64):eyJ0eXBlIjoid2ViYXV0aG4uZ2V0IiwiY2hhbGxlbmdlIjoiZWpaQmFtZElWbEE1TlRZeVZHOXRXV05KVUVKTlpUWk9TR1ZoSzFWM2RtNXljVFoxVnpNdlRqa3ZjejAiLCJvcmlnaW4iOiJodHRwczovL2Rhc2guY2xvdWRmbGFyZS5jb20iLCJjcm9zc09yaWdpbiI6ZmFsc2V9
解码hex:7b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a22656a5a42616d6449566c41354e5459795647397457574e4a55454a4e5a545a4f534756684b315633646d357963545a31567a4d76546a6b76637a30222c226f726967696e223a2268747470733a2f2f646173682e636c6f7564666c6172652e636f6d222c2263726f73734f726967696e223a66616c73657d
(3)clientDataJSON计算sha256结果:26B2E62D853467FC947686FB462FE4A7F70340F0F2729050282B595F858F883E
image7
把(1)拼接(2)就是原文值:19815cb9a5fb25d805debd7b32537ed578639b3ed108ec7c5bb9e8f0dfb168731d0000000026B2E62D853467FC947686FB462FE4A7F70340F0F2729050282B595F858F883E

4. 验签成功

  • 算法:ECDSA over P 256(secp256r1) + SHA 256
  • 签名格式:ASN.1 DER 编码,不是原始64字节r+s拼接格式,很多工具库默认raw格式,直接填会验签失败。
  • 输入:公钥(未压缩 04+X+Y)、待验签消息字节、DER签名字节。本次样本输入上述参数,验签结果为成功,证明整套报文完整可信。
    image8
posted @ 2026-09-15 00:31  小孩子才做选择  阅读(4)  评论(0)    收藏  举报