目录

1、WebAuthn简介

2、FIDO2:客户端到验证器协议(CTAP)

3、浏览器和平台

4、Web身份验证API 基本流程

5、使用 WebAuthn API

5.1 注册WebAuthn凭据

5.2使用WebAuthn凭据进行身份验证

6、 WebAuthn演示(注册和认证)

6.1 注册演示:

6.2 认证演示:

6.3 浏览器中存储


1、WebAuthn简介

WebAuthn 是FIDO联盟FIDO2规范集的核心组件,是一种基于Web的API,允许网站更新其登录页面,以便在支持的浏览器和平台上添加基于FIDO的身份验证。FIDO2使用户能够利用常见设备轻松地在移动的和桌面环境中对在线服务进行身份验证。

Web服务和应用程序可以-并且应该-打开此功能,通过生物识别技术,移动的设备和/或FIDO安全密钥为用户提供更轻松的登录体验-并且比单独的密码具有更高的安全性。

FIDO联盟决定与万维网国际标准组织万维网联盟(W3C)合作,为整个Web平台标准化FIDO身份验证。这种标准化将通过支持该标准的Web浏览器和Web应用服务器的整个社区来发展FIDO生态系统。

它允许服务器与现在内置于设备中的强身份验证器集成,如Windows Hello或Apple的Touch ID。为网站创建私钥-公钥对(称为 凭据 )而不是密码。私钥安全地存储在用户的设备上;公钥和随机生成的凭据 ID 将发送到服务器进行存储。然后,服务器可以使用该公钥来证明用户的身份。

公钥不是秘密的,因为如果没有相应的私钥,它实际上是无用的。服务器未收到任何机密这一事实对用户和组织的安全性具有深远的影响。数据库对黑客不再那么有吸引力,因为公钥对他们没有用。

FIDO联盟成员公司于2015年将FIDO规范提交给W3C进行正式标准化。然后,他们在W3C内部工作,最终确定了API,这被称为Web身份验证或WebAuthn。WebAuthn于2019年3月被正式认可为W3C Web标准。如今WebAuthn是FIDO联盟FIDO2规范的一部分,FIDO联盟运行认证程序以确保合规性。

什么是公钥密码?

公钥密码学发明于20世纪70年代,是解决共享秘密问题的一种方法。它是现代互联网安全的支柱;例如,每次我们连接到HTTPS网站时,都会发生公钥交易。

公钥加密使用密钥对的概念;一个私钥由用户安全存储,一个公钥可以与服务器共享。这些“密钥”是彼此具有数学关系的长随机数。

2、FIDO2:客户端到验证器协议(CTAP)

FIDO2的另一个组件,客户端到认证者协议(CTAP)
,是WebAuthn的补充。它使外部身份验证器(如安全密钥或移动的电话)能够与支持WebAuthn的浏览器一起使用,并且还可以用作桌面应用程序和Web服务的身份验证器。

3、浏览器和平台

WebAuthn目前在Google Chrome
、Mozilla  Firefox、Microsoft Edge和Apple Safari
 Web浏览器以及Windows 10和Android
平台中得到支持。

浏览器兼容性如下:

4、Web身份验证API 基本流程

本节规范性地指定了用于创建和使用公钥凭据的API。基本的 这个想法是凭证属于用户并由WebAuthn Authenticator管理,WebAuthn依赖方通过客户端平台与WebAuthn Authenticator交互。 依赖方脚本可以(在用户同意的情况下)请求 浏览器以创建新凭证供信赖方将来使用。参见下图:

注册流程:

1、依赖方服务端开始准备用户信息,以及依赖方信息,这些属于公钥凭证创建相关内容选项

2、把对应信息在依赖房应用程序通过WebAuthnAPI,生成依赖方id,用户信息,依赖方信息,客户数据哈希,把这些信息发送身份验证器进行验证。

3、身份验证器开始验证用户信息,会生成新的密钥对,和对应认证。

4、身份验证器,把新的公钥和认证id等相关认证信息返回。

5、经浏览器和依赖方js应用返回客户JOSN数据,认证对象信息,这一步是验证器认证响应。

6、服务端进行验证。

脚本还可以请求用户的权限,以便使用现有凭据执行身份验证操作。参见下图1、依赖方服务端发起询问,需要公钥认证请求需要的参数。


 身份验证流程:

1、依赖方服务端发起询问,需要公钥认证请求需要的参数。

2、经依赖方JS应用,浏览器得到依赖方id,客户对应的哈希数据发送给身份验证器。

3、身份验证器开始验证用户信息,开始创建认证信息。

4、验证数据签名返回给浏览器。

5、经依赖方返回客户端的json数据,验证数据,签名等信息。

6、依赖方服务端

5、使用 WebAuthn API

5.1 注册WebAuthn凭据

在基于密码的用户注册流程中,服务器通常会向用户呈现一个表单,询问用户名和密码。密码将被发送到服务器进行存储。

在WebAuthn中,服务器必须提供将用户绑定到凭证(私钥-公钥对)的数据;该数据包括用户和组织(也称为“依赖方”)的标识符。然后,网站将使用Web身份验证API来提示用户创建新的密钥对。需要注意的是,我们需要从服务器随机生成的字符串作为挑战,以防止重放攻击。

navigator.credentials.create()

服务器将通过调用客户机上的navigator.credentials.create()开始创建新的凭据。

navigator.credentials.create({ publicKeyCredentialCreationOptions }).then(function (newCredentialInfo) {// 发送新的凭证信息到服务器进行验证和注册.}).catch(function (err) {// 没有可接受的身份验证者或用户拒绝同意。再做对应处理。});
publicKeyCredentialCreationOptions 对象包含许多必需和可选字段,服务器指定这些字段为用户创建新凭证。
const publicKeyCredentialCreationOptions  = {// 在服务器上生成的加密随机字节的缓冲区,并且需要防止“重放攻击”。challenge: bufferToBase64URLString(utf8StringToBuffer('sd')),// 服务器希望从认证器接收证明数据(direct)attestation: 'direct',// 这是一个对象数组,描述服务器可以接受哪些公钥类型// -7表示服务器接受使用SHA-256签名算法的椭圆曲线公钥pubKeyCredParams: [{alg: -7,type: 'public-key',},],// 依赖方的id,是浏览器当前域名的子集rp: {id: 'duosecurity.dev',name: 'duosecurity',},// 用户信息user: {id: '5678',displayName: 'username',name: 'username',},timeout: 1000,
// 希望限制在单个身份验证器上为同一帐户创建多个凭据的依赖方使用。excludeCredentials: [{id: 'C0VGlvYFratUdAV1iCw-ULpUW8E-exHPXQChBfyVeJZCMfjMFcwDmOFgoMUz39LoMtCJUBW8WPlLkGT6q8qTCg',type: 'public-key',transports: ['internal'],},],
};

返回的create()对象是一个包含公钥和用于验证注册事件的其他属性的对象。

PublicKeyCredential {// 新生成的凭证的ID;它将用于在认证用户时标识凭证。ID是一个base64编码的字符串id: 'ADSUllKQmbqdGtpu4sjseh4cg2TxSvrbcHDTBsv4NSSX9...',// 属性返回包含内部槽中的标识符rawId: ArrayBuffer(59),response: AuthenticatorAttestationResponse {// 这表示从浏览器传递到身份验证器的数据,以便将新凭据与服务器和浏览器相关联。// 验证器将其作为UTF-8字节数组提供。clientDataJSON: ArrayBuffer(121),// 此对象包含凭证公钥、可选的证明证书和其他用于验证注册事件的元数据。// 它是以CBOR编码的二进制数据。attestationObject: ArrayBuffer(306),},type: 'public-key'
}

解析clientDataJSON数据:

// decode the clientDataJSON into a utf-8 string
const utf8Decoder = new TextDecoder('utf-8');
const decodedClientData = utf8Decoder.decode(credential.response.clientDataJSON)// parse the string as an object
const clientDataObj = JSON.parse(decodedClientData);console.log(clientDataObj){// 这是传递到create()调用中的challenge是否相同challenge: "p5aV2uHXr0AOqUk7HQitvi-Ny1....",// 服务器必须验证这个“origin”字符串与应用程序的源代码匹配。origin: "https://webauthn.guide",// 服务器验证该字符串是不是"webauthn.create",否则可能执行不正确的操作。type: "webauthn.create",// 客户端和callerOrigin之间的令牌绑定状态tokenBinding: {  // 如果缺失,表示客户端不支持令牌的绑定// status存在,则该成员必须存在,// 并且必须是与依赖方通信时使用的令牌绑定ID的base64url编码id:'ASAFDQWE12312aasDASD......';// supported 支持令牌绑定,但与依赖方通信时未协商// present 与依赖方通信时使用了令牌绑定,id必须存在status: 'present' | 'supported'';}}

解析attestationObject:

// note: a CBOR decoder library is needed here.
const decodedAttestationObj = CBOR.decode(credential.response.attestationObject);console.log(decodedAttestationObject);
{// 这里的authenticator数据是一个字节数组,包含有关注册事件的元数据,// 以及我们将用于未来身份验证的公钥。authData: Uint8Array(196),fmt: "fido-u2f",  // 表示证明格式attStmt: {sig: Uint8Array(70),  // 签名x5c: Array(1),        // X.509 格式编码的证明证书。alg: -7 // -7 使用SHA-256对应的哈希算法的摘要},
}

解析验证器数据:

const {authData} = decodedAttestationObject;// get the length of the credential ID
const dataView = new DataView(new ArrayBuffer(2));
const idLenBytes = authData.slice(53, 55);
idLenBytes.forEach((value, index) => dataView.setUint8(index, value));
const credentialIdLength = dataView.getUint16();// get the credential ID
const credentialId = authData.slice(55, 55 + credentialIdLength);// get the public key object
const publicKeyBytes = authData.slice(55 + credentialIdLength);// the publicKeyBytes are encoded again as CBOR
const publicKeyObject = CBOR.decode(publicKeyBytes.buffer);
console.log(publicKeyObject){1: 2,3: -7,-1: 1,-2: Uint8Array(32) ...-3: Uint8Array(32) ...
}

authData是规范中描述的字节数组。解析它将涉及从数组中切片字节并将它们转换为可用的对象。

最后检索到的publicKeyObject是一个以COSE标准编码的对象,这是一种描述凭证公钥和使用它所需的元数据的简洁方式。

1: 1字段描述密钥类型。值2表示关键点类型为椭圆曲线格式。

3: 3字段描述用于生成身份验证签名的算法。-7值指示此身份验证器将使用ES256。

-1: -1字段描述此键的“曲线类型”。值1指示该键使用“P-256”曲线。

-2: -2字段描述此公钥的x坐标。

-3: -3字段描述此公钥的y坐标。

5.2使用WebAuthn凭据进行身份验证

注册完成后,现在可以对用户进行身份验证。在认证期间,创建断言,这是用户拥有私钥的证明。此断言包含使用私钥创建的签名。服务器使用在注册期间检索到的公钥来验证此签名。

navigator.credentials.get() 

在身份验证过程中,用户证明他们拥有他们注册的私钥。 它们通过提供一个assertion来实现,是在客户端上调用navigator.credentials.get()生成的。这将检索在注册期间生成的包含签名的凭证。

const credential = await navigator.credentials.get({publicKey: publicKeyCredentialRequestOptions
});

publicKeyCredentialCreationOptions对象包含许多必需和可选字段,服务器指定这些字段为用户创建新凭证。

const publicKeyCredentialRequestOptions = {challenge: Uint8Array.from(randomStringFromServer, c => c.charCodeAt(0)),// 这个数组告诉浏览器服务器希望用户使用哪些凭据进行身份验证。allowCredentials: [{id: Uint8Array.from(credentialId, c => c.charCodeAt(0)),type: 'public-key',transports: ['usb', 'ble', 'nfc'], // 传输方式 USB、蓝牙,NFC}],timeout: 60000,
}const assertion = await navigator.credentials.get({publicKey: publicKeyCredentialRequestOptions
});

assertion调用返回的get()对象再次是PublicKeyCredential对象。它与我们在注册时收到的对象略有不同;特别是它包括signature成员,并且不包括公钥。

console.log(assertion);PublicKeyCredential {id: 'ADSUllKQmbqdGtpu4sjseh4cg2TxSvrbcHDTBsv4NSSX9...',rawId: ArrayBuffer(59),response: AuthenticatorAssertionResponse {// 认证器数据类似于注册期间接收的authData,但值得注意的是,这里不包括公钥。authenticatorData: ArrayBuffer(191),  clientDataJSON: ArrayBuffer(118), // 用作签名的一些数据signature: ArrayBuffer(70), // 私钥签名userHandle: ArrayBuffer(10),},type: 'public-key'
}

解析和验证身份验证数据:

获得认证后,将其发送到服务器进行验证。在验证数据完全有效之后,使用在注册期间存储在数据库中的公钥来验证签名。

const storedCredential = await getCredentialFromDatabase(userHandle, credentialId);const signedData = (authenticatorDataBytes +hashedClientDataJSON);const signatureIsValid = storedCredential.publicKey.verify(signature, signedData);if (signatureIsValid) {return "签名校验成功! 												

Web身份验证(WebAuthn)相关推荐

  1. Google登录强制启用二次身份验证与FIDO解决方案

    据外媒 mspoweruser 报道,谷歌宣布将从 2021年11月9日起将强制要求对 Google 账户进行两步验证登录,以保证安全性.谷歌表示,保护用户账户防止密码泄露造成损失的最佳方法是开启两步 ...

  2. 基于表单的网站身份验证的权威指南[关闭]

    基于表单的网站身份验证 我们认为Stack Overflow不仅应该是非常具体的技术问题的资源,而且还应该是关于如何解决常见问题变化的一般指导原则. "基于表单的网站身份验证"应该 ...

  3. 无密码身份验证:安全、简单且部署快速

    Passwordless authentication: Secure, simple, and fast to deploy [编者按]本文作者为 Florian Heinemann 与 Rober ...

  4. iis 网站添加 身份验证_在10分钟内将身份验证添加到任何网页

    iis 网站添加 身份验证 This content is sponsored via Syndicate Ads 该内容是通过辛迪加广告 赞助的 Adding authentication to w ...

  5. 关于IIS身份验证的方法

    一.身份验证方法 注意:使用下列某些身份验证方法时,您必须使用已用 NTFS 文件系统格式化的驱动器,因为 NTFS 格式化的驱动器的安全级别最高. IIS 支持以下几种 Web 身份验证方法. 1. ...

  6. 六种主流身份验证方法

    新钛云服已为您服务1465天 身份验证是数据安全.网络安全和应用安全的第一步.而身份和访问管理(IAM)的目标是确保正确的人能够以正确方式访问正确的资源,未经授权的用户则会被拒之门外. 在选择身份验证 ...

  7. 火狐和chrome_Firefox,Chrome和Edge都将支持WebAuthn的硬件两因素身份验证

    火狐和chrome Logging into Gmail or Facebook could soon mean plugging in a USB device, potentially makin ...

  8. 【WEB API项目实战干货系列】- API登录与身份验证(三)

    上一篇: [WEB API项目实战干货系列]- 接口文档与在线测试(二) 这篇我们主要来介绍我们如何在API项目中完成API的登录及身份认证. 所以这篇会分为两部分, 登录API, API身份验证. ...

  9. 如何实现RESTful Web API的身份验证

    最近想拿一个小项目来试水RESTful Web API,项目只有几个调用,比较简单,但同样需要身份验证,如果是传统的网站的话,那不用说,肯定是用户名+密码在登录页获得登录Token,并把登录Token ...

最新文章

  1. SharePoint 2013 调用WCF服务简单示例
  2. 电话号码 【trie树】
  3. 2019年10个最受欢迎的JavaScript动画库!
  4. OpenCV形态学运算
  5. 论证通过!依托顶尖985大学,争创国家实验室!
  6. Python机器学习:梯度下降法004实现线性回归中的梯度下降法
  7. Whl自助搜索下载器
  8. Atitit 多元化战略的艺术 attilax著 目录 1. 多元化战略 1 2. 常见的多元化 1 2.1.  企业多元化战略研究 1 3. 多元化优缺点 2 3.1. 多元化的消极意义 3
  9. 天正如何转为t3_天正插件 t3 天正文件转T3格式CAD图
  10. 开题报告(3.研究的思路、过程与方法)
  11. OpenCASCADE:Linux平台上构建OCCT使用的第三方库
  12. NTFS文件系统详解 之 文件定位
  13. ps -ef|grep详解
  14. 网络的性能指标:带宽和延迟
  15. 英语国际音标之元音发音技巧
  16. OS模块--批量修改文件名字(一)创建和修改文件路径
  17. 帝国CMS插件自动采集发布文章插件
  18. 禁U盘不禁USB设备
  19. 哈工程自考计算机应用数学,自考本科计算机应用数学 01332
  20. 百度api使用方法(java、js)

热门文章

  1. Android调取拍照和获取拍照后的照片
  2. Koa2实现电影微信公众号前后端开发学习视频
  3. 阿里云RDS数据库备份恢复【取证】教程
  4. ad怎么修改栅格_AD软件的3种栅格设置详解
  5. 微信小程序腾讯服务器地址要购买吗,微信小程序JavaScript SDK
  6. 数学三次危机(三)“希帕索斯悖论”或“毕达哥拉斯悖论”
  7. echarts饼图直观显示数值最实用的方式
  8. 台式计算机电源线 规格,台式电脑电源线怎么接
  9. IR-61|1895075-34-9|七甲川吲哚类花菁染料near-infrared fluorophore
  10. 论文解读--Multi-class Road User Detection with 3+1D Radar in the View-of-Delft Dataset