开通VIP,畅享免费电子书等14项超值服
首页
好书
留言交流
下载APP
联系客服
2024.11.21湖北
本文介绍作为Windows的一部分随附的WindowsHello技术,并讨论了开发人员如何实现这项技术来保护其Windows应用和后端服务。它重点介绍了这些技术的特定功能,这些技术有助于缓解使用传统凭据产生的威胁,并提供有关在Windows客户端推出过程中设计和部署这些技术的指导。
备注
密码的最大风险在于太过简单:攻击者可以轻松窃取密码。输入、处理或存储密码的每个位置都容易受到攻击。例如,攻击者可以通过窃听网络流量到应用程序服务器、在应用程序或设备上植入恶意软件、在设备上记录用户击键或监视查看用户类型的字符,从身份验证服务器窃取密码或哈希集合。这些只是最常见的攻击方法。
使用电子邮件地址作为用户名的常见方法使问题变得更糟。成功从受攻击的系统恢复用户名-密码对的攻击者可以在其他系统上尝试同一对。这种策略通常很出人意料地工作,使攻击者能够从被入侵的系统跳入其他系统。使用电子邮件地址作为用户名会导致本指南稍后将探讨的其他问题。
解决密码构成的问题很棘手。单独收紧密码策略不会这样做;用户只能回收、共享或记下密码。尽管用户教育对于身份验证安全性至关重要,但单独教育并不能消除该问题。
WindowsHello通过验证现有凭据以及创建生物识别或基于PIN的用户手势保护的设备特定凭据,将密码替换为强双因素身份验证(2FA)。
WindowsHello验证器称为Hello。Hello对单个设备和特定用户的组合是唯一的。它不会在设备之间漫游,不会与服务器或调用应用共享,并且无法从设备轻松提取。如果多个用户共享设备,则每个用户都需要设置自己的帐户。每个帐户都会获得该设备的唯一Hello。可以将Hello视为可用于解锁存储凭据(或释放)的令牌。Hello本身不会向应用或服务进行身份验证,但它会释放可以的凭据。换句话说,Hello不是用户凭据,但它是身份验证过程的第二个因素。
WindowsHello为设备识别单个用户提供了一种强大的方法,它解决了用户与请求的服务或数据项之间的第一部分路径。在设备识别出用户之后,在确定是否授予对所请求资源的访问权限之前,它仍然必须对用户进行身份验证。WindowsHello提供完全集成到Windows中的强2FA,并将可重用的密码替换为特定设备的组合以及生物识别手势或PIN。
不过,WindowsHello不仅仅是传统2FA系统的替代。从概念上讲,它类似于智能卡:身份验证是使用加密基元而不是字符串比较执行的,并且用户的密钥材料在防篡改硬件内是安全的。WindowsHello不需要智能卡部署所需的额外基础结构组件。特别是,如果当前没有公钥基础结构(PKI),则不需要公钥基础结构(PKI)来管理证书。WindowsHello结合了智能卡的主要优势(虚拟智能卡的部署灵活性和物理智能卡的可靠安全性),没有任何缺点。
若要在设备上启用WindowsHello,用户必须具有其MicrosoftEntraID帐户或在Windows设置中连接的Microsoft帐户。
每当生成密钥材料时,都必须保护它免受攻击。执行此操作的最可靠方法是通过专用硬件。使用硬件安全模块(HSM)为安全关键型应用程序生成、存储和处理密钥有着悠久的历史。智能卡是特殊类型的HSM,符合受信任的计算组TPM标准的设备也是如此。无论可能,WindowsHello实现都利用载入TPM硬件来生成、存储和处理密钥。但是,WindowsHello和WindowsHelloforWork不需要载入TPM。
只要可行,Microsoft建议使用TPM硬件。TPM可防范各种已知和潜在攻击,包括PIN暴力攻击。TPM在帐户锁定后还提供额外的保护层。当TPM锁定密钥材料时,用户必须重置PIN。重置PIN意味着将删除使用旧密钥材料加密的所有密钥和证书。
当用户想要访问受保护的密钥材料时,身份验证过程从用户输入PIN或生物识别手势解锁设备开始,此过程有时称为“释放密钥”。
应用程序永远不能使用来自另一个应用程序的密钥,也不能有人使用其他用户的密钥。这些密钥用于对发送到标识提供者或IDP的请求进行签名,以寻求对指定资源的访问权限。应用程序可以使用特定API请求需要特定操作密钥材料的操作。通过这些API进行访问确实需要通过用户手势进行显式验证,并且密钥材料不会向请求应用程序公开。相反,应用程序会要求执行特定操作,例如对一段数据进行签名,而WindowsHello层会处理实际工作并返回结果。
现在,我们已经基本了解了WindowsHello的工作原理,让我们看看如何在自己的应用程序中实现它们。
在本部分中,我们将从没有现有身份验证系统的绿地方案开始,并介绍如何实现WindowsHello。
下一部分介绍如何从现有用户名/密码系统迁移。但是,即使该部分更符合你的兴趣,你可能希望了解此部分,以便基本了解过程和所需的代码。
我们从一项全新的服务开始,该服务将使用WindowsHello,以及一个准备好在新设备上注册的假设新用户。
第一步是验证用户是否能够使用WindowsHello。应用会验证用户设置和计算机功能,以确保它可以创建用户ID密钥。如果应用确定用户尚未启用WindowsHello,它会提示用户在使用该应用之前进行此设置。
若要启用WindowsHello,用户只需在Windows设置中设置PIN,除非用户在开箱即用体验(OOBE)期间对其进行设置。
以下代码行显示了一种检查用户是否已为WindowsHello设置的简单方法。
varkeyCredentialAvailable=awaitKeyCredentialManager.IsSupportedAsync();if(!keyCredentialAvailable){//Userdidn'tsetupPINyetreturn;}下一步是要求用户提供注册服务的信息。可以选择请求用户输入名字、姓氏、电子邮件地址和唯一用户名。可以使用电子邮件地址作为唯一标识符;它由你决定。
在此方案中,我们使用电子邮件地址作为用户的唯一标识符。用户注册后,应考虑发送验证电子邮件以确保地址有效。这为你提供了一种机制来重置帐户(如有必要)。
在设备上创建密钥对和证明信息后,公钥、可选证明信息以及唯一标识符(如电子邮件地址)需要发送到后端注册服务并存储在后端中。
若要允许用户访问多个设备上的应用,后端服务需要能够存储同一用户的多个密钥。由于每个设备的每个密钥都是唯一的,因此我们将存储所有连接到同一用户的密钥。设备标识符用于在对用户进行身份验证时帮助优化服务器部件。我们将在下一部分中更详细地讨论这一点。
在后端存储此信息的示例数据库架构可能如下所示:
注册逻辑可能如下所示:
当它收到生成的RSA密钥、证明语句和AIK证书时,服务器将验证以下条件:
在系统中注册用户后,他或她可以使用该应用。根据方案,可以要求用户进行身份验证,然后才能开始使用应用,或者只是要求用户在开始使用后端服务后进行身份验证。
以下代码行将强制用户输入其凭据。
UserConsentVerificationResultconsentResult=awaitUserConsentVerifier.RequestVerificationAsync("userMessage");if(consentResult.Equals(UserConsentVerificationResult.Verified)){//continue}还可以使用来自服务器的质询响应机制,这要求用户输入其PIN代码或生物识别凭据。这取决于你作为开发人员需要实现的方案。以下部分介绍了此机制。
当应用尝试访问受保护的后端服务时,该服务会向应用发送质询。应用使用用户的私钥对质询进行签名,并将其发送回服务器。由于服务器存储了该用户的公钥,因此它使用标准加密API来确保消息确实使用正确的私钥进行签名。在客户端上,签名由WindowsHelloAPI完成;开发人员将永远无法访问任何用户的私钥。
除了检查密钥之外,服务还可以检查密钥证明,并判断在设备上存储密钥的方式是否有任何限制。例如,当设备使用TPM保护密钥时,它比在没有TPM的情况下存储密钥的设备更安全。例如,后端逻辑可以决定,仅当不使用TPM来降低风险时,才允许用户转移一定金额。
证明仅适用于具有版本2.0或更高版本的TPM芯片的设备。因此,需要考虑到此信息在每台设备上可能不可用。
客户端工作流可能如下图所示:
当应用在后端调用服务时,服务器会发送质询。质询使用以下代码进行签名:
此序列图中显示了基本质询-响应流:
获得CNGBlob后,需要针对用户的公钥验证已签名的质询。由于每个人都使用自己的系统或后端技术,因此无法实现此逻辑。我们将SHA256用作SignaturePadding的哈希算法和Pkcs1,因此请确保在验证来自客户端的签名响应时使用。同样,请参考示例,了解在.NET4.6中的服务器上执行此操作的方法,但一般情况下,示例将如下所示:
完整的代码可能如下所示:
用户通常现在安装了相同应用的多个设备。将WindowsHello与多个设备配合使用时,这如何工作?
使用WindowsHello时,每个设备都将创建唯一的私钥和公钥集。这意味着,如果希望用户能够使用多个设备,后端必须能够存储此用户的多个公钥。有关表结构示例,请参阅“注册新用户”部分中的数据库关系图。
注册另一台设备与首次注册用户几乎相同。你仍然需要确保注册此新设备的用户确实是他们声称的用户。可以使用今天使用的任何双因素身份验证机制来实现此目的。可通过多种方式安全地实现此目的。这一切都取决于你的方案。
注册新设备的代码与首次注册用户(从应用内部)完全相同。
varkeyCreationResult=awaitKeyCredentialManager.RequestCreateAsync(AccountId,KeyCredentialCreationOption.ReplaceExisting);为了方便用户识别已注册的设备,可以选择将设备名称或其他标识符作为注册的一部分发送。例如,如果要在后端实现服务,用户可以在设备丢失时注销设备,则这也很有用。
除了支持单个帐户的多个设备外,在单个应用中也经常支持多个帐户。例如,你可能从应用内连接到多个Twitter帐户。使用WindowsHello,可以创建多个密钥对并支持应用中的多个帐户。
执行此操作的一种方法是保留隔离存储上一部分中所述的用户名或唯一标识符。因此,每次创建新帐户时,都会将帐户ID存储在独立存储中。
varopenKeyResult=awaitKeyCredentialManager.OpenAsync(AccountId);流的其余部分与前面所述相同。为了清楚起见,所有这些帐户都受同一PIN或生物识别手势的保护,因为在此方案中,它们正在使用同一Windows帐户的单个设备上。
在本简短部分中,我们将解决使用存储用户名和密码的数据库的现有打包应用和后端系统。这些应用在应用启动时从用户收集凭据,并在后端系统返回身份验证质询时使用这些凭据。
在这里,我们将介绍需要更改或替换哪些部分才能使WindowsHello正常工作。
我们已经在前面的部分中介绍了大多数技术。将WindowsHello添加到现有系统涉及在代码的注册和身份验证部分中添加几个不同的流。
varkeyCredentialAvailable=awaitKeyCredentialManager.IsSupportedAsync();UI可能如下所示:
作为开发人员,可以使用本指南设计和部署这些技术,轻松将安全身份验证添加到打包的Windows应用推出,以保护应用和后端服务。所需的代码最少且易于理解。Windows处理繁重的工作。
灵活的实现选项允许WindowsHello替换或与现有身份验证系统一起工作。部署体验是无痛和经济的。无需其他基础结构即可部署Windows安全性。借助内置于操作系统的MicrosoftHello,Windows为新式开发人员面临的身份验证问题提供了最安全的解决方案。