35

随着最近关于 FIDO U2F 规范的所有讨论,我想在测试平台上实现 FIDO U2F 测试,为即将推出的最终规范做好准备。

到目前为止,我有一个由 Yubico 生产的 FIDO U2F 安全密钥和安装在 Chrome 中的 FIDO U2F(通用 2nd Factor)扩展。我还设法设置了安全密钥以使用我的 Google 登录。

现在,我不确定如何将这些东西用于我自己的网站。我浏览了 Google 的 Github 页面以了解 U2F 项目,并检查了他们的网络应用程序前端。它看起来非常简单(仅限 JavaScript)。那么使用 FIDO 实现第二因素身份验证就像实现几个 JavaScript 调用一样简单吗?示例中的注册似乎发生的所有事情都是这样的:

      var registerRequest = {
            appId: enrollData.appId,
            challenge: enrollData.challenge,
            version: enrollData.version
      };

      u2f.register([registerRequest], [], function (result) {
          if (result.errorCode) {
        document.getElementById('status')
          .innerHTML = "Failed. Error code: " + result.errorCode;
        return;
          }
          document.location = "/enrollFinish"
          + "?browserData=" + result.clientData
          + "&enrollData=" + result.registrationData
          + "&challenge=" + enrollData.challenge
          + "&sessionId=" + enrollData.sessionId;             
      });

但是我如何自己使用它来实现呢?我可以使用此方法调用的回调进行用户注册吗?

4

2 回答 2

53

您要做的是实现所谓的“依赖方”,这意味着您的 Web 服务将依赖 FIDO U2F 令牌提供的身份断言。

您需要了解U2F 规范才能做到这一点。尤其是挑战-响应范式是如何实现的,以及应用程序 id 和 facet 是如何工作的。这在规范中有详细描述。

你是对的:从应用程序的前端使用 FIDO U2F 所需的实际代码几乎是微不足道的(也就是说,如果你使用“高级”JavaScript API 而不是“低级”MessagePort API) . 但是,您的应用程序将需要使用令牌生成的消息并对其进行验证。这不是微不足道的。

为了说明如何实现依赖方站点,我将给出一些代码示例,这些示例取自我最近出于学术原因编写的虚拟 FIDO U2F 令牌扩展。您可以查看完整示例代码的页面。


在您的用户可以使用他们的 FIDO U2F 令牌进行身份验证之前,他们需要向您注册。为了允许他们这样做,您需要window.u2f.register在他们的浏览器中调用。为此,您需要提供一些参数(同样;请阅读规范了解详细信息)。其中一个挑战和你的应用程序的id。对于 Web 应用,此id必须是触发 FIDO 操作的网页的 Web 来源。假设它是example.org

window.u2f.register([
    {
        version : "U2F_V2",
        challenge : "YXJlIHlvdSBib3JlZD8gOy0p",
        appId : "http://example.org",
        sessionId : "26"
    }
], [], function (data) {

});

一旦用户执行“用户存在测试”(例如通过触摸令牌),您将收到一个响应,这是一个 JSON 对象(有关详细信息,请参阅规范)

dictionary RegisterResponse {
    DOMString registrationData;
    DOMString clientData;
};

此数据包含您的应用程序需要使用的几个元素。

FIDO U2F 注册响应消息的注册映射

  1. 生成的密钥对的公钥——您需要存储它以备将来验证使用。
  2. 生成的密钥对的密钥句柄——您还需要存储它以备将来使用。
  3. 证书 -- 您需要检查您是否信任此证书和 CA。
  4. 签名——您需要检查签名是否有效(即确认与证书一起存储的密钥)以及签名的数据是否是预期的数据。

我已经为 Java 中的依赖方服务器准备了一个粗略的实现草案,展示了最近如何提取和验证这些信息。


一旦注册完成并且您以某种方式存储了生成的密钥的详细信息,您就可以签署请求。

正如您所说,这可以通过高级 JavaScript API 简短而甜蜜地启动:

window.u2f.sign([{
    version : "U2F_V2",
    challenge : "c3RpbGwgYm9yZWQ/IQ",
    app_id : "http://example.org",
    sessionId : "42",
    keyHandle: "ZHVtbXlfa2V5X2hhbmRsZQ"
}], function (data) {

});

在这里,您需要提供您在注册时获得的密钥句柄。再一次,在用户执行“用户存在测试”(例如通过触摸令牌)之后,您将收到一个响应,它是一个 JSON 对象(再次,请参阅规范以获取更多详细信息)

dictionary SignResponse {
    DOMString keyHandle;
    DOMString signatureData;
    DOMString clientData;
};

您需要验证此处包含的签名数据。

FIDO U2F 认证响应消息的注册映射

  1. 您需要确保签名与您之前获得的公钥匹配。
  2. 您还需要验证签名的字符串是否合适。

执行这些验证后,您可以认为用户已通过身份验证。我的服务器示例中还包含了一个简短的服务器端代码实现示例。

于 2014-10-29T20:44:45.993 回答
24

我最近为此编写了说明,并在developer.yubico.com/U2F上列出了所有 U2F 服务器库(其中大多数捆绑了一个完全工作的演示服务器)。目标是使开发人员无需阅读规范即可实现/集成 U2F。

免责声明:我在 Yubico 担任开发人员。

于 2014-10-31T07:41:58.803 回答