Java Kerberos - 找不到合适类型的密钥来解密 AP REP - RC4 与 HMAC

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31877027/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 11:44:11  来源:igfitidea点击:

Kerberos - Cannot find key of appropriate type to decrypt AP REP - RC4 with HMAC

javakerberosspring-security-kerberos

提问by Gunnar Kiesel

I'm trying to setup SSO for Java WebApp using Kerberos/SpNego. I'm using:

我正在尝试使用 Kerberos/SpNego 为 Java WebApp 设置 SSO。我正在使用:

  • Java 1.7u67
  • org.springframework.security.kerberos 1.0.0.RELEASE
  • Active Directory
  • Tomcat 7 on Linux
  • Java 1.7u67
  • org.springframework.security.kerberos 1.0.0.RELEASE
  • 活动目录
  • Linux 上的 Tomcat 7

After overcoming the problem discribed in How to configure kerberos on Tomcat/linux server?, I'm now stuck with the following error:

在克服了如何在 Tomcat/linux 服务器上配置 kerberos 中描述的问题后,我现在遇到以下错误:

org.springframework.security.authentication.BadCredentialsException: Kerberos validation not succesful
        at org.springframework.security.kerberos.authentication.sun.SunJaasKerberosTicketValidator.validateTicket(SunJaasKerberosTicketValidator.java:70) ~[spring-security-kerberos-core-1.0.0.RELEASE.jar:1.0.0.RELEASE]
        at org.springframework.security.kerberos.authentication.KerberosServiceAuthenticationProvider.authenticate(KerberosServiceAuthenticationProvider.java:64) ~[spring-security-kerberos-core-1.0.0.RELEASE.jar:1.0.0.RELEASE]
        at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:156) ~[spring-security-core-3.2.7.RELEASE.jar:3.2.7.RELEASE]
        at org.springframework.security.kerberos.web.authentication.SpnegoAuthenticationProcessingFilter.doFilter(SpnegoAuthenticationProcessingFilter.java:145) ~[spring-security-kerberos-web-1.0.0.RELEASE.jar:1.0.0.RELEASE]
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.7.RELEASE.jar:3.2.7.RELEASE]
        at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:199) [spring-security-web-3.2.7.RELEASE.jar:3.2.7.RELEASE]
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.7.RELEASE.jar:3.2.7.RELEASE]
        at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:110) [spring-security-web-3.2.7.RELEASE.jar:3.2.7.RELEASE]
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.7.RELEASE.jar:3.2.7.RELEASE]
        at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50) [spring-security-web-3.2.7.RELEASE.jar:3.2.7.RELEASE]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.1.6.RELEASE.jar:4.1.6.RELEASE]
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.7.RELEASE.jar:3.2.7.RELEASE]
        at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87) [spring-security-web-3.2.7.RELEASE.jar:3.2.7.RELEASE]
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.7.RELEASE.jar:3.2.7.RELEASE]
        at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192) [spring-security-web-3.2.7.RELEASE.jar:3.2.7.RELEASE]
        at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160) [spring-security-web-3.2.7.RELEASE.jar:3.2.7.RELEASE]
        at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:344) [spring-web-4.1.6.RELEASE.jar:4.1.6.RELEASE]
        at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:261) [spring-web-4.1.6.RELEASE.jar:4.1.6.RELEASE]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) [catalina.jar:7.0.55]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) [catalina.jar:7.0.55]
        at org.lightadmin.core.view.TilesContainerEnrichmentFilter.doFilterInternal(TilesContainerEnrichmentFilter.java:40) [lightadmin-1.2.0.RC1.jar:1.2.0.RC1]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.1.6.RELEASE.jar:4.1.6.RELEASE]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) [catalina.jar:7.0.55]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) [catalina.jar:7.0.55]
        at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77) [spring-web-4.1.6.RELEASE.jar:4.1.6.RELEASE]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.1.6.RELEASE.jar:4.1.6.RELEASE]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) [catalina.jar:7.0.55]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) [catalina.jar:7.0.55]
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220) [catalina.jar:7.0.55]
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122) [catalina.jar:7.0.55]
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501) [catalina.jar:7.0.55]
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171) [catalina.jar:7.0.55]
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103) [catalina.jar:7.0.55]
        at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950) [catalina.jar:7.0.55]
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116) [catalina.jar:7.0.55]
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408) [catalina.jar:7.0.55]
        at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1070) [tomcat-coyote.jar:7.0.55]
        at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:611) [tomcat-coyote.jar:7.0.55]
        at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:316) [tomcat-coyote.jar:7.0.55]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [na:1.7.0_67]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [na:1.7.0_67]
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-coyote.jar:7.0.55]
        at java.lang.Thread.run(Thread.java:745) [na:1.7.0_67]
Caused by: java.security.PrivilegedActionException: null
        at java.security.AccessController.doPrivileged(Native Method) ~[na:1.7.0_67]
        at javax.security.auth.Subject.doAs(Subject.java:415) ~[na:1.7.0_67]
        at org.springframework.security.kerberos.authentication.sun.SunJaasKerberosTicketValidator.validateTicket(SunJaasKerberosTicketValidator.java:67) ~[spring-security-kerberos-core-1.0.0.RELEASE.jar:1.0.0.RELEASE]
        ... 42 common frames omitted
Caused by: org.ietf.jgss.GSSException: Failure unspecified at GSS-API level (Mechanism level: Invalid argument (400) - Cannot find key of appropriate type to decrypt AP REP - RC4 with HMAC)
        at sun.security.jgss.krb5.Krb5Context.acceptSecContext(Krb5Context.java:788) ~[na:1.7.0_67]
        at sun.security.jgss.GSSContextImpl.acceptSecContext(GSSContextImpl.java:342) ~[na:1.7.0_67]
        at sun.security.jgss.GSSContextImpl.acceptSecContext(GSSContextImpl.java:285) ~[na:1.7.0_67]
        at sun.security.jgss.spnego.SpNegoContext.GSS_acceptSecContext(SpNegoContext.java:875) ~[na:1.7.0_67]
        at sun.security.jgss.spnego.SpNegoContext.acceptSecContext(SpNegoContext.java:548) ~[na:1.7.0_67]
        at sun.security.jgss.GSSContextImpl.acceptSecContext(GSSContextImpl.java:342) ~[na:1.7.0_67]
        at sun.security.jgss.GSSContextImpl.acceptSecContext(GSSContextImpl.java:285) ~[na:1.7.0_67]
        at org.springframework.security.kerberos.authentication.sun.SunJaasKerberosTicketValidator$KerberosValidateAction.run(SunJaasKerberosTicketValidator.java:162) ~[spring-security-kerberos-core-1.0.0.RELEASE.jar:1.0.0.RELEASE]
        at org.springframework.security.kerberos.authentication.sun.SunJaasKerberosTicketValidator$KerberosValidateAction.run(SunJaasKerberosTicketValidator.java:152) ~[spring-security-kerberos-core-1.0.0.RELEASE.jar:1.0.0.RELEASE]
        ... 45 common frames omitted
Caused by: sun.security.krb5.KrbException: Invalid argument (400) - Cannot find key of appropriate type to decrypt AP REP - RC4 with HMAC
        at sun.security.krb5.KrbApReq.authenticate(KrbApReq.java:273) ~[na:1.7.0_67]
        at sun.security.krb5.KrbApReq.<init>(KrbApReq.java:144) ~[na:1.7.0_67]
        at sun.security.jgss.krb5.InitSecContextToken.<init>(InitSecContextToken.java:108) ~[na:1.7.0_67]
        at sun.security.jgss.krb5.Krb5Context.acceptSecContext(Krb5Context.java:771) ~[na:1.7.0_67]
        ... 53 common frames omitted

However it seems that the key should be there, since on startup of the application I got the following debug:

然而,似乎关键应该在那里,因为在应用程序启动时我得到了以下调试:

  Debug is  true storeKey true useTicketCache false useKeyTab true doNotPrompt true ticketCache is null isInitiator false KeyTab is /opt/pksvc/tomcat_edl/current/conf/TestSpnego.keytab refreshKrb5Config is false principal is [email protected] tryFirstPass is false useFirstPass is false storePass is false clearPass is false
principal is [email protected]
Will use keytab
>>> KeyTabInputStream, readName(): MYREALM.DE
>>> KeyTabInputStream, readName(): HTTP
>>> KeyTabInputStream, readName(): lxdetstpksvc01.mydomain.de
>>> KeyTab: load() entry length: 83; type: 23
Ordering keys wrt default_tkt_enctypes list
Java config name: /opt/pksvc/tomcat_edl/current/conf/krb5.conf
Loaded from Java config
default etypes for default_tkt_enctypes: 23.
Commit Succeeded

So enctype 23 = RC4 with HMAC is the type of the KeyTab entry and the default enctype. I can also see that the browser sends a token with this enctype (I removed the binary part from the following):

所以 enctype 23 = RC4 with HMAC 是 KeyTab 条目的类型和默认的 enctype。我还可以看到浏览器发送了一个带有此 enctype 的令牌(我从以下内容中删除了二进制部分):

Ticket  TicketType{TktVno=5,Realm=MYREALM.DE,Sname=HTTP/lxdetstpksvc01.mydomain.de,EncPart=EncryptedData{Etype=23,Kvno=4,Cipher=binary[...  352 16728   KerberosV5.TicketType   
Authenticator   EncryptedData{Etype=23,Kvno=nothing,Cipher=binary[...   17080   2872    KerberosV5.EncryptedData    

So everything seems to be encytpe 23 (RC4 with HMAC). When I had a look at the code I found that sun.security.krb5.EncryptionKey which is used by KrbApReq (which throws the error in the stack above) is indeed not only comparing the enctype, but also the version. So I guess that is what must be wrong in my case. In the ticket above is Kvno=4 for EncryptedData and for Authenticator EncryptedData it is Kvno=nothing. Should these match?

所以一切似乎都是 entpe 23(带有 HMAC 的 RC4)。当我查看代码时,我发现 KrbApReq 使用的 sun.security.krb5.EncryptionKey(在上面的堆栈中抛出错误)确实不仅在比较 enctype,而且还在比较版本。所以我想这就是我的情况一定是错误的。在上面的票证中,对于 EncryptedData 是 Kvno=4,对于 Authenticator EncryptedData 是 Kvno=nothing。这些应该匹配吗?

How can I resolve this? Is this influenced by the generation of the keytab?

我该如何解决这个问题?这是否受密钥表生成的影响?

采纳答案by Gunnar Kiesel

It turned out the error above resulted from two problems:

原来上面的错误是由两个问题引起的:

  1. The service principal in the spring configuration was wrong. It was [email protected], but HTTP/[email protected]is correct.

  2. The Kvno in the keytab was not identical with the Kvno stored in the active directory. As stated on https://tomcat.apache.org/tomcat-7.0-doc/windows-auth-howto.htmlActive Directory is raising the Kvno with every execution of ktpass. However I wasn't able to find the value (msDS-KeyVersionNumber) for it in our AD and could only grap it from the request.

  1. spring配置中的服务主体是错误的。它是 [email protected],但 HTTP/[email protected]是正确的。

  2. 密钥表中的 Kvno 与存储在活动目录中的 Kvno 不同。正如 https://tomcat.apache.org/tomcat-7.0-doc/windows-auth-howto.html 上所述,每次执行 ktpass 时,Active Directory 都会提高 Kvno。但是,我无法在我们的 AD 中找到它的值 (msDS-KeyVersionNumber),只能从请求中获取它。

Summarized the 'Cannot find key of appropriate type to decrypt ...' error can result from one of the following problems:

总结了“找不到合适类型的密钥来解密......”错误可能是由以下问题之一引起的:

  1. The service prinicpal in the spring security configuration is not identical with that from the keytab (param /princ from ktpass).
  2. There is no key for the enctype the AD has send the ticket with (param /crypto from ktpass and set in the krb5.conf/permitted_enctypes+default_tkt_enctypes).
  3. The Kvno from the ticket is different then the Kvno in the keytab (param /kvno from ktpass).
  4. The path to the keytab is wrong (see answer from Xavier Portebois)
  5. The process does not have permissions to read the keytab (See comment from user7610)
  1. spring 安全配置中的服务主体与密钥表中的服务主体不同(来自 ktpass 的参数 /princ)。
  2. AD 发送票证的加密类型没有密钥(来自 ktpass 的参数 /crypto 并在 krb5.conf/permitted_enctypes+default_tkt_enctypes 中设置)。
  3. 票证中的 Kvno 与密钥表中的 Kvno 不同(参数 /kvno 来自 ktpass)。
  4. 密钥表的路径错误(请参阅 Xavier Portebois 的回答)
  5. 该进程无权读取密钥表(请参阅user7610 的评论)

回答by Xavier Portebois

We also got a Invalid argument (400) - Cannot find key of appropriate type to decrypt ...error.

我们也有Invalid argument (400) - Cannot find key of appropriate type to decrypt ...错误。

This can simply be thrown if the path to the keytab is wrong(in our case, we forgot we got a docker volume mapping there).

如果keytab 的路径错误(在我们的例子中,我们忘记了我们在那里有一个 docker 卷映射),这可以简单地抛出。

So, be sure the keytab path is the right one, as this could fire this weird exception.

因此,请确保 keytab 路径是正确的,因为这可能会引发这个奇怪的异常。

回答by KWoodie

This can also be thrown if your using Active Directory as the KDC and the keytab user is configured for a different encryption setting than your keytab is using. In my case AES 128 was configured and I was expecting AES 256. A simple change of the configuration within AD resolved the issue.

如果您使用 Active Directory 作为 KDC 并且密钥表用户配置为与密钥表使用的加密设置不同的加密设置,则也可能引发此问题。在我的情况下,配置了 AES 128,我期待 AES 256。AD 中配置的简单更改解决了这个问题。

回答by hunger

In my case, the jaas config file of the server needed the parameter "storeKey" set to true.

就我而言,服务器的 jaas 配置文件需要将参数“storeKey”设置为 true。

回答by filip5114

The service prinicpal in the spring security configuration is not identical with that from the keytab (param /princ from ktpass).

spring 安全配置中的服务主体与密钥表中的服务主体不同(来自 ktpass 的参数 /princ)。

In my case they were the same, but param /princ was not correct. HTTP and domain part must be uppercase.

就我而言,它们是相同的,但 param /princ 不正确。HTTP 和域部分必须大写。

Correct example:

正确示例:

HTTP/[email protected]

HTTP/[email protected]

Incorrect example:

不正确的例子:

http/[email protected]

http/[email protected]

回答by sdraxxi

I've been struggling with this during 4 hours

我一直在努力解决这个问题 4 小时

the parameter "storeKey" set to true in the jaas file resolved the issue

jaas 文件中将参数“storeKey”设置为 true 解决了该问题