使用Spnego解密kerberos票

我正在使用spnego( http://spnego.sourceforge.net )在JBoss下进行kerberos身份validation。

我需要解密kerberos票证才能访问包含PAC数据的授权数据。 需要PAC数据来决定将哪些角色授予用户。

如何访问和解密kerberos票? 我搜索网上的例子,但没有努力。

这些人有完整的PAC解码实现:

http://jaaslounge.sourceforge.net/

您可以像这样使用令牌解析器:

HttpServletRequest request = (HttpServletRequest) req; String header = request.getHeader("Authorization"); byte[] base64Token = header.substring(10).getBytes("UTF-8"); byte[] spnegoHeader = Base64.decode(base64Token); SpnegoInitToken spnegoToken = new SpnegoInitToken(spnegoHeader); 

如果要解密基础Kerberos票证,您将需要跳过一些箍。 不确定你是否需要它。

格兰特

我已成功使用http://spnego.sourceforge.net中的servletfilter与http://jaaslounge.sourceforge.net/中的PAC解析器结合使用,而无需使用DER / ASN.1解析器明确执行某些操作:

 /** * Retrieve LogonInfo (for example, Group SID) from the PAC Authorization Data * from a Kerberos Ticket that was issued by Active Directory. */ byte[] kerberosTokenData = gssapiData; try { SpnegoToken token = SpnegoToken.parse(gssapiData); kerberosTokenData = token.getMechanismToken(); } catch (DecodingException dex) { // Chromium bug: sends a Kerberos response instead of an spnego response // with a Kerberos mechanism } catch (Exception ex) { log.error("", ex); } try { Object[] keyObjs = IteratorUtils.toArray(loginContext.getSubject() .getPrivateCredentials(KerberosKey.class).iterator()); KerberosKey[] keys = new KerberosKey[keyObjs.length]; System.arraycopy(keyObjs, 0, keys, 0, keyObjs.length); KerberosToken token = new KerberosToken(kerberosTokenData, keys); log.info("Authorizations: "); for (KerberosAuthData authData : token.getTicket().getEncData() .getUserAuthorizations()) { if (authData instanceof KerberosPacAuthData) { PacSid[] groupSIDs = ((KerberosPacAuthData) authData) .getPac().getLogonInfo().getGroupSids(); log.info("GroupSids: " + Arrays.toString(groupSIDs)); response.getWriter().println("Found group SIDs: " + Arrays.toString(groupSIDs)); } else { log.info("AuthData without PAC: " + authData.toString()); } } } catch (Exception ex) { log.error("", ex); } 

我还写了一个新的HttpFilter(从spnego.sf.net派生):spnego-pac,它通过getUserPrincipal()公开了LogonInfo。

可以在此处找到完整演示上述代码的示例项目:

https://github.com/EleotleCram/jetty-spnego-demo

spnego-pacfilter(在上面的例子中使用)可以在这里找到:

https://github.com/EleotleCram/spnego.sf.net-fork

希望这对任何人都有帮助。

__
马塞尔

如果你从spnegoToken获得机制令牌,如下所示:

 byte[] mechanismToken = spnegoToken.getMechanismToken(); 

机制令牌通常是KerberosApRequest 。 有一个KerberosToken构造函数,它接受KerberosApRequest 。 只需传入mechanismToken字节数组和密钥即可解密内容。

我提供了自己的问题解决方案:

我的解决方案基于BouncyCastle库(用于解析部分令牌)和JaasLounge(用于解密令牌的加密部分)。 不幸的是,从JaasLounge解码整个spnego令牌的代码失败了我的要求。 我必须自己写。

我已经逐部分解码,首先从byte []数组构造DERObjects:

 private DERObject[] readDERObjects(byte[] bytes) throws IOException { ASN1InputStream stream = new ASN1InputStream(new ByteArrayInputStream( bytes)); List objects = new ArrayList(); DERObject curObj; while ((curObj = stream.readObject()) != null) { objects.add(untag(curObj)); } return objects.toArray(new DERObject[0]); } 

untag()是我的辅助函数,用于删除DERTaggedObject包装

 private DERObject untag(DERObject src) { if (src instanceof DERTaggedObject) { return ((DERTaggedObject) src).getObject(); } return src; } 

为了从给定的DERObject中提取DERObject的序列,我编写了另一个辅助函数:

 private DERObject[] readDERObjects(DERObject container) throws IOException { // do operation varying from the type of container if (container instanceof DERSequence) { // decode using enumerator List objects = new ArrayList(); DERSequence seq = (DERSequence) container; Enumeration enumer = seq.getObjects(); while (enumer.hasMoreElements()) { DERObject curObj = (DERObject) enumer.nextElement(); objects.add(untag(curObj)); } return objects.toArray(new DERObject[0]); } if (container instanceof DERApplicationSpecific) { DERApplicationSpecific aps = (DERApplicationSpecific) container; byte[] bytes = aps.getContents(); return readDERObjects(bytes); } if (container instanceof DEROctetString) { DEROctetString octets = (DEROctetString) container; byte[] bytes = octets.getOctets(); return readDERObjects(bytes); } throw new IllegalArgumentException("Unable to decode sequence from "+container); } 

最后,当我得到包含加密部分的DEROctetStream时,我刚刚使用了KerberosEncData:

 KerberosEncData encData = new KerberosEncData(decrypted, matchingKey); 

我们从客户端浏览器接收的字节序列将被解析为单个DERApplicationSpecific,它是票根 – 级别0。
根包含:

  • DERObjectIdentifier – SPNEGO OID
  • DERSequence – 1级

1级包含:

  • DERObjectIdentifier的序列 – 机械类型
  • DEROctetString – 包裹DERApplicationSepecific – 级别2

2级包含:

  • DERObjectIndentifier – Kerberos OID
  • KRB5_AP_REQ标记0x01 0x00 ,解析为boolean(false)
  • DERApplicationSpecific – DERSequence的容器 – 级别3

3级包含:

  • 版本号 – 应为5
  • 消息类型 -​​ 14(AP_REQ)
  • AP选项(DERBITString)
  • DERApplicationSpecific – 包含票证部分的DERSequence
  • 带有额外票务部分的DERSeqeuence – 未处理

机票部分 – 第4级包含:

  • 机票版本 – 应为5
  • 票证领域 – 用户通过身份validation的领域的名称
  • 服务器名称的后缀。 每个服务器名称是2个字符串的DERSequence:服务器名称和实例名称
  • 带加密部分的DERSequence

加密的零件序列(级别5)包含:

  • 使用的算法编号
    • 1,3-DES
    • 16 – des3-cbc-sha1-kd
    • 17 – ETYPE-AES128-CTS-HMAC-SHA1-96
    • 18 – ETYPE-AES256-CTS-HMAC-SHA1-96
    • 23 – RC4-HMAC
    • 24 – RC4-HMAC-EXP
  • 密钥版本号
  • 加密部分(DEROctetStream)

问题出在DERBoolean构造函数,当发现序列0x01 0x00时抛出ArrayIndexOutOfBoundException。 我不得不改变那个构造函数:

 public DERBoolean( byte[] value) { // 2011-01-24 llech make it byte[0] proof, sequence 01 00 is KRB5_AP_REQ if (value.length == 0) this.value = 0; else this.value = value[0]; } 

自从我使用了spnego(将近一年)以来,已经有一段时间……你问的是一个非常酷的问题。

我做了一点挖掘,并尝试运行一些我曾经使用MS-AD的代码,但今天感觉不到: – /

无论如何,我通过谷歌找到了这个链接: http : //www.google.com/url? sa = t&source = web&cd = 1&sqi = 2&ed = 0CBMQFjAA&url = http% 3A%2F%2Fbofriis.dk%2Ffiles%2Fms_kerberos_pac.pdf&rct = j& q = java的%20kerberos%20privilege%20attribute%20certificate&EI = 2FASTbaLGcP38Abk07iQDg&USG = AFQjCNHcIfQRUTxkQUvLRcgOaQksCALTHA&SIG2 = g8yn7ie1PbzSkE2Mfv41Bw及CAD = RJA

希望这可以给你一些见解。