1:
37:
38:
39: package ;
40:
41: import ;
42:
43: import ;
44: import ;
45: import ;
46:
47: import ;
48:
49: import ;
50:
51: import ;
52: import ;
53: import ;
54: import ;
55: import ;
56:
57:
70: public class DERWriter implements DER
71: {
72:
73:
74:
75:
76:
77: private DERWriter()
78: {
79: }
80:
81:
82:
83:
84: public static int write(OutputStream out, DERValue object)
85: throws IOException
86: {
87: if (DER.CONSTRUCTED_VALUE.equals (object.getValue ()))
88: {
89: out.write (object.getEncoded ());
90: return object.getLength ();
91: }
92:
93: out.write(object.getExternalTag());
94: Object value = object.getValue();
95: if (value == null)
96: {
97: writeLength(out, 0);
98: return 0;
99: }
100: if (value instanceof Boolean)
101: return writeBoolean(out, (Boolean) value);
102: else if (value instanceof BigInteger)
103: return writeInteger(out, (BigInteger) value);
104: else if (value instanceof Date)
105: return writeDate(out, object.getExternalTag(), (Date) value);
106: else if (value instanceof String)
107: return writeString(out, object.getExternalTag(), (String) value);
108: else if (value instanceof List)
109: return writeSequence(out, (List) value);
110: else if (value instanceof Set)
111: return writeSet(out, (Set) value);
112: else if (value instanceof BitString)
113: return writeBitString(out, (BitString) value);
114: else if (value instanceof OID)
115: return writeOID(out, (OID) value);
116: else if (value instanceof byte[])
117: {
118: writeLength(out, ((byte[]) value).length);
119: out.write((byte[]) value);
120: return ((byte[]) value).length;
121: }
122: else if (value instanceof DERValue)
123: {
124: ByteArrayOutputStream bout = new ByteArrayOutputStream();
125: write(bout, (DERValue) value);
126: byte[] buf = bout.toByteArray();
127: writeLength(out, buf.length);
128: out.write(buf);
129: return buf.length;
130: }
131: else
132: throw new DEREncodingException("cannot encode " + value.getClass().getName());
133: }
134:
135: public static int definiteEncodingSize(int length)
136: {
137: if (length < 128)
138: return 1;
139: else if (length < 256)
140: return 2;
141: else if (length < 65536)
142: return 3;
143: else if (length < 16777216)
144: return 4;
145: else
146: return 5;
147: }
148:
149:
150:
151:
152:
158: private static int writeBoolean(OutputStream out, Boolean b)
159: throws IOException
160: {
161: writeLength(out, 1);
162: if (b.booleanValue())
163: out.write(0xFF);
164: else
165: out.write(0);
166: return 1;
167: }
168:
169:
175: private static int writeInteger(OutputStream out, BigInteger integer)
176: throws IOException
177: {
178: byte[] bytes = integer.toByteArray();
179: writeLength(out, bytes.length);
180: out.write(bytes);
181: return bytes.length;
182: }
183:
184: private static int writeSequence(OutputStream out, List sequence)
185: throws IOException
186: {
187: ByteArrayOutputStream bout = new ByteArrayOutputStream();
188: for (Iterator i = sequence.iterator(); i.hasNext(); )
189: {
190: write(bout, (DERValue) i.next());
191: }
192: byte[] buf = bout.toByteArray();
193: writeLength(out, buf.length);
194: out.write(buf);
195: return buf.length;
196: }
197:
198: private static int writeSet(OutputStream out, Set set)
199: throws IOException
200: {
201: ByteArrayOutputStream bout = new ByteArrayOutputStream();
202: for (Iterator i = set.iterator(); i.hasNext(); )
203: {
204: write(bout, (DERValue) i.next());
205: }
206: byte[] buf = bout.toByteArray();
207: writeLength(out, buf.length);
208: out.write(buf);
209: return buf.length;
210: }
211:
212: private static int writeOID(OutputStream out, OID oid)
213: throws IOException
214: {
215: byte[] der = oid.getDER();
216: writeLength(out, der.length);
217: out.write(der);
218: return der.length;
219: }
220:
221: private static int writeBitString(OutputStream out, BitString bs)
222: throws IOException
223: {
224: byte[] buf = bs.getShiftedByteArray();
225: writeLength(out, buf.length + 1);
226: out.write(bs.getIgnoredBits());
227: out.write(buf);
228: return buf.length + 1;
229: }
230:
231: private static int writeString(OutputStream out, int tag, String str)
232: throws IOException
233: {
234: byte[] b = null;
235: switch (tag & 0x1F)
236: {
237: case NUMERIC_STRING:
238: case PRINTABLE_STRING:
239: case T61_STRING:
240: case VIDEOTEX_STRING:
241: case IA5_STRING:
242: case GRAPHIC_STRING:
243: case ISO646_STRING:
244: case GENERAL_STRING:
245: b = toIso88591(str);
246: break;
247:
248: case UNIVERSAL_STRING:
249: case BMP_STRING:
250: b = toUtf16Be(str);
251: break;
252:
253: case UTF8_STRING:
254: default:
255: b = toUtf8(str);
256: break;
257: }
258: writeLength(out, b.length);
259: out.write(b);
260: return b.length;
261: }
262:
263: private static byte[] toIso88591(String string)
264: {
265: byte[] result = new byte[string.length()];
266: for (int i = 0; i < string.length(); i++)
267: result[i] = (byte) string.charAt(i);
268: return result;
269: }
270:
271: private static byte[] toUtf16Be(String string)
272: {
273: byte[] result = new byte[string.length() * 2];
274: for (int i = 0; i < string.length(); i++)
275: {
276: result[i*2 ] = (byte) ((string.charAt(i) >>> 8) & 0xFF);
277: result[i*2+1] = (byte) (string.charAt(i) & 0xFF);
278: }
279: return result;
280: }
281:
282: private static byte[] toUtf8(String string)
283: {
284: int len = string.length();
285: ByteArrayOutputStream buf = new ByteArrayOutputStream(len + (len >> 1));
286: for (int i = 0; i < len; i++)
287: {
288: char c = string.charAt(i);
289: if (c < 0x0080)
290: buf.write(c & 0xFF);
291: else if (c < 0x0800)
292: {
293: buf.write(0xC0 | ((c >>> 6) & 0x3F));
294: buf.write(0x80 | (c & 0x3F));
295: }
296: else
297: {
298: buf.write(0xE0 | ((c >>> 12) & 0x0F));
299: buf.write(0x80 | ((c >>> 6) & 0x3F));
300: buf.write(0x80 | (c & 0x3F));
301: }
302: }
303: return buf.toByteArray();
304: }
305:
306: private static int writeDate(OutputStream out, int tag, Date date)
307: throws IOException
308: {
309: SimpleDateFormat sdf = null;
310: if ((tag & 0x1F) == UTC_TIME)
311: sdf = new SimpleDateFormat("yyMMddHHmmss'Z'");
312: else
313: sdf = new SimpleDateFormat("yyyyMMddHHmmss'.'SSS'Z'");
314: sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
315: byte[] b = sdf.format(date).getBytes("ISO-8859-1");
316: writeLength(out, b.length);
317: out.write(b);
318: return b.length;
319: }
320:
321:
322:
323:
324: static void writeLength(OutputStream out, int len) throws IOException
325: {
326: if (len < 128)
327: out.write(len);
328: else if (len < 256)
329: {
330: out.write(0x81);
331: out.write(len);
332: }
333: else if (len < 65536)
334: {
335: out.write(0x82);
336: out.write(len >> 8);
337: out.write(len);
338: }
339: else if (len < 16777216)
340: {
341: out.write(0x83);
342: out.write(len >> 16);
343: out.write(len >> 8);
344: out.write(len);
345: }
346: else
347: {
348: out.write(0x84);
349: out.write(len >> 24);
350: out.write(len >> 16);
351: out.write(len >> 8);
352: out.write(len);
353: }
354: }
355: }