diff options
Diffstat (limited to 'pki/base/util/src/netscape/security/util/DerOutputStream.java')
-rw-r--r-- | pki/base/util/src/netscape/security/util/DerOutputStream.java | 746 |
1 files changed, 382 insertions, 364 deletions
diff --git a/pki/base/util/src/netscape/security/util/DerOutputStream.java b/pki/base/util/src/netscape/security/util/DerOutputStream.java index 0a297b193..be42322fa 100644 --- a/pki/base/util/src/netscape/security/util/DerOutputStream.java +++ b/pki/base/util/src/netscape/security/util/DerOutputStream.java @@ -31,105 +31,100 @@ import java.util.TimeZone; import sun.io.CharToByteConverter; /** - * Output stream marshaling DER-encoded data. This is eventually provided in the - * form of a byte array; there is no advance limit on the size of that byte - * array. - * - * <P> - * At this time, this class supports only a subset of the types of DER data - * encodings which are defined. That subset is sufficient for generating most - * X.509 certificates. - * + * Output stream marshaling DER-encoded data. This is eventually provided + * in the form of a byte array; there is no advance limit on the size of + * that byte array. + * + * <P>At this time, this class supports only a subset of the types of + * DER data encodings which are defined. That subset is sufficient for + * generating most X.509 certificates. + * * @version 1.32 - * + * * @author David Brownell * @author Amit Kapoor * @author Hemma Prafullchandra */ -public class DerOutputStream extends ByteArrayOutputStream implements - DerEncoder { +public class DerOutputStream +extends ByteArrayOutputStream implements DerEncoder { /** * Construct an DER output stream. - * + * * @param size how large a buffer to preallocate. */ - public DerOutputStream(int size) { - super(size); - } + public DerOutputStream(int size) { super(size); } /** * Construct an DER output stream. */ - public DerOutputStream() { - } + public DerOutputStream() { } /** - * Writes tagged, pre-marshaled data. This calcuates and encodes the length, - * so that the output data is the standard triple of { tag, length, data } - * used by all DER values. - * + * Writes tagged, pre-marshaled data. This calcuates and encodes + * the length, so that the output data is the standard triple of + * { tag, length, data } used by all DER values. + * * @param tag the DER value tag for the data, such as - * <em>DerValue.tag_Sequence</em> + * <em>DerValue.tag_Sequence</em> * @param buf buffered data, which must be DER-encoded */ public void write(byte tag, byte[] buf) throws IOException { - write(tag); - putLength(buf.length); - write(buf, 0, buf.length); + write(tag); + putLength(buf.length); + write(buf, 0, buf.length); } /** - * Writes tagged data using buffer-to-buffer copy. As above, this writes a - * standard DER record. This is often used when efficiently encapsulating - * values in sequences. - * + * Writes tagged data using buffer-to-buffer copy. As above, + * this writes a standard DER record. This is often used when + * efficiently encapsulating values in sequences. + * * @param tag the DER value tag for the data, such as - * <em>DerValue.tag_Sequence</em> + * <em>DerValue.tag_Sequence</em> * @param out buffered data */ public void write(byte tag, DerOutputStream out) throws IOException { - write(tag); - putLength(out.count); - write(out.buf, 0, out.count); + write(tag); + putLength(out.count); + write(out.buf, 0, out.count); } /** - * Writes implicitly tagged data using buffer-to-buffer copy. As above, this - * writes a standard DER record. This is often used when efficiently - * encapsulating implicitly tagged values. - * + * Writes implicitly tagged data using buffer-to-buffer copy. As above, + * this writes a standard DER record. This is often used when + * efficiently encapsulating implicitly tagged values. + * * @param tag the DER value of the context-specific tag that replaces - * original tag of the value in the output , such as in - * - * <pre> - * <em> <field> [N] IMPLICIT <type></em> + * original tag of the value in the output , such as in + * <pre> + * <em> <field> [N] IMPLICIT <type></em> * </pre> - * - * For example, <em>FooLength [1] IMPLICIT INTEGER</em>, with - * value=4; would be encoded as "81 01 04" whereas in explicit - * tagging it would be encoded as "A1 03 02 01 04". Notice that - * the tag is A1 and not 81, this is because with explicit - * tagging the form is always constructed. + * For example, <em>FooLength [1] IMPLICIT INTEGER</em>, with value=4; + * would be encoded as "81 01 04" whereas in explicit + * tagging it would be encoded as "A1 03 02 01 04". + * Notice that the tag is A1 and not 81, this is because with + * explicit tagging the form is always constructed. * @param value original value being implicitly tagged */ public void writeImplicit(byte tag, DerOutputStream value) - throws IOException { - write(tag); - write(value.buf, 1, value.count - 1); + throws IOException { + write(tag); + write(value.buf, 1, value.count-1); } /** * Marshals pre-encoded DER value onto the output stream. */ public void putDerValue(DerValue val) throws IOException { - val.encode(this); + val.encode(this); } /* * PRIMITIVES -- these are "universal" ASN.1 simple types. - * - * BOOLEAN, INTEGER, BIT STRING, OCTET STRING, NULL OBJECT IDENTIFIER, - * SEQUENCE(OF), SET(OF) PrintableString, T61String, IA5String, UTCTime + * + * BOOLEAN, INTEGER, BIT STRING, OCTET STRING, NULL + * OBJECT IDENTIFIER, SEQUENCE(OF), SET(OF) + * PrintableString, T61String, IA5String, UTCTime */ /** @@ -148,32 +143,34 @@ public class DerOutputStream extends ByteArrayOutputStream implements /** * Marshals a DER unsigned integer on the output stream. */ - public void putInteger(BigInt i) throws IOException { - putUnsignedInteger(i.toByteArray()); - } + public void putInteger(BigInt i) throws IOException + { + putUnsignedInteger(i.toByteArray()); + } /** * Marshals a DER unsigned integer on the output stream. */ - public void putUnsignedInteger(byte[] integerBytes) throws IOException { + public void putUnsignedInteger(byte [] integerBytes) throws IOException { - write(DerValue.tag_Integer); - if ((integerBytes[0] & 0x080) != 0) { - /* - * prepend zero so it's not read as a negative number - */ - putLength(integerBytes.length + 1); - write(0); - } else - putLength(integerBytes.length); - write(integerBytes, 0, integerBytes.length); + write(DerValue.tag_Integer); + if ((integerBytes [0] & 0x080) != 0) { + /* + * prepend zero so it's not read as a negative number + */ + putLength(integerBytes.length + 1); + write(0); + } else + putLength(integerBytes.length); + write(integerBytes, 0, integerBytes.length); } /** * Marshals a DER enumerated value on the output stream. */ - public void putEnumerated(int i) throws IOException { - write(DerValue.tag_Enumerated); + public void putEnumerated(int i) throws IOException + { + write(DerValue.tag_Enumerated); int bytemask = 0xff000000; int signmask = 0x80000000; @@ -181,91 +178,92 @@ public class DerOutputStream extends ByteArrayOutputStream implements if ((i & 0x80000000) != 0) { // negative case for (length = 4; length > 1; --length) { - if ((i & bytemask) != bytemask) + if((i & bytemask) != bytemask) break; - bytemask = bytemask >>> 8; - signmask = signmask >>> 8; + bytemask = bytemask >>> 8; + signmask = signmask >>> 8; } if ((i & signmask) == 0) { // ensure negative case - putLength(length + 1); + putLength(length+1); write(0xff); } else { - putLength(length); + putLength(length); } // unrolled loop switch (length) { - case 4: - write((byte) (i >>> 24)); - case 3: - write((byte) (i >>> 16)); - case 2: - write((byte) (i >>> 8)); - case 1: - write((byte) i); + case 4: + write((byte)(i >>> 24)); + case 3: + write((byte)(i >>> 16)); + case 2: + write((byte)(i >>> 8)); + case 1: + write((byte)i); } } else { // positive case for (length = 4; length > 0; --length) { - if ((i & bytemask) != 0) + if((i & bytemask) != 0) break; - bytemask = bytemask >>> 8; - signmask = signmask >>> 8; + bytemask = bytemask >>> 8; + signmask = signmask >>> 8; } if ((i & signmask) != 0) { // ensure posititive case - putLength(length + 1); + putLength(length+1); write(0x00); } else { - putLength(length); + putLength(length); } // unrolled loop switch (length) { - case 4: - write((byte) (i >>> 24)); - case 3: - write((byte) (i >>> 16)); - case 2: - write((byte) (i >>> 8)); - case 1: - write((byte) i); + case 4: + write((byte)(i >>> 24)); + case 3: + write((byte)(i >>> 16)); + case 2: + write((byte)(i >>> 8)); + case 1: + write((byte)i); } } } /** - * Marshals a DER bit string on the output stream. The bit string must be - * byte-aligned. - * + * Marshals a DER bit string on the output stream. The bit + * string must be byte-aligned. + * * @param bits the bit string, MSB first */ public void putBitString(byte[] bits) throws IOException { - write(DerValue.tag_BitString); - putLength(bits.length + 1); - write(0); // all of last octet is used - write(bits); + write(DerValue.tag_BitString); + putLength(bits.length + 1); + write(0); // all of last octet is used + write(bits); } /** - * Converts a boolean array to a BitArray. Trims trailing 0 bits in - * accordance with DER encoding standard. We assume the input is not null. + * Converts a boolean array to a BitArray. Trims trailing 0 bits + * in accordance with DER encoding standard. We assume the input is not + * null. */ private static BitArray toBitArray(boolean[] bitString) { - if (bitString.length == 0) { + if( bitString.length == 0 ) { return new BitArray(bitString); } // find index of last 1 bit. -1 if there aren't any int i; - for (i = bitString.length - 1; i >= 0; i--) { - if (bitString[i]) { + for(i=bitString.length-1; i >= 0; i--) { + if(bitString[i]) { break; } } - int length = i + 1; + int length = i+1; // if length changed, copy to new appropriately-sized array - if (length != bitString.length) { + if(length != bitString.length) { boolean[] newBitString = new boolean[length]; System.arraycopy(bitString, 0, newBitString, 0, length); bitString = newBitString; @@ -275,30 +273,30 @@ public class DerOutputStream extends ByteArrayOutputStream implements } /** - * Converts bit string to a BitArray, stripping off trailing 0 bits. We - * assume that the bit string is not null. + * Converts bit string to a BitArray, stripping off trailing 0 bits. + * We assume that the bit string is not null. */ private static BitArray toBitArray(byte[] bitString) { // compute length in bits of bit string int length, i; int maxIndex = 0; - if (bitString.length == 0) { + if( bitString.length == 0 ) { return new BitArray(0, bitString); } // find the index of the last byte with a 1 bit - for (i = 0; i < bitString.length; i++) { - if (bitString[i] != 0) { + for( i = 0; i < bitString.length; i++) { + if( bitString[i] != 0 ) { maxIndex = i; } } byte lastByte = bitString[maxIndex]; - length = (maxIndex + 1) * 8; // maximum, might reduce in next step + length = (maxIndex+1) * 8; // maximum, might reduce in next step - // now find the last 1 bit in this last byte - for (i = 1; i <= 0x80; i <<= 1) { - if ((lastByte & i) == 0) { + // now find the last 1 bit in this last byte + for(i=1; i <= 0x80; i <<= 1) { + if( (lastByte & i) == 0 ) { length--; } else { break; @@ -307,325 +305,345 @@ public class DerOutputStream extends ByteArrayOutputStream implements return new BitArray(length, bitString); } + /** - * Marshals a DER bit string on the output stream. The bit strings need not - * be byte-aligned. - * + * Marshals a DER bit string on the output stream. + * The bit strings need not be byte-aligned. + * * @param bits the bit string, MSB first */ public void putUnalignedBitString(BitArray ba) throws IOException { - byte[] bits = ba.toByteArray(); + byte[] bits = ba.toByteArray(); - write(DerValue.tag_BitString); - putLength(bits.length + 1); - write(bits.length * 8 - ba.length()); // excess bits in last octet - write(bits); + write(DerValue.tag_BitString); + putLength(bits.length + 1); + write(bits.length*8 - ba.length()); // excess bits in last octet + write(bits); } /** - * Marshals a DER bit string on the output stream. All trailing 0 bits will - * be stripped off in accordance with DER encoding. - * + * Marshals a DER bit string on the output stream. + * All trailing 0 bits will be stripped off in accordance with DER + * encoding. + * * @param bits the bit string, MSB first */ public void putUnalignedBitString(byte[] bitString) throws IOException { - putUnalignedBitString(toBitArray(bitString)); + putUnalignedBitString( toBitArray(bitString) ); } /** - * Marshals a DER bit string on the output stream. All trailing 0 bits will - * be stripped off in accordance with DER encoding. - * + * Marshals a DER bit string on the output stream. + * All trailing 0 bits will be stripped off in accordance with DER + * encoding. + * * @param bits the bit string as an array of booleans. */ public void putUnalignedBitString(boolean[] bitString) throws IOException { - putUnalignedBitString(toBitArray(bitString)); + putUnalignedBitString( toBitArray(bitString) ); } /** * DER-encodes an ASN.1 OCTET STRING value on the output stream. - * + * * @param octets the octet string */ public void putOctetString(byte[] octets) throws IOException { - write(DerValue.tag_OctetString, octets); + write(DerValue.tag_OctetString, octets); } /** - * Marshals a DER "null" value on the output stream. These are often used to - * indicate optional values which have been omitted. + * Marshals a DER "null" value on the output stream. These are + * often used to indicate optional values which have been omitted. */ public void putNull() throws IOException { - write(DerValue.tag_Null); - putLength(0); + write(DerValue.tag_Null); + putLength(0); } /** - * Marshals an object identifier (OID) on the output stream. Corresponds to - * the ASN.1 "OBJECT IDENTIFIER" construct. + * Marshals an object identifier (OID) on the output stream. + * Corresponds to the ASN.1 "OBJECT IDENTIFIER" construct. */ public void putOID(ObjectIdentifier oid) throws IOException { - oid.encode(this); + oid.encode(this); } /** - * Marshals a sequence on the output stream. This supports both the ASN.1 - * "SEQUENCE" (zero to N values) and "SEQUENCE OF" (one to N values) - * constructs. + * Marshals a sequence on the output stream. This supports both + * the ASN.1 "SEQUENCE" (zero to N values) and "SEQUENCE OF" + * (one to N values) constructs. */ public void putSequence(DerValue[] seq) throws IOException { - DerOutputStream bytes = new DerOutputStream(); - int i; + DerOutputStream bytes = new DerOutputStream(); + int i; - for (i = 0; i < seq.length; i++) - seq[i].encode(bytes); + for (i = 0; i < seq.length; i++) + seq [i].encode(bytes); - write(DerValue.tag_Sequence, bytes); + write(DerValue.tag_Sequence, bytes); } /** - * Marshals the contents of a set on the output stream without ordering the - * elements. Ok for BER encoding, but not for DER encoding. - * - * For DER encoding, use orderedPutSet() or orderedPutSetOf(). + * Marshals the contents of a set on the output stream without + * ordering the elements. Ok for BER encoding, but not for DER + * encoding. + * + * For DER encoding, use orderedPutSet() or orderedPutSetOf(). */ public void putSet(DerValue[] set) throws IOException { - DerOutputStream bytes = new DerOutputStream(); - int i; + DerOutputStream bytes = new DerOutputStream(); + int i; - for (i = 0; i < set.length; i++) - set[i].encode(bytes); + for (i = 0; i < set.length; i++) + set [i].encode(bytes); - write(DerValue.tag_Set, bytes); + write(DerValue.tag_Set, bytes); } /** - * NSCP : Like putOrderSetOf, except not sorted. This may defy DER encoding - * but is needed for compatibility with communicator. + * NSCP : + * Like putOrderSetOf, except not sorted. + * This may defy DER encoding but is needed for compatibility + * with communicator. */ public void putSet(byte tag, DerEncoder[] set) throws IOException { - putOrderedSet(tag, set, null); + putOrderedSet(tag, set, null); } - /** - * Marshals the contents of a set on the output stream. Sets are - * semantically unordered, but DER requires that encodings of set elements - * be sorted into ascending lexicographical order before being output. Hence - * sets with the same tags and elements have the same DER encoding. - * - * This method supports the ASN.1 "SET OF" construct, but not "SET", which - * uses a different order. + /** + * Marshals the contents of a set on the output stream. Sets + * are semantically unordered, but DER requires that encodings of + * set elements be sorted into ascending lexicographical order + * before being output. Hence sets with the same tags and + * elements have the same DER encoding. + * + * This method supports the ASN.1 "SET OF" construct, but not + * "SET", which uses a different order. */ public void putOrderedSetOf(byte tag, DerEncoder[] set) throws IOException { - putOrderedSet(tag, set, lexOrder); + putOrderedSet(tag, set, lexOrder); } - /** - * Marshals the contents of a set on the output stream. Sets are - * semantically unordered, but DER requires that encodings of set elements - * be sorted into ascending tag order before being output. Hence sets with - * the same tags and elements have the same DER encoding. - * - * This method supports the ASN.1 "SET" construct, but not "SET OF", which - * uses a different order. + /** + * Marshals the contents of a set on the output stream. Sets + * are semantically unordered, but DER requires that encodings of + * set elements be sorted into ascending tag order + * before being output. Hence sets with the same tags and + * elements have the same DER encoding. + * + * This method supports the ASN.1 "SET" construct, but not + * "SET OF", which uses a different order. */ public void putOrderedSet(byte tag, DerEncoder[] set) throws IOException { - putOrderedSet(tag, set, tagOrder); + putOrderedSet(tag, set, tagOrder); } /** - * Lexicographical order comparison on byte arrays, for ordering elements of - * a SET OF objects in DER encoding. + * Lexicographical order comparison on byte arrays, for ordering + * elements of a SET OF objects in DER encoding. */ private static ByteArrayLexOrder lexOrder = new ByteArrayLexOrder(); /** - * Tag order comparison on byte arrays, for ordering elements of SET objects - * in DER encoding. + * Tag order comparison on byte arrays, for ordering elements of + * SET objects in DER encoding. */ private static ByteArrayTagOrder tagOrder = new ByteArrayTagOrder(); - /** - * Marshals a the contents of a set on the output stream with the encodings - * of its sorted in increasing order. - * + /** + * Marshals a the contents of a set on the output stream with the + * encodings of its sorted in increasing order. + * * @param order the order to use when sorting encodings of components. */ - private void putOrderedSet(byte tag, DerEncoder[] set, Comparator order) - throws IOException { - DerOutputStream[] streams = new DerOutputStream[set.length]; + private void putOrderedSet(byte tag, DerEncoder[] set, + Comparator order) throws IOException { + DerOutputStream[] streams = new DerOutputStream[set.length]; - for (int i = 0; i < set.length; i++) { - streams[i] = new DerOutputStream(); - set[i].derEncode(streams[i]); - } + for (int i = 0; i < set.length; i++) { + streams[i] = new DerOutputStream(); + set[i].derEncode(streams[i]); + } - // order the element encodings - byte[][] bufs = new byte[streams.length][]; - for (int i = 0; i < streams.length; i++) { - bufs[i] = streams[i].toByteArray(); - } - if (order != null) { - Arrays.sort(bufs, order); - } + // order the element encodings + byte[][] bufs = new byte[streams.length][]; + for (int i = 0; i < streams.length; i++) { + bufs[i] = streams[i].toByteArray(); + } + if (order != null) { + Arrays.sort(bufs, order); + } - DerOutputStream bytes = new DerOutputStream(); - for (int i = 0; i < streams.length; i++) { - bytes.write(bufs[i]); - } - write(tag, bytes); + DerOutputStream bytes = new DerOutputStream(); + for (int i = 0; i < streams.length; i++) { + bytes.write(bufs[i]); + } + write(tag, bytes); } /** * Converts string to printable and writes to der output stream. */ - public void putPrintableString(String s) throws IOException { - putStringType(DerValue.tag_PrintableString, s); + public void putPrintableString(String s) throws IOException + { + putStringType(DerValue.tag_PrintableString, s); } - public void putVisibleString(String s) throws IOException { - putStringType(DerValue.tag_VisibleString, s); + public void putVisibleString(String s) throws IOException + { + putStringType(DerValue.tag_VisibleString, s); } - /** * Marshals a string which is consists of BMP (unicode) characters */ - public void putBMPString(String s) throws IOException { - putStringType(DerValue.tag_BMPString, s); + public void putBMPString(String s) throws IOException + { + putStringType(DerValue.tag_BMPString, s); } - public void putGeneralString(String s) throws IOException { - putStringType(DerValue.tag_GeneralString, s); + public void putGeneralString(String s) throws IOException + { + putStringType(DerValue.tag_GeneralString, s); } - // /* - // * T61 is an 8 bit extension to ASCII, escapes e.g. to Japanese - // */ - // void putT61String(String s) throws IOException - // { - // // XXX IMPLEMENT ME - // - // throw new IOException("DerOutputStream.putT61String() NYI"); - // } - - // /* - // * Universal String. - // */ - // void putUniversalString(String s) throws IOException - // { - // // XXX IMPLEMENT ME - // - // throw new IOException("DerOutputStream.putUniversalString() NYI"); - // } +// /* +// * T61 is an 8 bit extension to ASCII, escapes e.g. to Japanese +// */ +// void putT61String(String s) throws IOException +// { +// // XXX IMPLEMENT ME +// +// throw new IOException("DerOutputStream.putT61String() NYI"); +// } + +// /* +// * Universal String. +// */ +// void putUniversalString(String s) throws IOException +// { +// // XXX IMPLEMENT ME +// +// throw new IOException("DerOutputStream.putUniversalString() NYI"); +// } /** * Marshals a string which is consists of IA5(ASCII) characters */ - public void putIA5String(String s) throws IOException { - putStringType(DerValue.tag_IA5String, s); - } - - public void putUTF8String(String s) throws IOException { - putStringType(DerValue.tag_UTF8String, s); - } - - public void putStringType(byte tag, String s) throws IOException { - int next_byte_index; - CharToByteConverter cbc; - byte buf[]; - try { - cbc = ASN1CharStrConvMap.getDefault().getCBC(tag); - if (cbc == null) - throw new IOException("No character to byte converter for tag"); - buf = new byte[cbc.getMaxBytesPerChar() * s.length()]; - // Don't use convertAll() here b/c it does not throw - // UnknownCharacterException. - next_byte_index = cbc.convert(s.toCharArray(), 0, s.length(), buf, - 0, buf.length); - } catch (java.io.CharConversionException e) { - throw new IOException("Not a valid string type " + tag); - } catch (IllegalAccessException e) { - throw new IOException("Cannot load CharToByteConverter class " - + "for DER tag " + tag); - } catch (InstantiationException e) { - throw new IOException("Cannot instantiate CharToByteConverter " - + "class for DER tag " + tag); - } - - // next_byte_index = cbc.nextByteIndex(); - write(tag); - putLength(next_byte_index); - write(buf, 0, next_byte_index); - } - - private void put2DateBytes(byte[] buffer, int value, int offset) { - int upper = value / 10; - int lower = value % 10; - buffer[offset] = (byte) ((byte) upper + (byte) '0'); - buffer[offset + 1] = (byte) ((byte) lower + (byte) '0'); + public void putIA5String(String s) throws IOException + { + putStringType(DerValue.tag_IA5String, s); + } + + public void putUTF8String(String s) throws IOException + { + putStringType(DerValue.tag_UTF8String, s); + } + + public void putStringType(byte tag, String s) throws IOException + { + int next_byte_index; + CharToByteConverter cbc; + byte buf[]; + try { + cbc = ASN1CharStrConvMap.getDefault().getCBC(tag); + if (cbc == null) + throw new IOException("No character to byte converter for tag"); + buf= new byte[cbc.getMaxBytesPerChar()*s.length()]; + // Don't use convertAll() here b/c it does not throw + // UnknownCharacterException. + next_byte_index = cbc.convert(s.toCharArray(), 0, s.length(), buf, 0, buf.length); + } + catch (java.io.CharConversionException e) { + throw new IOException("Not a valid string type "+ tag); + } + catch (IllegalAccessException e) { + throw new IOException("Cannot load CharToByteConverter class "+ + "for DER tag "+tag); + } + catch (InstantiationException e) { + throw new IOException("Cannot instantiate CharToByteConverter "+ + "class for DER tag "+tag); + } + + //next_byte_index = cbc.nextByteIndex(); + write(tag); + putLength(next_byte_index); + write(buf, 0, next_byte_index); + } + + private void put2DateBytes(byte[] buffer, int value, int offset) + { + int upper= value/10; + int lower = value%10; + buffer[offset] = (byte)((byte)upper + (byte)'0'); + buffer[offset+1] = (byte)((byte)lower + (byte)'0'); } private static Calendar GMTGregorianCalendar = null; - private Calendar getGMTGregorianCalendar() { - if (GMTGregorianCalendar == null) { - TimeZone tz = TimeZone.getTimeZone("GMT"); - GMTGregorianCalendar = new GregorianCalendar(tz); - } - return (Calendar) GMTGregorianCalendar.clone(); - } - - public byte[] getDateBytes(Date d, boolean UTC) { - + private Calendar getGMTGregorianCalendar() + { + if (GMTGregorianCalendar == null) { + TimeZone tz = TimeZone.getTimeZone("GMT"); + GMTGregorianCalendar = new GregorianCalendar(tz); + } + return (Calendar)GMTGregorianCalendar.clone(); + } + + public byte[] getDateBytes(Date d, boolean UTC) + { + byte[] datebytes; if (UTC) { datebytes = new byte[13]; - } else { // generalized time has 4 digits for yr + } + else { // generalized time has 4 digits for yr datebytes = new byte[15]; } Calendar cal = getGMTGregorianCalendar(); cal.setTime(d); - int i = 0; + int i=0; if (!UTC) { - put2DateBytes(datebytes, cal.get(Calendar.YEAR) / 100, i); - i += 2; + put2DateBytes(datebytes,cal.get(Calendar.YEAR)/100,i); + i+= 2; } - put2DateBytes(datebytes, cal.get(Calendar.YEAR) % 100, i); + put2DateBytes(datebytes,cal.get(Calendar.YEAR)%100 ,i); // Calendar's MONTH is zero-based - i += 2; - put2DateBytes(datebytes, cal.get(Calendar.MONTH) + 1, i); - i += 2; - put2DateBytes(datebytes, cal.get(Calendar.DAY_OF_MONTH), i); - i += 2; - put2DateBytes(datebytes, cal.get(Calendar.HOUR_OF_DAY), i); - i += 2; - put2DateBytes(datebytes, cal.get(Calendar.MINUTE), i); - i += 2; - put2DateBytes(datebytes, cal.get(Calendar.SECOND), i); - i += 2; + i+= 2; + put2DateBytes(datebytes,cal.get(Calendar.MONTH)+1 ,i); + i+= 2; + put2DateBytes(datebytes,cal.get(Calendar.DAY_OF_MONTH),i); + i+= 2; + put2DateBytes(datebytes,cal.get(Calendar.HOUR_OF_DAY) ,i); + i+= 2; + put2DateBytes(datebytes,cal.get(Calendar.MINUTE) ,i); + i+= 2; + put2DateBytes(datebytes,cal.get(Calendar.SECOND) ,i); + i+= 2; // datebytes[i] = 'Z'; - datebytes[i] = (byte) 'Z'; - + datebytes[i] = (byte)'Z'; + return datebytes; } /** * Marshals a DER UTC time/date value. - * - * <P> - * YYMMDDhhmmss{Z|+hhmm|-hhmm} ... emits only using Zulu time and with - * seconds (even if seconds=0) as per IETF-PKIX partI. + * + * <P>YYMMDDhhmmss{Z|+hhmm|-hhmm} ... emits only using Zulu time + * and with seconds (even if seconds=0) as per IETF-PKIX partI. */ public void putUTCTime(Date d) throws IOException { - /* - * Format the date. - */ + /* + * Format the date. + */ + - // This was the old code. Way too slow to be usable (stevep) + // This was the old code. Way too slow to be usable (stevep) // String pattern = "yyMMddHHmmss'Z'"; // SimpleDateFormat sdf = new SimpleDateFormat(pattern); @@ -633,38 +651,37 @@ public class DerOutputStream extends ByteArrayOutputStream implements // sdf.setTimeZone(tz); // byte[] utc = (sdf.format(d)).getBytes(); - byte[] datebytes = getDateBytes(d, true); // UTC = true + byte[] datebytes = getDateBytes(d,true); // UTC = true - /* - * Write the formatted date. - */ - write(DerValue.tag_UtcTime); + /* + * Write the formatted date. + */ + write (DerValue.tag_UtcTime); putLength(datebytes.length); write(datebytes); } /** * Marshals a DER Generalized Time/date value. - * - * <P> - * YYYYMMDDhhmmss{Z|+hhmm|-hhmm} ... emits only using Zulu time and with - * seconds (even if seconds=0) as per IETF-PKIX partI. + * + * <P>YYYYMMDDhhmmss{Z|+hhmm|-hhmm} ... emits only using Zulu time + * and with seconds (even if seconds=0) as per IETF-PKIX partI. */ public void putGeneralizedTime(Date d) throws IOException { /* * Format the date. */ TimeZone tz = TimeZone.getTimeZone("GMT"); - - // This is way too slow to be usable (stevep) + + // This is way too slow to be usable (stevep) String pattern = "yyyyMMddHHmmss'Z'"; SimpleDateFormat sdf = new SimpleDateFormat(pattern); sdf.setTimeZone(tz); byte[] gt = (sdf.format(d)).getBytes(); - /* - * Write the formatted date. - */ + /* + * Write the formatted date. + */ write(DerValue.tag_GeneralizedTime); putLength(gt.length); write(gt); @@ -672,61 +689,62 @@ public class DerOutputStream extends ByteArrayOutputStream implements /** * Put the encoding of the length in the stream. - * + * * @param len the length of the attribute. * @exception IOException on writing errors. */ public void putLength(int len) throws IOException { - if (len < 128) { - write((byte) len); + if (len < 128) { + write ((byte)len); - } else if (len < (1 << 8)) { - write((byte) 0x081); - write((byte) len); + } else if (len < (1 << 8)) { + write ((byte)0x081); + write ((byte)len); - } else if (len < (1 << 16)) { - write((byte) 0x082); - write((byte) (len >> 8)); - write((byte) len); + } else if (len < (1 << 16)) { + write ((byte)0x082); + write ((byte) (len >> 8)); + write ((byte) len); - } else if (len < (1 << 24)) { - write((byte) 0x083); - write((byte) (len >> 16)); - write((byte) (len >> 8)); - write((byte) len); + } else if (len < (1 << 24)) { + write ((byte)0x083); + write ((byte) (len >> 16)); + write ((byte) (len >> 8)); + write ((byte) len); - } else { - write((byte) 0x084); - write((byte) (len >> 24)); - write((byte) (len >> 16)); - write((byte) (len >> 8)); - write((byte) len); - } + } else { + write ((byte)0x084); + write ((byte) (len >> 24)); + write ((byte) (len >> 16)); + write ((byte) (len >> 8)); + write ((byte) len); + } } /** * Put the tag of the attribute in the stream. - * - * @param class the tag class type, one of UNIVERSAL, CONTEXT, APPLICATION - * or PRIVATE - * @param form if true, the value is constructed, otherwise it is primitive. + * + * @param class the tag class type, one of UNIVERSAL, CONTEXT, + * APPLICATION or PRIVATE + * @param form if true, the value is constructed, otherwise it is + * primitive. * @param val the tag value */ public void putTag(byte tagClass, boolean form, byte val) { byte tag = (byte) (tagClass | val); if (form) { - tag |= (byte) 0x20; + tag |= (byte)0x20; } - write(tag); + write (tag); } /** - * Write the current contents of this <code>DerOutputStream</code> to an - * <code>OutputStream</code>. - * - * @exception IOException on output error. + * Write the current contents of this <code>DerOutputStream</code> + * to an <code>OutputStream</code>. + * + * @exception IOException on output error. */ public void derEncode(OutputStream out) throws IOException { - out.write(toByteArray()); + out.write(toByteArray()); } } |