的响应将会使得依赖方接受客户端拥有相应的私钥。
U2F协议的核心是发送到U2F令牌的请求信息和从U2F令牌接收的响应信息。
注意:请求消息通常在设置阶段期间由FIDO客户端从依赖方获得,并且因此到达FIDO客户端作为Http响应的一部
分。类似地,在验证阶段期间由依赖方出库的响应消息是由FIDO客户端在Http请求中发送给依赖方。
请求消息由依赖方创建并由U2F令牌消耗。响应消息由U2F令牌和由依赖方消费。
当消息从依赖方(通过FIDO客户端)流向U2F令牌并返回时,他们经历各种变换,并且编码。这些变换和编码中
的一些取决于各个实现,并且不是作为FIDO的一部分而标准化的U2F。
然而,为了确保来自不同供应商的U2F令牌可以在符合U2F的网站上工作,某些编码被标准化。
1.FIDO U2F标准化JavaScript API,规定Web应用程序如何将请求消息传递到FIDO客户端(在Web浏览器是FIDO客
户端的情况),以及响应信息的编码是什么。
2.FIDO U2F标准化从客户端通过USB传输发送到请求和响应消息时如何编码U2F令牌。除了指定编码,传输级别规
范还指定控制消息的格式和来自令牌的错误响应的格式。
在本文中,我们描述信息的"原始"或规范格式,即,不考虑在规定的各种编码U2F标准或者实现者可以选择何时
发送消息。知道消息的原始格式是非常重要的,因为:
1.在别处描述的消息和参数的编码可以指代本文档中描述的原始消息。例如:JavaScript API可以将函数的参数
称为原始注册响应消息的Base64encoding。
2.对原始数据计算加密签名。例如,标准可以规定某个加密签名是接收某个原始消息的字节5到60.因此,实现者
必须知道原始消息的外观。
U2F消息成帧
U2F协议是基于请求-响应机制,其中请求者向U2F设备发送请求消息,该U2F设备总是导致将响应消息从U2F设备
发送回请求者。
请求消息必须“成帧”以发送到较低层。以签名请求为例,“成帧”是一种方式FIDO客户端下传输层他正在发送
签名请求,然后发送原始消息内容。成帧也指定传输将如何传送响应原始消息和任何元信息,例如命令失败的错
误码。
在当前版本的U2F中,成帧是基于ISO78164,,2005扩展APDU格式定义的。这对于USB传输是非常合适的,因为设
备通常围绕已经知道该格式的安全元件构建。相同的论点可能适用于期货如基于蓝牙的设备。对于其他基于传输
的期货,例如移动设备TEE上的内置U2F令牌,者成帧可能不适当,并且可能需要定义不同的成帧。
请求消息成帧
原始请求消息将被成帧为命令APDU。
CLA INS P1 P2 LC1 LC2 LC3<request-data>
CLA: Reserved to be used by the underlying transport protocol (if applicable). The host application shall set this byte to zero.
INS: U2F command code, defined in the following sections.
P1,P2: Parameter 1 and 2, defined by each command.
LC1LC3: Length of the request data, bigendian coded, i.e. LC1 being MSB and LC3 LSB
响应消息成帧
SW1 SW2<reponse-data>
SW1,SW2: Status word bytes 1 and 2, forming a 16bit status word, defined below. SW1 is MSB and SW2 LSB.
状态码
下面的ISO7816-4定义的状态码有在U2F中有特殊的意义:
SW_NO_ERROR:这个命令成功完成并无错误。
SW_CONDITIONS_NOT_SATISFIED:请求被拒绝,因为需要..存在。
SW_WRONG_DATA:请求被拒绝因为不合法的key句柄
每个实现可以定义任何其他厂商特定的状态代码,提供关于错误状况的附加信息。只有上面列出的错误代码将由
FIDO客户端处理,其中其他将被视为常规错误,并且这些激励是可选的。
注册消息
注册请求消息-U2F_REGISTER
此消息用于启动U2F令牌注册。FIDO客户端首先联系依赖方以获取质询,然后构造注册请求消息。注册请求消息有两部分:
Application 参数:application参数是应用程序的应用程序标识的SHA256的哈希值。
注册失败的响应消息:Test-of-User-Presence Required(测试用户)
如果U2F令牌无法获取test-of-user的存在,则这是U2F令牌输出的错误信息。错误消息详细信息在底层传输的成帧中指定。
注册成功的响应消息:Success
A reserved byte[1 byte]:其由于遗留原因具有值0x05
A user public key[65 bytes]:这是P256 NIST椭圆曲线上曲线点的(未压缩)x,y表示
A key handle length byte[1 byte]:key handle的 长度
A key handle:这个句柄允许U2F令牌标识生成的密钥对。U2F令牌可以包装生成的私钥和为其生成的应用程序ID,
并将其作为键句柄输出。
An attestation cetificate[可变长度]:这是X.509 DER格式的证书。解析X.509证书明确地确定其结束。
A signature:这是以下字节字符串的ECDSA签名:
(1)为将来保留的字节[1字节],值为0x00。这将演变成一个字节,将允许RP跟踪来自特定供应商的U2F令牌的
已知良好applet版本。
(2)来自注册请求消息的Application参数[32字节]
(3)来自注册请求消息的Challenge参数[32字节]
(4)上面的key handle[可变长度]。(请注意,密钥句柄程度不包括在签名基本字符串中,这不会导致签基本
字符串混淆,因为签名基本字符串中的所有参数都是fixed length)
(5)上面的User public key[65字节]
签名将由依赖方使用在认证证书中认证的公钥验证。依赖方也应该进行验证认证证书由受信任的证书颁发机构颁发。
设置受信任的的证书颁发机构的确切过程由FIDO联盟定义,不在本文档的范围之内。
一旦依赖方验证签名,它应该存储公钥和密钥句柄,以便他们可以在将来的认证中使用操作。
认证消息
认证请求消息-U2F_AUTHENTICATE
此消息用于启动U2F令牌认证。FIDO客户端首先联系依赖方以获得质询,然后构建认证请求信息。
该注册请求信息有5个部分:
控制字节
0x07("check-only"):如果控制字节被FIDO客户端设置为0x07,则U2F令牌应该简单地检查提供的提供的key
handle是否为所提供的应用程序参数创建。如果是这样,U2F令牌必须用认证响应消息进行响应,错误:test-
of-user-presence-required)。如果为不同的应用程序参数创建,则令牌必须用认证进行响应 响应消息:error
:bad key handle
0x03 ("enforceuserpresenceandsign"):如果FIDO客户端将控制字节设置为0x03,则U2F令牌应为执行真实签名并用认证响应消息:成功或适当的错误响
应来响应。只有在可以验证用户存在时,才应提供签名。
其他的控制字节被保留以便将来使用。
在注册期间,FIDO客户端可以向U2F令牌发送认证请求消息以确定U2F令牌是否已经注册。在这种情况下,FIDO客
户端将使用校验值作为控制字节。在所有其他情况下(即,在认证期间,FIDO客户端必须使用enforce-user-
presence-and-sign值)
challenge参数
challenge参数是客户端数据的SHA256散列,这是FIDO客户端准备的一种带字符的JSON数据结构。除此之外,
Client Data包含了来自依赖方的challenge。
application参数
Application参数是请求有依赖方提供的认证的应用的应用标识的SHA256散列。
key handle length
key handle
这由依赖方提供,并且在注册期间有依赖方获得。
认证响应信息:Error:test-of-user-presence Requeired
如果U2F令牌无法获取test-of-user存在,则这是由U2F令牌输出的错误消息。错误消息的详细信息在底层传输的成帧中指定。
认证响应消息:Error:bad key handle
这是有U2F令牌输出的错误信息,如果提供key handle最初不是由此令牌创建的,或者如果提供的键句柄由此令牌创建,但是用于不同的
应用程序参数。错误消息的详细信息在底层传输的成帧中指定。
认证响应消息:Success
user presence type:位0设置为1,这意味着用户存在被验证。(此版本的协议没有指定一种用于请求认证响应
而不需要用户存在的方式)位1至7的值应为0。
counter:这是计数器值的大端表示,U2F令牌在执行一次认证操作时进行递增的操作。
signature:这是一个对下面字符串ECDSA签名的字节串
1.来自认证请求消息的Application参数
2.上面的User presence字节
3.上面的counter
4,来自认证请求消息的challenge参数
这个签名将由依赖方在注册期间获得公钥来验证。
其他消息
GetVersion请求和响应-U2F_VERSION
FIDO客户端可以查询U2F令牌所实现的U2F协议版本。本文档中描述的协议版本为U2F_V2。
响应消息的原始表示形式是字符串"U2F_V2"的ASCII表示形式
拓展和供应商特定的信息
在U2F_VENDOR_FIRST和U2F_VENDOR_LAST之间范围内的命令代码可以用于供应商特定实现。例如,供应商可以选
择放入一些测试命令。注意,FIDO客户端永远不会生成这些命令,所有其他的命令代码为RFU,不能使用。
Client Data
注册和认证请求消息包含一个challenge参数,它被定义为FIDO客户端必须准备的字符串化JSON数据结构的
SHA256散列。FIDO客户端必须发送客户端数据(而不是其散列challenge参数)到信任方,其中依赖方可以再生
challenge参数(通过客户端数据进行散列),这是为了在登记响应消息上验证签名所必须认证响应消息。
在FIDO客户端时Web浏览器的情况下,客户端数据定义如下(在WebIDL中):
dictionary ClientData {
DOMString typ;
DOMString challenge;
DOMString origin;
(DOMString or JwkKey) cid_pubkey;
};
字典Client Data成员:
typ of type DOMString
用于认证的常量"navigator.id getAssertion"和用于注册的"navigator.id finishEnrollment"
challenge of type DOMString
由依赖方提供的网络安全Base64编码的challenge
origin of type DOMString
呼叫者的facet id即依赖方的Web源(注意:这可能更准确的称为"facet id",但为了Chrome中现有实现兼容,
我们保留旧名称)
cid_pubkeyof type (DOMString or JwkKey)
此浏览器使用的渠道ID公钥与上述来源进行通信。此参数是可选的,如果浏览器不支持Channel ID则舍弃。如果
浏览器支持Channel ID,但未使用,它将显示并设置为"常量未使用",通道ID与上述源进行通信(可能是因为源
服务器没有信号支持Channel ID TLS扩展)。否则(即,上述源的浏览器和源服务器都支持Channel ID),它存在并且类型是JwkKey。
JwkKey是表示浏览器用于Channel ID TLS扩展的公钥的字典。当前版本的Channel ID草案规定了算法和使用的曲线,因此,字典将具有以下参数
dictionary JwkKey {
DOMString kty;
DOMString crv;
DOMString x;
DOMString y;
};
JwkKey成员字典
kty of type DOMString
用于Channel ID的签名算法,即常数"EC"
crv of type DOMString
在其上定义该公开密钥的椭圆曲线,即常数"P256"
x of type DOMString
公钥x坐标的网络安全的Base64编码(大端存储,32个字节)
y of type DOMString
公钥y坐标的网络安全的Base64编码(大端存储,32个字节)