代码之家  ›  专栏  ›  技术社区  ›  Gunnar Kiesel

Kerberos-找不到适当类型的密钥,无法使用HMAC解密AP REP-RC4

  •  17
  • Gunnar Kiesel  · 技术社区  · 9 年前

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

    • Java 1.7u67
    • 组织弹簧框架安全。kerberos 1.0.0发布
    • Active Directory(Active Directory)
    • Linux上的Tomcat 7

    克服了中所述的问题后 How to configure kerberos on Tomcat/linux server? ,我现在遇到以下错误:

    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
    

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

      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 TestSpnego@MYREALM.DE tryFirstPass is false useFirstPass is false storePass is false clearPass is false
    principal is TestSpnego@MYREALM.DE
    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
    

    因此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    
    

    因此,一切似乎都被包裹了23(RC4与HMAC)。当我查看代码时,我发现KrbApReq使用的sun.security.krb5.EncryptionKey(它在上面的堆栈中抛出错误)不仅在比较enctype,而且还在比较版本。所以我想这就是我的问题所在。 在上面的票据中,EncryptedData的Kvno=4,而Authenticator EncryptedData为Kvno=nothing。这些是否匹配?

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

    9 回复  |  直到 3 年前
        1
  •  26
  •   Gunnar Kiesel    7 年前

    事实证明,上述错误是由两个问题引起的:

    1. 弹簧配置中的服务主体错误。是的 lxdetstpksvc01.mydomain.de@MYREALM.DE但是 HTTP/lxdetstpksvc01.mydomain.de@MYREALM.DE 是正确的。

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

    摘要:“找不到要解密的适当类型的密钥…”错误可能由以下问题之一导致:

    1. spring安全配置中的服务prinicpal与keytab中的服务不相同(来自ktpass的param/princ)。
    2. AD发送票据时使用的enctype没有密钥(来自ktpass的param/crypto,并在krb5.conf/permitted_enctypes+default_tkt_enctypes中设置)。
    3. 票据中的Kvno与keytab中的Kvno不同(来自ktpass的param/Kvno)。
    4. 键标签的路径错误(请参阅Xavier Portebois的答案)
    5. 进程没有读取keytab的权限(请参阅 user7610 )
        2
  •  10
  •   Xavier Portebois    7 年前

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

    如果 指向keytab的路径错误 (在我们的例子中,我们忘记了那里有一个docker体积映射)。

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

        3
  •  1
  •   KWoodie    7 年前

    如果您使用Active Directory作为KDC,并且keytab用户配置的加密设置与keytab使用的加密设置不同,则也会引发此问题。在我的案例中,配置了AES 128,而我期望的是AES 256。AD中配置的简单更改解决了问题。

        4
  •  1
  •   Preetam Palwe    3 年前

    如果您使用的是Spring Boot,请注意如何指定keytab文件。

    注意 classpath: 当你跑步时它会起作用 spring-boot:run 然而,当你跑步时却不会 java -jar xyz.jar 因为JAAS无法从类路径读取它。 所以请选择 file: 同时指定keytab文件路径。 (这是使用docker打包和运行应用程序时的典型情况)

        5
  •  0
  •   hunger    6 年前

    在我的例子中,服务器的jaas配置文件需要将参数“storeKey”设置为true。

        6
  •  0
  •   filip5114    5 年前

    spring安全配置中的服务prinicpal与keytab中的服务不相同(来自ktpass的param/princ)。

    在我的例子中,它们是相同的,但param/princ不正确。 HTTP和域部分必须大写。

    正确示例:

    HTTP/service.example.lan@EXAMPLE.LAN

    错误示例:

    http/service.example.lan@Eexample.lan

        7
  •  0
  •   sdraxxi    5 年前

    我在这4个小时里一直在挣扎

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

        8
  •  0
  •   flavio.donze    3 年前

    我也有同样的错误,因为keytab文件是用错误的 /crypto 配置

    GSS-API级别未指定失败(机制级别:无效参数(400)
    找不到适当类型的密钥以使用HMAC解密AP-REQ-RC4)

    使用生成新的keytab文件 /crypto ALL 使用 ktpass 命令:

    ktpass /out "server.keytab" /crypto ALL /princ HTTP/server@REALM /mapuser KERBEROS_SERVICEUSER /pass PASSWORD /ptype KRB5_NT_PRINCIPAL
    

    代替 HTTP/server@REALM , KERBEROS_SERVICEUSER PASSWORD 具有相应的值。

        9
  •  0
  •   yoon    3 年前

    在我的情况下,我得到了以下日志,

    警告SpnegoAuthenticationProcessingFilter:149-协商标头无效:协商XXX
    org.springframework.security.authentication。BadCredentialsException:Kerberos验证未成功
    原因:java.security。PrivilegedActionException:GSSException:在GSS-API级别未指定失败(机制级别:无效参数(400)-找不到适当类型的密钥来解密AP REP-AES256 CTS模式(HMAC SHA1-96)
    导致原因:GSSException:GSS-API级别未指定失败(机制级别:无效参数(400)-找不到适当类型的密钥来解密AP REP-AES256 CTS模式和HMAC SHA1-96)

    这是一个许可问题。

    执行用户没有读取keytab文件的权限,因此我使用 chmod 命令