证书要求和枚举
本主题面向 IT 专业人员和智能卡开发人员介绍了如何管理和使用证书进行智能卡登录。
插入智能卡时,将执行以下步骤。
注意
除非另有说明,否则所有操作都以静默方式执行, (CRYPT_SILENT 传递给 CryptAcquireContext) 。
智能卡资源管理器数据库 (CSP) 搜索智能卡的加密服务提供程序。
使用智能卡读卡器名称构造限定的容器名称,并将其传递给 CSP。 格式为
\\.<Reader name>\
调用 CryptAcquireContext 以检索默认容器的上下文。 如果发生故障,智能卡将无法登录智能卡。
通过将 PP_CONTAINER 参数与 CryptGetProvParam 一起使用来检索容器的名称。
使用步骤 3 中获取的上下文,向 CSP 查询 PP_USER_CERTSTORE 参数。 有关详细信息,请参阅 智能卡体系结构。 如果操作成功,则返回证书存储的名称,并且程序流将跳到步骤 8。
如果步骤 5 中的操作失败,则会查询步骤 3 中的默认容器上下文以获取AT_KEYEXCHANGE键。
然后使用KP_CERTIFICATE从密钥上下文中查询证书。 证书将添加到内存中的证书存储中。
对于步骤 5 或步骤 7 中证书存储中的每个证书,将执行以下检查:
- 证书必须有效,具体取决于计算机系统时钟 (未过期或在未来日期)
- 证书不得位于容器的AT_SIGNATURE部分
- 证书必须具有有效的用户主体名称 (UPN)
- 证书必须具有数字签名密钥用法
- 证书必须具有智能卡登录 EKU
满足这些要求的任何证书都显示给用户,其中包含证书的 UPN (、电子邮件地址或主题,具体取决于证书扩展)
然后,该过程选择一个证书,并输入 PIN
LogonUI.exe 打包信息并将其发送到 Lsass.exe 以处理登录尝试
如果成功,
LogonUI.exe
则关闭。 这会导致释放步骤 3 中获取的上下文
Windows 中的智能卡登录流
身份验证过程中的大多数问题都是由于会话行为更改而发生的。 发生更改时,本地安全机构 (LSA) 不会重新获取会话上下文;它依赖于加密服务提供程序来处理会话更改。
可以为证书的 subjectAltName
“ (SAN) ”字段中不包含 UPN 的客户端证书启用登录,该登录支持多种证书,并支持同一张卡上的多个登录证书。
默认情况下,对同一张卡上的多个证书的支持处于启用状态。 必须通过组策略启用新的证书类型。
如果启用 “允许登录凭据提供程序的签名密钥有效 ”策略,则会在登录屏幕上列出智能卡上具有仅签名密钥的任何证书。 这允许用户选择其登录体验。 如果禁用或未配置策略,则基于智能卡签名密钥的证书不会在登录屏幕上列出。
下图演示了在受支持的 Windows 版本中智能卡登录的工作原理。
智能卡登录流
下面是在智能卡登录期间执行的步骤:
Winlogon 请求登录 UI 凭据信息
异步,智能卡资源管理器启动,智能卡凭据提供程序执行以下操作:
- 获取 (已知凭据列表的凭据信息,如果没有凭据,则获取 Windows 检测到的智能卡读取器信息)
- 使用 WinSCard API) 获取 (智能卡读卡器的列表以及每个读卡器中插入的智能卡的列表
- 枚举每张卡,验证是否存在由组策略控制的登录证书。 如果证书存在,智能卡凭据提供程序会将其复制到计算机或终端上的临时安全缓存中
注意
为具有使用者名称或使用者密钥标识符的证书创建智能卡缓存条目。 如果证书具有使用者名称,则会使用基于使用者名称和证书颁发者的索引来存储该证书。 如果使用同一使用者名称和证书颁发者的另一个证书,它将替换现有的缓存条目。 此行为的更改允许在证书没有使用者名称的情况下使用基于使用者密钥标识符和证书颁发者的索引创建缓存的条件。 如果另一个证书具有相同的使用者密钥标识符和证书颁发者,则会替换缓存条目。 如果证书既没有使用者名称也没有使用者密钥标识符,则不会创建缓存条目。
- 通知登录 UI 具有新凭据
登录 UI 从智能卡凭据提供程序请求新凭据。 作为响应,智能卡凭据提供程序向登录 UI 提供每个登录证书,并显示相应的登录磁贴。 用户选择基于智能卡的登录证书磁贴,Windows 将显示 PIN 对话框
用户输入 PIN,然后按 Enter。 智能卡凭据提供程序加密 PIN
驻留在 LogonUI 系统中的凭据提供程序收集 PIN。 作为在智能卡凭据提供程序中打包凭据的一部分,数据打包在KERB_CERTIFICATE_LOGON结构中。 KERB_CERTIFICATE_LOGON结构的主要内容是智能卡 PIN、CSP 数据 (如读取器名称和容器名称) 、用户名和域名。 如果登录域不在同一林中,则用户名是必需的,因为它允许将证书映射到多个用户帐户
凭据提供程序包装数据 (,例如加密的 PIN、容器名称、读取器名称和卡片密钥规范) ,并将其发送回 LogonUI
Winlogon 使用 LSALogonUser 中的用户信息将 LogonUI 中的数据呈现给 LSA
LSA (Kerberos SSP) 调用 Kerberos 身份验证包来创建 Kerberos 身份验证服务请求 (KRB_AS_REQ) ,其中包含 RFC 4556: Kerberos 中初始身份验证的公钥加密) ) 中指定的预身份验证器 ( (PKINIT) ) 。
如果使用使用数字签名的证书执行身份验证,则预身份验证数据由用户的公用证书和使用相应的私钥进行数字签名的证书组成。
如果使用使用密钥加密的证书执行身份验证,则预身份验证数据由用户的公用证书和使用相应私钥加密的证书组成。
若要根据 RFC 4556) 以数字方式 (对请求进行签名,请调用相应的 CSP 执行私钥操作。 由于在这种情况下,私钥存储在智能卡中,因此调用智能卡子系统,并完成必要的操作。 结果将发回到 Kerberos 安全支持提供程序 (SSP) 。
Kerberos SSP 根据 RFC 4556) 将票证授予票证 (TGT) (的身份验证请求发送到在域控制器上运行的密钥分发中心 (KDC) 服务。
如 客户端证书要求和映射中所述,KDC 在 Active Directory 域服务 (AD DS) 中找到用户的帐户对象,并使用用户的证书验证签名。
KDC (时间、路径和吊销状态) 验证用户的证书,以确保证书来自受信任的源。 KDC 使用 CryptoAPI 生成从用户证书到根证书颁发机构的证书路径, (位于域控制器根存储中的 CA) 证书。 然后,KDC 使用 CryptoAPI 验证预身份验证数据字段中包含的已签名验证器的数字签名。 域控制器验证签名并使用用户证书中的公钥来证明请求源自与公钥对应的私钥的所有者。 KDC 还会验证颁发者是否受信任并显示在 NTAUTH 证书存储中。
KDC 服务从 AD DS 检索用户帐户信息。 KDC 基于从 AD DS 检索的用户帐户信息构造 TGT。 TGT 的授权数据字段包括用户的安全标识符 (SID) 、用户所属的通用域组和全局域组的 SID,以及多域环境中的 () 用户所属的任何通用组的 SID。
域控制器将 TGT 作为KRB_AS_REP响应的一部分返回给客户端。
注意
KRB_AS_REP数据包包括:
- 特权属性证书 (PAC)
- 用户的 SID
- 用户所属的任何组的 SID
- (TGS) 请求票证授予服务
- 预身份验证数据
TGT 使用 KDC 的主密钥进行加密,会话密钥使用临时密钥进行加密。 此临时密钥基于 RFC 4556 派生。 使用 CryptoAPI 解密临时密钥。 在解密过程中,如果私钥位于智能卡上,则会使用指定的 CSP 来提取与用户公钥对应的证书,从而调用智能卡子系统。 (证书的编程调用包括 CryptAcquireContext、具有 PIN 的 CryptSetProvParam、CryptgetUserKey 和 CryptGetKeyParam.) 获取临时密钥后,Kerberos SSP 将解密会话密钥。
客户端验证 KDC 的回复 (时间、路径和吊销状态) 。 它首先通过构建从 KDC 证书到受信任的根 CA 的认证路径来验证 KDC 的签名,然后使用 KDC 的公钥来验证答复签名。
获取 TGT 后,客户端会获取用于登录到本地计算机的服务票证。
成功后,LSA 会存储票证并将成功消息返回给 LSALogonUser。 发出此成功消息后,选择并设置设备的用户配置文件,实例化组策略刷新,并执行其他操作。
加载用户配置文件后,认证传播服务 (CertPropSvc) 检测到此事件,从智能卡 (读取证书,包括根证书) ,然后将其填充到用户的证书存储 (MYSTORE)
CSP 到智能卡资源管理器的通信发生在 LRPC 通道上。
身份验证成功后,证书传播服务 (CertPropSvc) 异步传播到用户的存储区。
删除卡后,将删除临时安全缓存存储中的证书。 证书不再可用于登录,但它们仍保留在用户的证书存储中。
注意
在本地安全帐户数据库或 AD DS 中创建用户帐户或组帐户时,将为每个用户或组创建 SID。 SID 永远不会更改,即使用户或组帐户已重命名。
有关 Kerberos 协议的详细信息,请参阅 Microsoft Kerberos。
默认情况下,KDC 会验证客户端的证书是否包含智能卡客户端身份验证 EKU szOID_KP_SMARTCARD_LOGON。 但是,如果启用, 则允许没有扩展密钥使用证书的证书属性 组策略设置允许 KDC 不需要 SC-LOGON EKU。 基于公钥的帐户映射不需要 SC-LOGON EKU。
KDC 证书
Active Directory 证书服务提供三种类型的证书模板:
- 域控制器
- 域控制器身份验证
- Kerberos 身份验证
根据域控制器的配置,其中一种类型的证书作为AS_REP数据包的一部分发送。
客户端证书要求和映射
证书要求按 Windows 操作系统的版本列出。 证书映射描述如何将证书中的信息映射到用户帐户。
证书要求
组件 | 要求 |
---|---|
CRL 分发点位置 | 不需要 |
密钥用法 | 数字签名 |
基本约束 | 不需要 |
扩展密钥用法 (EKU) | 不需要智能卡登录对象标识符。 注意 如果存在 EKU,则它必须包含智能卡登录 EKU。 没有 EKU 的证书可用于登录。 |
使用者可选名称 | 智能卡登录不需要电子邮件 ID。 |
主题 | 不需要 |
密钥交换 (AT_KEYEXCHANGE 字段) | 如果启用了组策略设置,则智能卡登录证书不需要。 (默认情况下,不会启用组策略设置。) |
CRL | 不需要 |
UPN | 不需要 |
注释 | 可以启用对智能卡凭据提供程序可见的任何证书。 |
客户端证书映射
证书映射基于证书的 subjectAltName (SAN) 字段中包含的 UPN。 还支持不包含 SAN 字段中信息的客户端证书。
SSL/TLS 可以映射没有 SAN 的证书,并且映射通过使用客户端帐户上的 AltSecID 属性来完成。 SSL/TLS 客户端身份验证使用的 X509 AltSecID 格式为“X509: <Issuer Name>
<Subject Name
”。
<Issuer Name>
和 <Subject Name>
取自客户端证书,将“\r”和“\n”替换为“,”。
证书吊销列表分发点
“使用者可选名称”字段中的 UPN
“主题”和“颁发者”字段
除其他六种映射方法外,KDC 还支持此帐户映射。 下图演示 KDC 使用的用户帐户映射逻辑流。
用于登录的高级证书处理流
将分析证书对象以查找要执行用户帐户映射的内容。
- 当用户名随证书一起提供时,该用户名用于查找帐户对象。 此操作速度最快,因为发生字符串匹配
- 仅提供证书对象时,将执行多个操作来查找用户名,将用户名映射到帐户对象
- 如果没有可用于身份验证的域信息,则默认使用本地域。 如果要使用任何其他域进行查找,则应提供域名提示来执行映射和绑定
无法基于泛型属性进行映射,因为没有泛型 API 可以从证书中检索属性。 目前,成功定位帐户的第一种方法会停止搜索。 但是,当客户端未通过映射提示提供客户端名称时,如果两种方法将同一证书映射到不同的用户帐户,则会发生配置错误。
下图演示了通过查看证书中的各种条目来映射用于登录目录中的用户帐户的过程。
证书处理逻辑
NT_AUTH策略最好在 CertVerifyCertificateChainPolicy 函数的 CERT_CHAIN_POLICY_NT_AUTH 参数部分进行说明。 有关详细信息,请参阅 CertVerifyCertificateChainPolicy。
使用一个证书登录到多个帐户的单个用户的智能卡登录
单个用户证书可以映射到多个帐户。 例如,用户可能能够登录到用户帐户,还可以以域管理员身份登录。 映射通过使用基于客户端帐户中的属性构造的 AltSecID 来完成。 有关如何评估此映射的信息,请参阅 客户端证书要求和映射。
注意
由于每个帐户都有不同的用户名,因此建议启用“ 允许用户名提示 组策略”设置 (X509HintsNeeded 注册表项) ,以提供允许用户输入其用户名和域信息的可选字段进行登录。
根据证书中提供的信息,登录条件为:
- 如果证书中不存在 UPN:
- 如果具有一个证书的单个用户需要登录到不同的帐户,则登录可以发生在本地林或其他林中
- 如果映射不是唯一 ((例如,如果多个用户映射到同一证书),则必须提供提示)
- 如果证书中存在 UPN:
- 证书无法映射到同一林中的多个用户
- 证书可以映射到不同林中的多个用户。 用户若要登录到其他林,必须向用户提供 X509 提示
将多个用户的智能卡登录到单个帐户
一组用户可能会登录到单个帐户 (例如管理员帐户) 。 对于该帐户,会映射用户证书,以便为它们启用登录。
多个不同的证书可以映射到单个帐户。 要使此功能正常工作,证书不能有 UPN。
例如,如果 Certificate1 具有 CN=CNName1,Certificate2 具有 CN=User1,Certificate3 具有 CN=User2,则可以通过使用 Active Directory 用户和计算机名称映射将这些证书的 AltSecID 映射到单个帐户。
跨林的智能卡登录
若要跨林进行帐户映射,尤其是在证书上没有足够的可用信息的情况下,用户可能会以用户名(如 domain\user)或完全限定的 UPN(如 user@contoso.com
)的形式输入提示。
注意
若要在智能卡登录期间显示提示字段,必须在客户端上启用 “允许用户名提示 组策略”设置 (X509HintsNeededed 注册表项) 。
对 PKINIT 的 OCSP 支持
联机证书状态协议 (OCSP) (RFC 2560 中定义)使应用程序能够及时获取有关证书吊销状态的信息。 由于 OCSP 响应较小且绑定良好,受约束的客户端可能需要使用 OCSP 检查 KDC 上 Kerberos 证书的有效性,以避免传输大型 CRL,并节省受约束网络上的带宽。 有关 CRL 注册表项的信息,请参阅 智能卡组策略和注册表设置。
Windows 中的 KDC 尝试获取 OCSP 响应并在可用时使用它们。 无法禁用此行为。 OCSP 的 CryptoAPI 缓存 OCSP 响应和响应状态。 KDC 仅支持签名者证书的 OCSP 响应。
Windows 客户端计算机尝试请求 OCSP 响应,并在回复可用时使用它们。 无法禁用此行为。
用于域登录的智能卡根证书要求
若要在基于智能卡的域中登录,智能卡证书必须满足以下条件:
- 智能卡上的 KDC 根证书必须在其证书中列出 HTTP CRL 分发点
- 智能卡登录证书必须在其证书中列出 HTTP CRL 分发点
- 即使 CRL 分发点为空,CRL 分发点也必须发布有效的 CRL 和增量 CRL(如果适用)
- 智能卡证书必须包含以下项之一:
- 一个使用者字段,其中包含可分辨名称中的 DNS 域名。 否则,解析相应域会失败,因此远程桌面服务和使用智能卡的域登录失败
- 域名解析为实际域的 UPN。 例如,如果域名为
Engineering.Corp.Contoso
,则 UPN 为username@engineering.corp.contoso.com
。 如果省略域名的任何部分,则 Kerberos 客户端找不到相应的域
若要允许智能卡登录到这些版本中的域,请执行以下操作:
- 在 CA 上启用 HTTP CRL 分发点
- 重启 CA
- 重新颁发 KDC 证书
- 颁发或重新颁发智能卡登录证书
- 将更新的根证书传播到要用于域登录的智能卡
解决方法是启用“ 允许用户名提示 组策略”设置 (X509HintsNeeded 注册表项) ,从而允许用户在凭据用户界面中提供用于域登录的提示。
如果客户端计算机未加入域或已加入其他域,则客户端计算机只能通过查看证书上的可分辨名称(而不是 UPN)来解析服务器域。 要使此方案正常工作,证书需要完整的使用者(包括 DC=<DomainControllerName>
)才能进行域名解析。
若要在智能卡上为当前加入的域部署根证书,可以使用以下命令:
certutil.exe -scroots update
有关命令行工具的此选项的详细信息,请参阅 -SCRoots。