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

PHP实现WebAuthn时,如何解析CBOR解码后的authData为可用格式?

PHP环境下解析WebAuthn的authData数据

你遇到的核心问题是authData不是CBOR格式,它是WebAuthn规范定义的固定结构二进制数据,不能用CBOR解码器直接解析。需要按照WebAuthn官方规范的结构手动解析,以下是具体实现步骤:

步骤1:提取authData的原始二进制数据

你使用的CBOR库返回的CBOR\Types\CBORByteString对象,需要先获取其私有属性byte_string的内容,可通过反射实现:

// $attestationObject为CBOR解码后的数组
$authDataObj = $attestationObject['authData'];

// 反射获取私有属性
$reflection = new ReflectionClass($authDataObj);
$property = $reflection->getProperty('byte_string');
$property->setAccessible(true);
$authDataBytes = $property->getValue($authDataObj);

步骤2:按WebAuthn规范解析二进制数据

根据WebAuthn规范,authData由固定分段组成,逐段解析如下:

$parsedAuthData = [];

// 1. 解析rpIdHash(前32字节,依赖方ID的SHA-256哈希)
$parsedAuthData['rpIdHash'] = substr($authDataBytes, 0, 32);
$parsedAuthData['rpIdHashHex'] = bin2hex($parsedAuthData['rpIdHash']);

// 2. 解析flags(第33字节,8位标志位)
$flagsByte = ord(substr($authDataBytes, 32, 1));
$parsedAuthData['flags'] = [
    'userPresent' => ($flagsByte & 0x01) !== 0,
    'userVerified' => ($flagsByte & 0x02) !== 0,
    'backupEligibility' => ($flagsByte & 0x04) !== 0,
    'backupState' => ($flagsByte & 0x08) !== 0,
    'attestedCredentialDataPresent' => ($flagsByte & 0x10) !== 0,
    'extensionDataPresent' => ($flagsByte & 0x20) !== 0,
];

// 3. 解析signCount(接下来4字节,大端序无符号32位整数)
$signCountBytes = substr($authDataBytes, 33, 4);
$parsedAuthData['signCount'] = unpack('N', $signCountBytes)[1];

// 4. 解析Attested Credential Data(仅当标志位attestedCredentialDataPresent为true时存在)
$offset = 37; // 32(rpIdHash)+1(flags)+4(signCount)
if ($parsedAuthData['flags']['attestedCredentialDataPresent']) {
    // 4.1 AAGUID(16字节,认证器厂商唯一标识)
    $parsedAuthData['aaguid'] = substr($authDataBytes, $offset, 16);
    $parsedAuthData['aaguidHex'] = bin2hex($parsedAuthData['aaguid']);
    $offset += 16;

    // 4.2 凭证ID长度(2字节,大端序)
    $credIdLengthBytes = substr($authDataBytes, $offset, 2);
    $credIdLength = unpack('n', $credIdLengthBytes)[1];
    $offset += 2;

    // 4.3 凭证ID
    $parsedAuthData['credentialId'] = substr($authDataBytes, $offset, $credIdLength);
    $parsedAuthData['credentialIdBase64'] = base64_encode($parsedAuthData['credentialId']);
    $offset += $credIdLength;

    // 4.4 COSE公钥(剩余字节,CBOR格式)
    $coseKeyBytes = substr($authDataBytes, $offset);
    $parsedAuthData['cosePublicKey'] = \CBOR\CBOREncoder::decode($coseKeyBytes);
}

// 5. 解析扩展数据(仅当标志位extensionDataPresent为true时存在)
if ($parsedAuthData['flags']['extensionDataPresent']) {
    $extensionBytes = substr($authDataBytes, $offset);
    $parsedAuthData['extensions'] = \CBOR\CBOREncoder::decode($extensionBytes);
}

// 输出结构化解析结果
print_r($parsedAuthData);

测试示例数据

将你提供的$attestationString代入代码运行,即可得到包含凭证ID、公钥等关键信息的结构化数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 13:35:57