/**
   * Parse (unmarshal) a <code>PrincipalName</code> from a DER input stream. This form parsing might
   * be used when expanding a value which is part of a constructed sequence and uses explicitly
   * tagged type.
   *
   * @exception Asn1Exception on error.
   * @param data the Der input stream value, which contains one or more marshaled value.
   * @param explicitTag tag number.
   * @param optional indicate if this data field is optional
   * @param realm the realm for the name
   * @return an instance of <code>PrincipalName</code>, or null if the field is optional and
   *     missing.
   */
  public static PrincipalName parse(
      DerInputStream data, byte explicitTag, boolean optional, Realm realm)
      throws Asn1Exception, IOException, RealmException {

    if ((optional) && (((byte) data.peekByte() & (byte) 0x1F) != explicitTag)) return null;
    DerValue der = data.getDerValue();
    if (explicitTag != (der.getTag() & (byte) 0x1F)) {
      throw new Asn1Exception(Krb5.ASN1_BAD_ID);
    } else {
      DerValue subDer = der.getData().getDerValue();
      if (realm == null) {
        realm = Realm.getDefault();
      }
      return new PrincipalName(subDer, realm);
    }
  }
 /**
  * Encodes a <code>PrincipalName</code> object. Note that only the type and names are encoded. To
  * encode the realm, call getRealm().asn1Encode().
  *
  * @return the byte array of the encoded PrncipalName object.
  * @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
  * @exception IOException if an I/O error occurs while reading encoded data.
  */
 public byte[] asn1Encode() throws Asn1Exception, IOException {
   DerOutputStream bytes = new DerOutputStream();
   DerOutputStream temp = new DerOutputStream();
   BigInteger bint = BigInteger.valueOf(this.nameType);
   temp.putInteger(bint);
   bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0x00), temp);
   temp = new DerOutputStream();
   DerValue der[] = new DerValue[nameStrings.length];
   for (int i = 0; i < nameStrings.length; i++) {
     der[i] = new KerberosString(nameStrings[i]).toDerValue();
   }
   temp.putSequence(der);
   bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0x01), temp);
   temp = new DerOutputStream();
   temp.write(DerValue.tag_Sequence, bytes);
   return temp.toByteArray();
 }
 /**
  * Returns the ASN.1 encoding of the <xmp> PrincipalName ::= SEQUENCE { name-type [0] Int32,
  * name-string [1] SEQUENCE OF KerberosString }
  *
  * <p>KerberosString ::= GeneralString (IA5String) </xmp>
  *
  * <p>This definition reflects the Network Working Group RFC 4120 specification available at <a
  * href="http://www.ietf.org/rfc/rfc4120.txt">http://www.ietf.org/rfc/rfc4120.txt</a>.
  *
  * @param encoding a Der-encoded data.
  * @param realm the realm for this name
  * @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
  * @exception Asn1Exception if there is an ASN1 encoding error
  * @exception IOException if an I/O error occurs
  * @exception IllegalArgumentException if encoding is null reading encoded data.
  */
 public PrincipalName(DerValue encoding, Realm realm) throws Asn1Exception, IOException {
   if (realm == null) {
     throw new IllegalArgumentException("Null realm not allowed");
   }
   nameRealm = realm;
   DerValue der;
   if (encoding == null) {
     throw new IllegalArgumentException("Null encoding not allowed");
   }
   if (encoding.getTag() != DerValue.tag_Sequence) {
     throw new Asn1Exception(Krb5.ASN1_BAD_ID);
   }
   der = encoding.getData().getDerValue();
   if ((der.getTag() & 0x1F) == 0x00) {
     BigInteger bint = der.getData().getBigInteger();
     nameType = bint.intValue();
   } else {
     throw new Asn1Exception(Krb5.ASN1_BAD_ID);
   }
   der = encoding.getData().getDerValue();
   if ((der.getTag() & 0x01F) == 0x01) {
     DerValue subDer = der.getData().getDerValue();
     if (subDer.getTag() != DerValue.tag_SequenceOf) {
       throw new Asn1Exception(Krb5.ASN1_BAD_ID);
     }
     Vector<String> v = new Vector<>();
     DerValue subSubDer;
     while (subDer.getData().available() > 0) {
       subSubDer = subDer.getData().getDerValue();
       String namePart = new KerberosString(subSubDer).toString();
       v.addElement(namePart);
     }
     nameStrings = new String[v.size()];
     v.copyInto(nameStrings);
     validateNameStrings(nameStrings);
   } else {
     throw new Asn1Exception(Krb5.ASN1_BAD_ID);
   }
 }