如何使用jldap库在openldap中解析Kerberos的属性'krbprincipalkey'?

How to use jldap library to parse Kerberos' attribute 'krbprincipalkey' in openldap?

我们正在使用 Kerberos + openldap。在我们的java项目中,希望通过JavaAPI在openldap中创建krbprincipal,读取openldap中的krbprincipal条目,解析其属性krbprincipalkey,写入KeyTab文件。

下面是我使用jldap库解析krbprincipalkey的demo

public static KrbPrincipalKey asn1Decode(byte[] values) throws HengHeLdapException {
    LBERDecoder decoder = new LBERDecoder();
    ASN1Sequence root = ((ASN1Sequence) decoder.decode(values));
    // attribute-major-vno
    ASN1Tagged attributeMajorVnoTag = ((ASN1Tagged) root.get(0));
    ASN1OctetString asn1OctetString = (ASN1OctetString) attributeMajorVnoTag.taggedValue();
    byte[] bytes = asn1OctetString.byteValue();
    int attributeMajorVno = ((ASN1Integer) decoder.decode(bytes)).intValue();

    ASN1Tagged attributeMinorVnoTag = ((ASN1Tagged) root.get(1));
    int attributeMinorVno = ((ASN1Integer) decoder.decode(((ASN1OctetString)
            attributeMinorVnoTag.taggedValue()).byteValue())).intValue();

    ASN1Tagged kvnoTag = ((ASN1Tagged) root.get(2));
    int kvno = ((ASN1Integer) decoder.decode(((ASN1OctetString)
            kvnoTag.taggedValue()).byteValue())).intValue();

    ASN1Tagged mkvnoTag = ((ASN1Tagged) root.get(3));
    int mkvno = ((ASN1Integer) decoder.decode(((ASN1OctetString)
            mkvnoTag.taggedValue()).byteValue())).intValue();

    ASN1Tagged keysTag = ((ASN1Tagged) root.get(4));
    ASN1Sequence keysSequence = (ASN1Sequence) decoder.decode(((ASN1OctetString)
            keysTag.taggedValue()).byteValue());
    int size = keysSequence.size();
    try {
      List<EncryptionKey> encryptionKeys = new ArrayList<>();
      for (int i = 0; i < size; i++) {
        ASN1Sequence keySequence = (ASN1Sequence) (keysSequence.get(i)); // KrbKey
        ASN1Tagged keyTag = ((ASN1Tagged) keySequence.get(1));
        ASN1OctetString asn1Object = (ASN1OctetString)keyTag.taggedValue();
        ASN1Sequence decode = (ASN1Sequence)(decoder.decode(asn1Object.byteValue())); // EncryptionKey
        // type
        final ASN1Tagged asn1Tagged = (ASN1Tagged) decode.get(0);
        final ASN1OctetString asn1Object1 = (ASN1OctetString)(asn1Tagged.taggedValue());
        final ASN1Object decode1 = decoder.decode(asn1Object1.byteValue());
        final long e = ((ASN1Integer) decode1).longValue();
        // key
        final ASN1Tagged asn1Tagged1 = (ASN1Tagged) decode.get(1);
        final ASN1OctetString asn1Object2 = (ASN1OctetString)asn1Tagged1.taggedValue();
        final ASN1OctetString decode2 = (ASN1OctetString)decoder.decode(asn1Object2.byteValue());
        final byte[] bytes1 = decode2.byteValue();
        final EncryptionKey encryptionKey = new EncryptionKey(bytes1, ((int) e), kvno);
        encryptionKeys.add(encryptionKey);
      }
      KrbPrincipalKey krbPrincipalKey = new KrbPrincipalKey(encryptionKeys, kvno);
      krbPrincipalKey.setAttributeMajorVno(attributeMajorVno);
      krbPrincipalKey.setAttributeMinorVno(attributeMinorVno);
      return krbPrincipalKey;
    } catch (Exception e) {
      throw new HengHeLdapException(e);
    }
  }

我从 krbprincipalkey 获得的密钥生成了 KeyTab,但是当我 Kinit 时它不起作用。

我怎么了?请求您的指导。 期待有效的解决方案。谢谢。

我找到了解决办法。谢谢观看

krbprincipalkey中的key是用master key加密的,即ASN1解码后,需要用master key再次解密,才能放入KeyTab文件进行认证。

krbprincipalkey ASN1解码后的密钥字节数组中,第一位为实际密钥的长度。从第二位开始,就是主密钥加密后的结果。所以在解密的时候需要使用第二位之后的字节数组才能正确解密。

解密代码如下:

public static byte[] decrypto(byte[] encrypted, byte[] masterKey, int type) throws Exception {
    try {
      EType instance = EType.getInstance(type);
      return instance.decrypt(encrypted, masterKey, KeyUsage.KU_UNKNOWN);
    } catch (Exception e) {
      throw e;
    }
  }

其中type为生成主密钥时的加密类型。

3q.