History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/security/util/DerOutputStream.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/security/util/DerOutputStream.java+576−0
@@ -0,0 +1,576 @@
1+/*
2+ * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.security.util;
27+
28+import java.io.ByteArrayOutputStream;
29+import java.io.OutputStream;
30+import java.io.IOException;
31+import java.text.SimpleDateFormat;
32+import java.util.Date;
33+import java.util.TimeZone;
34+import java.util.Comparator;
35+import java.util.Arrays;
36+import java.math.BigInteger;
37+import java.util.Locale;
38+
39+
40+/**
41+ * Output stream marshaling DER-encoded data. This is eventually provided
42+ * in the form of a byte array; there is no advance limit on the size of
43+ * that byte array.
44+ *
45+ * <P>At this time, this class supports only a subset of the types of
46+ * DER data encodings which are defined. That subset is sufficient for
47+ * generating most X.509 certificates.
48+ *
49+ *
50+ * @author David Brownell
51+ * @author Amit Kapoor
52+ * @author Hemma Prafullchandra
53+ */
54+public class DerOutputStream
55+extends ByteArrayOutputStream implements DerEncoder {
56+ /**
57+ * Construct an DER output stream.
58+ *
59+ * @param size how large a buffer to preallocate.
60+ */
61+ public DerOutputStream(int size) { super(size); }
62+
63+ /**
64+ * Construct an DER output stream.
65+ */
66+ public DerOutputStream() { }
67+
68+ /**
69+ * Writes tagged, pre-marshaled data. This calcuates and encodes
70+ * the length, so that the output data is the standard triple of
71+ * { tag, length, data } used by all DER values.
72+ *
73+ * @param tag the DER value tag for the data, such as
74+ * <em>DerValue.tag_Sequence</em>
75+ * @param buf buffered data, which must be DER-encoded
76+ */
77+ public void write(byte tag, byte[] buf) throws IOException {
78+ write(tag);
79+ putLength(buf.length);
80+ write(buf, 0, buf.length);
81+ }
82+
83+ /**
84+ * Writes tagged data using buffer-to-buffer copy. As above,
85+ * this writes a standard DER record. This is often used when
86+ * efficiently encapsulating values in sequences.
87+ *
88+ * @param tag the DER value tag for the data, such as
89+ * <em>DerValue.tag_Sequence</em>
90+ * @param out buffered data
91+ */
92+ public void write(byte tag, DerOutputStream out) throws IOException {
93+ write(tag);
94+ putLength(out.count);
95+ write(out.buf, 0, out.count);
96+ }
97+
98+ /**
99+ * Writes implicitly tagged data using buffer-to-buffer copy. As above,
100+ * this writes a standard DER record. This is often used when
101+ * efficiently encapsulating implicitly tagged values.
102+ *
103+ * @param tag the DER value of the context-specific tag that replaces
104+ * original tag of the value in the output, such as in
105+ * <pre>
106+ * <em> <field> [N] IMPLICIT <type></em>
107+ * </pre>
108+ * For example, <em>FooLength [1] IMPLICIT INTEGER</em>, with value=4;
109+ * would be encoded as "81 01 04" whereas in explicit
110+ * tagging it would be encoded as "A1 03 02 01 04".
111+ * Notice that the tag is A1 and not 81, this is because with
112+ * explicit tagging the form is always constructed.
113+ * @param value original value being implicitly tagged
114+ */
115+ public void writeImplicit(byte tag, DerOutputStream value)
116+ throws IOException {
117+ write(tag);
118+ write(value.buf, 1, value.count-1);
119+ }
120+
121+ /**
122+ * Marshals pre-encoded DER value onto the output stream.
123+ */
124+ public void putDerValue(DerValue val) throws IOException {
125+ val.encode(this);
126+ }
127+
128+ /*
129+ * PRIMITIVES -- these are "universal" ASN.1 simple types.
130+ *
131+ * BOOLEAN, INTEGER, BIT STRING, OCTET STRING, NULL
132+ * OBJECT IDENTIFIER, SEQUENCE(OF), SET(OF)
133+ * PrintableString, T61String, IA5String, UTCTime
134+ */
135+
136+ /**
137+ * Marshals a DER boolean on the output stream.
138+ */
139+ public void putBoolean(boolean val) throws IOException {
140+ write(DerValue.tag_Boolean);
141+ putLength(1);
142+ if (val) {
143+ write(0xff);
144+ } else {
145+ write(0);
146+ }
147+ }
148+
149+ /**
150+ * Marshals a DER enumerated on the output stream.
151+ * @param i the enumerated value.
152+ */
153+ public void putEnumerated(int i) throws IOException {
154+ write(DerValue.tag_Enumerated);
155+ putIntegerContents(i);
156+ }
157+
158+ /**
159+ * Marshals a DER integer on the output stream.
160+ *
161+ * @param i the integer in the form of a BigInteger.
162+ */
163+ public void putInteger(BigInteger i) throws IOException {
164+ write(DerValue.tag_Integer);
165+ byte[] buf = i.toByteArray(); // least number of bytes
166+ putLength(buf.length);
167+ write(buf, 0, buf.length);
168+ }
169+
170+ /**
171+ * Marshals a DER integer on the output stream.
172+ * @param i the integer in the form of an Integer.
173+ */
174+ public void putInteger(Integer i) throws IOException {
175+ putInteger(i.intValue());
176+ }
177+
178+ /**
179+ * Marshals a DER integer on the output stream.
180+ * @param i the integer.
181+ */
182+ public void putInteger(int i) throws IOException {
183+ write(DerValue.tag_Integer);
184+ putIntegerContents(i);
185+ }
186+
187+ private void putIntegerContents(int i) throws IOException {
188+
189+ byte[] bytes = new byte[4];
190+ int start = 0;
191+
192+ // Obtain the four bytes of the int
193+
194+ bytes[3] = (byte) (i & 0xff);
195+ bytes[2] = (byte)((i & 0xff00) >>> 8);
196+ bytes[1] = (byte)((i & 0xff0000) >>> 16);
197+ bytes[0] = (byte)((i & 0xff000000) >>> 24);
198+
199+ // Reduce them to the least number of bytes needed to
200+ // represent this int
201+
202+ if (bytes[0] == (byte)0xff) {
203+
204+ // Eliminate redundant 0xff
205+
206+ for (int j = 0; j < 3; j++) {
207+ if ((bytes[j] == (byte)0xff) &&
208+ ((bytes[j+1] & 0x80) == 0x80))
209+ start++;
210+ else
211+ break;
212+ }
213+ } else if (bytes[0] == 0x00) {
214+
215+ // Eliminate redundant 0x00
216+
217+ for (int j = 0; j < 3; j++) {
218+ if ((bytes[j] == 0x00) &&
219+ ((bytes[j+1] & 0x80) == 0))
220+ start++;
221+ else
222+ break;
223+ }
224+ }
225+
226+ putLength(4 - start);
227+ for (int k = start; k < 4; k++)
228+ write(bytes[k]);
229+ }
230+
231+ /**
232+ * Marshals a DER bit string on the output stream. The bit
233+ * string must be byte-aligned.
234+ *
235+ * @param bits the bit string, MSB first
236+ */
237+ public void putBitString(byte[] bits) throws IOException {
238+ write(DerValue.tag_BitString);
239+ putLength(bits.length + 1);
240+ write(0); // all of last octet is used
241+ write(bits);
242+ }
243+
244+ /**
245+ * Marshals a DER bit string on the output stream.
246+ * The bit strings need not be byte-aligned.
247+ *
248+ * @param bits the bit string, MSB first
249+ */
250+ public void putUnalignedBitString(BitArray ba) throws IOException {
251+ byte[] bits = ba.toByteArray();
252+
253+ write(DerValue.tag_BitString);
254+ putLength(bits.length + 1);
255+ write(bits.length*8 - ba.length()); // excess bits in last octet
256+ write(bits);
257+ }
258+
259+ /**
260+ * Marshals a truncated DER bit string on the output stream.
261+ * The bit strings need not be byte-aligned.
262+ *
263+ * @param bits the bit string, MSB first
264+ */
265+ public void putTruncatedUnalignedBitString(BitArray ba) throws IOException {
266+ putUnalignedBitString(ba.truncate());
267+ }
268+
269+ /**
270+ * DER-encodes an ASN.1 OCTET STRING value on the output stream.
271+ *
272+ * @param octets the octet string
273+ */
274+ public void putOctetString(byte[] octets) throws IOException {
275+ write(DerValue.tag_OctetString, octets);
276+ }
277+
278+ /**
279+ * Marshals a DER "null" value on the output stream. These are
280+ * often used to indicate optional values which have been omitted.
281+ */
282+ public void putNull() throws IOException {
283+ write(DerValue.tag_Null);
284+ putLength(0);
285+ }
286+
287+ /**
288+ * Marshals an object identifier (OID) on the output stream.
289+ * Corresponds to the ASN.1 "OBJECT IDENTIFIER" construct.
290+ */
291+ public void putOID(ObjectIdentifier oid) throws IOException {
292+ oid.encode(this);
293+ }
294+
295+ /**
296+ * Marshals a sequence on the output stream. This supports both
297+ * the ASN.1 "SEQUENCE" (zero to N values) and "SEQUENCE OF"
298+ * (one to N values) constructs.
299+ */
300+ public void putSequence(DerValue[] seq) throws IOException {
301+ DerOutputStream bytes = new DerOutputStream();
302+ int i;
303+
304+ for (i = 0; i < seq.length; i++)
305+ seq[i].encode(bytes);
306+
307+ write(DerValue.tag_Sequence, bytes);
308+ }
309+
310+ /**
311+ * Marshals the contents of a set on the output stream without
312+ * ordering the elements. Ok for BER encoding, but not for DER
313+ * encoding.
314+ *
315+ * For DER encoding, use orderedPutSet() or orderedPutSetOf().
316+ */
317+ public void putSet(DerValue[] set) throws IOException {
318+ DerOutputStream bytes = new DerOutputStream();
319+ int i;
320+
321+ for (i = 0; i < set.length; i++)
322+ set[i].encode(bytes);
323+
324+ write(DerValue.tag_Set, bytes);
325+ }
326+
327+ /**
328+ * Marshals the contents of a set on the output stream. Sets
329+ * are semantically unordered, but DER requires that encodings of
330+ * set elements be sorted into ascending lexicographical order
331+ * before being output. Hence sets with the same tags and
332+ * elements have the same DER encoding.
333+ *
334+ * This method supports the ASN.1 "SET OF" construct, but not
335+ * "SET", which uses a different order.
336+ */
337+ public void putOrderedSetOf(byte tag, DerEncoder[] set) throws IOException {
338+ putOrderedSet(tag, set, lexOrder);
339+ }
340+
341+ /**
342+ * Marshals the contents of a set on the output stream. Sets
343+ * are semantically unordered, but DER requires that encodings of
344+ * set elements be sorted into ascending tag order
345+ * before being output. Hence sets with the same tags and
346+ * elements have the same DER encoding.
347+ *
348+ * This method supports the ASN.1 "SET" construct, but not
349+ * "SET OF", which uses a different order.
350+ */
351+ public void putOrderedSet(byte tag, DerEncoder[] set) throws IOException {
352+ putOrderedSet(tag, set, tagOrder);
353+ }
354+
355+ /**
356+ * Lexicographical order comparison on byte arrays, for ordering
357+ * elements of a SET OF objects in DER encoding.
358+ */
359+ private static ByteArrayLexOrder lexOrder = new ByteArrayLexOrder();
360+
361+ /**
362+ * Tag order comparison on byte arrays, for ordering elements of
363+ * SET objects in DER encoding.
364+ */
365+ private static ByteArrayTagOrder tagOrder = new ByteArrayTagOrder();
366+
367+ /**
368+ * Marshals a the contents of a set on the output stream with the
369+ * encodings of its sorted in increasing order.
370+ *
371+ * @param order the order to use when sorting encodings of components.
372+ */
373+ private void putOrderedSet(byte tag, DerEncoder[] set,
374+ Comparator<byte[]> order) throws IOException {
375+ DerOutputStream[] streams = new DerOutputStream[set.length];
376+
377+ for (int i = 0; i < set.length; i++) {
378+ streams[i] = new DerOutputStream();
379+ set[i].derEncode(streams[i]);
380+ }
381+
382+ // order the element encodings
383+ byte[][] bufs = new byte[streams.length][];
384+ for (int i = 0; i < streams.length; i++) {
385+ bufs[i] = streams[i].toByteArray();
386+ }
387+ Arrays.<byte[]>sort(bufs, order);
388+
389+ DerOutputStream bytes = new DerOutputStream();
390+ for (int i = 0; i < streams.length; i++) {
391+ bytes.write(bufs[i]);
392+ }
393+ write(tag, bytes);
394+
395+ }
396+
397+ /**
398+ * Marshals a string as a DER encoded UTF8String.
399+ */
400+ public void putUTF8String(String s) throws IOException {
401+ writeString(s, DerValue.tag_UTF8String, "UTF8");
402+ }
403+
404+ /**
405+ * Marshals a string as a DER encoded PrintableString.
406+ */
407+ public void putPrintableString(String s) throws IOException {
408+ writeString(s, DerValue.tag_PrintableString, "ASCII");
409+ }
410+
411+ /**
412+ * Marshals a string as a DER encoded T61String.
413+ */
414+ public void putT61String(String s) throws IOException {
415+ /*
416+ * Works for characters that are defined in both ASCII and
417+ * T61.
418+ */
419+ writeString(s, DerValue.tag_T61String, "ISO-8859-1");
420+ }
421+
422+ /**
423+ * Marshals a string as a DER encoded IA5String.
424+ */
425+ public void putIA5String(String s) throws IOException {
426+ writeString(s, DerValue.tag_IA5String, "ASCII");
427+ }
428+
429+ /**
430+ * Marshals a string as a DER encoded BMPString.
431+ */
432+ public void putBMPString(String s) throws IOException {
433+ writeString(s, DerValue.tag_BMPString, "UnicodeBigUnmarked");
434+ }
435+
436+ /**
437+ * Marshals a string as a DER encoded GeneralString.
438+ */
439+ public void putGeneralString(String s) throws IOException {
440+ writeString(s, DerValue.tag_GeneralString, "ASCII");
441+ }
442+
443+ /**
444+ * Private helper routine for writing DER encoded string values.
445+ * @param s the string to write
446+ * @param stringTag one of the DER string tags that indicate which
447+ * encoding should be used to write the string out.
448+ * @param enc the name of the encoder that should be used corresponding
449+ * to the above tag.
450+ */
451+ private void writeString(String s, byte stringTag, String enc)
452+ throws IOException {
453+
454+ byte[] data = s.getBytes(enc);
455+ write(stringTag);
456+ putLength(data.length);
457+ write(data);
458+ }
459+
460+ /**
461+ * Marshals a DER UTC time/date value.
462+ *
463+ * <P>YYMMDDhhmmss{Z|+hhmm|-hhmm} ... emits only using Zulu time
464+ * and with seconds (even if seconds=0) as per RFC 3280.
465+ */
466+ public void putUTCTime(Date d) throws IOException {
467+ putTime(d, DerValue.tag_UtcTime);
468+ }
469+
470+ /**
471+ * Marshals a DER Generalized Time/date value.
472+ *
473+ * <P>YYYYMMDDhhmmss{Z|+hhmm|-hhmm} ... emits only using Zulu time
474+ * and with seconds (even if seconds=0) as per RFC 3280.
475+ */
476+ public void putGeneralizedTime(Date d) throws IOException {
477+ putTime(d, DerValue.tag_GeneralizedTime);
478+ }
479+
480+ /**
481+ * Private helper routine for marshalling a DER UTC/Generalized
482+ * time/date value. If the tag specified is not that for UTC Time
483+ * then it defaults to Generalized Time.
484+ * @param d the date to be marshalled
485+ * @param tag the tag for UTC Time or Generalized Time
486+ */
487+ private void putTime(Date d, byte tag) throws IOException {
488+
489+ /*
490+ * Format the date.
491+ */
492+
493+ TimeZone tz = TimeZone.getTimeZone("GMT");
494+ String pattern = null;
495+
496+ if (tag == DerValue.tag_UtcTime) {
497+ pattern = "yyMMddHHmmss'Z'";
498+ } else {
499+ tag = DerValue.tag_GeneralizedTime;
500+ pattern = "yyyyMMddHHmmss'Z'";
501+ }
502+
503+ SimpleDateFormat sdf = new SimpleDateFormat(pattern, Locale.US);
504+ sdf.setTimeZone(tz);
505+ byte[] time = (sdf.format(d)).getBytes("ISO-8859-1");
506+
507+ /*
508+ * Write the formatted date.
509+ */
510+
511+ write(tag);
512+ putLength(time.length);
513+ write(time);
514+ }
515+
516+ /**
517+ * Put the encoding of the length in the stream.
518+ *
519+ * @params len the length of the attribute.
520+ * @exception IOException on writing errors.
521+ */
522+ public void putLength(int len) throws IOException {
523+ if (len < 128) {
524+ write((byte)len);
525+
526+ } else if (len < (1 << 8)) {
527+ write((byte)0x081);
528+ write((byte)len);
529+
530+ } else if (len < (1 << 16)) {
531+ write((byte)0x082);
532+ write((byte)(len >> 8));
533+ write((byte)len);
534+
535+ } else if (len < (1 << 24)) {
536+ write((byte)0x083);
537+ write((byte)(len >> 16));
538+ write((byte)(len >> 8));
539+ write((byte)len);
540+
541+ } else {
542+ write((byte)0x084);
543+ write((byte)(len >> 24));
544+ write((byte)(len >> 16));
545+ write((byte)(len >> 8));
546+ write((byte)len);
547+ }
548+ }
549+
550+ /**
551+ * Put the tag of the attribute in the stream.
552+ *
553+ * @params class the tag class type, one of UNIVERSAL, CONTEXT,
554+ * APPLICATION or PRIVATE
555+ * @params form if true, the value is constructed, otherwise it is
556+ * primitive.
557+ * @params val the tag value
558+ */
559+ public void putTag(byte tagClass, boolean form, byte val) {
560+ byte tag = (byte)(tagClass | val);
561+ if (form) {
562+ tag |= (byte)0x20;
563+ }
564+ write(tag);
565+ }
566+
567+ /**
568+ * Write the current contents of this <code>DerOutputStream</code>
569+ * to an <code>OutputStream</code>.
570+ *
571+ * @exception IOException on output error.
572+ */
573+ public void derEncode(OutputStream out) throws IOException {
574+ out.write(toByteArray());
575+ }
576+}