1

我正在开发一个项目,我们将 JAAS/Krb5LoginModule 与useTicketCachedoNotPrompt以及allowtgtsessionkey注册表更改一起使用,以在加入域的计算机的 Windows 登录上搭载我们的身份验证。

然后,我们使用 jgss /kerberos获取GSS API Kerberos 令牌 (rfc1964) ,在与服务通信时,我们使用WSS Kerberos 令牌配置文件 1.1.1来保护 SOAP 消息。这包括在 SOAP Envelope/Header 的 Security 元素中包含 b64 编码的 GSS 令牌,并使用客户端/服务 sessionKey 对元素的组件进行签名。

我们通过查询 JAAS/Krb5LoginModule 返回的 javax.security.auth.Subject 的私有凭据并查找与我们的服务对等名称匹配的 javax.security.auth.kerberos.KerberosTicket 并调用其 getSessionKey 来获取客户端/会话密钥()。

所有这些在 Java-6 中都可以正常工作,但是 Java-7 客户端失败了,因为 Java-7 创建的 Kerberos KRB_AP_REQ 消息似乎发生了变化。Java-7 KRB_AP_REQ Authenticator 包含一个与sessionKey不同的子密钥。由于 Kerberos 规范(请参阅下面的摘录)说此子密钥取代了 sessionKey,因此我们使用 sessionKey 进行签名的 Java-6 行为不再正确。

RFC1510 - Kerberos 网络身份验证服务 (V5)

5.3.2. 身份验证器

subkey  This field contains the client's choice for an encryption
        key which is to be used to protect this specific
        application session. Unless an application specifies
        otherwise, if this field is left out the session key from
        the ticket will be used.

我没有看到任何记录此更改的地方,但至少在 Java(TM) SE 运行时环境(内部版本 1.7.0_11-b21)中确认了该行为。

在这一点上,除非我错过了一些明显的东西(我希望我有),我们的选择似乎是:

  1. 更改 Java-7 Kerberos 配置以恢复到 Java-6 行为 - 不幸的是,我在文档中没有看到任何似乎表明这是可能的内容。

  2. 找到访问子项的方法。对于我探索的这个选项是

    一个。解码 b64 编码的 GSS Token,取出加密的 Authenticator,使用 sessionKey 解密,解码 ASN.1 DER 编码并取出子密钥。

    湾。使用看似非标准的GSS API 扩展,并使用带有 KRB5_GET_SESSION_KEY的ExtendedGSSContext.inquireSecContext()方法来获取子密钥。

对这些或其他可能的选项有任何建议/见解吗?

4

2 回答 2

0

我们在 Java 1.7 中使用 JGSS Api 获取客户端的会话密钥时也遇到了这个问题。显然,在 Java 1.6 中,子密钥总是从会话密钥中克隆出来的,请参见sun.security.krb5.EncryptionKey构造函数:

EncryptionKey(EncryptionKey encryptionkey)
    throws KrbCryptoException
{
    keyValue = (byte[])(byte[])encryptionkey.keyValue.clone();
    keyType = encryptionkey.keyType;
}

从 Java 1.7.0_b07 开始,此构造函数java.security.SecureRandom用于生成新的子键。我认为这已作为JDK-4460771 的一部分完成:Kerberos 应该能够生成子会话密钥。从现在开始(在 Sun JVM 上)似乎com.sun.security.jgss.ExtendedGSSContext提供了访问子键的“标准”方式,所以我想如果它可用(在底层 JVM 上)我们应该使用这个类,请参阅:

JDK-6710360:将 Kerberos 会话密钥导出到应用程序

谢谢,德特林

于 2013-08-20T14:58:47.403 回答
0

我在 ExtendedGSSContext.inquireSecContext() 文档中看不到任何内容表明它返回子键(如果 KRB5_GET_SESSION_KEY 存在);你从其他来源知道它吗?

无论如何,使用子键是您需要做的。我会这样看:您的原始实现不正确,因为 WSS Kerberos 文档明确指出如果存在子项将被使用。它只是碰巧起作用了,因为 Java 6 Kerberos 库没有生成子键。既然已经出现了一个错误,那么您的错误就被揭露了,您必须对其进行修复。

我对 WSS 不熟悉,但文档似乎表明您可以为令牌选择各种编码,一种是直接使用 GSSAPI 而不是 Kerberos AP-REQ。或许如果您一开始就使用 GSSAPI,它会使您免受这种变化的影响——也许现在切换到它会是最简单的解决方法。

于 2013-07-27T06:34:16.793 回答