完全用托管代码构建的完整 Kerberos 库,没有(许多)操作系统依赖性。
该项目由 .NET 基金会支持。
该库不受 Microsoft 官方支持。如果您通过 Oracle 的 ODP.NET 使用它,则仅通过 Oracle 支持支持 Kerberos.NET。即使您知道问题出在 Kerberos.NET 中,您也必须联系 Oracle 支持。如果 Kerberos.NET 中存在问题,Oracle 支持人员将直接与 Microsoft 合作。 Microsoft 将关闭直接与 Microsoft 创建的 Kerberos.NET 支持案例。
总结一下:尽管一些 Microsoft 员工可能正在管理它并为其做出贡献,但该存储库并未得到 Microsoft 的正式支持。他们要么在空闲时间执行此操作,要么部分作为内部使用的工作时间执行此操作,而没有来自 Microsoft(或 Microsoft 员工)的任何 SLA。仅通过 Oracle 支持支持 ODP.NET 使用 Kerberos.NET。
.NET 中内置的库,可让您操作 Kerberos 消息。您可以运行客户端、托管您自己的 KDC,或者只是验证传入的票证。它的目的是尽可能轻量。
深入探讨 Kerberos.NET 的设计值得一读。
该项目主要是一个库,但还包括一系列包装该库的有用工具,以帮助构建应用程序并解决 Kerberos 问题。
您可以在本页右侧的版本下找到 Fiddler 扩展安装程序。有关更多信息,请阅读有关如何安装和使用它的文章。
Bruce 命令行工具是一个实用程序集合,可让您与 Kerberos.NET 库组件进行交互,并可通过dotnet tool install bruce -g
获得。它包括用于票证缓存和密钥表管理等有用的工具。它还包括下面提到的票证解码器实用程序。该工具或多或少遵循 MIT 和 Heimdal 命令行标准,但有关套件中所有工具的更多信息,请从 Bruce 命令行键入help
。
请参阅此博客文章了解如何使用该工具。
查看和修改 krb5 配置文件。
解码 Kerberos/协商票证,如果您知道秘密,则可以选择解密。
删除所有票证缓存文件。
对用户进行身份验证并请求 TGT,其中包含一系列可用的请求选项。
查看缓存中的所有票证,并可选择请求更多票证。
向当前或提供的用户的 KDC 发送 AS-REQ“ping”,以获取该用户的元数据。
查看和操作密钥表文件并支持故障排除。
为当前用户请求票证并以有用的方式格式化详细信息。
如果您传递/verbose
命令行参数,该工具会公开有用的日志消息。
该库将在所有受支持的 .NET Standard 2.0 平台上运行,但有一些注意事项。
您可以通过两种方式使用该库。首先是下载代码并在本地构建。第二个更好的选择是只使用 nuget。
PM> 安装包 Kerberos.NET
您可以通过三种方式使用该库。
与其他平台中的客户端相比,该客户端故意变得简单。它功能齐全,支持生成 SPNego 消息。
var client = new KerberosClient();var kerbCred = new KerberosPasswordCredential("[email protected]", "userP@ssw0rd!");await client.Authenticate(kerbCred);var Ticket = wait client.GetServiceTicket("host/appservice .corp.identityintervention.com");var header = "协商" + Convert.ToBase64String(ticket.EncodeGssApi().ToArray());
托管 KDC 稍微复杂一些,因为它需要侦听特定端口。通常您在端口 88 上监听。
var port = 88;var options = new ListenerOptions{ListeningOn = new IPEndPoint(IPAddress.Loopback, port),DefaultRealm = "corp.identityintervention.com".ToUpper(),RealmLocator = realName => new MyRealmService(realmName)};var监听器 = new KdcServiceListener(options);等待监听器.Start();
侦听器将等待,直到调用(或释放) listener.Stop()
。
票证身份验证分两个阶段进行。第一阶段通过IKerberosValidator
和KerberosValidator
的默认实现来验证票证的正确性。第二阶段涉及将票证转换为可用的ClaimsIdentity
(具体为KerberosIdentity : ClaimsIdentity
),这发生在KerberosAuthenticator
中。
最简单的开始方法是创建一个新的KerberosAuthenticator
并调用Authenticate
。如果需要调整转换的行为,可以通过重写ConvertTicket(DecryptedData data)
方法来实现。
varauthenticator=newKerberosAuthenticator(newKeyTable(File.ReadAllBytes("sample.keytab")));varidentity=authenticator.Authenticate("YIIHCAYGKwYBBQUCoIIG...");Assert.IsNotNull(identity);varname=identity.Name ;Assert.IsFalse(string.IsNullOrWhitespace(name));
请注意,身份验证器的构造函数参数是KeyTable
。 KeyTable
是用于在其他平台上存储密钥的常见格式。您可以使用ktpass
等工具创建的文件,也可以在实例化期间传递KerberosKey
,它会产生相同的效果。
nuget 包通常会随着核心库的任何更改而保持最新。
嘿,它有效!只需添加 nuget 包作为参考即可。
更多信息
Active Directory 要求存在与发送令牌的域相匹配的身份。此身份可以是 Active Directory 中的任何用户或计算机对象,但需要正确配置。这意味着它需要一个服务主体名称 (SPN)。您可以在此处找到有关设置测试用户的说明。
Active Directory 自 Server 2012 起就支持声明。当时您只能通过 Windows 主体或 ADFS 黑魔法访问声明。 Kerberos.NET 现在原生支持解析 kerberos 票证中的声明。请参阅《索赔指南》,了解有关设置的更多信息。
Kerberos.NET 支持 KeyTable (keytab) 文件格式,用于传递用于解密和验证 Kerberos 票证的密钥。 keytab 文件格式是许多平台用于存储密钥的常见格式。您可以使用ktpass
命令行实用程序在 Windows 上生成这些文件,该实用程序是远程服务器管理工具 (RSAT) 包的一部分。您可以通过 PowerShell(或通过添加 Windows 组件对话框)将其安装在服务器上:
添加 Windows 功能 RSAT
从那里您可以通过运行以下命令生成密钥表文件:
ktpass /princ HTTP/[email protected] /mapuser IDENTITYINTERserver01$ /pass P@ssw0rd! /out Sample.keytab /crypto all /PTYPE KRB5_NT_SRV_INST /mapop 设置
参数princ
用于指定生成的PrincipalName, mapuser
用于将其映射到Active Directory中的用户。 crypto
参数指定哪些算法应生成条目。
本机支持 AES 票证。无需做任何额外的事情!
现在还包括通过 RFC8009 对 SHA256 和 SHA384 的支持。
有关更多信息,请参阅快速装甲。
目前尚不支持此功能,但已在路线图中。
您可以添加自己对 DES 等其他算法的支持(不知道为什么要这样做,但是...),您可以将加密类型与实例化新解密器的 Func<> 相关联。如果您愿意,也没有什么可以阻止您直接执行此过程。
KerberosRequest.RegisterDecryptor( 加密类型.DES_CBC_MD5, (令牌) => 新的 DESMD5DecryptedData(令牌));
内置重播检测使用MemoryCache
临时存储对票证随机数哈希值的引用。当票证过期时,这些引用将被删除。一旦验证器序列号可用,检测过程就会在解密后立即发生。
请注意,当应用程序集群时,内置检测逻辑无法有效工作,因为缓存不是跨机器共享的。内置实现使用内存服务,因此不与任何人共享。
您需要创建一个跨计算机共享的缓存,才能在集群环境中正常工作。通过新的 .NET Core 依赖项注入服务,这已大大简化。您需要做的就是注册一个IDistributedCache
实现。您可以在 Microsoft 文档中找到更多相关信息。
如果您想使用自己的重播检测,只需实现ITicketReplayValidator
接口并将其传递到KerberosValidator
构造函数中。
有样品!
KerbCrypto 通过 6 种支持的令牌格式运行。
rc4-kerberos-数据
rc4-spnego-数据
aes128-kerberos-数据
aes128-spnego-数据
aes256-kerberos-数据
aes256-spnego-数据
KerbTester 用于测试真实票据并转储解析结果的命令行工具。
KerberosMiddlewareEndToEndSample 一个端到端示例,显示服务器如何提示协商以及模拟浏览器的响应。
KerberosMiddlewareSample 一个简单的通过/失败中间件示例,用于解码票证(如果存在),但从不提示协商。
KerberosWebSample 一个示例 Web 项目,旨在托管在 IIS 中,提示协商并验证来自浏览器的任何传入票证。
该项目拥有 MIT 许可证。有关更多详细信息,请参阅许可证文件。另请参阅通知文件以获取有关其所依赖的项目许可证的更多信息。
该库附带一个可选实用程序来解码服务票证。它很容易使用。只需将票证的 Base64 编码副本复制到左侧文本框中即可。如果您不提供密钥,它将解码未加密的消息。如果您提供密钥,它将尝试解密该消息。如果票证使用 RC4 加密,则无需提供主机值,但如果使用 AES 加密(以派生盐),则需要提供主机值。或者,如果您碰巧也有密钥表文件,您也可以包含该文件。
您可以使用 Bruce 工具和bruce kdecode
来启动它。
解码器会将 Kerberos 票证转换为结构化树视图。该过程是Kerberos ASN.1 => JSON() => Tree View渲染。下面是中间 JSON,它向您显示票证中可用的所有信息。
{ “请求”:{“KrbApReq”:{“ProtocolVersionNumber”:5,“MessageType”:“KRB_AP_REQ”,“ApOptions”:“保留”,“票证”:{“TicketNumber”:5,“领域”:“CORP。 IDENTITYINTERVENTION.COM","SName": { "FullyQualifiedName": “desktop-h71o9uu”,“IsServiceName”:false,“类型”:“NT_PRINCIPAL”,“名称”:[“desktop-h71o9uu”]},“EncryptedPart”:{“EType”:“AES256_CTS_HMAC_SHA1_96”,“KeyVersionNumber”: 3、《密码》: "Vo4uodU2...snip...XBwjmsshgyjs+Vr+A=="} }, "身份验证器": {"EType": "AES256_CTS_HMAC_SHA1_96","KeyVersionNumber": null,"Cipher": "NnLmEFkmO3HXCS...snip。 ..up0YmNW5AicQVvvk" }},"KrbApRep": null }, “解密”:{“选项”:“保留”,“EType”:“AES256_CTS_HMAC_SHA1_96”,“SName”:{“FullyQualifiedName”:“desktop-h71o9uu”,“IsServiceName”:false,“类型”:“NT_PRINCIPAL”, “名称”:[“桌面-h71o9uu” ]},"Authenticator": { "AuthenticatorVersionNumber": 5, "Realm": "CORP.IDENTITYINTERVENTION.COM", "CName": {"FullyQualifiedName": "jack","IsServiceName": false,"Type": " NT_PRINCIPAL","名称": [ "jack"] }, "校验和": {"类型": “32771”,“校验和”:“EAAAAAAAAAAAAAAAAAAAAAAAA8QAAA”},“CuSec”:305,“CTime”:“2021-04-21T17:38:11 + 00:00”,“子密钥”:{“用途”:“未知","E类型": “AES256_CTS_HMAC_SHA1_96”,“KeyValue”:“nPIQrMQu/tpUV3dmeIJYjdUCnpg0sVDjFGHt8EK94EM =”},“序列号”:404160760,“AuthorizationData”:[{“类型”:“AdIfRelevant”,“数据”: "MIHTMD+gBAIAI2hNwQ1M...snip...BJAE8ATgAuAEMATwBNAA=="} ]},"票证": { "标志": ["EncryptedPreAuthentication","PreAuthenticated","可更新","可转发" ], "密钥": {“用法”:“未知”,“EType”: "AES256_CTS_HMAC_SHA1_96","KeyValue": "gXZ5AIsNAdQSo/qdEzkfw3RrLhhypyuG+YcZwqdX9mk=" }, "CRealm": "CORP.IDENTITYINTERVENTION.COM", "CName": {"FullyQualifiedName": "jack","IsServiceName": false,"类型": "NT_PRINCIPAL","名称": [ "jack"] }, "已传输": {"类型": "DomainX500Compress","内容": "" }, "AuthTime": "2021-04 -21T17:24:53+00:00", "开始时间": “2021-04-21T17:38:11 + 00:00”,“结束时间”:“2021-04-22T03:24:53 + 00:00”,“续订”:“2021-04-28T17:24:53 +00:00", "CAddr": null, "AuthorizationData": [{ "类型": "AdIfRelevant", "数据": "MIIDIjCCAx6gBAICAIChg...snip...muoGI9Mcg0="},{ "类型": "AdIfRelevant", "数据": "MF0wP6AEAgIAj...snip...AXg9hCAgAACTDBBAAAAAA="} ]} ,"DelegationTicket": null,"SessionKey": { "Usage": null, “EncryptionType”:“AES256_CTS_HMAC_SHA1_96”,“Host”:null,“PrincipalName”:null,“Version”:null,“Salt”:“”,“Password”:null,“IterationParameter”:“”,“PasswordBytes”: "", "SaltFormat": "ActiveDirectoryService", "RequiresDerivation": false},"倾斜": “00:05:00” }, “计算”:{“名称”:“[email protected]”,“限制”:{“KerbAuthDataTokenRestrictions”:[{“RestrictionType”:0,“限制”:{“标志”:“完整”,“ TokenIntegrityLevel": "高","MachineId": "Txr82+sI2kbFmPnkrjldLUfESt/oJzLaWWNqCkOgC7I=" }, "Type": "KerbAuthDataTokenRestrictions"},{ "RestrictionType": 0, "Restriction": {"Flags": "Full","TokenIntegrityLevel": "High","MachineId" : "Txr82+sI2kbFmPnkrjldLUfESt/oJzLaWWNqCkOgC7I=" }, "类型": "KerbAuthDataTokenRestrictions"} ], "KerbLocal": [{ "值": "EBeD2EICAAAAJMMEEAAAAAA==", "类型": "KerbLocal"},{ "值": "EBeD2EICAAAJMMEEAAAAAA==", "Type": "KerbLocal"} ], "KerbApOptions": [{ "Options": "ChannelBindingSupported", "Type": "KerbApOptions"} ], "KerbServiceTarget": [{ "ServiceName": "[email protected]", "类型": "KerbServiceTarget"} ], "AdWin2kPac": [{ "模式": "服务器", "解码错误": [], "版本": 0, " LogonInfo": {"PacType": "LOGON_INFO","LogonTime": "2021-04-21T17:24:53.4021307+00:00","注销时间": "0001-01-01T00:00:00+00:00","启动时间": "0001-01-01T00:00:00 +00:00","PwdLastChangeTime": "2021-01-14T23:55:39.0024458+00:00","PwdCanChangeTime": "2021-01-15T23:55:39.0024458+00:00","PwdMustChangeTime": “0001-01-01T00:00:00+00:00”,“用户名”:“杰克”,“用户显示名称”:“杰克·汉迪”,“LogonScript”:“”,“ProfilePath”:“”,“HomeDirectory” :“”,“HomeDrive”:“”,“LogonCount”:99,“BadPasswordCount”:0,“UserId”:第1126章 513 第1132章 513 第1132章 1132 1131、"属性": [ "SE_GROUP_MANDATORY", "SE_GROUP_ENABLED_BY_DEFAULT", "SE_GROUP_ENABLED"] }, {"RelativeId": 1128,"属性": [ "SE_GROUP_MANDATORY", "SE_GROUP_ENABLED_BY_DEFAULT", "SE_GROUP_ENABLED"] }, {“RelativeId”:1130,“属性”:[“SE_GROUP_MANDATORY”,“SE_GROUP_ENABLED_BY_DEFAULT”,“SE_GROUP_ENABLED”]},{“RelativeId”:513,“属性”:[“SE_GROUP_MANDATORY”, "SE_GROUP_ENABLED_BY_DEFAULT", "SE_GROUP_ENABLED"] }, {"RelativeId": 1129,"属性": [ "SE_GROUP_MANDATORY", "SE_GROUP_ENABLED_BY_DEFAULT", "SE_GROUP_ENABLED"] }],"UserFlags": “LOGON_EXTRA_SIDS”,“UserSessionKey”:“AAAAAAAAAAAAAAAAAAAAA==”,“服务器名称”:“DC01u0000”,“域名”:“CORPu0000”,“DomainId”:“S-1-5-21-311626132-1109945507-1757856464”, “保留1”: “AAAAAAAAAAA=”,“UserAccountControl”:[“ADS_UF_LOCKOUT”,“ADS_UF_NORMAL_ACCOUNT”],“SubAuthStatus”:0,“LastSuccessfulILogon”:“1601-01-01T00:00:00 + 00:00”,“LastFailedILogon”: "1601-01-01T00:00:00+00:00","FailedILogonCount": 0,"Reserved3": 0,"ExtraSidCount": 1,"ExtraIds": [ {"Sid": "S-1-18 -1","属性": [ "SE_GROUP_MANDATORY", “SE_GROUP_ENABLED_BY_DEFAULT”,“SE_GROUP_ENABLED”] }],“ResourceDomainId”:null,“ResourceGroupCount”:0,“ResourceGroupIds”:null,“UserSid”:{“Id”:1126,“属性”:“0”,“值”: “S-1-5-21-311626132-1109945507-1757856464-1126”},“GroupSid”:{“Id”:513,“属性”:“0”,“值”: "S-1-5-21-311626132-1109945507-1757856464-513"},"GroupSids": [ {"Id": 1132,"属性": [ "SE_GROUP_MANDATORY", "SE_GROUP_ENABLED_BY_DEFAULT", "SE_GROUP_ENABLED"],"值": "S-1-5-21-311626132-1109945507-1757856464-1132" }, {"Id": 1131,"属性": [ "SE_GROUP_MANDATORY", "SE_GROUP_ENABLED_BY_DEFAULT", "SE_GROUP_ENABLED"],"值": "S-1-5-21-311626132-1109945507-1757856464-1131" }, {"Id": 1128,"属性": [ "SE_GROUP_MANDATORY", "SE_GROUP_ENABLED_BY_DEFAULT", "SE_GROUP_ENABLED"],"值": "S-1-5-21-311626132-1109945507-1757856464-1128" }, {"Id": 1130,"属性": [ "SE_GROUP_MANDATORY", "SE_GROUP_ENABLED_BY_DEFAULT", "SE_GROUP_ENABLED"],"值": "S-1-5-21-311626132-1109945507-1757856464-1130" }, {"Id": 513,"属性": [ "SE_GROUP_MANDATORY", "SE_GROUP_ENABLED_BY_DEFAULT", "SE_GROUP_ENABLED"],"值": "S-1-5-21-311626132-1109945507-1757856464-513" }, {"Id": 1129,"属性": [ "SE_GROUP_MANDATORY", "SE_GROUP_ENABLED_BY_DEFAULT", "SE_GROUP_ENABLED"],"值": "S-1-5-21-311626132-1109945507-1757856464-1129" }],"ExtraSids": [ {"Id": 1,"属性": "0","值”:“S-1-18-1” }],“ResourceDomainSid”:null,“ResourceGroups”:[],“DomainSid”:{“Id”:1757856464,“属性”:“0”,“值”:“S-1-5-21-311626132- 1109945507-1757856464"} }, "服务器签名": {“类型”:“HMAC_SHA1_96_AES256”,“签名”:“Q0gnRmxBoh5w0DzS”,“RODCIdentifier”:0,“PacType”:“0”},“CredentialType”:null,“KdcSignature”:{“类型”:“HMAC_SHA1_96_AES256” ,“签名”: “HVsreq5rqBiPTHIN”,“RODCIdentifier”:0,“PacType”:“0”},“ClientClaims”:null,“DeviceClaims”:null,“ClientInformation”:{“ClientId”:“2021-04-21T17:24:53 +00:00","姓名": "杰克","PacType": "CLIENT_NAME_TICKET_INFO" }, "UpnDomainInformation": {"Upn": "[email protected]","域名": "CORP.IDENTITYINTERVENTION.COM","Flags": "0","PacType": "UPN_DOMAIN_INFO " }, "DelegationInformation": null, "HasRequiredFields": true, “类型”:“AdWin2kPac”} ]},“ValidationMode”:“Pac”,“声明”:[ {“类型”:“http://schemas.xmlsoap.org/ws/2005/05/identity/claims/ sid","值": "S-1-5-21-311626132-1109945507-1757856464-1126" }, {"类型": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname","值": "杰克·汉迪" }, {"类型": “http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier”,“值”:“[email protected]”},{“类型”:“http://schemas .microsoft.com/ws/2008/06/identity/claims/groupsid","值": “S-1-5-21-311626132-1109945507-1757856464-1132”},{“类型”:“http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid”,“值”: “S-1-5-21-311626132-1109945507-1757856464-1131”},{“类型”:“http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid”,“值”: “S-1-5-21-311626132-1109945507-1757856464-1128”},{“类型”:“http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid”,“值”: “S-1-5-21-311626132-1109945507-1757856464-1130”},{“类型”:“http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid”,“值”: “S-1-5-21-311626132-1109945507-1757856464-513”},{“类型”:“http://schemas.microsoft.com/ws/2008/06/identity/claims/role”,“值": "域用户" }, {"类型": “http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid”,“值”:“S-1-5-21-311626132-1109945507-1757856464-1129”},{“类型”: “http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid”,“值”:“S-1-18-1”}] }, “KeyTable”:{“FileVersion”:2,“KerberosVersion”:5,“条目”:[ {“EncryptionType”:“NULL”,“长度”:0,“时间戳”:“2021-04-21T23:52: 22.5460123+00:00","版本": 5,"主机": null,"密码字节": "jBBI1KL19X3olbCK/f9p/+cxZi3RnqqQRH4WawB4EzY=","KeyPrincipalName": { "Realm": "CORP.IDENTITYINTERVENTION.COM", "Names": ["STEVE-HOME" ], "NameType": "NT_SRV_HST", "FullyQualifiedName" : "STEVE-HOME"},"盐": null }] }}