Пример #1
0
  /**
   * Decode an ASN.1 BIT STRING.
   *
   * @param buf the buffer containing the DER-encoded BIT STRING.
   * @return the bits in the BIT STRING
   */
  public static BitSet decodeBitString(ByteBuffer buf) {
    DerId id = DerId.decode(buf);
    if (!id.matches(DerId.TagClass.UNIVERSAL, DerId.EncodingType.PRIMITIVE, ASN1_BIT_STRING_TAG_NUM)
        && !id.matches(
            DerId.TagClass.UNIVERSAL, DerId.EncodingType.CONSTRUCTED, ASN1_BIT_STRING_TAG_NUM)) {
      throw new IllegalArgumentException("Expected BIT STRING identifier, received " + id);
    }
    int len = DerUtils.decodeLength(buf);
    if (buf.remaining() < len) {
      throw new IllegalArgumentException("Insufficient content for BIT STRING");
    }

    // If primitive encoding, then the initial octet is just used for padding
    if (id.getEncodingType() == DerId.EncodingType.PRIMITIVE) {
      buf.get();
      len--;
    }

    int nbits = len * 8;
    BitSet bits = new BitSet(nbits);
    for (int i = 0; i < len; i++) {
      short next = (short) (0xff & buf.get());
      int bitIndex = (i + 1) * 8 - 1;
      while (next != 0) {
        if ((next & 1) == 1) {
          bits.set(bitIndex);
        }
        bitIndex--;
        next >>>= 1;
      }
    }
    return bits;
  }
Пример #2
0
 /**
  * Decode an ASN.1 SEQUENCE by reading the identifier and length octets. The remaining data in the
  * buffer is the SEQUENCE.
  *
  * @param buf the DER-encoded SEQUENCE
  * @return the length of the SEQUENCE
  */
 public static int decodeSequence(ByteBuffer buf) {
   DerId id = DerId.decode(buf);
   if (!id.matches(
       DerId.TagClass.UNIVERSAL, DerId.EncodingType.CONSTRUCTED, ASN1_SEQUENCE_TAG_NUM)) {
     throw new IllegalArgumentException("Expected SEQUENCE identifier, received " + id);
   }
   int len = DerUtils.decodeLength(buf);
   if (buf.remaining() < len) {
     throw new IllegalArgumentException("Insufficient content for SEQUENCE");
   }
   return len;
 }
Пример #3
0
 /**
  * Decode an ASN.1 IA5String.
  *
  * @param buf the DER-encoded IA5String
  * @return the string
  */
 public static String decodeIA5String(ByteBuffer buf) {
   DerId id = DerId.decode(buf);
   if (!id.matches(
       DerId.TagClass.UNIVERSAL, DerId.EncodingType.PRIMITIVE, ASN1_IA5STRING_TAG_NUM)) {
     throw new IllegalArgumentException("Expected IA5String identifier, received " + id);
   }
   int len = DerUtils.decodeLength(buf);
   if (buf.remaining() < len) {
     throw new IllegalArgumentException("Insufficient content for IA5String");
   }
   byte[] dst = new byte[len];
   buf.get(dst);
   return new String(dst);
 }
Пример #4
0
  /**
   * Decode an ASN.1 GeneralizedTime.
   *
   * @param buf the DER-encoded GeneralizedTime
   * @return the data and time
   */
  public static Date decodeGeneralizedTime(ByteBuffer buf) {
    // GeneralizedTime ::= [UNIVERSAL 24] IMPLICIT VisibleString
    DerId id = DerId.decode(buf);
    if (!id.matches(
        DerId.TagClass.UNIVERSAL, DerId.EncodingType.PRIMITIVE, ASN1_GENERALIZED_TIME_TAG_NUM)) {
      throw new IllegalArgumentException("Expected GeneralizedTime identifier, received " + id);
    }
    int len = DerUtils.decodeLength(buf);
    if (buf.remaining() < len) {
      throw new IllegalArgumentException("Insufficient content for GeneralizedTime");
    }

    Date date = null;

    byte[] dst = new byte[len];
    buf.get(dst);
    String iso8601DateString = new String(dst);
    Matcher matcher = GENERALIZED_TIME_PATTERN.matcher(iso8601DateString);
    if (matcher.matches()) {
      Calendar cal = Calendar.getInstance();
      cal.clear();

      // Process yyyyMMddHHmmss
      cal.set(Calendar.YEAR, Integer.parseInt(matcher.group(1)));
      cal.set(
          Calendar.MONTH, Integer.parseInt(matcher.group(2)) - 1); // Calendar.MONTH is zero based
      cal.set(Calendar.DAY_OF_MONTH, Integer.parseInt(matcher.group(3)));
      cal.set(Calendar.HOUR_OF_DAY, Integer.parseInt(matcher.group(4)));
      cal.set(Calendar.MINUTE, Integer.parseInt(matcher.group(5)));
      cal.set(Calendar.SECOND, Integer.parseInt(matcher.group(6)));

      // Process fractional seconds, if any
      String fracSecStr = matcher.group(7);
      if (fracSecStr != null) {
        cal.set(Calendar.MILLISECOND, (int) (Float.parseFloat(fracSecStr) * 1000));
      }

      // Process time zone, if any
      String tzStr = matcher.group(8);
      if (tzStr != null) {
        cal.setTimeZone(TimeZone.getTimeZone("Z".equals(tzStr) ? "GMT" : "GMT" + tzStr));
      }

      date = cal.getTime();
    } else {
      throw new IllegalArgumentException("Malformed GeneralizedTime " + iso8601DateString);
    }
    return date;
  }
Пример #5
0
 /**
  * Decode an ASN.1 OCTET STRING.
  *
  * @param buf the DER-encoded OCTET STRING
  * @return the octets
  */
 public static short[] decodeOctetString(ByteBuffer buf) {
   DerId id = DerId.decode(buf);
   if (!id.matches(DerId.TagClass.UNIVERSAL, ASN1_OCTET_STRING_TAG_NUM)) {
     throw new IllegalArgumentException("Expected OCTET STRING identifier, received " + id);
   }
   int len = DerUtils.decodeLength(buf);
   if (buf.remaining() < len) {
     throw new IllegalArgumentException("Insufficient content for OCTET STRING");
   }
   short[] dst = new short[len];
   for (int i = 0; i < len; i++) {
     dst[i] = (short) (0xff & buf.get());
   }
   return dst;
 }
Пример #6
0
 /**
  * Decode an ASN.1 INTEGER.
  *
  * @param buf the buffer containing the DER-encoded INTEGER
  * @return the value of the INTEGER
  */
 public static int decodeInteger(ByteBuffer buf) {
   DerId id = DerId.decode(buf);
   if (!id.matches(DerId.TagClass.UNIVERSAL, DerId.EncodingType.PRIMITIVE, ASN1_INTEGER_TAG_NUM)) {
     throw new IllegalArgumentException("Expected INTEGER identifier, received " + id);
   }
   int len = DerUtils.decodeLength(buf);
   if (buf.remaining() < len) {
     throw new IllegalArgumentException("Insufficient content for INTEGER");
   }
   int value = 0;
   for (int i = 0; i < len; i++) {
     value = (value << 8) + (0xff & buf.get());
   }
   return value;
 }