启动与系统组件

用于在 msDS-KeyCredentialLink 属性中查看证书信息的脚本 - Windows Server

· 52CE 我爱测

可以在 PowerShell 中查看 msDS-KeyCredentialLink 属性。 但是,该值采用二进制格式,无法读取。 此脚本可帮助你执行以下作: - 枚举在 msDS-KeyCredentialLink 中具有非 null 值的 Active Directory(AD)中的所有用户。 - 提取 msDS-KeyCredentialLink 中保存的每个证书的 bcrypt-sha256 密钥 ID 哈希,并将其保存到文件中。 然后,可以使用保存

可以在 PowerShell 中查看 msDS-KeyCredentialLink 属性。 但是,该值采用二进制格式,无法读取。 此脚本可帮助你执行以下作:

  • 枚举在 msDS-KeyCredentialLink** 中**具有非 null 值的 Active Directory(AD)中的所有用户。
  • 提取 msDS-KeyCredentialLink** 中**保存的每个证书的 bcrypt-sha256 密钥 ID 哈希,并将其保存到文件中。

然后,可以使用保存的信息来检查预期值是否位于用户的 msDS-KeyCredentialLink 属性中。

Script

重要

此示例脚本在任何Microsoft标准支持计划或服务下都不受支持。

示例脚本按原样提供,没有任何保证。 Microsoft进一步否认所有默示担保,包括不限于适销性或针对特定用途的适用性的任何默示担保。

示例脚本和文档的使用或性能导致的整个风险依然存在。 在任何情况下,不得Microsoft、其作者或参与创建、制作或交付脚本的任何其他人对任何损害负责(包括但不限于业务利润损失、业务中断、业务中断、业务信息损失或其他经济损失)因使用或无法使用示例脚本或文档而导致的损害。 即使Microsoft被告知这种损害的可能性。

运行脚本后,结果将保存在文件 C:\temp\KeyCredentialLink-report.txt中。

$outputfile = "C:\temp\KeyCredentialLink-report.txt"
New-Item -ItemType file -Path $outputfile -Force | Out-Null

"Report generated on " + (Get-Date) | Out-File $outputfile 

# Enumerate all AD users that has a msds-KeyCredentialLink value
foreach ($user in (Get-ADUser -LDAPFilter '(msDS-KeyCredentialLink=*)' -Properties "msDS-KeyCredentialLink")) {

    # For each user, output the UPN, DN, and all key IDs in msDS-KeyCredentialLink
    "===========`nUser: $($user.UserPrincipalName)`nDN: $($user.DistinguishedName)" | Out-File $outputfile -Append
    "KeyCredialLink Entries:" | Out-File $outputfile -Append
    "   Source|Usage|DeviceID                            |KeyID" | Out-File $outputfile -Append
    "   -------------------------------------------------------------------" | Out-File $outputfile -Append

    foreach ($blob in ($user."msDS-KeyCredentialLink")) {
        $KCLstring = ($blob -split ':')[2]
        
        # Check that the entries are version 2
        if ($KCLstring.Substring(0, 8) -eq "00020000") {
            $curIndex = 8   
            
            # Parse all KeyCredentialLink entries from the hex string
            while ($curIndex -lt $KCLstring.Length) {

                # Read the length, reverse the byte order to account for endianess, then convert to an int
                # The length is in bytes, so multiply by 2 to get the length in characters
                $strLength = ($KCLstring.Substring($curIndex, 4)) -split '(?<=\G..)(?!$)'
                [array]::Reverse($strLength)
                $kcle_Length = ([convert]::ToInt16(-join $strLength, 16)) * 2
            
                # Read the identifier and value
                $kcle_Identifier = $KCLstring.Substring($curIndex + 4, 2)
                $kcle_Value = $KCLstring.Substring($curIndex + 6, $kcle_Length)
            
                switch ($kcle_Identifier) {
                    # KeyID 
                    '01' {
                        $KeyID = $kcle_Value
                    }

                    # KeyUsage
                    '04' {
                        switch ($kcle_Value) {
                            '01' { $Usage = "NGC  " }
                            '07' { $Usage = "FIDO " }
                            '08' { $Usage = "FEK  " }
                            Default { $Usage = $kcle_Value }
                        }
                    }

                    # Source
                    '05' {
                        switch ($kcle_Value) {
                            '00' { $Source = "AD    " }
                            '01' { $Source = "Entra " }
                            Default { $Source = $kcle_Value }
                        }
                    }
                    
                    # DeviceID
                    '06' {
                        $tempByteArray = $kcle_Value -split '(?<=\G..)(?!$)'
                        $DeviceID = [System.Guid]::new($tempByteArray[3..0] + $tempByteArray[5..4] + $tempByteArray[7..6] + $tempByteArray[8..16] -join "")
                    }
                }

                $curIndex += 6 + $kcle_Length
            }

            # Save the data to file
            "   $Source|$Usage|$DeviceID|$KeyID" | Out-File $outputfile -Append
        }
    }
}

脚本示例输出和分析

下面是脚本的示例输出:

User: user1@contoso.com
DN: CN=user1,OU=MyOU,DC=contoso,DC=com
KeyCredialLink Entries:
   Source|Usage|DeviceID                            |KeyID
   -------------------------------------------------------------------
   Entra |NGC  |8a763ab0-0f6f-44f3-99ae-599a6aaca45b|FD68391824C44158B23C5605F567A588D02C4B2962AC96B789EDBCE091CF5067
   Entra |NGC  |9cf88f41-1e1e-462b-87d5-6938410ea82c|E91EF4E058513155A3F7E7E5B3E34951ADE923FFD0A7C24BB9957510F007E2F3
   Entra |NGC  |d04581fc-d1c8-45fc-a5ad-192bc649574f|E60B476088CC5CDF6FB75454CFA6E17C3059D51F2CA1E414E1554715BE6C0527
===========
User: user2@contoso.com
DN: CN=user2,OU=MyOU,DC=contoso,DC=com
KeyCredialLink Entries:
   Source|Usage|DeviceID                            |KeyID
   ---------------------------
   Entra |NGC  |c8fcc7a6-8f3f-4ec7-a90b-49c6988ba3a4|32EF67B902CB498710F0091F5B10B6A4A2F05D621B748B8150E08FA3048F227F

每个 KeyCredentialLink 条目表示证书。 输出包含以下信息:

  • Source:证书的源。 此信息可以来自 Microsoft Entra ID 或本地 AD。
  • Usage:证书的已定义用法。 此信息可以是 NGC (WHfB)、FIDO 或 FEK (文件加密密钥)。
  • DeviceID:创建证书的计算机的 ID。 此信息是 Microsoft Entra ID 中的设备 ID 和 AD 中的 objectGUID。
  • KeyID:证书的 bcrypt-sha256 密钥 ID 哈希。

匹配的证书应位于具有匹配 DeviceID项的计算机上的用户个人证书存储中。 若要查找客户端上使用的证书,可以从 PowerShell 或命令提示符运行 certutil -v -user -store my ,以转储用户个人存储中的详细证书信息。 在此示例中,应找到一个自签名证书,其中使用者和颁发者相同,并且格式相同 CN=<User SID>/login.windows.net/<Tenant ID>/<user UPN>。 找到此证书后,请检查 bcrypt-sha256 密钥 ID 哈希。 此哈希值应与 msDS-KeyCredentialLink** 属性中的**一个条目匹配。

下面是“证书存储”的摘录 user2@contoso.com:

> certutil -v -user -store my
my "Personal"
================ Certificate 0 ================
X509 Certificate:
Version: 3
Serial Number: 184621…
Signature Algorithm:
    Algorithm ObjectId: 1.2.840.113549.1.1.11 sha256RSA
    Algorithm Parameters:
    05 00
Issuer:
    CN=S-1-5-21-394…7436/login.windows.net/ccf…83a/user2@contoso.com

  :

Signature Algorithm:
    Algorithm ObjectId: 1.2.840.113549.1.1.11 sha256RSA
    Algorithm Parameters:
    05 00
Signature: UnusedBits=0
    0000  19 17 8f 65 c1 e3 f1 0a  3b 62 90 7f fa 94 13 ad
 // snip
    00f0  a2 e3 72 54 a5 0a 84 30  9e 8b 81 19 d3 61 46 58
Signature matches Public Key
Root Certificate: Subject matches Issuer
Key Id Hash(rfc-sha1): 9a546…
Key Id Hash(sha1): d66eb…
Key Id Hash(bcrypt-sha1): 7f4a0…
Key Id Hash(bcrypt-sha256): 32ef67b902cb…

参考

密钥凭据链接结构

资料来源与适用范围

资料来源
微软官方中文故障文档
适用范围
按正文的 Windows / Windows Server 适用版本;保留原文兼容性要求
内容语言
中文;命令、路径和错误标识保留技术原文
本地收录日期
2026-10-26
授权说明
CC BY 4.0

正文与所需资源由本站本地存储。查看来源及更新记录 ↗

请按适用版本和实际日志确认原因;本站没有对每一种系统或设备逐项执行文中的操作。