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
相关产品推荐
相关产品推荐

