Search code examples
kerberosopenldap

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


We are using Kerberos + openldap. In our java project, we hope to create krbprincipal in openldap through Java API, read krbprincipal entry in openldap, parse its attribute krbprincipalkey, and write it to KeyTab file.

The following is a demo of how I use the jldap library to parse krbprincipalkey.

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);
    }
  }

I generated KeyTab from the key I got from krbprincipalkey, but it didn't work when I Kinit.

What's wrong with me? Ask for your guidance. Looking forward to an effective solution. Thank you.


Solution

  • I've found a solution. Thank you for watching.

    The key in the krbprincipalkey is encrypted by the master key, that is, after ASN1 decode, the master key needs to be used to decrypt again before it can be put into the KeyTab file for authentication.

    In the key byte array after krbprincipalkey ASN1 decode, the first bit is the length of the actual key. Starting from the second bit, it is the result encrypted by master key. Therefore, when decrypting, you need to use the byte array after the second bit to decrypt correctly.

    The decryption code is as follows:

    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;
        }
      }
    

    Where type is the encryption type when the master key is generated.

    3q.