1 // This is just a cut-and-paste of a bunch of files from Bouncycastle
2 package org.xwt.shoehorn3;
5 import java.math.BigInteger;
9 abstract class ASN1OctetString
15 * return an Octet String from a tagged object.
17 * @param obj the tagged object holding the object we want.
18 * @param explicit true if the object is meant to be explicitly
19 * tagged false otherwise.
20 * @exception IllegalArgumentException if the tagged object cannot
23 public static ASN1OctetString getInstance(
27 return getInstance(obj.getObject());
31 * return an Octet String from the given object.
33 * @param obj the object we want converted.
34 * @exception IllegalArgumentException if the object cannot be converted.
36 public static ASN1OctetString getInstance(
39 if (obj == null || obj instanceof ASN1OctetString)
41 return (ASN1OctetString)obj;
44 if (obj instanceof ASN1TaggedObject)
46 return getInstance(((ASN1TaggedObject)obj).getObject());
49 if (obj instanceof ASN1Sequence)
51 Vector v = new Vector();
52 Enumeration e = ((ASN1Sequence)obj).getObjects();
54 while (e.hasMoreElements())
56 v.addElement(e.nextElement());
59 return new BERConstructedOctetString(v);
62 throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
66 * @param string the octets making up the octet string.
68 public ASN1OctetString(
74 public ASN1OctetString(
79 ByteArrayOutputStream bOut = new ByteArrayOutputStream();
80 DEROutputStream dOut = new DEROutputStream(bOut);
82 dOut.writeObject(obj);
85 this.string = bOut.toByteArray();
89 throw new IllegalArgumentException("Error processing object : " + e.toString());
93 public byte[] getOctets()
100 byte[] b = this.getOctets();
103 for (int i = 0; i != b.length; i++)
105 value ^= (b[i] & 0xff) << (i % 4);
111 public boolean equals(
114 if (o == null || !(o instanceof DEROctetString))
119 DEROctetString other = (DEROctetString)o;
121 byte[] b1 = other.getOctets();
122 byte[] b2 = this.getOctets();
124 if (b1.length != b2.length)
129 for (int i = 0; i != b1.length; i++)
140 abstract void encode(DEROutputStream out)
145 class ASN1OutputStream
146 extends DEROutputStream
148 public ASN1OutputStream(
154 public void writeObject(
162 else if (obj instanceof DERObject)
164 ((DERObject)obj).encode(this);
166 else if (obj instanceof DEREncodable)
168 ((DEREncodable)obj).getDERObject().encode(this);
172 throw new IOException("object not ASN1Encodable");
178 abstract class ASN1Sequence
181 private Vector seq = new Vector();
184 * return an ASN1Sequence from the given object.
186 * @param obj the object we want converted.
187 * @exception IllegalArgumentException if the object cannot be converted.
189 public static ASN1Sequence getInstance(
192 if (obj == null || obj instanceof ASN1Sequence)
194 return (ASN1Sequence)obj;
197 throw new IllegalArgumentException("unknown object in getInstance");
201 * Return an ASN1 sequence from a tagged object. There is a special
202 * case here, if an object appears to have been explicitly tagged on
203 * reading but we were expecting it to be implictly tagged in the
204 * normal course of events it indicates that we lost the surrounding
205 * sequence - so we need to add it back (this will happen if the tagged
206 * object is a sequence that contains other sequences). If you are
207 * dealing with implicitly tagged sequences you really <b>should</b>
208 * be using this method.
210 * @param obj the tagged object.
211 * @param explicit true if the object is meant to be explicitly tagged,
213 * @exception IllegalArgumentException if the tagged object cannot
216 public static ASN1Sequence getInstance(
217 ASN1TaggedObject obj,
222 if (!obj.isExplicit())
224 throw new IllegalArgumentException("object implicit - explicit expected.");
227 return (ASN1Sequence)obj.getObject();
232 // constructed object which appears to be explicitly tagged
233 // when it should be implicit means we have to add the
234 // surrounding sequence.
236 if (obj.isExplicit())
240 if (obj instanceof BERTaggedObject)
242 seq = new BERConstructedSequence();
246 seq = new DERConstructedSequence();
249 seq.addObject(obj.getObject());
257 if (obj.getObject() instanceof ASN1Sequence)
259 return (ASN1Sequence)obj.getObject();
264 throw new IllegalArgumentException(
265 "unknown object in getInstanceFromTagged");
268 public Enumeration getObjects()
270 return seq.elements();
274 * return the object at the sequence postion indicated by index.
276 * @param the sequence number (starting at zero) of the object
277 * @return the object at the sequence postion indicated by index.
279 public DEREncodable getObjectAt(
282 return (DEREncodable)seq.elementAt(index);
286 * return the number of objects in this sequence.
288 * @return the number of objects in this sequence.
295 public int hashCode()
297 Enumeration e = this.getObjects();
300 while (e.hasMoreElements())
302 hashCode ^= e.nextElement().hashCode();
308 public boolean equals(
311 if (o == null || !(o instanceof ASN1Sequence))
316 ASN1Sequence other = (ASN1Sequence)o;
318 if (this.size() != other.size())
323 Enumeration s1 = this.getObjects();
324 Enumeration s2 = other.getObjects();
326 while (s1.hasMoreElements())
328 if (!s1.nextElement().equals(s2.nextElement()))
337 protected void addObject(
343 abstract void encode(DEROutputStream out)
348 abstract class ASN1Set
351 protected Vector set = new Vector();
354 * return an ASN1Set from the given object.
356 * @param obj the object we want converted.
357 * @exception IllegalArgumentException if the object cannot be converted.
359 public static ASN1Set getInstance(
362 if (obj == null || obj instanceof ASN1Set)
367 throw new IllegalArgumentException("unknown object in getInstance");
371 * Return an ASN1 set from a tagged object. There is a special
372 * case here, if an object appears to have been explicitly tagged on
373 * reading but we were expecting it to be implictly tagged in the
374 * normal course of events it indicates that we lost the surrounding
375 * set - so we need to add it back (this will happen if the tagged
376 * object is a sequence that contains other sequences). If you are
377 * dealing with implicitly tagged sets you really <b>should</b>
378 * be using this method.
380 * @param obj the tagged object.
381 * @param explicit true if the object is meant to be explicitly tagged
383 * @exception IllegalArgumentException if the tagged object cannot
386 public static ASN1Set getInstance(
387 ASN1TaggedObject obj,
392 if (!obj.isExplicit())
394 throw new IllegalArgumentException("object implicit - explicit expected.");
397 return (ASN1Set)obj.getObject();
402 // constructed object which appears to be explicitly tagged
403 // and it's really implicit means we have to add the
404 // surrounding sequence.
406 if (obj.isExplicit())
408 ASN1Set set = new DERSet(obj.getObject());
415 // in this case the parser returns a sequence, convert it
418 DEREncodableVector v = new DEREncodableVector();
420 if (obj.getObject() instanceof ASN1Sequence)
422 ASN1Sequence s = (ASN1Sequence)obj.getObject();
423 Enumeration e = s.getObjects();
425 while (e.hasMoreElements())
427 v.add((DEREncodable)e.nextElement());
430 return new DERSet(v);
435 throw new IllegalArgumentException(
436 "unknown object in getInstanceFromTagged");
443 public Enumeration getObjects()
445 return set.elements();
449 * return the object at the set postion indicated by index.
451 * @param the set number (starting at zero) of the object
452 * @return the object at the set postion indicated by index.
454 public DEREncodable getObjectAt(
457 return (DEREncodable)set.elementAt(index);
461 * return the number of objects in this set.
463 * @return the number of objects in this set.
470 public int hashCode()
472 Enumeration e = this.getObjects();
475 while (e.hasMoreElements())
477 hashCode ^= e.nextElement().hashCode();
483 public boolean equals(
486 if (o == null || !(o instanceof ASN1Set))
491 ASN1Set other = (ASN1Set)o;
493 if (this.size() != other.size())
498 Enumeration s1 = this.getObjects();
499 Enumeration s2 = other.getObjects();
501 while (s1.hasMoreElements())
503 if (!s1.nextElement().equals(s2.nextElement()))
512 protected void addObject(
518 abstract void encode(DEROutputStream out)
524 * ASN.1 TaggedObject - in ASN.1 nottation this is any object proceeded by
525 * a [n] where n is some number - these are assume to follow the construction
526 * rules (as with sequences).
528 abstract class ASN1TaggedObject
532 boolean empty = false;
533 boolean explicit = true;
534 DEREncodable obj = null;
537 * @param tagNo the tag number for this object.
538 * @param obj the tagged object.
540 public ASN1TaggedObject(
544 this.explicit = true;
550 * @param explicit true if the object is explicitly tagged.
551 * @param tagNo the tag number for this object.
552 * @param obj the tagged object.
554 public ASN1TaggedObject(
559 this.explicit = explicit;
564 public boolean equals(
567 if (o == null || !(o instanceof ASN1TaggedObject))
572 ASN1TaggedObject other = (ASN1TaggedObject)o;
574 if(tagNo != other.tagNo || empty != other.empty || explicit != other.explicit)
581 if(other.obj != null)
588 if(!(obj.equals(other.obj)))
597 public int getTagNo()
603 * return whether or not the object may be explicitly tagged.
605 * Note: if the object has been read from an input stream, the only
606 * time you can be sure if isExplicit is returning the true state of
607 * affairs is if it returns false. An implicitly tagged object may appear
608 * to be explicitly tagged, so you need to understand the context under
609 * which the reading was done as well, see getObject below.
611 public boolean isExplicit()
616 public boolean isEmpty()
622 * return whatever was following the tag.
624 * Note: tagged objects are generally context dependent if you're
625 * trying to extract a tagged object you should be going via the
626 * appropriate getInstance method.
628 public DERObject getObject()
632 return obj.getDERObject();
638 abstract void encode(DEROutputStream out)
643 class BERConstructedOctetString
644 extends DEROctetString
647 * convert a vector of octet strings into a single byte string
649 static private byte[] toBytes(
652 ByteArrayOutputStream bOut = new ByteArrayOutputStream();
654 for (int i = 0; i != octs.size(); i++)
656 DEROctetString o = (DEROctetString)octs.elementAt(i);
660 bOut.write(o.getOctets());
662 catch (IOException e)
664 throw new RuntimeException("exception converting octets " + e.toString());
668 return bOut.toByteArray();
674 * @param string the octets making up the octet string.
676 public BERConstructedOctetString(
682 public BERConstructedOctetString(
685 super(toBytes(octs));
690 public BERConstructedOctetString(
696 public BERConstructedOctetString(
699 super(obj.getDERObject());
702 public byte[] getOctets()
708 * return the DER octets that make up this string.
710 public Enumeration getObjects()
714 octs = generateOcts();
717 return octs.elements();
720 private Vector generateOcts()
724 Vector vec = new Vector();
726 while ((end + 1) < string.length)
728 if (string[end] == 0 && string[end + 1] == 0)
730 byte[] nStr = new byte[end - start + 1];
732 for (int i = 0; i != nStr.length; i++)
734 nStr[i] = string[start + i];
737 vec.addElement(new DEROctetString(nStr));
743 byte[] nStr = new byte[string.length - start];
744 for (int i = 0; i != nStr.length; i++)
746 nStr[i] = string[start + i];
749 vec.addElement(new DEROctetString(nStr));
758 if (out instanceof ASN1OutputStream || out instanceof BEROutputStream)
760 out.write(CONSTRUCTED | OCTET_STRING);
766 octs = generateOcts();
769 for (int i = 0; i != octs.size(); i++)
771 out.writeObject(octs.elementAt(i));
785 class BERConstructedSequence
786 extends DERConstructedSequence
794 if (out instanceof ASN1OutputStream || out instanceof BEROutputStream)
796 out.write(SEQUENCE | CONSTRUCTED);
799 Enumeration e = getObjects();
800 while (e.hasMoreElements())
802 out.writeObject(e.nextElement());
817 extends DERInputStream
819 private DERObject END_OF_STREAM = new DERObject() {
824 throw new IOException("Eeek!");
828 public BERInputStream(
835 * read a string of bytes representing an indefinite length object.
837 private byte[] readIndefiniteLengthFully()
840 ByteArrayOutputStream bOut = new ByteArrayOutputStream();
845 while ((b = read()) >= 0)
847 if (b1 == 0 && b == 0)
856 return bOut.toByteArray();
859 private BERConstructedOctetString buildConstructedOctetString()
862 Vector octs = new Vector();
866 DERObject o = readObject();
868 if (o == END_OF_STREAM)
876 return new BERConstructedOctetString(octs);
879 public DERObject readObject()
885 throw new EOFException();
888 int length = readLength();
890 if (length < 0) // indefinite length method
896 case SEQUENCE | CONSTRUCTED:
897 BERConstructedSequence seq = new BERConstructedSequence();
901 DERObject obj = readObject();
903 if (obj == END_OF_STREAM)
911 case OCTET_STRING | CONSTRUCTED:
912 return buildConstructedOctetString();
913 case SET | CONSTRUCTED:
914 DEREncodableVector v = new DEREncodableVector();
918 DERObject obj = readObject();
920 if (obj == END_OF_STREAM)
927 return new BERSet(v);
930 // with tagged object tag number is bottom 5 bits
932 if ((tag & TAGGED) != 0)
934 if ((tag & 0x1f) == 0x1f)
936 throw new IOException("unsupported high tag encountered");
940 // simple type - implicit... return an octet string
942 if ((tag & CONSTRUCTED) == 0)
944 byte[] bytes = readIndefiniteLengthFully();
946 return new BERTaggedObject(false, tag & 0x1f, new DEROctetString(bytes));
950 // either constructed or explicitly tagged
952 DERObject dObj = readObject();
954 if (dObj == END_OF_STREAM) // empty tag!
956 return new DERTaggedObject(tag & 0x1f);
959 DERObject next = readObject();
962 // explicitly tagged (probably!) - if it isn't we'd have to
963 // tell from the context
965 if (next == END_OF_STREAM)
967 return new BERTaggedObject(tag & 0x1f, dObj);
971 // another implicit object, we'll create a sequence...
973 seq = new BERConstructedSequence();
982 while (next != END_OF_STREAM);
984 return new BERTaggedObject(false, tag & 0x1f, seq);
987 throw new IOException("unknown BER object encountered");
992 if (tag == 0 && length == 0) // end of contents marker.
994 return END_OF_STREAM;
997 byte[] bytes = new byte[length];
1001 return buildObject(tag, bytes);
1007 class BEROutputStream
1008 extends DEROutputStream
1010 public BEROutputStream(
1016 public void writeObject(
1024 else if (obj instanceof DERObject)
1026 ((DERObject)obj).encode(this);
1028 else if (obj instanceof DEREncodable)
1030 ((DEREncodable)obj).getDERObject().encode(this);
1034 throw new IOException("object not BEREncodable");
1044 * create an empty sequence
1051 * create a set containing one object
1060 * create a set containing a vector of objects.
1063 DEREncodableVector v)
1071 DEROutputStream out)
1074 if (out instanceof ASN1OutputStream || out instanceof BEROutputStream)
1076 out.write(SET | CONSTRUCTED);
1079 Enumeration e = getObjects();
1080 while (e.hasMoreElements())
1082 out.writeObject(e.nextElement());
1097 * BER TaggedObject - in ASN.1 nottation this is any object proceeded by
1098 * a [n] where n is some number - these are assume to follow the construction
1099 * rules (as with sequences).
1101 class BERTaggedObject
1102 extends DERTaggedObject
1105 * @param tagNo the tag number for this object.
1106 * @param obj the tagged object.
1108 public BERTaggedObject(
1116 * @param explicit true if an explicitly tagged object.
1117 * @param tagNo the tag number for this object.
1118 * @param obj the tagged object.
1120 public BERTaggedObject(
1125 super(explicit, tagNo, obj);
1129 * create an implicitly tagged object that contains a zero
1132 public BERTaggedObject(
1135 super(false, tagNo, new BERConstructedSequence());
1139 DEROutputStream out)
1142 if (out instanceof ASN1OutputStream || out instanceof BEROutputStream)
1144 out.write(CONSTRUCTED | TAGGED | tagNo);
1151 if (obj instanceof BERConstructedOctetString)
1153 Enumeration e = ((BERConstructedOctetString)obj).getObjects();
1155 while (e.hasMoreElements())
1157 out.writeObject(e.nextElement());
1160 else if (obj instanceof ASN1Sequence)
1162 Enumeration e = ((ASN1Sequence)obj).getObjects();
1164 while (e.hasMoreElements())
1166 out.writeObject(e.nextElement());
1169 else if (obj instanceof ASN1Set)
1171 Enumeration e = ((ASN1Set)obj).getObjects();
1173 while (e.hasMoreElements())
1175 out.writeObject(e.nextElement());
1180 throw new RuntimeException("not implemented: " + obj.getClass().getName());
1185 out.writeObject(obj);
1201 implements DEREncodable
1203 private DERObjectIdentifier attrType;
1204 private ASN1Set attrValues;
1207 * return an Attribute object from the given object.
1209 * @param o the object we want converted.
1210 * @exception IllegalArgumentException if the object cannot be converted.
1212 public static Attribute getInstance(
1215 if (o == null || o instanceof Attribute)
1217 return (Attribute)o;
1220 if (o instanceof ASN1Sequence)
1222 return new Attribute((ASN1Sequence)o);
1225 throw new IllegalArgumentException("unknown object in factory");
1231 attrType = (DERObjectIdentifier)seq.getObjectAt(0);
1232 attrValues = (ASN1Set)seq.getObjectAt(1);
1236 DERObjectIdentifier attrType,
1239 this.attrType = attrType;
1240 this.attrValues = attrValues;
1243 public DERObjectIdentifier getAttrType()
1248 public ASN1Set getAttrValues()
1255 * Attribute ::= SEQUENCE {
1256 * attrType OBJECT IDENTIFIER,
1257 * attrValues SET OF AttributeValue
1261 public DERObject getDERObject()
1263 DEREncodableVector v = new DEREncodableVector();
1268 return new DERSequence(v);
1271 // Decompiled by Jad v1.5.7f. Copyright 2000 Pavel Kouznetsov.
1272 // Jad home page: http://www.geocities.com/SiliconValley/Bridge/8617/jad.html
1273 // Decompiler options: packimports(3)
1274 // Source File Name: SignedAttributes.java
1278 // Referenced classes of package org.bouncycastle.asn1.cms:
1281 class SignedAttributes
1282 implements DEREncodable
1285 public SignedAttributes(Vector vector)
1287 setAttributes(vector);
1290 public SignedAttributes(DERConstructedSet derconstructedset)
1292 attributes = derconstructedset;
1295 public SignedAttributes(SignedAttributes signedattributes)
1297 attributes = signedattributes.attributes;
1300 public static SignedAttributes getInstance(Object obj)
1304 if(obj instanceof SignedAttributes)
1305 return (SignedAttributes)obj;
1306 if(obj instanceof DERConstructedSet)
1307 return new SignedAttributes((DERConstructedSet)obj);
1308 if(obj instanceof DERTaggedObject)
1309 return getInstance(((DERTaggedObject)obj).getObject());
1311 throw new IllegalArgumentException("Invalid SignedAttributes");
1314 public static SignedAttributes newInstance(Object obj)
1318 if(obj instanceof SignedAttributes)
1319 return new SignedAttributes((SignedAttributes)obj);
1320 if(obj instanceof DERConstructedSet)
1321 return new SignedAttributes((DERConstructedSet)obj);
1322 if(obj instanceof DERTaggedObject)
1323 return getInstance(((DERTaggedObject)obj).getObject());
1325 throw new IllegalArgumentException("Invalid SignedAttributes");
1328 public Vector getAttributes()
1330 int i = attributes.getSize();
1331 Vector vector = new Vector();
1332 for(int j = 0; j < i; j++)
1333 vector.addElement(Attribute.getInstance(attributes.getObjectAt(j)));
1338 private void setAttributes(Vector vector)
1340 int i = vector.size();
1341 attributes = new DERConstructedSet();
1342 for(int j = 0; j < i; j++)
1343 attributes.addObject(Attribute.getInstance(vector.elementAt(j)));
1347 public DERObject getDERObject()
1352 private DERConstructedSet attributes;
1359 protected byte[] data;
1360 protected int padBits;
1363 * return the correct number of pad bits for a bit string defined in
1366 static protected int getPadBits(
1376 if (bitString > 255)
1378 val = ((bitString >> 8) & 0xFF);
1382 val = (bitString & 0xFF);
1387 while (((val <<= 1) & 0xFF) != 0)
1396 * return the correct number of bytes for a bit string defined in
1399 static protected byte[] getBytes(
1402 if (bitString > 255)
1404 byte[] bytes = new byte[2];
1406 bytes[0] = (byte)(bitString & 0xFF);
1407 bytes[1] = (byte)((bitString >> 8) & 0xFF);
1413 byte[] bytes = new byte[1];
1415 bytes[0] = (byte)(bitString & 0xFF);
1422 * return a Bit String from the passed in object
1424 * @exception IllegalArgumentException if the object cannot be converted.
1426 public static DERBitString getInstance(
1429 if (obj == null || obj instanceof DERBitString)
1431 return (DERBitString)obj;
1434 if (obj instanceof ASN1OctetString)
1436 byte[] bytes = ((ASN1OctetString)obj).getOctets();
1437 int padBits = bytes[0];
1438 byte[] data = new byte[bytes.length - 1];
1440 System.arraycopy(bytes, 1, data, 0, bytes.length - 1);
1442 return new DERBitString(data, padBits);
1445 if (obj instanceof ASN1TaggedObject)
1447 return getInstance(((ASN1TaggedObject)obj).getObject());
1450 throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
1454 * return a Bit String from a tagged object.
1456 * @param obj the tagged object holding the object we want
1457 * @param explicit true if the object is meant to be explicitly
1458 * tagged false otherwise.
1459 * @exception IllegalArgumentException if the tagged object cannot
1462 public static DERBitString getInstance(
1463 ASN1TaggedObject obj,
1466 return getInstance(obj.getObject());
1469 protected DERBitString(
1473 this.data = new byte[1];
1474 this.data[0] = data;
1475 this.padBits = padBits;
1479 * @param data the octets making up the bit string.
1480 * @param padBits the number of extra bits at the end of the string.
1482 public DERBitString(
1487 this.padBits = padBits;
1490 public DERBitString(
1496 public DERBitString(
1501 ByteArrayOutputStream bOut = new ByteArrayOutputStream();
1502 DEROutputStream dOut = new DEROutputStream(bOut);
1504 dOut.writeObject(obj);
1507 this.data = bOut.toByteArray();
1510 catch (IOException e)
1512 throw new IllegalArgumentException("Error processing object : " + e.toString());
1516 public byte[] getBytes()
1521 public int getPadBits()
1527 DEROutputStream out)
1530 byte[] bytes = new byte[getBytes().length + 1];
1532 bytes[0] = (byte)getPadBits();
1533 System.arraycopy(getBytes(), 0, bytes, 1, bytes.length - 1);
1535 out.writeEncoded(BIT_STRING, bytes);
1538 public boolean equals(
1541 if (o == null || !(o instanceof DERBitString))
1546 DERBitString other = (DERBitString)o;
1548 if (data.length != other.data.length)
1553 for (int i = 0; i != data.length; i++)
1555 if (data[i] != other.data[i])
1561 return (padBits == other.padBits);
1567 * DER BMPString object.
1571 implements DERString
1576 * return a BMP String from the given object.
1578 * @param obj the object we want converted.
1579 * @exception IllegalArgumentException if the object cannot be converted.
1581 public static DERBMPString getInstance(
1584 if (obj == null || obj instanceof DERBMPString)
1586 return (DERBMPString)obj;
1589 if (obj instanceof ASN1OctetString)
1591 return new DERBMPString(((ASN1OctetString)obj).getOctets());
1594 if (obj instanceof ASN1TaggedObject)
1596 return getInstance(((ASN1TaggedObject)obj).getObject());
1599 throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
1603 * return a BMP String from a tagged object.
1605 * @param obj the tagged object holding the object we want
1606 * @param explicit true if the object is meant to be explicitly
1607 * tagged false otherwise.
1608 * @exception IllegalArgumentException if the tagged object cannot
1611 public static DERBMPString getInstance(
1612 ASN1TaggedObject obj,
1615 return getInstance(obj.getObject());
1620 * basic constructor - byte encoded string.
1622 public DERBMPString(
1625 char[] cs = new char[string.length / 2];
1627 for (int i = 0; i != cs.length; i++)
1629 cs[i] = (char)((string[2 * i] << 8) | (string[2 * i + 1] & 0xff));
1632 this.string = new String(cs);
1638 public DERBMPString(
1641 this.string = string;
1644 public String getString()
1649 public int hashCode()
1651 return this.getString().hashCode();
1654 public boolean equals(
1657 if (!(o instanceof DERBMPString))
1662 DERPrintableString s = (DERPrintableString)o;
1664 return this.getString().equals(s.getString());
1668 DEROutputStream out)
1671 char[] c = string.toCharArray();
1672 byte[] b = new byte[c.length * 2];
1674 for (int i = 0; i != c.length; i++)
1676 b[2 * i] = (byte)(c[i] >> 8);
1677 b[2 * i + 1] = (byte)c[i];
1680 out.writeEncoded(BMP_STRING, b);
1690 public static final DERBoolean FALSE = new DERBoolean(false);
1691 public static final DERBoolean TRUE = new DERBoolean(true);
1694 * return a boolean from the passed in object.
1696 * @exception IllegalArgumentException if the object cannot be converted.
1698 public static DERBoolean getInstance(
1701 if (obj == null || obj instanceof DERBoolean)
1703 return (DERBoolean)obj;
1706 if (obj instanceof ASN1OctetString)
1708 return new DERBoolean(((ASN1OctetString)obj).getOctets());
1711 if (obj instanceof ASN1TaggedObject)
1713 return getInstance(((ASN1TaggedObject)obj).getObject());
1716 throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
1720 * return a DERBoolean from the passed in boolean.
1722 public static DERBoolean getInstance(
1725 return (value ? TRUE : FALSE);
1729 * return a Boolean from a tagged object.
1731 * @param obj the tagged object holding the object we want
1732 * @param explicit true if the object is meant to be explicitly
1733 * tagged false otherwise.
1734 * @exception IllegalArgumentException if the tagged object cannot
1737 public static DERBoolean getInstance(
1738 ASN1TaggedObject obj,
1741 return getInstance(obj.getObject());
1747 this.value = value[0];
1753 this.value = (value) ? (byte)0xff : (byte)0;
1756 public boolean isTrue()
1758 return (value != 0);
1762 DEROutputStream out)
1765 byte[] bytes = new byte[1];
1769 out.writeEncoded(BOOLEAN, bytes);
1772 public boolean equals(
1775 if ((o == null) || !(o instanceof DERBoolean))
1780 return (value == ((DERBoolean)o).value);
1786 class DERConstructedSequence
1787 extends ASN1Sequence
1789 public void addObject(
1792 super.addObject(obj);
1795 public int getSize()
1801 * A note on the implementation:
1803 * As DER requires the constructed, definite-length model to
1804 * be used for structured types, this varies slightly from the
1805 * ASN.1 descriptions given. Rather than just outputing SEQUENCE,
1806 * we also have to specify CONSTRUCTED, and the objects length.
1809 DEROutputStream out)
1812 ByteArrayOutputStream bOut = new ByteArrayOutputStream();
1813 DEROutputStream dOut = new DEROutputStream(bOut);
1814 Enumeration e = this.getObjects();
1816 while (e.hasMoreElements())
1818 Object obj = e.nextElement();
1820 dOut.writeObject(obj);
1825 byte[] bytes = bOut.toByteArray();
1827 out.writeEncoded(SEQUENCE | CONSTRUCTED, bytes);
1832 class DERConstructedSet
1835 public DERConstructedSet()
1840 * @param obj - a single object that makes up the set.
1842 public DERConstructedSet(
1845 this.addObject(obj);
1849 * @param v - a vector of objects making up the set.
1851 public DERConstructedSet(
1852 DEREncodableVector v)
1854 for (int i = 0; i != v.size(); i++)
1856 this.addObject(v.get(i));
1860 public void addObject(
1863 super.addObject(obj);
1866 public int getSize()
1872 * A note on the implementation:
1874 * As DER requires the constructed, definite-length model to
1875 * be used for structured types, this varies slightly from the
1876 * ASN.1 descriptions given. Rather than just outputing SET,
1877 * we also have to specify CONSTRUCTED, and the objects length.
1880 DEROutputStream out)
1883 ByteArrayOutputStream bOut = new ByteArrayOutputStream();
1884 DEROutputStream dOut = new DEROutputStream(bOut);
1885 Enumeration e = this.getObjects();
1887 while (e.hasMoreElements())
1889 Object obj = e.nextElement();
1891 dOut.writeObject(obj);
1896 byte[] bytes = bOut.toByteArray();
1898 out.writeEncoded(SET | CONSTRUCTED, bytes);
1902 interface DEREncodable
1904 public DERObject getDERObject();
1909 * a general class for building up a vector of DER encodable objects
1911 class DEREncodableVector
1913 private Vector v = new Vector();
1921 public DEREncodable get(
1924 return (DEREncodable)v.elementAt(i);
1940 * return an integer from the passed in object
1942 * @exception IllegalArgumentException if the object cannot be converted.
1944 public static DEREnumerated getInstance(
1947 if (obj == null || obj instanceof DEREnumerated)
1949 return (DEREnumerated)obj;
1952 if (obj instanceof ASN1OctetString)
1954 return new DEREnumerated(((ASN1OctetString)obj).getOctets());
1957 if (obj instanceof ASN1TaggedObject)
1959 return getInstance(((ASN1TaggedObject)obj).getObject());
1962 throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
1966 * return an Enumerated from a tagged object.
1968 * @param obj the tagged object holding the object we want
1969 * @param explicit true if the object is meant to be explicitly
1970 * tagged false otherwise.
1971 * @exception IllegalArgumentException if the tagged object cannot
1974 public static DEREnumerated getInstance(
1975 ASN1TaggedObject obj,
1978 return getInstance(obj.getObject());
1981 public DEREnumerated(
1984 bytes = BigInteger.valueOf(value).toByteArray();
1987 public DEREnumerated(
1990 bytes = value.toByteArray();
1993 public DEREnumerated(
1999 public BigInteger getValue()
2001 return new BigInteger(bytes);
2005 DEROutputStream out)
2008 out.writeEncoded(ENUMERATED, bytes);
2011 public boolean equals(
2014 if (o == null || !(o instanceof DEREnumerated))
2019 DEREnumerated other = (DEREnumerated)o;
2021 if (bytes.length != other.bytes.length)
2026 for (int i = 0; i != bytes.length; i++)
2028 if (bytes[i] != other.bytes[i])
2040 * Generalized time object.
2042 class DERGeneralizedTime
2048 * return a generalized time from the passed in object
2050 * @exception IllegalArgumentException if the object cannot be converted.
2052 public static DERGeneralizedTime getInstance(
2055 if (obj == null || obj instanceof DERGeneralizedTime)
2057 return (DERGeneralizedTime)obj;
2060 if (obj instanceof ASN1OctetString)
2062 return new DERGeneralizedTime(((ASN1OctetString)obj).getOctets());
2065 throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
2069 * return a Generalized Time object from a tagged object.
2071 * @param obj the tagged object holding the object we want
2072 * @param explicit true if the object is meant to be explicitly
2073 * tagged false otherwise.
2074 * @exception IllegalArgumentException if the tagged object cannot
2077 public static DERGeneralizedTime getInstance(
2078 ASN1TaggedObject obj,
2081 return getInstance(obj.getObject());
2085 * The correct format for this is YYYYMMDDHHMMSSZ, or without the Z
2086 * for local time, or Z+-HHMM on the end, for difference between local
2087 * time and UTC time.
2090 * @param time the time string.
2092 public DERGeneralizedTime(
2099 * base constructer from a java.util.date object
2101 public DERGeneralizedTime(
2104 SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmss'Z'");
2106 dateF.setTimeZone(new SimpleTimeZone(0,"Z"));
2108 this.time = dateF.format(time);
2115 // explicitly convert to characters
2117 char[] dateC = new char[bytes.length];
2119 for (int i = 0; i != dateC.length; i++)
2121 dateC[i] = (char)(bytes[i] & 0xff);
2124 this.time = new String(dateC);
2128 * return the time - always in the form of
2129 * YYYYMMDDhhmmssGMT(+hh:mm|-hh:mm).
2131 * Normally in a certificate we would expect "Z" rather than "GMT",
2132 * however adding the "GMT" means we can just use:
2134 * dateF = new SimpleDateFormat("yyyyMMddHHmmssz");
2136 * To read in the time and get a date which is compatible with our local
2139 public String getTime()
2142 // standardise the format.
2144 if (time.length() == 15)
2146 return time.substring(0, 14) + "GMT+00:00";
2148 else if (time.length() == 17)
2150 return time.substring(0, 14) + "GMT" + time.substring(15, 17) + ":" + time.substring(17, 19);
2156 private byte[] getOctets()
2158 char[] cs = time.toCharArray();
2159 byte[] bs = new byte[cs.length];
2161 for (int i = 0; i != cs.length; i++)
2163 bs[i] = (byte)cs[i];
2171 DEROutputStream out)
2174 out.writeEncoded(GENERALIZED_TIME, this.getOctets());
2177 public boolean equals(
2180 if ((o == null) || !(o instanceof DERGeneralizedTime))
2185 return time.equals(((DERGeneralizedTime)o).time);
2191 * DER IA5String object - this is an ascii string.
2195 implements DERString
2200 * return a IA5 string from the passed in object
2202 * @exception IllegalArgumentException if the object cannot be converted.
2204 public static DERIA5String getInstance(
2207 if (obj == null || obj instanceof DERIA5String)
2209 return (DERIA5String)obj;
2212 if (obj instanceof ASN1OctetString)
2214 return new DERIA5String(((ASN1OctetString)obj).getOctets());
2217 if (obj instanceof ASN1TaggedObject)
2219 return getInstance(((ASN1TaggedObject)obj).getObject());
2222 throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
2226 * return an IA5 String from a tagged object.
2228 * @param obj the tagged object holding the object we want
2229 * @param explicit true if the object is meant to be explicitly
2230 * tagged false otherwise.
2231 * @exception IllegalArgumentException if the tagged object cannot
2234 public static DERIA5String getInstance(
2235 ASN1TaggedObject obj,
2238 return getInstance(obj.getObject());
2242 * basic constructor - with bytes.
2244 public DERIA5String(
2247 char[] cs = new char[string.length];
2249 for (int i = 0; i != cs.length; i++)
2251 cs[i] = (char)(string[i] & 0xff);
2254 this.string = new String(cs);
2258 * basic constructor - with string.
2260 public DERIA5String(
2263 this.string = string;
2266 public String getString()
2271 public byte[] getOctets()
2273 char[] cs = string.toCharArray();
2274 byte[] bs = new byte[cs.length];
2276 for (int i = 0; i != cs.length; i++)
2278 bs[i] = (byte)cs[i];
2285 DEROutputStream out)
2288 out.writeEncoded(IA5_STRING, this.getOctets());
2291 public int hashCode()
2293 return this.getString().hashCode();
2296 public boolean equals(
2299 if (!(o instanceof DERIA5String))
2304 DERIA5String s = (DERIA5String)o;
2306 return this.getString().equals(s.getString());
2313 class DERInputStream
2314 extends FilterInputStream implements DERTags
2316 public DERInputStream(
2322 protected int readLength()
2325 int length = read();
2328 throw new IOException("EOF found when length expected");
2333 return -1; // indefinite-length encoding
2338 int size = length & 0x7f;
2341 for (int i = 0; i < size; i++)
2347 throw new IOException("EOF found reading length");
2350 length = (length << 8) + next;
2357 protected void readFully(
2361 int left = bytes.length;
2368 while ((left -= read(bytes, bytes.length - left, left)) != 0)
2375 * build an object given its tag and a byte stream to construct it
2378 protected DERObject buildObject(
2387 case SEQUENCE | CONSTRUCTED:
2388 ByteArrayInputStream bIn = new ByteArrayInputStream(bytes);
2389 BERInputStream dIn = new BERInputStream(bIn);
2390 DERConstructedSequence seq = new DERConstructedSequence();
2396 DERObject obj = dIn.readObject();
2401 catch (EOFException ex)
2405 case SET | CONSTRUCTED:
2406 bIn = new ByteArrayInputStream(bytes);
2407 dIn = new BERInputStream(bIn);
2409 DEREncodableVector v = new DEREncodableVector();
2415 DERObject obj = dIn.readObject();
2420 catch (EOFException ex)
2422 return new DERConstructedSet(v);
2425 return new DERBoolean(bytes);
2427 return new DERInteger(bytes);
2429 return new DEREnumerated(bytes);
2430 case OBJECT_IDENTIFIER:
2431 return new DERObjectIdentifier(bytes);
2433 int padBits = bytes[0];
2434 byte[] data = new byte[bytes.length - 1];
2436 System.arraycopy(bytes, 1, data, 0, bytes.length - 1);
2438 return new DERBitString(data, padBits);
2440 return new DERUTF8String(bytes);
2441 case PRINTABLE_STRING:
2442 return new DERPrintableString(bytes);
2444 return new DERIA5String(bytes);
2446 return new DERT61String(bytes);
2447 case VISIBLE_STRING:
2448 return new DERVisibleString(bytes);
2449 case UNIVERSAL_STRING:
2450 return new DERUniversalString(bytes);
2452 return new DERBMPString(bytes);
2454 return new DEROctetString(bytes);
2456 return new DERUTCTime(bytes);
2457 case GENERALIZED_TIME:
2458 return new DERGeneralizedTime(bytes);
2461 // with tagged object tag number is bottom 5 bits
2463 if ((tag & TAGGED) != 0)
2465 if ((tag & 0x1f) == 0x1f)
2467 throw new IOException("unsupported high tag encountered");
2470 if (bytes.length == 0) // empty tag!
2472 return new DERTaggedObject(false, tag & 0x1f, new DERConstructedSequence());
2476 // simple type - implicit... return an octet string
2478 if ((tag & CONSTRUCTED) == 0)
2480 return new DERTaggedObject(false, tag & 0x1f, new DEROctetString(bytes));
2483 bIn = new ByteArrayInputStream(bytes);
2484 dIn = new BERInputStream(bIn);
2486 DEREncodable dObj = dIn.readObject();
2489 // explicitly tagged (probably!) - if it isn't we'd have to
2490 // tell from the context
2492 if (dIn.available() == 0)
2494 return new DERTaggedObject(tag & 0x1f, dObj);
2498 // another implicit object, we'll create a sequence...
2500 seq = new DERConstructedSequence();
2502 seq.addObject(dObj);
2508 dObj = dIn.readObject();
2510 seq.addObject(dObj);
2513 catch (EOFException ex)
2518 return new DERTaggedObject(false, tag & 0x1f, seq);
2521 return new DERUnknownTag(tag, bytes);
2525 public DERObject readObject()
2531 throw new EOFException();
2534 int length = readLength();
2535 byte[] bytes = new byte[length];
2539 return buildObject(tag, bytes);
2550 * return an integer from the passed in object
2552 * @exception IllegalArgumentException if the object cannot be converted.
2554 public static DERInteger getInstance(
2557 if (obj == null || obj instanceof DERInteger)
2559 return (DERInteger)obj;
2562 if (obj instanceof ASN1OctetString)
2564 return new DERInteger(((ASN1OctetString)obj).getOctets());
2567 if (obj instanceof ASN1TaggedObject)
2569 return getInstance(((ASN1TaggedObject)obj).getObject());
2572 throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
2576 * return an Integer from a tagged object.
2578 * @param obj the tagged object holding the object we want
2579 * @param explicit true if the object is meant to be explicitly
2580 * tagged false otherwise.
2581 * @exception IllegalArgumentException if the tagged object cannot
2584 public static DERInteger getInstance(
2585 ASN1TaggedObject obj,
2588 return getInstance(obj.getObject());
2594 bytes = BigInteger.valueOf(value).toByteArray();
2600 bytes = value.toByteArray();
2609 public BigInteger getValue()
2611 return new BigInteger(bytes);
2615 * in some cases positive values get crammed into a space,
2616 * that's not quite big enough...
2618 public BigInteger getPositiveValue()
2620 return new BigInteger(1, bytes);
2624 DEROutputStream out)
2627 out.writeEncoded(INTEGER, bytes);
2630 public boolean equals(
2633 if (o == null || !(o instanceof DERInteger))
2638 DERInteger other = (DERInteger)o;
2640 if (bytes.length != other.bytes.length)
2645 for (int i = 0; i != bytes.length; i++)
2647 if (bytes[i] != other.bytes[i])
2658 abstract class DERObject
2659 implements DERTags, DEREncodable
2661 public DERObject getDERObject()
2666 abstract void encode(DEROutputStream out)
2671 class DERObjectIdentifier
2677 * return an OID from the passed in object
2679 * @exception IllegalArgumentException if the object cannot be converted.
2681 public static DERObjectIdentifier getInstance(
2684 if (obj == null || obj instanceof DERObjectIdentifier)
2686 return (DERObjectIdentifier)obj;
2689 if (obj instanceof ASN1OctetString)
2691 return new DERObjectIdentifier(((ASN1OctetString)obj).getOctets());
2694 if (obj instanceof ASN1TaggedObject)
2696 return getInstance(((ASN1TaggedObject)obj).getObject());
2699 throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
2703 * return an Object Identifier from a tagged object.
2705 * @param obj the tagged object holding the object we want
2706 * @param explicit true if the object is meant to be explicitly
2707 * tagged false otherwise.
2708 * @exception IllegalArgumentException if the tagged object cannot
2711 public static DERObjectIdentifier getInstance(
2712 ASN1TaggedObject obj,
2715 return getInstance(obj.getObject());
2719 DERObjectIdentifier(
2722 int head = bytes[0] & 0xff;
2723 StringBuffer objId = new StringBuffer();
2725 boolean first = true;
2727 for (int i = 0; i != bytes.length; i++)
2729 int b = bytes[i] & 0xff;
2731 value = value * 128 + (b & 0x7f);
2732 if ((b & 0x80) == 0) // end of number reached
2753 objId.append(Integer.toString(value));
2758 this.identifier = objId.toString();
2761 public DERObjectIdentifier(
2764 this.identifier = identifier;
2767 public String getId()
2772 private void writeField(
2777 if (fieldValue >= (1 << 7))
2779 if (fieldValue >= (1 << 14))
2781 if (fieldValue >= (1 << 21))
2783 if (fieldValue >= (1 << 28))
2785 out.write((fieldValue >> 28) | 0x80);
2787 out.write((fieldValue >> 21) | 0x80);
2789 out.write((fieldValue >> 14) | 0x80);
2791 out.write((fieldValue >> 7) | 0x80);
2793 out.write(fieldValue & 0x7f);
2797 DEROutputStream out)
2800 OIDTokenizer tok = new OIDTokenizer(identifier);
2801 ByteArrayOutputStream bOut = new ByteArrayOutputStream();
2802 DEROutputStream dOut = new DEROutputStream(bOut);
2805 Integer.parseInt(tok.nextToken()) * 40
2806 + Integer.parseInt(tok.nextToken()));
2808 while (tok.hasMoreTokens())
2810 writeField(bOut, Integer.parseInt(tok.nextToken()));
2815 byte[] bytes = bOut.toByteArray();
2817 out.writeEncoded(OBJECT_IDENTIFIER, bytes);
2820 public int hashCode()
2822 return identifier.hashCode();
2825 public boolean equals(
2828 if ((o == null) || !(o instanceof DERObjectIdentifier))
2833 return identifier.equals(((DERObjectIdentifier)o).identifier);
2838 class DEROctetString
2839 extends ASN1OctetString
2842 * @param string the octets making up the octet string.
2844 public DEROctetString(
2850 public DEROctetString(
2857 DEROutputStream out)
2860 out.writeEncoded(OCTET_STRING, string);
2866 class DEROutputStream
2867 extends FilterOutputStream implements DERTags
2869 public DEROutputStream(
2875 private void writeLength(
2884 while ((val >>>= 8) != 0)
2889 write((byte)(size | 0x80));
2891 for (int i = (size - 1) * 8; i >= 0; i -= 8)
2893 write((byte)(length >> i));
2898 write((byte)length);
2908 writeLength(bytes.length);
2912 protected void writeNull()
2919 public void writeObject(
2927 else if (obj instanceof DERObject)
2929 ((DERObject)obj).encode(this);
2931 else if (obj instanceof DEREncodable)
2933 ((DEREncodable)obj).getDERObject().encode(this);
2937 throw new IOException("object not DEREncodable");
2944 * DER PrintableString object.
2946 class DERPrintableString
2948 implements DERString
2953 * return a printable string from the passed in object.
2955 * @exception IllegalArgumentException if the object cannot be converted.
2957 public static DERPrintableString getInstance(
2960 if (obj == null || obj instanceof DERPrintableString)
2962 return (DERPrintableString)obj;
2965 if (obj instanceof ASN1OctetString)
2967 return new DERPrintableString(((ASN1OctetString)obj).getOctets());
2970 if (obj instanceof ASN1TaggedObject)
2972 return getInstance(((ASN1TaggedObject)obj).getObject());
2975 throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
2979 * return a Printable String from a tagged object.
2981 * @param obj the tagged object holding the object we want
2982 * @param explicit true if the object is meant to be explicitly
2983 * tagged false otherwise.
2984 * @exception IllegalArgumentException if the tagged object cannot
2987 public static DERPrintableString getInstance(
2988 ASN1TaggedObject obj,
2991 return getInstance(obj.getObject());
2995 * basic constructor - byte encoded string.
2997 public DERPrintableString(
3000 char[] cs = new char[string.length];
3002 for (int i = 0; i != cs.length; i++)
3004 cs[i] = (char)(string[i] & 0xff);
3007 this.string = new String(cs);
3013 public DERPrintableString(
3016 this.string = string;
3019 public String getString()
3024 public byte[] getOctets()
3026 char[] cs = string.toCharArray();
3027 byte[] bs = new byte[cs.length];
3029 for (int i = 0; i != cs.length; i++)
3031 bs[i] = (byte)cs[i];
3038 DEROutputStream out)
3041 out.writeEncoded(PRINTABLE_STRING, this.getOctets());
3044 public int hashCode()
3046 return this.getString().hashCode();
3049 public boolean equals(
3052 if (!(o instanceof DERPrintableString))
3057 DERPrintableString s = (DERPrintableString)o;
3059 return this.getString().equals(s.getString());
3065 extends ASN1Sequence
3068 * create an empty sequence
3070 public DERSequence()
3075 * create a sequence containing one object
3080 this.addObject(obj);
3084 * create a sequence containing a vector of objects.
3087 DEREncodableVector v)
3089 for (int i = 0; i != v.size(); i++)
3091 this.addObject(v.get(i));
3096 * A note on the implementation:
3098 * As DER requires the constructed, definite-length model to
3099 * be used for structured types, this varies slightly from the
3100 * ASN.1 descriptions given. Rather than just outputing SEQUENCE,
3101 * we also have to specify CONSTRUCTED, and the objects length.
3104 DEROutputStream out)
3107 ByteArrayOutputStream bOut = new ByteArrayOutputStream();
3108 DEROutputStream dOut = new DEROutputStream(bOut);
3109 Enumeration e = this.getObjects();
3111 while (e.hasMoreElements())
3113 Object obj = e.nextElement();
3115 dOut.writeObject(obj);
3120 byte[] bytes = bOut.toByteArray();
3122 out.writeEncoded(SEQUENCE | CONSTRUCTED, bytes);
3128 * A DER encoded set object
3134 * create an empty set
3141 * @param obj - a single object that makes up the set.
3146 this.addObject(obj);
3150 * @param v - a vector of objects making up the set.
3153 DEREncodableVector v)
3155 for (int i = 0; i != v.size(); i++)
3157 this.addObject(v.get(i));
3162 * A note on the implementation:
3164 * As DER requires the constructed, definite-length model to
3165 * be used for structured types, this varies slightly from the
3166 * ASN.1 descriptions given. Rather than just outputing SET,
3167 * we also have to specify CONSTRUCTED, and the objects length.
3170 DEROutputStream out)
3173 ByteArrayOutputStream bOut = new ByteArrayOutputStream();
3174 DEROutputStream dOut = new DEROutputStream(bOut);
3175 Enumeration e = this.getObjects();
3177 while (e.hasMoreElements())
3179 Object obj = e.nextElement();
3181 dOut.writeObject(obj);
3186 byte[] bytes = bOut.toByteArray();
3188 out.writeEncoded(SET | CONSTRUCTED, bytes);
3193 * basic interface for DER string objects.
3197 public String getString();
3202 * DER T61String (also the teletex string)
3206 implements DERString
3211 * return a T61 string from the passed in object.
3213 * @exception IllegalArgumentException if the object cannot be converted.
3215 public static DERT61String getInstance(
3218 if (obj == null || obj instanceof DERT61String)
3220 return (DERT61String)obj;
3223 if (obj instanceof ASN1OctetString)
3225 return new DERT61String(((ASN1OctetString)obj).getOctets());
3228 if (obj instanceof ASN1TaggedObject)
3230 return getInstance(((ASN1TaggedObject)obj).getObject());
3233 throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
3237 * return an T61 String from a tagged object.
3239 * @param obj the tagged object holding the object we want
3240 * @param explicit true if the object is meant to be explicitly
3241 * tagged false otherwise.
3242 * @exception IllegalArgumentException if the tagged object cannot
3245 public static DERT61String getInstance(
3246 ASN1TaggedObject obj,
3249 return getInstance(obj.getObject());
3253 * basic constructor - with bytes.
3255 public DERT61String(
3258 this.string = new String(string);
3262 * basic constructor - with string.
3264 public DERT61String(
3267 this.string = string;
3270 public String getString()
3276 DEROutputStream out)
3279 out.writeEncoded(T61_STRING, string.getBytes());
3282 public boolean equals(
3285 if ((o == null) || !(o instanceof DERT61String))
3290 return this.getString().equals(((DERT61String)o).getString());
3296 * DER TaggedObject - in ASN.1 nottation this is any object proceeded by
3297 * a [n] where n is some number - these are assume to follow the construction
3298 * rules (as with sequences).
3300 class DERTaggedObject
3301 extends ASN1TaggedObject
3304 * @param tagNo the tag number for this object.
3305 * @param obj the tagged object.
3307 public DERTaggedObject(
3315 * @param explicit true if an explicitly tagged object.
3316 * @param tagNo the tag number for this object.
3317 * @param obj the tagged object.
3319 public DERTaggedObject(
3324 super(explicit, tagNo, obj);
3328 * create an implicitly tagged object that contains a zero
3331 public DERTaggedObject(
3334 super(false, tagNo, new DERSequence());
3338 DEROutputStream out)
3343 ByteArrayOutputStream bOut = new ByteArrayOutputStream();
3344 DEROutputStream dOut = new DEROutputStream(bOut);
3346 dOut.writeObject(obj);
3349 byte[] bytes = bOut.toByteArray();
3353 out.writeEncoded(CONSTRUCTED | TAGGED | tagNo, bytes);
3358 // need to mark constructed types...
3360 if ((bytes[0] & CONSTRUCTED) != 0)
3362 bytes[0] = (byte)(CONSTRUCTED | TAGGED | tagNo);
3366 bytes[0] = (byte)(TAGGED | tagNo);
3374 out.writeEncoded(CONSTRUCTED | TAGGED | tagNo, new byte[0]);
3381 public static final int BOOLEAN = 0x01;
3382 public static final int INTEGER = 0x02;
3383 public static final int BIT_STRING = 0x03;
3384 public static final int OCTET_STRING = 0x04;
3385 public static final int NULL = 0x05;
3386 public static final int OBJECT_IDENTIFIER = 0x06;
3387 public static final int EXTERNAL = 0x08;
3388 public static final int ENUMERATED = 0x0a;
3389 public static final int SEQUENCE = 0x10;
3390 public static final int SEQUENCE_OF = 0x10; // for completeness
3391 public static final int SET = 0x11;
3392 public static final int SET_OF = 0x11; // for completeness
3393 public static final int CONSTRUCTED = 0x20;
3394 public static final int TAGGED = 0x80;
3396 public static final int NUMERIC_STRING = 0x12;
3397 public static final int PRINTABLE_STRING = 0x13;
3398 public static final int T61_STRING = 0x14;
3399 public static final int VIDEOTEX_STRING = 0x15;
3400 public static final int IA5_STRING = 0x16;
3401 public static final int UTC_TIME = 0x17;
3402 public static final int GENERALIZED_TIME = 0x18;
3403 public static final int GRAPHIC_STRING = 0x19;
3404 public static final int VISIBLE_STRING = 0x1a;
3405 public static final int GENERAL_STRING = 0x1b;
3406 public static final int UNIVERSAL_STRING = 0x1c;
3407 public static final int BMP_STRING = 0x1e;
3408 public static final int UTF8_STRING = 0x0c;
3413 * DER UniversalString object.
3415 class DERUniversalString
3417 implements DERString
3420 char[] table = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
3423 * return a Universal String from the passed in object.
3425 * @exception IllegalArgumentException if the object cannot be converted.
3427 public static DERUniversalString getInstance(
3430 if (obj == null || obj instanceof DERUniversalString)
3432 return (DERUniversalString)obj;
3435 if (obj instanceof ASN1OctetString)
3437 return new DERUniversalString(((ASN1OctetString)obj).getOctets());
3440 throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
3444 * return a Universal String from a tagged object.
3446 * @param obj the tagged object holding the object we want
3447 * @param explicit true if the object is meant to be explicitly
3448 * tagged false otherwise.
3449 * @exception IllegalArgumentException if the tagged object cannot
3452 public static DERUniversalString getInstance(
3453 ASN1TaggedObject obj,
3456 return getInstance(obj.getObject());
3460 * basic constructor - byte encoded string.
3462 public DERUniversalString(
3465 this.string = string;
3469 * UniversalStrings have characters which are 4 bytes long - for the
3470 * moment we just return them in Hex...
3472 public String getString()
3474 StringBuffer buf = new StringBuffer();
3476 for (int i = 0; i != string.length; i++)
3478 buf.append(table[(string[i] >>> 4) % 0xf]);
3479 buf.append(table[string[i] & 0xf]);
3482 return buf.toString();
3485 public byte[] getOctets()
3491 DEROutputStream out)
3494 out.writeEncoded(UNIVERSAL_STRING, this.getOctets());
3497 public boolean equals(
3500 if ((o == null) || !(o instanceof DERUniversalString))
3505 return this.getString().equals(((DERUniversalString)o).getString());
3511 * We insert one of these when we find a tag we don't recognise.
3520 * @param tag the tag value.
3521 * @param data the octets making up the time.
3523 public DERUnknownTag(
3536 public byte[] getData()
3542 DEROutputStream out)
3545 out.writeEncoded(tag, data);
3548 public boolean equals(
3551 if ((o == null) || !(o instanceof DERUnknownTag))
3556 DERUnknownTag other = (DERUnknownTag)o;
3558 if(tag != other.tag)
3563 if(data.length != other.data.length)
3568 for(int i = 0; i < data.length; i++)
3570 if(data[i] != other.data[i])
3590 * return an UTC Time from the passed in object.
3592 * @exception IllegalArgumentException if the object cannot be converted.
3594 public static DERUTCTime getInstance(
3597 if (obj == null || obj instanceof DERUTCTime)
3599 return (DERUTCTime)obj;
3602 if (obj instanceof ASN1OctetString)
3604 return new DERUTCTime(((ASN1OctetString)obj).getOctets());
3607 throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
3611 * return an UTC Time from a tagged object.
3613 * @param obj the tagged object holding the object we want
3614 * @param explicit true if the object is meant to be explicitly
3615 * tagged false otherwise.
3616 * @exception IllegalArgumentException if the tagged object cannot
3619 public static DERUTCTime getInstance(
3620 ASN1TaggedObject obj,
3623 return getInstance(obj.getObject());
3627 * The correct format for this is YYMMDDHHMMSSZ (it used to be that seconds were
3628 * never encoded. When you're creating one of these objects from scratch, that's
3629 * what you want to use, otherwise we'll try to deal with whatever gets read from
3630 * the input stream... (this is why the input format is different from the getTime()
3634 * @param time the time string.
3643 * base constructer from a java.util.date object
3648 SimpleDateFormat dateF = new SimpleDateFormat("yyMMddHHmmss'Z'");
3650 dateF.setTimeZone(new SimpleTimeZone(0,"Z"));
3652 this.time = dateF.format(time);
3659 // explicitly convert to characters
3661 char[] dateC = new char[bytes.length];
3663 for (int i = 0; i != dateC.length; i++)
3665 dateC[i] = (char)(bytes[i] & 0xff);
3668 this.time = new String(dateC);
3672 * return the time - always in the form of
3673 * YYMMDDhhmmssGMT(+hh:mm|-hh:mm).
3675 * Normally in a certificate we would expect "Z" rather than "GMT",
3676 * however adding the "GMT" means we can just use:
3678 * dateF = new SimpleDateFormat("yyMMddHHmmssz");
3680 * To read in the time and get a date which is compatible with our local
3683 * <b>Note:</b> In some cases, due to the local date processing, this
3684 * may lead to unexpected results. If you want to stick the normal
3685 * convention of 1950 to 2049 use the getAdjustedTime() method.
3687 public String getTime()
3690 // standardise the format.
3692 if (time.length() == 11)
3694 return time.substring(0, 10) + "00GMT+00:00";
3696 else if (time.length() == 13)
3698 return time.substring(0, 12) + "GMT+00:00";
3700 else if (time.length() == 17)
3702 return time.substring(0, 12) + "GMT" + time.substring(12, 15) + ":" + time.substring(15, 17);
3709 * return the time as an adjusted date with a 4 digit year. This goes
3710 * in the range of 1950 - 2049.
3712 public String getAdjustedTime()
3714 String d = this.getTime();
3716 if (d.charAt(0) < '5')
3726 private byte[] getOctets()
3728 char[] cs = time.toCharArray();
3729 byte[] bs = new byte[cs.length];
3731 for (int i = 0; i != cs.length; i++)
3733 bs[i] = (byte)cs[i];
3740 DEROutputStream out)
3743 out.writeEncoded(UTC_TIME, this.getOctets());
3746 public boolean equals(
3749 if ((o == null) || !(o instanceof DERUTCTime))
3754 return time.equals(((DERUTCTime)o).time);
3760 * DER UTF8String object.
3764 implements DERString
3769 * return an UTF8 string from the passed in object.
3771 * @exception IllegalArgumentException if the object cannot be converted.
3773 public static DERUTF8String getInstance(
3776 if (obj == null || obj instanceof DERUTF8String)
3778 return (DERUTF8String)obj;
3781 if (obj instanceof ASN1OctetString)
3783 return new DERUTF8String(((ASN1OctetString)obj).getOctets());
3786 if (obj instanceof ASN1TaggedObject)
3788 return getInstance(((ASN1TaggedObject)obj).getObject());
3791 throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
3795 * return an UTF8 String from a tagged object.
3797 * @param obj the tagged object holding the object we want
3798 * @param explicit true if the object is meant to be explicitly
3799 * tagged false otherwise.
3800 * @exception IllegalArgumentException if the tagged object cannot
3803 public static DERUTF8String getInstance(
3804 ASN1TaggedObject obj,
3807 return getInstance(obj.getObject());
3811 * basic constructor - byte encoded string.
3819 while (i < string.length)
3822 if ((string[i] & 0xe0) == 0xe0)
3826 else if ((string[i] & 0xc0) == 0xc0)
3836 char[] cs = new char[length];
3841 while (i < string.length)
3845 if ((string[i] & 0xe0) == 0xe0)
3847 ch = (char)(((string[i] & 0x1f) << 12)
3848 | ((string[i + 1] & 0x3f) << 6) | (string[i + 2] & 0x3f));
3851 else if ((string[i] & 0xc0) == 0xc0)
3853 ch = (char)(((string[i] & 0x3f) << 6) | (string[i + 1] & 0x3f));
3858 ch = (char)(string[i] & 0xff);
3865 this.string = new String(cs);
3871 public DERUTF8String(
3874 this.string = string;
3877 public String getString()
3882 public int hashCode()
3884 return this.getString().hashCode();
3887 public boolean equals(
3890 if (!(o instanceof DERUTF8String))
3895 DERUTF8String s = (DERUTF8String)o;
3897 return this.getString().equals(s.getString());
3901 DEROutputStream out)
3904 char[] c = string.toCharArray();
3905 ByteArrayOutputStream bOut = new ByteArrayOutputStream();
3907 for (int i = 0; i != c.length; i++)
3915 else if (ch < 0x0800)
3917 bOut.write(0xc0 | (ch >> 6));
3918 bOut.write(0x80 | (ch & 0x3f));
3922 bOut.write(0xe0 | (ch >> 12));
3923 bOut.write(0x80 | ((ch >> 6) & 0x3F));
3924 bOut.write(0x80 | (ch & 0x3F));
3928 out.writeEncoded(UTF8_STRING, bOut.toByteArray());
3934 * DER VisibleString object.
3936 class DERVisibleString
3938 implements DERString
3943 * return a Visible String from the passed in object.
3945 * @exception IllegalArgumentException if the object cannot be converted.
3947 public static DERVisibleString getInstance(
3950 if (obj == null || obj instanceof DERVisibleString)
3952 return (DERVisibleString)obj;
3955 if (obj instanceof ASN1OctetString)
3957 return new DERVisibleString(((ASN1OctetString)obj).getOctets());
3960 if (obj instanceof ASN1TaggedObject)
3962 return getInstance(((ASN1TaggedObject)obj).getObject());
3965 throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
3969 * return a Visible String from a tagged object.
3971 * @param obj the tagged object holding the object we want
3972 * @param explicit true if the object is meant to be explicitly
3973 * tagged false otherwise.
3974 * @exception IllegalArgumentException if the tagged object cannot
3977 public static DERVisibleString getInstance(
3978 ASN1TaggedObject obj,
3981 return getInstance(obj.getObject());
3985 * basic constructor - byte encoded string.
3987 public DERVisibleString(
3990 char[] cs = new char[string.length];
3992 for (int i = 0; i != cs.length; i++)
3994 cs[i] = (char)(string[i] & 0xff);
3997 this.string = new String(cs);
4003 public DERVisibleString(
4006 this.string = string;
4009 public String getString()
4014 public byte[] getOctets()
4016 char[] cs = string.toCharArray();
4017 byte[] bs = new byte[cs.length];
4019 for (int i = 0; i != cs.length; i++)
4021 bs[i] = (byte)cs[i];
4028 DEROutputStream out)
4031 out.writeEncoded(VISIBLE_STRING, this.getOctets());
4034 public boolean equals(
4037 if ((o == null) || !(o instanceof DERVisibleString))
4042 return this.getString().equals(((DERVisibleString)o).getString());
4047 * class for breaking up an OID into it's component tokens, ala
4048 * java.util.StringTokenizer. We need this class as some of the
4049 * lightweight Java environment don't support classes like
4057 public OIDTokenizer(
4064 public boolean hasMoreTokens()
4066 return (index != -1);
4069 public String nextToken()
4077 int end = oid.indexOf('.', index);
4081 token = oid.substring(index);
4086 token = oid.substring(index, end);
4094 interface PKCSObjectIdentifiers
4097 // pkcs-1 OBJECT IDENTIFIER ::= {
4098 // iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 }
4100 static final String pkcs_1 = "1.2.840.113549.1.1";
4101 static final DERObjectIdentifier rsaEncryption = new DERObjectIdentifier(pkcs_1 + ".1");
4102 static final DERObjectIdentifier md2WithRSAEncryption = new DERObjectIdentifier(pkcs_1 + ".2");
4103 static final DERObjectIdentifier md4WithRSAEncryption = new DERObjectIdentifier(pkcs_1 + ".3");
4104 static final DERObjectIdentifier md5WithRSAEncryption = new DERObjectIdentifier(pkcs_1 + ".4");
4105 static final DERObjectIdentifier sha1WithRSAEncryption = new DERObjectIdentifier(pkcs_1 + ".5");
4106 static final DERObjectIdentifier srsaOAEPEncryptionSET = new DERObjectIdentifier(pkcs_1 + ".6");
4107 static final DERObjectIdentifier sha256WithRSAEncryption = new DERObjectIdentifier(pkcs_1 + ".11");
4108 static final DERObjectIdentifier sha384WithRSAEncryption = new DERObjectIdentifier(pkcs_1 + ".12");
4109 static final DERObjectIdentifier sha512WithRSAEncryption = new DERObjectIdentifier(pkcs_1 + ".13");
4112 // pkcs-3 OBJECT IDENTIFIER ::= {
4113 // iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 3 }
4115 static final String pkcs_3 = "1.2.840.113549.1.3";
4116 static final DERObjectIdentifier dhKeyAgreement = new DERObjectIdentifier(pkcs_3 + ".1");
4119 // pkcs-5 OBJECT IDENTIFIER ::= {
4120 // iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 5 }
4122 static final String pkcs_5 = "1.2.840.113549.1.5";
4124 static final DERObjectIdentifier id_PBES2 = new DERObjectIdentifier(pkcs_5 + ".13");
4126 static final DERObjectIdentifier id_PBKDF2 = new DERObjectIdentifier(pkcs_5 + ".12");
4129 // encryptionAlgorithm OBJECT IDENTIFIER ::= {
4130 // iso(1) member-body(2) us(840) rsadsi(113549) 3 }
4132 static final String encryptionAlgorithm = "1.2.840.113549.3";
4134 static final DERObjectIdentifier des_EDE3_CBC = new DERObjectIdentifier(encryptionAlgorithm + ".7");
4135 static final DERObjectIdentifier RC2_CBC = new DERObjectIdentifier(encryptionAlgorithm + ".2");
4138 // object identifiers for digests
4142 // md2 OBJECT IDENTIFIER ::=
4143 // {iso(1) member-body(2) US(840) rsadsi(113549) digestAlgorithm(2) 2}
4145 static final DERObjectIdentifier md2 = new DERObjectIdentifier("1.2.840.113549.2.2");
4148 // md5 OBJECT IDENTIFIER ::=
4149 // {iso(1) member-body(2) US(840) rsadsi(113549) digestAlgorithm(2) 5}
4151 static final DERObjectIdentifier md5 = new DERObjectIdentifier("1.2.840.113549.2.5");
4154 // pkcs-7 OBJECT IDENTIFIER ::= {
4155 // iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 7 }
4157 static final String pkcs_7 = "1.2.840.113549.1.7";
4158 static final DERObjectIdentifier data = new DERObjectIdentifier(pkcs_7 + ".1");
4159 static final DERObjectIdentifier signedData = new DERObjectIdentifier(pkcs_7 + ".2");
4160 static final DERObjectIdentifier envelopedData = new DERObjectIdentifier(pkcs_7 + ".3");
4161 static final DERObjectIdentifier signedAndEnvelopedData = new DERObjectIdentifier(pkcs_7 + ".4");
4162 static final DERObjectIdentifier digestedData = new DERObjectIdentifier(pkcs_7 + ".5");
4163 static final DERObjectIdentifier encryptedData = new DERObjectIdentifier(pkcs_7 + ".6");
4166 // pkcs-9 OBJECT IDENTIFIER ::= {
4167 // iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 9 }
4169 static final String pkcs_9 = "1.2.840.113549.1.9";
4171 static final DERObjectIdentifier pkcs_9_at_emailAddress = new DERObjectIdentifier(pkcs_9 + ".1");
4172 static final DERObjectIdentifier pkcs_9_at_unstructuredName = new DERObjectIdentifier(pkcs_9 + ".2");
4173 static final DERObjectIdentifier pkcs_9_at_contentType = new DERObjectIdentifier(pkcs_9 + ".3");
4174 static final DERObjectIdentifier pkcs_9_at_messageDigest = new DERObjectIdentifier(pkcs_9 + ".4");
4175 static final DERObjectIdentifier pkcs_9_at_signingTime = new DERObjectIdentifier(pkcs_9 + ".5");
4176 static final DERObjectIdentifier pkcs_9_at_counterSignature = new DERObjectIdentifier(pkcs_9 + ".6");
4177 static final DERObjectIdentifier pkcs_9_at_challengePassword = new DERObjectIdentifier(pkcs_9 + ".7");
4178 static final DERObjectIdentifier pkcs_9_at_unstructuredAddress = new DERObjectIdentifier(pkcs_9 + ".8");
4179 static final DERObjectIdentifier pkcs_9_at_extendedCertificateAttributes = new DERObjectIdentifier(pkcs_9 + ".9");
4181 static final DERObjectIdentifier pkcs_9_at_signingDescription = new DERObjectIdentifier(pkcs_9 + ".13");
4182 static final DERObjectIdentifier pkcs_9_at_extensionRequest = new DERObjectIdentifier(pkcs_9 + ".14");
4183 static final DERObjectIdentifier pkcs_9_at_smimeCapabilities = new DERObjectIdentifier(pkcs_9 + ".15");
4185 static final DERObjectIdentifier pkcs_9_at_friendlyName = new DERObjectIdentifier(pkcs_9 + ".20");
4186 static final DERObjectIdentifier pkcs_9_at_localKeyId = new DERObjectIdentifier(pkcs_9 + ".21");
4188 static final DERObjectIdentifier x509certType = new DERObjectIdentifier(pkcs_9 + ".22.1");
4191 // SMIME capability sub oids.
4193 static final DERObjectIdentifier preferSignedData = new DERObjectIdentifier(pkcs_9 + ".15.1");
4194 static final DERObjectIdentifier canNotDecryptAny = new DERObjectIdentifier(pkcs_9 + ".15.2");
4195 static final DERObjectIdentifier sMIMECapabilitiesVersions = new DERObjectIdentifier(pkcs_9 + ".15.3");
4198 // other SMIME attributes
4202 // id-aa OBJECT IDENTIFIER ::= {iso(1) member-body(2) usa(840)
4203 // rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) attributes(2)}
4205 static String id_aa = "1.2.840.113549.1.9.16.2";
4208 * id-aa-encrypKeyPref OBJECT IDENTIFIER ::= {id-aa 11}
4211 static DERObjectIdentifier id_aa_encrypKeyPref = new DERObjectIdentifier(id_aa + ".11");
4214 // pkcs-12 OBJECT IDENTIFIER ::= {
4215 // iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 12 }
4217 static final String pkcs_12 = "1.2.840.113549.1.12";
4218 static final String bagtypes = pkcs_12 + ".10.1";
4220 static final DERObjectIdentifier keyBag = new DERObjectIdentifier(bagtypes + ".1");
4221 static final DERObjectIdentifier pkcs8ShroudedKeyBag = new DERObjectIdentifier(bagtypes + ".2");
4222 static final DERObjectIdentifier certBag = new DERObjectIdentifier(bagtypes + ".3");
4223 static final DERObjectIdentifier crlBag = new DERObjectIdentifier(bagtypes + ".4");
4224 static final DERObjectIdentifier secretBag = new DERObjectIdentifier(bagtypes + ".5");
4225 static final DERObjectIdentifier safeContentsBag = new DERObjectIdentifier(bagtypes + ".6");
4231 class AlgorithmIdentifier
4232 implements DEREncodable
4234 private DERObjectIdentifier objectId;
4235 private DEREncodable parameters;
4236 private boolean parametersDefined = false;
4238 public static AlgorithmIdentifier getInstance(
4239 ASN1TaggedObject obj,
4242 return getInstance(ASN1Sequence.getInstance(obj, explicit));
4245 public static AlgorithmIdentifier getInstance(
4248 if (obj instanceof AlgorithmIdentifier)
4250 return (AlgorithmIdentifier)obj;
4253 if (obj instanceof DERObjectIdentifier)
4255 return new AlgorithmIdentifier((DERObjectIdentifier)obj);
4258 if (obj instanceof String)
4260 return new AlgorithmIdentifier((String)obj);
4263 if (obj instanceof ASN1Sequence)
4265 return new AlgorithmIdentifier((ASN1Sequence)obj);
4268 throw new IllegalArgumentException("unknown object in factory");
4271 public AlgorithmIdentifier(
4272 DERObjectIdentifier objectId)
4274 this.objectId = objectId;
4277 public AlgorithmIdentifier(
4280 this.objectId = new DERObjectIdentifier(objectId);
4283 public AlgorithmIdentifier(
4284 DERObjectIdentifier objectId,
4285 DEREncodable parameters)
4287 parametersDefined = true;
4288 this.objectId = objectId;
4289 this.parameters = parameters;
4292 public AlgorithmIdentifier(
4295 objectId = (DERObjectIdentifier)seq.getObjectAt(0);
4297 if (seq.size() == 2)
4299 parametersDefined = true;
4300 parameters = seq.getObjectAt(1);
4308 public DERObjectIdentifier getObjectId()
4313 public DEREncodable getParameters()
4320 * AlgorithmIdentifier ::= SEQUENCE {
4321 * algorithm OBJECT IDENTIFIER,
4322 * parameters ANY DEFINED BY algorithm OPTIONAL }
4325 public DERObject getDERObject()
4327 DERConstructedSequence seq = new DERConstructedSequence();
4329 seq.addObject(objectId);
4331 if (parametersDefined)
4333 seq.addObject(parameters);
4339 public boolean equals(
4342 if ((o == null) || !(o instanceof AlgorithmIdentifier))
4347 AlgorithmIdentifier other = (AlgorithmIdentifier)o;
4349 if (!this.getObjectId().equals(other.getObjectId()))
4354 if (this.getParameters() == null && other.getParameters() == null)
4359 if (this.getParameters() == null || other.getParameters() == null)
4364 ByteArrayOutputStream b1Out = new ByteArrayOutputStream();
4365 ByteArrayOutputStream b2Out = new ByteArrayOutputStream();
4366 DEROutputStream d1Out = new DEROutputStream(b1Out);
4367 DEROutputStream d2Out = new DEROutputStream(b2Out);
4371 d1Out.writeObject(this.getParameters());
4372 d2Out.writeObject(other.getParameters());
4374 byte[] b1 = b1Out.toByteArray();
4375 byte[] b2 = b2Out.toByteArray();
4377 if (b1.length != b2.length)
4382 for (int i = 0; i != b1.length; i++)
4404 * id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 35 }
4406 * AuthorityKeyIdentifier ::= SEQUENCE {
4407 * keyIdentifier [0] IMPLICIT KeyIdentifier OPTIONAL,
4408 * authorityCertIssuer [1] IMPLICIT GeneralNames OPTIONAL,
4409 * authorityCertSerialNumber [2] IMPLICIT CertificateSerialNumber OPTIONAL }
4411 * KeyIdentifier ::= OCTET STRING
4415 class AuthorityKeyIdentifier
4416 implements DEREncodable, DERTags
4418 ASN1OctetString keyidentifier=null;
4419 GeneralNames certissuer=null;
4420 DERInteger certserno=null;
4422 public static AuthorityKeyIdentifier getInstance(
4423 ASN1TaggedObject obj,
4426 return getInstance(ASN1Sequence.getInstance(obj, explicit));
4429 public static AuthorityKeyIdentifier getInstance(
4432 if (obj instanceof AuthorityKeyIdentifier)
4434 return (AuthorityKeyIdentifier)obj;
4436 else if (obj instanceof ASN1Sequence)
4438 return new AuthorityKeyIdentifier((ASN1Sequence)obj);
4441 throw new IllegalArgumentException("unknown object in factory");
4444 public AuthorityKeyIdentifier(
4447 Enumeration e = seq.getObjects();
4449 while (e.hasMoreElements())
4451 DERTaggedObject o = (DERTaggedObject)e.nextElement();
4453 switch (o.getTagNo())
4456 this.keyidentifier = ASN1OctetString.getInstance(o, false);
4459 this.certissuer = GeneralNames.getInstance(o, false);
4462 this.certserno = DERInteger.getInstance(o, false);
4465 throw new IllegalArgumentException("illegal tag");
4472 * Calulates the keyidentifier using a SHA1 hash over the BIT STRING
4473 * from SubjectPublicKeyInfo as defined in RFC2459.
4475 * Example of making a AuthorityKeyIdentifier:
4477 * SubjectPublicKeyInfo apki = new SubjectPublicKeyInfo((DERConstructedSequence)new DERInputStream(
4478 * new ByteArrayInputStream(publicKey.getEncoded())).readObject());
4479 * AuthorityKeyIdentifier aki = new AuthorityKeyIdentifier(apki);
4483 public AuthorityKeyIdentifier(
4484 SubjectPublicKeyInfo spki)
4486 Digest digest = new SHA1Digest();
4487 byte[] resBuf = new byte[digest.getDigestSize()];
4489 byte[] bytes = spki.getPublicKeyData().getBytes();
4490 digest.update(bytes, 0, bytes.length);
4491 digest.doFinal(resBuf, 0);
4492 this.keyidentifier = new DEROctetString(resBuf);
4496 * create an AuthorityKeyIdentifier with the GeneralNames tag and
4497 * the serial number provided as well.
4499 public AuthorityKeyIdentifier(
4500 SubjectPublicKeyInfo spki,
4502 BigInteger serialNumber)
4504 Digest digest = new SHA1Digest();
4505 byte[] resBuf = new byte[digest.getDigestSize()];
4507 byte[] bytes = spki.getPublicKeyData().getBytes();
4508 digest.update(bytes, 0, bytes.length);
4509 digest.doFinal(resBuf, 0);
4511 this.keyidentifier = new DEROctetString(resBuf);
4512 this.certissuer = name;
4513 this.certserno = new DERInteger(serialNumber);
4516 public byte[] getKeyIdentifier()
4518 if (keyidentifier != null)
4520 return keyidentifier.getOctets();
4528 * AuthorityKeyIdentifier ::= SEQUENCE {
4529 * keyIdentifier [0] IMPLICIT KeyIdentifier OPTIONAL,
4530 * authorityCertIssuer [1] IMPLICIT GeneralNames OPTIONAL,
4531 * authorityCertSerialNumber [2] IMPLICIT CertificateSerialNumber OPTIONAL }
4533 * KeyIdentifier ::= OCTET STRING
4536 public DERObject getDERObject()
4538 DERConstructedSequence seq = new DERConstructedSequence();
4540 if (keyidentifier != null)
4542 seq.addObject(new DERTaggedObject(false, 0, keyidentifier));
4545 if (certissuer != null)
4547 seq.addObject(new DERTaggedObject(false, 1, certissuer));
4550 if (certserno != null)
4552 seq.addObject(new DERTaggedObject(false, 2, certserno));
4559 public String toString()
4561 return ("AuthorityKeyIdentifier: KeyID(" + this.keyidentifier.getOctets() + ")");
4567 class BasicConstraints
4568 implements DEREncodable
4570 DERBoolean cA = new DERBoolean(false);
4571 DERInteger pathLenConstraint = null;
4573 public static BasicConstraints getInstance(
4574 ASN1TaggedObject obj,
4577 return getInstance(ASN1Sequence.getInstance(obj, explicit));
4580 public static BasicConstraints getInstance(
4583 if (obj instanceof BasicConstraints)
4585 return (BasicConstraints)obj;
4587 else if (obj instanceof ASN1Sequence)
4589 return new BasicConstraints((ASN1Sequence)obj);
4592 throw new IllegalArgumentException("unknown object in factory");
4595 public BasicConstraints(
4598 if (seq.size() != 0)
4600 this.cA = (DERBoolean)seq.getObjectAt(0);
4601 this.pathLenConstraint = (DERInteger)seq.getObjectAt(1);
4605 public BasicConstraints(
4607 int pathLenConstraint)
4609 this.cA = new DERBoolean(cA);
4610 this.pathLenConstraint = new DERInteger(pathLenConstraint);
4613 public BasicConstraints(
4616 this.cA = new DERBoolean(cA);
4617 this.pathLenConstraint = null;
4620 public boolean isCA()
4625 public BigInteger getPathLenConstraint()
4627 if (pathLenConstraint != null)
4629 return pathLenConstraint.getValue();
4637 * BasicConstraints := SEQUENCE {
4638 * cA BOOLEAN DEFAULT FALSE,
4639 * pathLenConstraint INTEGER (0..MAX) OPTIONAL
4643 public DERObject getDERObject()
4645 DERConstructedSequence seq = new DERConstructedSequence();
4649 if (pathLenConstraint != null)
4651 seq.addObject(pathLenConstraint);
4657 public String toString()
4659 return "BasicConstraints: isCa(" + this.isCA() + "), pathLenConstraint = " + pathLenConstraint.getValue();
4668 * The X.509 v2 CRL syntax is as follows. For signature calculation,
4669 * the data that is to be signed is ASN.1 DER encoded.
4672 * CertificateList ::= SEQUENCE {
4673 * tbsCertList TBSCertList,
4674 * signatureAlgorithm AlgorithmIdentifier,
4675 * signatureValue BIT STRING }
4678 class CertificateList
4679 implements DEREncodable
4681 TBSCertList tbsCertList;
4682 AlgorithmIdentifier sigAlgId;
4685 public static CertificateList getInstance(
4686 ASN1TaggedObject obj,
4689 return getInstance(ASN1Sequence.getInstance(obj, explicit));
4692 public static CertificateList getInstance(
4695 if (obj instanceof CertificateList)
4697 return (CertificateList)obj;
4699 else if (obj instanceof ASN1Sequence)
4701 return new CertificateList((ASN1Sequence)obj);
4704 throw new IllegalArgumentException("unknown object in factory");
4707 public CertificateList(
4710 tbsCertList = TBSCertList.getInstance(seq.getObjectAt(0));
4711 sigAlgId = AlgorithmIdentifier.getInstance(seq.getObjectAt(1));
4712 sig = (DERBitString)seq.getObjectAt(2);
4715 public TBSCertList getTBSCertList()
4720 public TBSCertList.CRLEntry[] getRevokedCertificates()
4722 return tbsCertList.getRevokedCertificates();
4725 public AlgorithmIdentifier getSignatureAlgorithm()
4730 public DERBitString getSignature()
4735 public int getVersion()
4737 return tbsCertList.getVersion();
4740 public X509Name getIssuer()
4742 return tbsCertList.getIssuer();
4745 public Time getThisUpdate()
4747 return tbsCertList.getThisUpdate();
4750 public Time getNextUpdate()
4752 return tbsCertList.getNextUpdate();
4755 public DERObject getDERObject()
4757 DERConstructedSequence seq = new DERConstructedSequence();
4758 seq.addObject(tbsCertList);
4759 seq.addObject(sigAlgId);
4767 implements DEREncodable
4769 ASN1Sequence seq = null;
4771 public static CRLDistPoint getInstance(
4772 ASN1TaggedObject obj,
4775 return getInstance(ASN1Sequence.getInstance(obj, explicit));
4778 public static CRLDistPoint getInstance(
4781 if (obj instanceof CRLDistPoint)
4783 return (CRLDistPoint)obj;
4785 else if (obj instanceof ASN1Sequence)
4787 return new CRLDistPoint((ASN1Sequence)obj);
4790 throw new IllegalArgumentException("unknown object in factory");
4793 public CRLDistPoint(
4799 public CRLDistPoint(
4800 DistributionPoint[] points)
4802 DEREncodableVector v = new DEREncodableVector();
4804 for (int i = 0; i != points.length; i++)
4809 seq = new DERSequence(v);
4814 * CRLDistPoint ::= SEQUENCE SIZE {1..MAX} OF DistributionPoint
4817 public DERObject getDERObject()
4827 * CRLNumber::= INTEGER(0..MAX)
4840 public BigInteger getCRLNumber()
4842 return getPositiveValue();
4848 extends DEREnumerated
4850 public static final int UNSPECIFIED = 0;
4851 public static final int KEY_COMPROMISE = 1;
4852 public static final int CA_COMPROMISE = 2;
4853 public static final int AFFILIATION_CHANGED = 3;
4854 public static final int SUPERSEDED = 4;
4855 public static final int CESSATION_OF_OPERATION = 5;
4856 public static final int CERTIFICATE_HOLD = 6;
4857 public static final int REMOVE_FROM_CRL = 8;
4858 public static final int PRIVILEGE_WITHDRAWN = 9;
4859 public static final int AA_COMPROMISE = 10;
4863 * CRLReason ::= ENUMERATED {
4865 * keyCompromise (1),
4867 * affiliationChanged (3),
4869 * cessationOfOperation (5),
4870 * certificateHold (6),
4871 * removeFromCRL (8),
4872 * privilegeWithdrawn (9),
4888 * DigestInfo::=SEQUENCE{
4889 * digestAlgorithm AlgorithmIdentifier,
4890 * digest OCTET STRING }
4894 implements DEREncodable
4896 private byte[] digest;
4897 private AlgorithmIdentifier algId;
4899 public static DigestInfo getInstance(
4900 ASN1TaggedObject obj,
4903 return getInstance(ASN1Sequence.getInstance(obj, explicit));
4906 public static DigestInfo getInstance(
4909 if (obj instanceof DigestInfo)
4911 return (DigestInfo)obj;
4913 else if (obj instanceof ASN1Sequence)
4915 return new DigestInfo((ASN1Sequence)obj);
4918 throw new IllegalArgumentException("unknown object in factory");
4922 AlgorithmIdentifier algId,
4925 this.digest = digest;
4932 Enumeration e = obj.getObjects();
4934 algId = AlgorithmIdentifier.getInstance(e.nextElement());
4935 digest = ((ASN1OctetString)e.nextElement()).getOctets();
4938 public AlgorithmIdentifier getAlgorithmId()
4943 public byte[] getDigest()
4948 public DERObject getDERObject()
4950 DEREncodableVector v = new DEREncodableVector();
4953 v.add(new DEROctetString(digest));
4955 return new DERSequence(v);
4960 class DistributionPoint
4961 implements DEREncodable
4963 ASN1Sequence seq = null;
4965 public static DistributionPoint getInstance(
4966 ASN1TaggedObject obj,
4969 return getInstance(ASN1Sequence.getInstance(obj, explicit));
4972 public static DistributionPoint getInstance(
4975 if(obj == null || obj instanceof DistributionPoint)
4977 return (DistributionPoint)obj;
4980 if(obj instanceof ASN1Sequence)
4982 return new DistributionPoint((ASN1Sequence)obj);
4985 throw new IllegalArgumentException("Invalid DistributionPoint: " + obj.getClass().getName());
4988 public DistributionPoint(
4994 public DistributionPoint(
4995 DistributionPointName distributionPoint,
4996 ReasonFlags reasons,
4997 GeneralNames cRLIssuer)
4999 DEREncodableVector v = new DEREncodableVector();
5001 if (distributionPoint != null)
5003 v.add(new DERTaggedObject(0, distributionPoint));
5006 if (reasons != null)
5008 v.add(new DERTaggedObject(1, reasons));
5011 if (cRLIssuer != null)
5013 v.add(new DERTaggedObject(2, cRLIssuer));
5016 seq = new DERSequence(v);
5021 * DistributionPoint ::= SEQUENCE {
5022 * distributionPoint [0] DistributionPointName OPTIONAL,
5023 * reasons [1] ReasonFlags OPTIONAL,
5024 * cRLIssuer [2] GeneralNames OPTIONAL
5028 public DERObject getDERObject()
5035 class DistributionPointName
5036 implements DEREncodable
5041 public static final int FULL_NAME = 0;
5042 public static final int NAME_RELATIVE_TO_CRL_ISSUER = 1;
5044 public DistributionPointName(
5054 * DistributionPointName ::= CHOICE {
5055 * fullName [0] GeneralNames,
5056 * nameRelativeToCRLIssuer [1] RelativeDistinguishedName
5060 public DERObject getDERObject()
5062 return new DERTaggedObject(false, type, name);
5069 implements DEREncodable
5073 public static DSAParameter getInstance(
5074 ASN1TaggedObject obj,
5077 return getInstance(ASN1Sequence.getInstance(obj, explicit));
5080 public static DSAParameter getInstance(
5083 if(obj == null || obj instanceof DSAParameter)
5085 return (DSAParameter)obj;
5088 if(obj instanceof ASN1Sequence)
5090 return new DSAParameter((ASN1Sequence)obj);
5093 throw new IllegalArgumentException("Invalid DSAParameter: " + obj.getClass().getName());
5096 public DSAParameter(
5101 this.p = new DERInteger(p);
5102 this.q = new DERInteger(q);
5103 this.g = new DERInteger(g);
5106 public DSAParameter(
5109 Enumeration e = seq.getObjects();
5111 p = (DERInteger)e.nextElement();
5112 q = (DERInteger)e.nextElement();
5113 g = (DERInteger)e.nextElement();
5116 public BigInteger getP()
5118 return p.getPositiveValue();
5121 public BigInteger getQ()
5123 return q.getPositiveValue();
5126 public BigInteger getG()
5128 return g.getPositiveValue();
5131 public DERObject getDERObject()
5133 DEREncodableVector v = new DEREncodableVector();
5139 return new DERSequence(v);
5146 * GeneralName ::= CHOICE {
5147 * otherName [0] OtherName,
5148 * rfc822Name [1] IA5String,
5149 * dNSName [2] IA5String,
5150 * x400Address [3] ORAddress,
5151 * directoryName [4] Name,
5152 * ediPartyName [5] EDIPartyName,
5153 * uniformResourceIdentifier [6] IA5String,
5154 * iPAddress [7] OCTET STRING,
5155 * registeredID [8] OBJECT IDENTIFIER}
5157 * OtherName ::= SEQUENCE {
5158 * type-id OBJECT IDENTIFIER,
5159 * value [0] EXPLICIT ANY DEFINED BY type-id }
5161 * EDIPartyName ::= SEQUENCE {
5162 * nameAssigner [0] DirectoryString OPTIONAL,
5163 * partyName [1] DirectoryString }
5167 implements DEREncodable
5171 boolean isInsideImplicit = false; // if we are in an implicitly tagged object
5174 X509Name directoryName)
5176 this.obj = directoryName;
5181 * When the subjectAltName extension contains an Internet mail address,
5182 * the address MUST be included as an rfc822Name. The format of an
5183 * rfc822Name is an "addr-spec" as defined in RFC 822 [RFC 822].
5185 * When the subjectAltName extension contains a domain name service
5186 * label, the domain name MUST be stored in the dNSName (an IA5String).
5187 * The name MUST be in the "preferred name syntax," as specified by RFC
5190 * When the subjectAltName extension contains a URI, the name MUST be
5191 * stored in the uniformResourceIdentifier (an IA5String). The name MUST
5192 * be a non-relative URL, and MUST follow the URL syntax and encoding
5193 * rules specified in [RFC 1738]. The name must include both a scheme
5194 * (e.g., "http" or "ftp") and a scheme-specific-part. The scheme-
5195 * specific-part must include a fully qualified domain name or IP
5196 * address as the host.
5198 * When the subjectAltName extension contains a iPAddress, the address
5199 * MUST be stored in the octet string in "network byte order," as
5200 * specified in RFC 791 [RFC 791]. The least significant bit (LSB) of
5201 * each octet is the LSB of the corresponding byte in the network
5202 * address. For IP Version 4, as specified in RFC 791, the octet string
5203 * MUST contain exactly four octets. For IP Version 6, as specified in
5204 * RFC 1883, the octet string MUST contain exactly sixteen octets [RFC
5208 DERObject name, int tag)
5215 * mark whether or not we are contained inside an implicitly tagged
5219 public void markInsideImplicit(
5220 boolean isInsideImplicit)
5222 this.isInsideImplicit = isInsideImplicit;
5225 public DERObject getDERObject()
5227 if (obj.getDERObject() instanceof ASN1Sequence)
5229 return new DERTaggedObject(true, tag, obj);
5233 return new DERTaggedObject(false, tag, obj);
5241 implements DEREncodable
5244 boolean isInsideImplicit = false;
5246 public static GeneralNames getInstance(
5249 if (obj == null || obj instanceof GeneralNames)
5251 return (GeneralNames)obj;
5254 if (obj instanceof ASN1Sequence)
5256 return new GeneralNames((ASN1Sequence)obj);
5259 throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
5262 public static GeneralNames getInstance(
5263 ASN1TaggedObject obj,
5266 return getInstance(ASN1Sequence.getInstance(obj, explicit));
5269 public GeneralNames(
5276 * this is a hack! But it will have to do until the ambiguity rules
5277 * get sorted out for implicit/explicit tagging...
5280 public void markInsideImplicit(
5281 boolean isInsideImplicit)
5283 this.isInsideImplicit = isInsideImplicit;
5288 * GeneralNames ::= SEQUENCE SIZE {1..MAX} OF GeneralName
5291 public DERObject getDERObject()
5300 * id-ce-keyUsage OBJECT IDENTIFIER ::= { id-ce 15 }
5302 * KeyUsage ::= BIT STRING {
5303 * digitalSignature (0),
5304 * nonRepudiation (1),
5305 * keyEncipherment (2),
5306 * dataEncipherment (3),
5311 * decipherOnly (8) }
5315 extends DERBitString
5317 public static final int digitalSignature = (1 << 7);
5318 public static final int nonRepudiation = (1 << 6);
5319 public static final int keyEncipherment = (1 << 5);
5320 public static final int dataEncipherment = (1 << 4);
5321 public static final int keyAgreement = (1 << 3);
5322 public static final int keyCertSign = (1 << 2);
5323 public static final int cRLSign = (1 << 1);
5324 public static final int encipherOnly = (1 << 0);
5325 public static final int decipherOnly = (1 << 15);
5328 * Basic constructor.
5330 * @param usage - the bitwise OR of the Key Usage flags giving the
5331 * allowed uses for the key.
5332 * e.g. (X509KeyUsage.keyEncipherment | X509KeyUsage.dataEncipherment)
5337 super(getBytes(usage), getPadBits(usage));
5343 super(usage.getBytes(), usage.getPadBits());
5346 public String toString()
5348 return "KeyUsage: 0x" + Integer.toHexString(data[0] & 0xff);
5354 extends DERBitString
5356 public static final int UNUSED = (1 << 7);
5357 public static final int KEY_COMPROMISE = (1 << 6);
5358 public static final int CA_COMPROMISE = (1 << 5);
5359 public static final int AFFILIATION_CHANGED = (1 << 4);
5360 public static final int SUPERSEDED = (1 << 3);
5361 public static final int CESSATION_OF_OPERATION = (1 << 2);
5362 public static final int CERTIFICATE_HOLD = (1 << 1);
5363 public static final int PRIVILEGE_WITHDRAWN = (1 << 0);
5364 public static final int AA_COMPROMISE = (1 << 15);
5368 * ReasonFlags ::= BIT STRING {
5372 * affiliationChanged(3),
5374 * cessationOfOperation(5),
5378 * @param reasons - the bitwise OR of the Key Reason flags giving the
5379 * allowed uses for the key.
5384 super(getBytes(reasons), getPadBits(reasons));
5388 DERBitString reasons)
5390 super(reasons.getBytes(), reasons.getPadBits());
5396 class RSAPublicKeyStructure
5397 implements DEREncodable
5399 private BigInteger modulus;
5400 private BigInteger publicExponent;
5402 public static RSAPublicKeyStructure getInstance(
5403 ASN1TaggedObject obj,
5406 return getInstance(ASN1Sequence.getInstance(obj, explicit));
5409 public static RSAPublicKeyStructure getInstance(
5412 if(obj == null || obj instanceof RSAPublicKeyStructure)
5414 return (RSAPublicKeyStructure)obj;
5417 if(obj instanceof ASN1Sequence)
5419 return new RSAPublicKeyStructure((ASN1Sequence)obj);
5422 throw new IllegalArgumentException("Invalid RSAPublicKeyStructure: " + obj.getClass().getName());
5425 public RSAPublicKeyStructure(
5427 BigInteger publicExponent)
5429 this.modulus = modulus;
5430 this.publicExponent = publicExponent;
5433 public RSAPublicKeyStructure(
5436 Enumeration e = seq.getObjects();
5438 modulus = ((DERInteger)e.nextElement()).getValue();
5439 publicExponent = ((DERInteger)e.nextElement()).getValue();
5442 public BigInteger getModulus()
5447 public BigInteger getPublicExponent()
5449 return publicExponent;
5453 * This outputs the key in PKCS1v2 format.
5455 * RSAPublicKey ::= SEQUENCE {
5456 * modulus INTEGER, -- n
5457 * publicExponent INTEGER, -- e
5462 public DERObject getDERObject()
5464 DERConstructedSequence seq = new DERConstructedSequence();
5466 seq.addObject(new DERInteger(getModulus()));
5467 seq.addObject(new DERInteger(getPublicExponent()));
5476 * SubjectKeyIdentifier::= OCTET STRING
5479 class SubjectKeyIdentifier
5480 implements DEREncodable
5482 private byte[] keyidentifier;
5484 public static SubjectKeyIdentifier getInstance(
5485 ASN1TaggedObject obj,
5488 return getInstance(ASN1OctetString.getInstance(obj, explicit));
5491 public static SubjectKeyIdentifier getInstance(
5494 if(obj == null || obj instanceof SubjectKeyIdentifier)
5496 return (SubjectKeyIdentifier)obj;
5499 if(obj instanceof SubjectPublicKeyInfo)
5501 return new SubjectKeyIdentifier((SubjectPublicKeyInfo)obj);
5504 if(obj instanceof ASN1OctetString)
5506 return new SubjectKeyIdentifier((ASN1OctetString)obj);
5509 throw new IllegalArgumentException("Invalid SubjectKeyIdentifier: " + obj.getClass().getName());
5512 public SubjectKeyIdentifier(
5515 this.keyidentifier=keyid;
5518 public SubjectKeyIdentifier(
5519 ASN1OctetString keyid)
5521 this.keyidentifier=keyid.getOctets();
5527 * Calulates the keyidentifier using a SHA1 hash over the BIT STRING
5528 * from SubjectPublicKeyInfo as defined in RFC2459.
5531 public SubjectKeyIdentifier(
5532 SubjectPublicKeyInfo spki)
5534 Digest digest = new SHA1Digest();
5535 byte[] resBuf = new byte[digest.getDigestSize()];
5537 byte[] bytes = spki.getPublicKeyData().getBytes();
5538 digest.update(bytes, 0, bytes.length);
5539 digest.doFinal(resBuf, 0);
5540 this.keyidentifier=resBuf;
5543 public byte[] getKeyIdentifier()
5545 return keyidentifier;
5550 * SubjectKeyIdentifier := OCTET STRING
5553 public DERObject getDERObject()
5555 return new DEROctetString(keyidentifier);
5562 * The object that contains the public key stored in a certficate.
5564 * The getEncoded() method in the public keys in the JCE produces a DER
5565 * encoded one of these.
5567 class SubjectPublicKeyInfo
5568 implements DEREncodable
5570 private AlgorithmIdentifier algId;
5571 private DERBitString keyData;
5573 public static SubjectPublicKeyInfo getInstance(
5574 ASN1TaggedObject obj,
5577 return getInstance(ASN1Sequence.getInstance(obj, explicit));
5580 public static SubjectPublicKeyInfo getInstance(
5583 if (obj instanceof SubjectPublicKeyInfo)
5585 return (SubjectPublicKeyInfo)obj;
5587 else if (obj instanceof ASN1Sequence)
5589 return new SubjectPublicKeyInfo((ASN1Sequence)obj);
5592 throw new IllegalArgumentException("unknown object in factory");
5595 public SubjectPublicKeyInfo(
5596 AlgorithmIdentifier algId,
5597 DEREncodable publicKey)
5599 this.keyData = new DERBitString(publicKey);
5603 public SubjectPublicKeyInfo(
5604 AlgorithmIdentifier algId,
5607 this.keyData = new DERBitString(publicKey);
5611 public SubjectPublicKeyInfo(
5614 Enumeration e = seq.getObjects();
5616 this.algId = AlgorithmIdentifier.getInstance(e.nextElement());
5617 this.keyData = (DERBitString)e.nextElement();
5620 public AlgorithmIdentifier getAlgorithmId()
5626 * for when the public key is an encoded object - if the bitstring
5627 * can't be decoded this routine throws an IOException.
5629 * @exception IOException - if the bit string doesn't represent a DER
5632 public DERObject getPublicKey()
5635 ByteArrayInputStream bIn = new ByteArrayInputStream(keyData.getBytes());
5636 DERInputStream dIn = new DERInputStream(bIn);
5638 return dIn.readObject();
5642 * for when the public key is raw bits...
5644 public DERBitString getPublicKeyData()
5651 * SubjectPublicKeyInfo ::= SEQUENCE {
5652 * algorithm AlgorithmIdentifier,
5653 * publicKey BIT STRING }
5656 public DERObject getDERObject()
5658 DERConstructedSequence seq = new DERConstructedSequence();
5660 seq.addObject(algId);
5661 seq.addObject(keyData);
5670 * TBSCertificate ::= SEQUENCE {
5671 * version [ 0 ] Version DEFAULT v1(0),
5672 * serialNumber CertificateSerialNumber,
5673 * signature AlgorithmIdentifier,
5675 * validity Validity,
5677 * subjectPublicKeyInfo SubjectPublicKeyInfo,
5678 * issuerUniqueID [ 1 ] IMPLICIT UniqueIdentifier OPTIONAL,
5679 * subjectUniqueID [ 2 ] IMPLICIT UniqueIdentifier OPTIONAL,
5680 * extensions [ 3 ] Extensions OPTIONAL
5684 * Note: issuerUniqueID and subjectUniqueID are both deprecated by the IETF. This class
5685 * will parse them, but you really shouldn't be creating new ones.
5687 class TBSCertificateStructure
5688 implements DEREncodable, X509ObjectIdentifiers, PKCSObjectIdentifiers
5693 DERInteger serialNumber;
5694 AlgorithmIdentifier signature;
5696 Time startDate, endDate;
5698 SubjectPublicKeyInfo subjectPublicKeyInfo;
5699 DERBitString issuerUniqueId;
5700 DERBitString subjectUniqueId;
5701 X509Extensions extensions;
5703 public static TBSCertificateStructure getInstance(
5704 ASN1TaggedObject obj,
5707 return getInstance(ASN1Sequence.getInstance(obj, explicit));
5710 public static TBSCertificateStructure getInstance(
5713 if (obj instanceof TBSCertificateStructure)
5715 return (TBSCertificateStructure)obj;
5717 else if (obj instanceof ASN1Sequence)
5719 return new TBSCertificateStructure((ASN1Sequence)obj);
5722 throw new IllegalArgumentException("unknown object in factory");
5725 public TBSCertificateStructure(
5733 // some certficates don't include a version number - we assume v1
5735 if (seq.getObjectAt(0) instanceof DERTaggedObject)
5737 version = DERInteger.getInstance(seq.getObjectAt(0));
5741 seqStart = -1; // field 0 is missing!
5742 version = new DERInteger(0);
5745 serialNumber = DERInteger.getInstance(seq.getObjectAt(seqStart + 1));
5747 signature = AlgorithmIdentifier.getInstance(seq.getObjectAt(seqStart + 2));
5748 issuer = X509Name.getInstance(seq.getObjectAt(seqStart + 3));
5751 // before and after dates
5753 ASN1Sequence dates = (ASN1Sequence)seq.getObjectAt(seqStart + 4);
5755 startDate = Time.getInstance(dates.getObjectAt(0));
5756 endDate = Time.getInstance(dates.getObjectAt(1));
5758 subject = X509Name.getInstance(seq.getObjectAt(seqStart + 5));
5763 subjectPublicKeyInfo = SubjectPublicKeyInfo.getInstance(seq.getObjectAt(seqStart + 6));
5765 for (int extras = seq.size() - (seqStart + 6) - 1; extras > 0; extras--)
5767 DERTaggedObject extra = (DERTaggedObject)seq.getObjectAt(seqStart + 6 + extras);
5769 switch (extra.getTagNo())
5772 issuerUniqueId = DERBitString.getInstance(extra);
5775 subjectUniqueId = DERBitString.getInstance(extra);
5778 extensions = X509Extensions.getInstance(extra);
5783 public int getVersion()
5785 return version.getValue().intValue() + 1;
5788 public DERInteger getVersionNumber()
5793 public DERInteger getSerialNumber()
5795 return serialNumber;
5798 public AlgorithmIdentifier getSignature()
5803 public X509Name getIssuer()
5808 public Time getStartDate()
5813 public Time getEndDate()
5818 public X509Name getSubject()
5823 public SubjectPublicKeyInfo getSubjectPublicKeyInfo()
5825 return subjectPublicKeyInfo;
5828 public DERBitString getIssuerUniqueId()
5830 return issuerUniqueId;
5833 public DERBitString getSubjectUniqueId()
5835 return subjectUniqueId;
5838 public X509Extensions getExtensions()
5843 public DERObject getDERObject()
5855 * TBSCertList ::= SEQUENCE {
5856 * version Version OPTIONAL,
5857 * -- if present, shall be v2
5858 * signature AlgorithmIdentifier,
5861 * nextUpdate Time OPTIONAL,
5862 * revokedCertificates SEQUENCE OF SEQUENCE {
5863 * userCertificate CertificateSerialNumber,
5864 * revocationDate Time,
5865 * crlEntryExtensions Extensions OPTIONAL
5866 * -- if present, shall be v2
5868 * crlExtensions [0] EXPLICIT Extensions OPTIONAL
5869 * -- if present, shall be v2
5875 implements DEREncodable
5878 implements DEREncodable
5880 DERConstructedSequence seq;
5882 DERInteger userCertificate;
5883 Time revocationDate;
5884 X509Extensions crlEntryExtensions;
5887 DERConstructedSequence seq)
5891 userCertificate = (DERInteger)seq.getObjectAt(0);
5892 revocationDate = Time.getInstance(seq.getObjectAt(1));
5893 if (seq.getSize() == 3)
5895 crlEntryExtensions = X509Extensions.getInstance(seq.getObjectAt(2));
5899 public DERInteger getUserCertificate()
5901 return userCertificate;
5904 public Time getRevocationDate()
5906 return revocationDate;
5909 public X509Extensions getExtensions()
5911 return crlEntryExtensions;
5914 public DERObject getDERObject()
5923 AlgorithmIdentifier signature;
5927 CRLEntry[] revokedCertificates;
5928 X509Extensions crlExtensions;
5930 public static TBSCertList getInstance(
5931 ASN1TaggedObject obj,
5934 return getInstance(ASN1Sequence.getInstance(obj, explicit));
5937 public static TBSCertList getInstance(
5940 if (obj instanceof TBSCertList)
5942 return (TBSCertList)obj;
5944 else if (obj instanceof ASN1Sequence)
5946 return new TBSCertList((ASN1Sequence)obj);
5949 throw new IllegalArgumentException("unknown object in factory");
5959 if (seq.getObjectAt(seqPos) instanceof DERInteger)
5961 version = (DERInteger)seq.getObjectAt(seqPos++);
5965 version = new DERInteger(0);
5968 signature = AlgorithmIdentifier.getInstance(seq.getObjectAt(seqPos++));
5969 issuer = X509Name.getInstance(seq.getObjectAt(seqPos++));
5970 thisUpdate = Time.getInstance(seq.getObjectAt(seqPos++));
5972 if (seqPos < seq.size()
5973 && (seq.getObjectAt(seqPos) instanceof DERUTCTime
5974 || seq.getObjectAt(seqPos) instanceof DERGeneralizedTime
5975 || seq.getObjectAt(seqPos) instanceof Time))
5977 nextUpdate = Time.getInstance(seq.getObjectAt(seqPos++));
5980 if (seqPos < seq.size()
5981 && !(seq.getObjectAt(seqPos) instanceof DERTaggedObject))
5983 DERConstructedSequence certs = (DERConstructedSequence)seq.getObjectAt(seqPos++);
5984 revokedCertificates = new CRLEntry[certs.getSize()];
5986 for ( int i = 0; i < revokedCertificates.length; i++)
5988 revokedCertificates[i] = new CRLEntry((DERConstructedSequence)certs.getObjectAt(i));
5992 if (seqPos < seq.size()
5993 && seq.getObjectAt(seqPos) instanceof DERTaggedObject)
5995 crlExtensions = X509Extensions.getInstance(seq.getObjectAt(seqPos++));
5999 public int getVersion()
6001 return version.getValue().intValue() + 1;
6004 public DERInteger getVersionNumber()
6009 public AlgorithmIdentifier getSignature()
6014 public X509Name getIssuer()
6019 public Time getThisUpdate()
6024 public Time getNextUpdate()
6029 public CRLEntry[] getRevokedCertificates()
6031 return revokedCertificates;
6034 public X509Extensions getExtensions()
6036 return crlExtensions;
6039 public DERObject getDERObject()
6048 implements DEREncodable
6052 public static Time getInstance(
6053 ASN1TaggedObject obj,
6056 return getInstance(obj.getObject());
6062 if (!(time instanceof DERUTCTime)
6063 && !(time instanceof DERGeneralizedTime))
6065 throw new IllegalArgumentException("unknown object passed to Time");
6072 * creates a time object from a given date - if the date is between 1950
6073 * and 2049 a UTCTime object is generated, otherwise a GeneralizedTime
6079 SimpleTimeZone tz = new SimpleTimeZone(0, "Z");
6080 SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmss");
6082 dateF.setTimeZone(tz);
6084 String d = dateF.format(date) + "Z";
6085 int year = Integer.parseInt(d.substring(0, 4));
6087 if (year < 1950 || year > 2049)
6089 time = new DERGeneralizedTime(d);
6093 time = new DERUTCTime(d.substring(2));
6097 public static Time getInstance(
6100 if (obj instanceof Time)
6104 else if (obj instanceof DERUTCTime)
6106 return new Time((DERUTCTime)obj);
6108 else if (obj instanceof DERGeneralizedTime)
6110 return new Time((DERGeneralizedTime)obj);
6113 throw new IllegalArgumentException("unknown object in factory");
6116 public String getTime()
6118 if (time instanceof DERUTCTime)
6120 return ((DERUTCTime)time).getAdjustedTime();
6124 return ((DERGeneralizedTime)time).getTime();
6128 public Date getDate()
6130 SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmssz");
6132 return dateF.parse(this.getTime(), new ParsePosition(0));
6139 * generalTime GeneralizedTime }
6142 public DERObject getDERObject()
6150 * Generator for Version 1 TBSCertificateStructures.
6152 * TBSCertificate ::= SEQUENCE {
6153 * version [ 0 ] Version DEFAULT v1(0),
6154 * serialNumber CertificateSerialNumber,
6155 * signature AlgorithmIdentifier,
6157 * validity Validity,
6159 * subjectPublicKeyInfo SubjectPublicKeyInfo,
6164 class V1TBSCertificateGenerator
6166 DERTaggedObject version = new DERTaggedObject(0, new DERInteger(0));
6168 DERInteger serialNumber;
6169 AlgorithmIdentifier signature;
6171 Time startDate, endDate;
6173 SubjectPublicKeyInfo subjectPublicKeyInfo;
6175 public V1TBSCertificateGenerator()
6179 public void setSerialNumber(
6180 DERInteger serialNumber)
6182 this.serialNumber = serialNumber;
6185 public void setSignature(
6186 AlgorithmIdentifier signature)
6188 this.signature = signature;
6191 public void setIssuer(
6194 this.issuer = issuer;
6197 public void setStartDate(
6200 this.startDate = startDate;
6203 public void setStartDate(
6204 DERUTCTime startDate)
6206 this.startDate = new Time(startDate);
6209 public void setEndDate(
6212 this.endDate = endDate;
6215 public void setEndDate(
6218 this.endDate = new Time(endDate);
6221 public void setSubject(
6224 this.subject = subject;
6227 public void setSubjectPublicKeyInfo(
6228 SubjectPublicKeyInfo pubKeyInfo)
6230 this.subjectPublicKeyInfo = pubKeyInfo;
6233 public TBSCertificateStructure generateTBSCertificate()
6235 if ((serialNumber == null) || (signature == null)
6236 || (issuer == null) || (startDate == null) || (endDate == null)
6237 || (subject == null) || (subjectPublicKeyInfo == null))
6239 throw new IllegalStateException("not all mandatory fields set in V1 TBScertificate generator");
6242 DERConstructedSequence seq = new DERConstructedSequence();
6244 seq.addObject(version);
6245 seq.addObject(serialNumber);
6246 seq.addObject(signature);
6247 seq.addObject(issuer);
6250 // before and after dates
6252 DERConstructedSequence validity = new DERConstructedSequence();
6254 validity.addObject(startDate);
6255 validity.addObject(endDate);
6257 seq.addObject(validity);
6259 seq.addObject(subject);
6261 seq.addObject(subjectPublicKeyInfo);
6263 return new TBSCertificateStructure(seq);
6270 * Generator for Version 2 TBSCertList structures.
6272 * TBSCertList ::= SEQUENCE {
6273 * version Version OPTIONAL,
6274 * -- if present, shall be v2
6275 * signature AlgorithmIdentifier,
6278 * nextUpdate Time OPTIONAL,
6279 * revokedCertificates SEQUENCE OF SEQUENCE {
6280 * userCertificate CertificateSerialNumber,
6281 * revocationDate Time,
6282 * crlEntryExtensions Extensions OPTIONAL
6283 * -- if present, shall be v2
6285 * crlExtensions [0] EXPLICIT Extensions OPTIONAL
6286 * -- if present, shall be v2
6290 * <b>Note: This class may be subject to change</b>
6292 class V2TBSCertListGenerator
6294 DERInteger version = new DERInteger(1);
6296 AlgorithmIdentifier signature;
6298 Time thisUpdate, nextUpdate=null;
6299 X509Extensions extensions=null;
6300 private Vector crlentries=null;
6302 public V2TBSCertListGenerator()
6307 public void setSignature(
6308 AlgorithmIdentifier signature)
6310 this.signature = signature;
6313 public void setIssuer(
6316 this.issuer = issuer;
6319 public void setThisUpdate(
6320 DERUTCTime thisUpdate)
6322 this.thisUpdate = new Time(thisUpdate);
6325 public void setNextUpdate(
6326 DERUTCTime nextUpdate)
6328 this.nextUpdate = new Time(nextUpdate);
6331 public void setThisUpdate(
6334 this.thisUpdate = thisUpdate;
6337 public void setNextUpdate(
6340 this.nextUpdate = nextUpdate;
6343 public void addCRLEntry(
6344 DERConstructedSequence crlEntry)
6346 if (crlentries == null)
6347 crlentries = new Vector();
6348 crlentries.addElement(crlEntry);
6351 public void addCRLEntry(DERInteger userCertificate, DERUTCTime revocationDate, int reason)
6353 addCRLEntry(userCertificate, new Time(revocationDate), reason);
6356 public void addCRLEntry(DERInteger userCertificate, Time revocationDate, int reason)
6358 DERConstructedSequence seq = new DERConstructedSequence();
6359 seq.addObject(userCertificate);
6360 seq.addObject(revocationDate);
6364 CRLReason rf = new CRLReason(reason);
6365 ByteArrayOutputStream bOut = new ByteArrayOutputStream();
6366 DEROutputStream dOut = new DEROutputStream(bOut);
6369 dOut.writeObject(rf);
6371 catch (IOException e)
6373 throw new IllegalArgumentException("error encoding value: " + e);
6375 byte[] value = bOut.toByteArray();
6376 DERConstructedSequence eseq = new DERConstructedSequence();
6377 DERConstructedSequence eseq1 = new DERConstructedSequence();
6378 eseq1.addObject(X509Extensions.ReasonCode);
6379 eseq1.addObject(new DEROctetString(value));
6380 eseq.addObject(eseq1);
6381 X509Extensions ex = new X509Extensions(eseq);
6384 if (crlentries == null)
6385 crlentries = new Vector();
6386 crlentries.addElement(seq);
6389 public void setExtensions(
6390 X509Extensions extensions)
6392 this.extensions = extensions;
6395 public TBSCertList generateTBSCertList()
6397 if ((signature == null) || (issuer == null) || (thisUpdate == null))
6399 throw new IllegalStateException("Not all mandatory fields set in V2 TBSCertList generator.");
6402 DERConstructedSequence seq = new DERConstructedSequence();
6404 seq.addObject(version);
6405 seq.addObject(signature);
6406 seq.addObject(issuer);
6408 seq.addObject(thisUpdate);
6409 if (nextUpdate != null)
6410 seq.addObject(nextUpdate);
6412 // Add CRLEntries if they exist
6413 if (crlentries != null) {
6414 DERConstructedSequence certseq = new DERConstructedSequence();
6415 Enumeration it = crlentries.elements();
6416 while( it.hasMoreElements() ) {
6417 certseq.addObject((DERConstructedSequence)it.nextElement());
6419 seq.addObject(certseq);
6422 if (extensions != null)
6424 seq.addObject(new DERTaggedObject(0, extensions));
6427 return new TBSCertList(seq);
6433 * Generator for Version 3 TBSCertificateStructures.
6435 * TBSCertificate ::= SEQUENCE {
6436 * version [ 0 ] Version DEFAULT v1(0),
6437 * serialNumber CertificateSerialNumber,
6438 * signature AlgorithmIdentifier,
6440 * validity Validity,
6442 * subjectPublicKeyInfo SubjectPublicKeyInfo,
6443 * issuerUniqueID [ 1 ] IMPLICIT UniqueIdentifier OPTIONAL,
6444 * subjectUniqueID [ 2 ] IMPLICIT UniqueIdentifier OPTIONAL,
6445 * extensions [ 3 ] Extensions OPTIONAL
6450 class V3TBSCertificateGenerator
6452 DERTaggedObject version = new DERTaggedObject(0, new DERInteger(2));
6454 DERInteger serialNumber;
6455 AlgorithmIdentifier signature;
6457 Time startDate, endDate;
6459 SubjectPublicKeyInfo subjectPublicKeyInfo;
6460 X509Extensions extensions;
6462 public V3TBSCertificateGenerator()
6466 public void setSerialNumber(
6467 DERInteger serialNumber)
6469 this.serialNumber = serialNumber;
6472 public void setSignature(
6473 AlgorithmIdentifier signature)
6475 this.signature = signature;
6478 public void setIssuer(
6481 this.issuer = issuer;
6484 public void setStartDate(
6485 DERUTCTime startDate)
6487 this.startDate = new Time(startDate);
6490 public void setStartDate(
6493 this.startDate = startDate;
6496 public void setEndDate(
6499 this.endDate = new Time(endDate);
6502 public void setEndDate(
6505 this.endDate = endDate;
6508 public void setSubject(
6511 this.subject = subject;
6514 public void setSubjectPublicKeyInfo(
6515 SubjectPublicKeyInfo pubKeyInfo)
6517 this.subjectPublicKeyInfo = pubKeyInfo;
6520 public void setExtensions(
6521 X509Extensions extensions)
6523 this.extensions = extensions;
6526 public TBSCertificateStructure generateTBSCertificate()
6528 if ((serialNumber == null) || (signature == null)
6529 || (issuer == null) || (startDate == null) || (endDate == null)
6530 || (subject == null) || (subjectPublicKeyInfo == null))
6532 throw new IllegalStateException("not all mandatory fields set in V3 TBScertificate generator");
6535 DERConstructedSequence seq = new DERConstructedSequence();
6537 seq.addObject(version);
6538 seq.addObject(serialNumber);
6539 seq.addObject(signature);
6540 seq.addObject(issuer);
6543 // before and after dates
6545 DERConstructedSequence validity = new DERConstructedSequence();
6547 validity.addObject(startDate);
6548 validity.addObject(endDate);
6550 seq.addObject(validity);
6552 seq.addObject(subject);
6554 seq.addObject(subjectPublicKeyInfo);
6556 if (extensions != null)
6558 seq.addObject(new DERTaggedObject(3, extensions));
6561 return new TBSCertificateStructure(seq);
6567 * an X509Certificate structure.
6569 * Certificate ::= SEQUENCE {
6570 * tbsCertificate TBSCertificate,
6571 * signatureAlgorithm AlgorithmIdentifier,
6572 * signature BIT STRING
6576 class X509CertificateStructure
6577 implements DEREncodable, X509ObjectIdentifiers, PKCSObjectIdentifiers
6580 TBSCertificateStructure tbsCert;
6581 AlgorithmIdentifier sigAlgId;
6584 public static X509CertificateStructure getInstance(
6585 ASN1TaggedObject obj,
6588 return getInstance(ASN1Sequence.getInstance(obj, explicit));
6591 public static X509CertificateStructure getInstance(
6594 if (obj instanceof X509CertificateStructure)
6596 return (X509CertificateStructure)obj;
6598 else if (obj instanceof ASN1Sequence)
6600 return new X509CertificateStructure((ASN1Sequence)obj);
6603 throw new IllegalArgumentException("unknown object in factory");
6606 public X509CertificateStructure(
6612 // correct x509 certficate
6614 if (seq.size() == 3)
6616 tbsCert = TBSCertificateStructure.getInstance(seq.getObjectAt(0));
6617 sigAlgId = AlgorithmIdentifier.getInstance(seq.getObjectAt(1));
6619 sig = (DERBitString)seq.getObjectAt(2);
6623 public TBSCertificateStructure getTBSCertificate()
6628 public int getVersion()
6630 return tbsCert.getVersion();
6633 public DERInteger getSerialNumber()
6635 return tbsCert.getSerialNumber();
6638 public X509Name getIssuer()
6640 return tbsCert.getIssuer();
6643 public Time getStartDate()
6645 return tbsCert.getStartDate();
6648 public Time getEndDate()
6650 return tbsCert.getEndDate();
6653 public X509Name getSubject()
6655 return tbsCert.getSubject();
6658 public SubjectPublicKeyInfo getSubjectPublicKeyInfo()
6660 return tbsCert.getSubjectPublicKeyInfo();
6663 public AlgorithmIdentifier getSignatureAlgorithm()
6668 public DERBitString getSignature()
6673 public DERObject getDERObject()
6681 * an object for the elements in the X.509 V3 extension block.
6686 DEROctetString value;
6688 public X509Extension(
6689 DERBoolean critical,
6690 DEROctetString value)
6692 this.critical = critical.isTrue();
6696 public X509Extension(
6698 DEROctetString value)
6700 this.critical = critical;
6704 public boolean isCritical()
6709 public DEROctetString getValue()
6714 public int hashCode()
6716 if (this.isCritical())
6718 return this.getValue().hashCode();
6722 return ~this.getValue().hashCode();
6725 public boolean equals(
6728 if (o == null || !(o instanceof X509Extension))
6733 X509Extension other = (X509Extension)o;
6735 return other.getValue().equals(this.getValue())
6736 && (other.isCritical() == this.isCritical());
6742 class X509Extensions
6743 implements DEREncodable
6746 * Subject Key Identifier
6748 public static final DERObjectIdentifier SubjectKeyIdentifier = new DERObjectIdentifier("2.5.29.14");
6753 public static final DERObjectIdentifier KeyUsage = new DERObjectIdentifier("2.5.29.15");
6756 * Private Key Usage Period
6758 public static final DERObjectIdentifier PrivateKeyUsagePeriod = new DERObjectIdentifier("2.5.29.16");
6761 * Subject Alternative Name
6763 public static final DERObjectIdentifier SubjectAlternativeName = new DERObjectIdentifier("2.5.29.17");
6766 * Issuer Alternative Name
6768 public static final DERObjectIdentifier IssuerAlternativeName = new DERObjectIdentifier("2.5.29.18");
6773 public static final DERObjectIdentifier BasicConstraints = new DERObjectIdentifier("2.5.29.19");
6778 public static final DERObjectIdentifier CRLNumber = new DERObjectIdentifier("2.5.29.20");
6783 public static final DERObjectIdentifier ReasonCode = new DERObjectIdentifier("2.5.29.21");
6786 * Hold Instruction Code
6788 public static final DERObjectIdentifier InstructionCode = new DERObjectIdentifier("2.5.29.23");
6793 public static final DERObjectIdentifier InvalidityDate = new DERObjectIdentifier("2.5.29.24");
6796 * Delta CRL indicator
6798 public static final DERObjectIdentifier DeltaCRLIndicator = new DERObjectIdentifier("2.5.29.27");
6801 * Issuing Distribution Point
6803 public static final DERObjectIdentifier IssuingDistributionPoint = new DERObjectIdentifier("2.5.29.28");
6806 * Certificate Issuer
6808 public static final DERObjectIdentifier CertificateIssuer = new DERObjectIdentifier("2.5.29.29");
6813 public static final DERObjectIdentifier NameConstraints = new DERObjectIdentifier("2.5.29.30");
6816 * CRL Distribution Points
6818 public static final DERObjectIdentifier CRLDistributionPoints = new DERObjectIdentifier("2.5.29.31");
6821 * Certificate Policies
6823 public static final DERObjectIdentifier CertificatePolicies = new DERObjectIdentifier("2.5.29.32");
6828 public static final DERObjectIdentifier PolicyMappings = new DERObjectIdentifier("2.5.29.33");
6831 * Authority Key Identifier
6833 public static final DERObjectIdentifier AuthorityKeyIdentifier = new DERObjectIdentifier("2.5.29.35");
6836 * Policy Constraints
6838 public static final DERObjectIdentifier PolicyConstraints = new DERObjectIdentifier("2.5.29.36");
6841 * Extended Key Usage
6843 public static final DERObjectIdentifier ExtendedKeyUsage = new DERObjectIdentifier("2.5.29.37");
6845 private Hashtable extensions = new Hashtable();
6846 private Vector ordering = new Vector();
6848 public static X509Extensions getInstance(
6849 ASN1TaggedObject obj,
6852 return getInstance(ASN1Sequence.getInstance(obj, explicit));
6855 public static X509Extensions getInstance(
6858 if (obj == null || obj instanceof X509Extensions)
6860 return (X509Extensions)obj;
6863 if (obj instanceof ASN1Sequence)
6865 return new X509Extensions((ASN1Sequence)obj);
6868 if (obj instanceof ASN1TaggedObject)
6870 return getInstance(((ASN1TaggedObject)obj).getObject());
6873 throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
6877 * Constructor from DERConstructedSequence.
6879 * the extensions are a list of constructed sequences, either with (OID, OctetString) or (OID, Boolean, OctetString)
6881 public X509Extensions(
6884 Enumeration e = seq.getObjects();
6886 while (e.hasMoreElements())
6888 ASN1Sequence s = (ASN1Sequence)e.nextElement();
6889 Enumeration e1 = s.getObjects();
6893 extensions.put(s.getObjectAt(0), new X509Extension((DERBoolean)s.getObjectAt(1), (DEROctetString)s.getObjectAt(2)));
6897 extensions.put(s.getObjectAt(0), new X509Extension(false, (DEROctetString)s.getObjectAt(1)));
6900 ordering.addElement(s.getObjectAt(0));
6905 * constructor from a table of extensions.
6907 * it's is assumed the table contains OID/String pairs.
6909 public X509Extensions(
6910 Hashtable extensions)
6912 this(null, extensions);
6916 * constructor from a table of extensions with ordering
6918 * it's is assumed the table contains OID/String pairs.
6920 public X509Extensions(
6922 Hashtable extensions)
6926 if (ordering == null)
6928 e = extensions.keys();
6932 e = ordering.elements();
6935 while (e.hasMoreElements())
6937 this.ordering.addElement(e.nextElement());
6940 e = this.ordering.elements();
6942 while (e.hasMoreElements())
6944 DERObjectIdentifier oid = (DERObjectIdentifier)e.nextElement();
6945 X509Extension ext = (X509Extension)extensions.get(oid);
6947 this.extensions.put(oid, ext);
6952 * return an Enumeration of the extension field's object ids.
6954 public Enumeration oids()
6956 return ordering.elements();
6960 * return the extension represented by the object identifier
6963 * @return the extension if it's present, null otherwise.
6965 public X509Extension getExtension(
6966 DERObjectIdentifier oid)
6968 return (X509Extension)extensions.get(oid);
6971 public DERObject getDERObject()
6973 DEREncodableVector vec = new DEREncodableVector();
6974 Enumeration e = ordering.elements();
6976 while (e.hasMoreElements())
6978 DERObjectIdentifier oid = (DERObjectIdentifier)e.nextElement();
6979 X509Extension ext = (X509Extension)extensions.get(oid);
6980 DEREncodableVector v = new DEREncodableVector();
6984 if (ext.isCritical())
6986 v.add(new DERBoolean(true));
6989 v.add(ext.getValue());
6991 vec.add(new DERSequence(v));
6994 return new DERSequence(vec);
6997 public int hashCode()
6999 Enumeration e = extensions.keys();
7002 while (e.hasMoreElements())
7004 Object o = e.nextElement();
7006 hashCode ^= o.hashCode();
7007 hashCode ^= extensions.get(o).hashCode();
7013 public boolean equals(
7016 if (o == null || !(o instanceof X509Extensions))
7021 X509Extensions other = (X509Extensions)o;
7023 Enumeration e1 = extensions.keys();
7024 Enumeration e2 = other.extensions.keys();
7026 while (e1.hasMoreElements() && e2.hasMoreElements())
7028 Object o1 = e1.nextElement();
7029 Object o2 = e2.nextElement();
7037 if (e1.hasMoreElements() || e2.hasMoreElements())
7049 implements DEREncodable
7052 * country code - StringType(SIZE(2))
7054 public static final DERObjectIdentifier C = new DERObjectIdentifier("2.5.4.6");
7057 * organization - StringType(SIZE(1..64))
7059 public static final DERObjectIdentifier O = new DERObjectIdentifier("2.5.4.10");
7062 * organizational unit name - StringType(SIZE(1..64))
7064 public static final DERObjectIdentifier OU = new DERObjectIdentifier("2.5.4.11");
7069 public static final DERObjectIdentifier T = new DERObjectIdentifier("2.5.4.12");
7072 * common name - StringType(SIZE(1..64))
7074 public static final DERObjectIdentifier CN = new DERObjectIdentifier("2.5.4.3");
7077 * device serial number name - StringType(SIZE(1..64))
7079 public static final DERObjectIdentifier SN = new DERObjectIdentifier("2.5.4.5");
7082 * locality name - StringType(SIZE(1..64))
7084 public static final DERObjectIdentifier L = new DERObjectIdentifier("2.5.4.7");
7087 * state, or province name - StringType(SIZE(1..64))
7089 public static final DERObjectIdentifier ST = new DERObjectIdentifier("2.5.4.8");
7093 * email address (RSA PKCS#9 extension) - IA5String
7095 * note: if you're trying to be ultra orthodox, don't use this! It shouldn't be in here.
7097 public static final DERObjectIdentifier EmailAddress = new DERObjectIdentifier("1.2.840.113549.1.9.1");
7100 * email address in Verisign certificates
7102 public static final DERObjectIdentifier E = EmailAddress;
7107 public static final DERObjectIdentifier DC = new DERObjectIdentifier("0.9.2342.19200300.100.1.25");
7112 public static final DERObjectIdentifier UID = new DERObjectIdentifier("0.9.2342.19200300.100.1.1");
7115 * look up table translating OID values into their common symbols.
7117 public static Hashtable OIDLookUp = new Hashtable();
7120 * look up table translating common symbols into their OIDS.
7122 public static Hashtable SymbolLookUp = new Hashtable();
7126 OIDLookUp.put(C, "C");
7127 OIDLookUp.put(O, "O");
7128 OIDLookUp.put(T, "T");
7129 OIDLookUp.put(OU, "OU");
7130 OIDLookUp.put(CN, "CN");
7131 OIDLookUp.put(L, "L");
7132 OIDLookUp.put(ST, "ST");
7133 OIDLookUp.put(SN, "SN");
7134 OIDLookUp.put(EmailAddress, "E");
7135 OIDLookUp.put(DC, "DC");
7136 OIDLookUp.put(UID, "UID");
7138 SymbolLookUp.put("c", C);
7139 SymbolLookUp.put("o", O);
7140 SymbolLookUp.put("t", T);
7141 SymbolLookUp.put("ou", OU);
7142 SymbolLookUp.put("cn", CN);
7143 SymbolLookUp.put("l", L);
7144 SymbolLookUp.put("st", ST);
7145 SymbolLookUp.put("sn", SN);
7146 SymbolLookUp.put("emailaddress", E);
7147 SymbolLookUp.put("dc", DC);
7148 SymbolLookUp.put("e", E);
7149 SymbolLookUp.put("uid", UID);
7152 private Vector ordering = new Vector();
7153 private Vector values = new Vector();
7154 private ASN1Sequence seq;
7156 public static X509Name getInstance(
7157 ASN1TaggedObject obj,
7160 return getInstance(ASN1Sequence.getInstance(obj, explicit));
7163 public static X509Name getInstance(
7166 if (obj == null || obj instanceof X509Name)
7168 return (X509Name)obj;
7170 else if (obj instanceof ASN1Sequence)
7172 return new X509Name((ASN1Sequence)obj);
7175 throw new IllegalArgumentException("unknown object in factory");
7179 * Constructor from ASN1Sequence
7181 * the principal will be a list of constructed sets, each containing an (OID, String) pair.
7188 Enumeration e = seq.getObjects();
7190 while (e.hasMoreElements())
7192 ASN1Set set = (ASN1Set)e.nextElement();
7193 ASN1Sequence s = (ASN1Sequence)set.getObjectAt(0);
7195 ordering.addElement(s.getObjectAt(0));
7196 values.addElement(((DERString)s.getObjectAt(1)).getString());
7201 * constructor from a table of attributes.
7203 * it's is assumed the table contains OID/String pairs, and the contents
7204 * of the table are copied into an internal table as part of the
7205 * construction process.
7207 * <b>Note:</b> if the name you are trying to generate should be
7208 * following a specific ordering, you should use the constructor
7209 * with the ordering specified below.
7212 Hashtable attributes)
7214 this(null, attributes);
7218 * constructor from a table of attributes with ordering.
7220 * it's is assumed the table contains OID/String pairs, and the contents
7221 * of the table are copied into an internal table as part of the
7222 * construction process. The ordering vector should contain the OIDs
7223 * in the order they are meant to be encoded or printed in toString.
7227 Hashtable attributes)
7229 if (ordering != null)
7231 for (int i = 0; i != ordering.size(); i++)
7233 this.ordering.addElement(ordering.elementAt(i));
7238 Enumeration e = attributes.keys();
7240 while (e.hasMoreElements())
7242 this.ordering.addElement(e.nextElement());
7246 for (int i = 0; i != this.ordering.size(); i++)
7248 DERObjectIdentifier oid = (DERObjectIdentifier)this.ordering.elementAt(i);
7250 if (OIDLookUp.get(oid) == null)
7252 throw new IllegalArgumentException("Unknown object id - " + oid.getId() + " - passed to distinguished name");
7255 if (attributes.get(oid) == null)
7257 throw new IllegalArgumentException("No attribute for object id - " + oid.getId() + " - passed to distinguished name");
7260 this.values.addElement(attributes.get(oid)); // copy the hash table
7265 * takes two vectors one of the oids and the other of the values.
7271 if (ordering.size() != values.size())
7273 throw new IllegalArgumentException("ordering vector must be same length as values.");
7276 for (int i = 0; i < ordering.size(); i++)
7278 this.ordering.addElement(ordering.elementAt(i));
7279 this.values.addElement(values.elementAt(i));
7284 * takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
7285 * some such, converting it into an ordered set of name attributes.
7290 X509NameTokenizer nTok = new X509NameTokenizer(dirName);
7292 while (nTok.hasMoreTokens())
7294 String token = nTok.nextToken();
7295 int index = token.indexOf('=');
7299 throw new IllegalArgumentException("badly formated directory string");
7302 String name = token.substring(0, index);
7303 String value = token.substring(index + 1);
7304 DERObjectIdentifier oid = null;
7306 if (name.toUpperCase().startsWith("OID."))
7308 oid = new DERObjectIdentifier(name.substring(4));
7310 else if (name.charAt(0) >= '0' && name.charAt(0) <= '9')
7312 oid = new DERObjectIdentifier(name);
7316 oid = (DERObjectIdentifier)SymbolLookUp.get(name.toLowerCase());
7319 throw new IllegalArgumentException("Unknown object id - " + name + " - passed to distinguished name");
7323 this.ordering.addElement(oid);
7324 this.values.addElement(value);
7329 * return false if we have characters out of the range of a printable
7330 * string, true otherwise.
7332 private boolean canBePrintable(
7335 for (int i = str.length() - 1; i >= 0; i--)
7337 if (str.charAt(i) > 0x007f)
7346 public DERObject getDERObject()
7350 DEREncodableVector vec = new DEREncodableVector();
7352 for (int i = 0; i != ordering.size(); i++)
7354 DEREncodableVector v = new DEREncodableVector();
7355 DERObjectIdentifier oid = (DERObjectIdentifier)ordering.elementAt(i);
7359 String str = (String)values.elementAt(i);
7361 if (oid.equals(EmailAddress))
7363 v.add(new DERIA5String(str));
7367 if (canBePrintable(str))
7369 v.add(new DERPrintableString(str));
7373 v.add(new DERUTF8String(str));
7377 vec.add(new DERSet(new DERSequence(v)));
7380 seq = new DERSequence(vec);
7387 * test for equality - note: case is ignored.
7389 public boolean equals(Object _obj)
7396 if (_obj == null || !(_obj instanceof X509Name))
7401 X509Name _oxn = (X509Name)_obj;
7402 int _orderingSize = ordering.size();
7404 if (_orderingSize != _oxn.ordering.size())
7409 boolean[] _indexes = new boolean[_orderingSize];
7411 for(int i = 0; i < _orderingSize; i++)
7413 boolean _found = false;
7414 String _oid = ((DERObjectIdentifier)ordering.elementAt(i)).getId();
7415 String _val = (String)values.elementAt(i);
7417 for(int j = 0; j < _orderingSize; j++)
7419 if(_indexes[j] == true)
7424 String _oOID = ((DERObjectIdentifier)_oxn.ordering.elementAt(j)).getId();
7425 String _oVal = (String)_oxn.values.elementAt(j);
7427 // was equalsIgnoreCase but MIDP doesn't like that.
7428 if(_oid.equals(_oOID) && _val.toLowerCase().equals(_oVal.toLowerCase()))
7446 public int hashCode()
7448 ASN1Sequence seq = (ASN1Sequence)this.getDERObject();
7449 Enumeration e = seq.getObjects();
7452 while (e.hasMoreElements())
7454 hashCode ^= e.nextElement().hashCode();
7460 public String toString()
7462 StringBuffer buf = new StringBuffer();
7463 boolean first = true;
7464 Enumeration e1 = ordering.elements();
7465 Enumeration e2 = values.elements();
7467 while (e1.hasMoreElements())
7469 Object oid = e1.nextElement();
7470 String sym = (String)OIDLookUp.get(oid);
7487 buf.append(((DERObjectIdentifier)oid).getId());
7492 int index = buf.length();
7494 buf.append((String)e2.nextElement());
7496 int end = buf.length();
7498 while (index != end)
7500 if ((buf.charAt(index) == ',')
7501 || (buf.charAt(index) == '"')
7502 || (buf.charAt(index) == '\\')
7503 || (buf.charAt(index) == '+')
7504 || (buf.charAt(index) == '<')
7505 || (buf.charAt(index) == '>')
7506 || (buf.charAt(index) == ';'))
7508 buf.insert(index, "\\");
7517 return buf.toString();
7522 * class for breaking up an X500 Name into it's component tokens, ala
7523 * java.util.StringTokenizer. We need this class as some of the
7524 * lightweight Java environment don't support classes like
7527 class X509NameTokenizer
7531 private StringBuffer buf = new StringBuffer();
7533 public X509NameTokenizer(
7540 public boolean hasMoreTokens()
7542 return (index != oid.length());
7545 public String nextToken()
7547 if (index == oid.length())
7552 int end = index + 1;
7553 boolean quoted = false;
7554 boolean escaped = false;
7558 while (end != oid.length())
7560 char c = oid.charAt(end);
7576 if (escaped || quoted)
7598 return buf.toString().trim();
7603 interface X509ObjectIdentifiers
7608 static final String id = "2.5.4";
7610 static final DERObjectIdentifier commonName = new DERObjectIdentifier(id + ".3");
7611 static final DERObjectIdentifier countryName = new DERObjectIdentifier(id + ".6");
7612 static final DERObjectIdentifier localityName = new DERObjectIdentifier(id + ".7");
7613 static final DERObjectIdentifier stateOrProvinceName = new DERObjectIdentifier(id + ".8");
7614 static final DERObjectIdentifier organization = new DERObjectIdentifier(id + ".10");
7615 static final DERObjectIdentifier organizationalUnitName = new DERObjectIdentifier(id + ".11");
7617 // id-SHA1 OBJECT IDENTIFIER ::=
7618 // {iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 26 } //
7619 static final DERObjectIdentifier id_SHA1 = new DERObjectIdentifier("1.3.14.3.2.26");
7622 // ripemd160 OBJECT IDENTIFIER ::=
7623 // {iso(1) identified-organization(3) TeleTrust(36) algorithm(3) hashAlgorithm(2) RIPEMD-160(1)}
7625 static final DERObjectIdentifier ripemd160 = new DERObjectIdentifier("1.3.36.3.2.1");
7628 // ripemd160WithRSAEncryption OBJECT IDENTIFIER ::=
7629 // {iso(1) identified-organization(3) TeleTrust(36) algorithm(3) signatureAlgorithm(3) rsaSignature(1) rsaSignatureWithripemd160(2) }
7631 static final DERObjectIdentifier ripemd160WithRSAEncryption = new DERObjectIdentifier("1.3.36.3.3.1.2");
7634 static final DERObjectIdentifier id_ea_rsa = new DERObjectIdentifier("2.5.8.1.1");
7640 * base interface that a public/private key block cipher needs
7643 interface AsymmetricBlockCipher
7646 * initialise the cipher.
7648 * @param forEncryption if true the cipher is initialised for
7649 * encryption, if false for decryption.
7650 * @param param the key and other data required by the cipher.
7652 public void init(boolean forEncryption, CipherParameters param);
7655 * returns the largest size an input block can be.
7657 * @return maximum size for an input block.
7659 public int getInputBlockSize();
7662 * returns the maximum size of the block produced by this cipher.
7664 * @return maximum size of the output block produced by the cipher.
7666 public int getOutputBlockSize();
7669 * process the block of len bytes stored in in from offset inOff.
7671 * @param in the input data
7672 * @param inOff offset into the in array where the data starts
7673 * @param len the length of the block to be processed.
7674 * @return the resulting byte array of the encryption/decryption process.
7675 * @exception InvalidCipherTextException data decrypts improperly.
7676 * @exception DataLengthException the input data is too large for the cipher.
7678 public byte[] processBlock(byte[] in, int inOff, int len)
7679 throws InvalidCipherTextException;
7683 * a holding class for public/private parameter pairs.
7685 class AsymmetricCipherKeyPair
7687 private CipherParameters publicParam;
7688 private CipherParameters privateParam;
7691 * basic constructor.
7693 * @param publicParam a public key parameters object.
7694 * @param privateParam the corresponding private key parameters.
7696 public AsymmetricCipherKeyPair(
7697 CipherParameters publicParam,
7698 CipherParameters privateParam)
7700 this.publicParam = publicParam;
7701 this.privateParam = privateParam;
7705 * return the public key parameters.
7707 * @return the public key parameters.
7709 public CipherParameters getPublic()
7715 * return the private key parameters.
7717 * @return the private key parameters.
7719 public CipherParameters getPrivate()
7721 return privateParam;
7726 * interface that a public/private key pair generator should conform to.
7728 interface AsymmetricCipherKeyPairGenerator
7731 * intialise the key pair generator.
7733 * @param the parameters the key pair is to be initialised with.
7735 public void init(KeyGenerationParameters param);
7738 * return an AsymmetricCipherKeyPair containing the generated keys.
7740 * @return an AsymmetricCipherKeyPair containing the generated keys.
7742 public AsymmetricCipherKeyPair generateKeyPair();
7748 * Block cipher engines are expected to conform to this interface.
7750 interface BlockCipher
7753 * Initialise the cipher.
7755 * @param forEncryption if true the cipher is initialised for
7756 * encryption, if false for decryption.
7757 * @param param the key and other data required by the cipher.
7758 * @exception IllegalArgumentException if the params argument is
7761 public void init(boolean forEncryption, CipherParameters params)
7762 throws IllegalArgumentException;
7765 * Return the name of the algorithm the cipher implements.
7767 * @return the name of the algorithm the cipher implements.
7769 public String getAlgorithmName();
7772 * Return the block size for this cipher (in bytes).
7774 * @return the block size for this cipher in bytes.
7776 public int getBlockSize();
7779 * Process one block of input from the array in and write it to
7782 * @param in the array containing the input data.
7783 * @param inOff offset into the in array the data starts at.
7784 * @param out the array the output data will be copied into.
7785 * @param outOff the offset into the out array the output will start at.
7786 * @exception DataLengthException if there isn't enough data in in, or
7788 * @exception IllegalStateException if the cipher isn't initialised.
7789 * @return the number of bytes processed and produced.
7791 public int processBlock(byte[] in, int inOff, byte[] out, int outOff)
7792 throws DataLengthException, IllegalStateException;
7795 * Reset the cipher. After resetting the cipher is in the same state
7796 * as it was after the last init (if there was one).
7798 public void reset();
7803 * The base class for symmetric, or secret, cipher key generators.
7805 class CipherKeyGenerator
7807 protected Random random;
7808 protected int strength;
7811 * initialise the key generator.
7813 * @param param the parameters to be used for key generation
7816 KeyGenerationParameters param)
7818 this.random = param.getRandom();
7819 this.strength = (param.getStrength() + 7) / 8;
7823 * generate a secret key.
7825 * @return a byte array containing the key value.
7827 public byte[] generateKey()
7829 byte[] key = new byte[strength];
7831 random.nextBytes(key);
7838 * all parameter classes implement this.
7840 interface CipherParameters
7845 * the foundation class for the hard exceptions thrown by the crypto packages.
7847 class CryptoException
7853 public CryptoException()
7858 * create a CryptoException with the given message.
7860 * @param message the message to be carried with the exception.
7862 public CryptoException(
7870 * this exception is thrown if a buffer that is meant to have output
7871 * copied into it turns out to be too short, or if we've been given
7872 * insufficient input. In general this exception will get thrown rather
7873 * than an ArrayOutOfBounds exception.
7875 class DataLengthException
7876 extends RuntimeCryptoException
7881 public DataLengthException()
7886 * create a DataLengthException with the given message.
7888 * @param message the message to be carried with the exception.
7890 public DataLengthException(
7898 * interface that a message digest conforms to.
7903 * return the algorithm name
7905 * @return the algorithm name
7907 public String getAlgorithmName();
7910 * return the size, in bytes, of the digest produced by this message digest.
7912 * @return the size, in bytes, of the digest produced by this message digest.
7914 public int getDigestSize();
7917 * update the message digest with a single byte.
7919 * @param in the input byte to be entered.
7921 public void update(byte in);
7924 * update the message digest with a block of bytes.
7926 * @param in the byte array containing the data.
7927 * @param inOff the offset into the byte array where the data starts.
7928 * @param len the length of the data.
7930 public void update(byte[] in, int inOff, int len);
7933 * close the digest, producing the final digest value. The doFinal
7934 * call leaves the digest reset.
7936 * @param out the array the digest is to be copied into.
7937 * @param outOff the offset into the out array the digest is to start at.
7939 public int doFinal(byte[] out, int outOff);
7942 * reset the digest back to it's initial state.
7944 public void reset();
7949 * base implementation of MD4 family style digest as outlined in
7950 * "Handbook of Applied Cryptography", pages 344 - 347.
7952 abstract class GeneralDigest
7955 private byte[] xBuf;
7956 private int xBufOff;
7958 private long byteCount;
7961 * Standard constructor
7963 protected GeneralDigest()
7970 * Copy constructor. We are using copy constructors in place
7971 * of the Object.clone() interface as this interface is not
7972 * supported by J2ME.
7974 protected GeneralDigest(GeneralDigest t)
7976 xBuf = new byte[t.xBuf.length];
7977 System.arraycopy(t.xBuf, 0, xBuf, 0, t.xBuf.length);
7979 xBufOff = t.xBufOff;
7980 byteCount = t.byteCount;
7986 xBuf[xBufOff++] = in;
7988 if (xBufOff == xBuf.length)
7990 processWord(xBuf, 0);
8003 // fill the current word
8005 while ((xBufOff != 0) && (len > 0))
8014 // process whole words.
8016 while (len > xBuf.length)
8018 processWord(in, inOff);
8020 inOff += xBuf.length;
8022 byteCount += xBuf.length;
8026 // load in the remainder.
8037 public void finish()
8039 long bitLength = (byteCount << 3);
8042 // add the pad bytes.
8046 while (xBufOff != 0)
8051 processLength(bitLength);
8061 for ( int i = 0; i < xBuf.length; i++ ) {
8066 protected abstract void processWord(byte[] in, int inOff);
8068 protected abstract void processLength(long bitLength);
8070 protected abstract void processBlock();
8074 * implementation of MD2
8075 * as outlined in RFC1319 by B.Kaliski from RSA Laboratories April 1992
8080 private static final int DIGEST_LENGTH = 16;
\r
8083 private byte[] X = new byte[48];
\r
8086 \r private byte[] M = new byte[16];
\r
8089 \r private byte[] C = new byte[16];
8092 public MD2Digest()
\r
8096 public MD2Digest(MD2Digest t)
\r
8098 System.arraycopy(t.X, 0, X, 0, t.X.length);
8100 System.arraycopy(t.M, 0, M, 0, t.M.length);
8102 System.arraycopy(t.C, 0, C, 0, t.C.length);
8106 * return the algorithm name
8108 * @return the algorithm name
8110 public String getAlgorithmName()
8115 * return the size, in bytes, of the digest produced by this message digest.
8117 * @return the size, in bytes, of the digest produced by this message digest.
8119 public int getDigestSize()
8121 return DIGEST_LENGTH;
8124 * close the digest, producing the final digest value. The doFinal
8125 * call leaves the digest reset.
8127 * @param out the array the digest is to be copied into.
8128 * @param outOff the offset into the out array the digest is to start at.
8130 public int doFinal(byte[] out, int outOff)
8133 byte paddingByte = (byte)(M.length-mOff);
8134 for (int i=mOff;i<M.length;i++)
8138 //do final check sum
8140 // do final block process
8145 System.arraycopy(X,xOff,out,outOff,16);
8149 return DIGEST_LENGTH;
8152 * reset the digest back to it's initial state.
8154 public void reset()
\r
8157 for (int i = 0; i != X.length; i++)
8162 for (int i = 0; i != M.length; i++)
8167 for (int i = 0; i != C.length; i++)
8173 * update the message digest with a single byte.
8175 * @param in the input byte to be entered.
8177 public void update(byte in)
8190 * update the message digest with a block of bytes.
8192 * @param in the byte array containing the data.
8193 * @param inOff the offset into the byte array where the data starts.
8194 * @param len the length of the data.
8196 public void update(byte[] in, int inOff, int len)
\r
8199 // fill the current word
8201 while ((mOff != 0) && (len > 0))
8209 // process whole words.
8213 System.arraycopy(in,inOff,M,0,16);
8221 // load in the remainder.
8230 protected void processCheckSum(byte[] m)
\r
8233 for (int i=0;i<16;i++)
\r
8235 C[i] ^= S[(m[i] ^ L) & 0xff];
\r
8239 protected void processBlock(byte[] m)
\r
8241 for (int i=0;i<16;i++)
8244 X[i+32] = (byte)(m[i] ^ X[i]);
8249 for (int j=0;j<18;j++)
8251 for (int k=0;k<48;k++)
8259 // 256-byte random permutation constructed from the digits of PI
8260 private static final byte[] S = {
\r
8261 (byte)41,(byte)46,(byte)67,(byte)201,(byte)162,(byte)216,(byte)124,
\r
8262 (byte)1,(byte)61,(byte)54,(byte)84,(byte)161,(byte)236,(byte)240,
\r
8263 (byte)6,(byte)19,(byte)98,(byte)167,(byte)5,(byte)243,(byte)192,
\r
8264 (byte)199,(byte)115,(byte)140,(byte)152,(byte)147,(byte)43,(byte)217,
\r
8265 (byte)188,(byte)76,(byte)130,(byte)202,(byte)30,(byte)155,(byte)87,
\r
8266 (byte)60,(byte)253,(byte)212,(byte)224,(byte)22,(byte)103,(byte)66,
\r
8267 (byte)111,(byte)24,(byte)138,(byte)23,(byte)229,(byte)18,(byte)190,
\r
8268 (byte)78,(byte)196,(byte)214,(byte)218,(byte)158,(byte)222,(byte)73,
\r
8269 (byte)160,(byte)251,(byte)245,(byte)142,(byte)187,(byte)47,(byte)238,
\r
8270 (byte)122,(byte)169,(byte)104,(byte)121,(byte)145,(byte)21,(byte)178,
\r
8271 (byte)7,(byte)63,(byte)148,(byte)194,(byte)16,(byte)137,(byte)11,
\r
8272 (byte)34,(byte)95,(byte)33,(byte)128,(byte)127,(byte)93,(byte)154,
\r
8273 (byte)90,(byte)144,(byte)50,(byte)39,(byte)53,(byte)62,(byte)204,
\r
8274 (byte)231,(byte)191,(byte)247,(byte)151,(byte)3,(byte)255,(byte)25,
\r
8275 (byte)48,(byte)179,(byte)72,(byte)165,(byte)181,(byte)209,(byte)215,
\r
8276 (byte)94,(byte)146,(byte)42,(byte)172,(byte)86,(byte)170,(byte)198,
\r
8277 (byte)79,(byte)184,(byte)56,(byte)210,(byte)150,(byte)164,(byte)125,
\r
8278 (byte)182,(byte)118,(byte)252,(byte)107,(byte)226,(byte)156,(byte)116,
\r
8279 (byte)4,(byte)241,(byte)69,(byte)157,(byte)112,(byte)89,(byte)100,
\r
8280 (byte)113,(byte)135,(byte)32,(byte)134,(byte)91,(byte)207,(byte)101,
\r
8281 (byte)230,(byte)45,(byte)168,(byte)2,(byte)27,(byte)96,(byte)37,
\r
8282 (byte)173,(byte)174,(byte)176,(byte)185,(byte)246,(byte)28,(byte)70,
\r
8283 (byte)97,(byte)105,(byte)52,(byte)64,(byte)126,(byte)15,(byte)85,
\r
8284 (byte)71,(byte)163,(byte)35,(byte)221,(byte)81,(byte)175,(byte)58,
\r
8285 (byte)195,(byte)92,(byte)249,(byte)206,(byte)186,(byte)197,(byte)234,
\r
8286 (byte)38,(byte)44,(byte)83,(byte)13,(byte)110,(byte)133,(byte)40,
\r
8287 (byte)132, 9,(byte)211,(byte)223,(byte)205,(byte)244,(byte)65,
\r
8288 (byte)129,(byte)77,(byte)82,(byte)106,(byte)220,(byte)55,(byte)200,
\r
8289 (byte)108,(byte)193,(byte)171,(byte)250,(byte)36,(byte)225,(byte)123,
\r
8290 (byte)8,(byte)12,(byte)189,(byte)177,(byte)74,(byte)120,(byte)136,
\r
8291 (byte)149,(byte)139,(byte)227,(byte)99,(byte)232,(byte)109,(byte)233,
\r
8292 (byte)203,(byte)213,(byte)254,(byte)59,(byte)0,(byte)29,(byte)57,
\r
8293 (byte)242,(byte)239,(byte)183,(byte)14,(byte)102,(byte)88,(byte)208,
\r
8294 (byte)228,(byte)166,(byte)119,(byte)114,(byte)248,(byte)235,(byte)117,
\r
8295 (byte)75,(byte)10,(byte)49,(byte)68,(byte)80,(byte)180,(byte)143,
\r
8296 (byte)237,(byte)31,(byte)26,(byte)219,(byte)153,(byte)141,(byte)51,
\r
8297 (byte)159,(byte)17,(byte)131,(byte)20
\r
8303 * implementation of MD5 as outlined in "Handbook of Applied Cryptography", pages 346 - 347.
8306 extends GeneralDigest
8308 private static final int DIGEST_LENGTH = 16;
8310 private int H1, H2, H3, H4; // IV's
8312 private int[] X = new int[16];
8316 * Standard constructor
8324 * Copy constructor. This will copy the state of the provided
8327 public MD5Digest(MD5Digest t)
8336 System.arraycopy(t.X, 0, X, 0, t.X.length);
8340 public String getAlgorithmName()
8345 public int getDigestSize()
8347 return DIGEST_LENGTH;
8350 protected void processWord(
8354 X[xOff++] = (in[inOff] & 0xff) | ((in[inOff + 1] & 0xff) << 8)
8355 | ((in[inOff + 2] & 0xff) << 16) | ((in[inOff + 3] & 0xff) << 24);
8363 protected void processLength(
8371 X[14] = (int)(bitLength & 0xffffffff);
8372 X[15] = (int)(bitLength >>> 32);
8375 private void unpackWord(
8380 out[outOff] = (byte)word;
8381 out[outOff + 1] = (byte)(word >>> 8);
8382 out[outOff + 2] = (byte)(word >>> 16);
8383 out[outOff + 3] = (byte)(word >>> 24);
8392 unpackWord(H1, out, outOff);
8393 unpackWord(H2, out, outOff + 4);
8394 unpackWord(H3, out, outOff + 8);
8395 unpackWord(H4, out, outOff + 12);
8399 return DIGEST_LENGTH;
8403 * reset the chaining variables to the IV values.
8416 for (int i = 0; i != X.length; i++)
8423 // round 1 left rotates
8425 private static final int S11 = 7;
8426 private static final int S12 = 12;
8427 private static final int S13 = 17;
8428 private static final int S14 = 22;
8431 // round 2 left rotates
8433 private static final int S21 = 5;
8434 private static final int S22 = 9;
8435 private static final int S23 = 14;
8436 private static final int S24 = 20;
8439 // round 3 left rotates
8441 private static final int S31 = 4;
8442 private static final int S32 = 11;
8443 private static final int S33 = 16;
8444 private static final int S34 = 23;
8447 // round 4 left rotates
8449 private static final int S41 = 6;
8450 private static final int S42 = 10;
8451 private static final int S43 = 15;
8452 private static final int S44 = 21;
8455 * rotate int x left n bits.
8457 private int rotateLeft(
8461 return (x << n) | (x >>> (32 - n));
8465 * F, G, H and I are the basic MD5 functions.
8472 return (u & v) | (~u & w);
8480 return (u & w) | (v & ~w);
8496 return v ^ (u | ~w);
8499 protected void processBlock()
8507 // Round 1 - F cycle, 16 times.
8509 a = rotateLeft((a + F(b, c, d) + X[ 0] + 0xd76aa478), S11) + b;
8510 d = rotateLeft((d + F(a, b, c) + X[ 1] + 0xe8c7b756), S12) + a;
8511 c = rotateLeft((c + F(d, a, b) + X[ 2] + 0x242070db), S13) + d;
8512 b = rotateLeft((b + F(c, d, a) + X[ 3] + 0xc1bdceee), S14) + c;
8513 a = rotateLeft((a + F(b, c, d) + X[ 4] + 0xf57c0faf), S11) + b;
8514 d = rotateLeft((d + F(a, b, c) + X[ 5] + 0x4787c62a), S12) + a;
8515 c = rotateLeft((c + F(d, a, b) + X[ 6] + 0xa8304613), S13) + d;
8516 b = rotateLeft((b + F(c, d, a) + X[ 7] + 0xfd469501), S14) + c;
8517 a = rotateLeft((a + F(b, c, d) + X[ 8] + 0x698098d8), S11) + b;
8518 d = rotateLeft((d + F(a, b, c) + X[ 9] + 0x8b44f7af), S12) + a;
8519 c = rotateLeft((c + F(d, a, b) + X[10] + 0xffff5bb1), S13) + d;
8520 b = rotateLeft((b + F(c, d, a) + X[11] + 0x895cd7be), S14) + c;
8521 a = rotateLeft((a + F(b, c, d) + X[12] + 0x6b901122), S11) + b;
8522 d = rotateLeft((d + F(a, b, c) + X[13] + 0xfd987193), S12) + a;
8523 c = rotateLeft((c + F(d, a, b) + X[14] + 0xa679438e), S13) + d;
8524 b = rotateLeft((b + F(c, d, a) + X[15] + 0x49b40821), S14) + c;
8527 // Round 2 - G cycle, 16 times.
8529 a = rotateLeft((a + G(b, c, d) + X[ 1] + 0xf61e2562), S21) + b;
8530 d = rotateLeft((d + G(a, b, c) + X[ 6] + 0xc040b340), S22) + a;
8531 c = rotateLeft((c + G(d, a, b) + X[11] + 0x265e5a51), S23) + d;
8532 b = rotateLeft((b + G(c, d, a) + X[ 0] + 0xe9b6c7aa), S24) + c;
8533 a = rotateLeft((a + G(b, c, d) + X[ 5] + 0xd62f105d), S21) + b;
8534 d = rotateLeft((d + G(a, b, c) + X[10] + 0x02441453), S22) + a;
8535 c = rotateLeft((c + G(d, a, b) + X[15] + 0xd8a1e681), S23) + d;
8536 b = rotateLeft((b + G(c, d, a) + X[ 4] + 0xe7d3fbc8), S24) + c;
8537 a = rotateLeft((a + G(b, c, d) + X[ 9] + 0x21e1cde6), S21) + b;
8538 d = rotateLeft((d + G(a, b, c) + X[14] + 0xc33707d6), S22) + a;
8539 c = rotateLeft((c + G(d, a, b) + X[ 3] + 0xf4d50d87), S23) + d;
8540 b = rotateLeft((b + G(c, d, a) + X[ 8] + 0x455a14ed), S24) + c;
8541 a = rotateLeft((a + G(b, c, d) + X[13] + 0xa9e3e905), S21) + b;
8542 d = rotateLeft((d + G(a, b, c) + X[ 2] + 0xfcefa3f8), S22) + a;
8543 c = rotateLeft((c + G(d, a, b) + X[ 7] + 0x676f02d9), S23) + d;
8544 b = rotateLeft((b + G(c, d, a) + X[12] + 0x8d2a4c8a), S24) + c;
8547 // Round 3 - H cycle, 16 times.
8549 a = rotateLeft((a + H(b, c, d) + X[ 5] + 0xfffa3942), S31) + b;
8550 d = rotateLeft((d + H(a, b, c) + X[ 8] + 0x8771f681), S32) + a;
8551 c = rotateLeft((c + H(d, a, b) + X[11] + 0x6d9d6122), S33) + d;
8552 b = rotateLeft((b + H(c, d, a) + X[14] + 0xfde5380c), S34) + c;
8553 a = rotateLeft((a + H(b, c, d) + X[ 1] + 0xa4beea44), S31) + b;
8554 d = rotateLeft((d + H(a, b, c) + X[ 4] + 0x4bdecfa9), S32) + a;
8555 c = rotateLeft((c + H(d, a, b) + X[ 7] + 0xf6bb4b60), S33) + d;
8556 b = rotateLeft((b + H(c, d, a) + X[10] + 0xbebfbc70), S34) + c;
8557 a = rotateLeft((a + H(b, c, d) + X[13] + 0x289b7ec6), S31) + b;
8558 d = rotateLeft((d + H(a, b, c) + X[ 0] + 0xeaa127fa), S32) + a;
8559 c = rotateLeft((c + H(d, a, b) + X[ 3] + 0xd4ef3085), S33) + d;
8560 b = rotateLeft((b + H(c, d, a) + X[ 6] + 0x04881d05), S34) + c;
8561 a = rotateLeft((a + H(b, c, d) + X[ 9] + 0xd9d4d039), S31) + b;
8562 d = rotateLeft((d + H(a, b, c) + X[12] + 0xe6db99e5), S32) + a;
8563 c = rotateLeft((c + H(d, a, b) + X[15] + 0x1fa27cf8), S33) + d;
8564 b = rotateLeft((b + H(c, d, a) + X[ 2] + 0xc4ac5665), S34) + c;
8567 // Round 4 - K cycle, 16 times.
8569 a = rotateLeft((a + K(b, c, d) + X[ 0] + 0xf4292244), S41) + b;
8570 d = rotateLeft((d + K(a, b, c) + X[ 7] + 0x432aff97), S42) + a;
8571 c = rotateLeft((c + K(d, a, b) + X[14] + 0xab9423a7), S43) + d;
8572 b = rotateLeft((b + K(c, d, a) + X[ 5] + 0xfc93a039), S44) + c;
8573 a = rotateLeft((a + K(b, c, d) + X[12] + 0x655b59c3), S41) + b;
8574 d = rotateLeft((d + K(a, b, c) + X[ 3] + 0x8f0ccc92), S42) + a;
8575 c = rotateLeft((c + K(d, a, b) + X[10] + 0xffeff47d), S43) + d;
8576 b = rotateLeft((b + K(c, d, a) + X[ 1] + 0x85845dd1), S44) + c;
8577 a = rotateLeft((a + K(b, c, d) + X[ 8] + 0x6fa87e4f), S41) + b;
8578 d = rotateLeft((d + K(a, b, c) + X[15] + 0xfe2ce6e0), S42) + a;
8579 c = rotateLeft((c + K(d, a, b) + X[ 6] + 0xa3014314), S43) + d;
8580 b = rotateLeft((b + K(c, d, a) + X[13] + 0x4e0811a1), S44) + c;
8581 a = rotateLeft((a + K(b, c, d) + X[ 4] + 0xf7537e82), S41) + b;
8582 d = rotateLeft((d + K(a, b, c) + X[11] + 0xbd3af235), S42) + a;
8583 c = rotateLeft((c + K(d, a, b) + X[ 2] + 0x2ad7d2bb), S43) + d;
8584 b = rotateLeft((b + K(c, d, a) + X[ 9] + 0xeb86d391), S44) + c;
8592 // reset the offset and clean out the word buffer.
8595 for (int i = 0; i != X.length; i++)
8604 * implementation of SHA-1 as outlined in "Handbook of Applied Cryptography", pages 346 - 349.
8606 * It is interesting to ponder why the, apart from the extra IV, the other difference here from MD5
8607 * is the "endienness" of the word processing!
8610 extends GeneralDigest
8612 private static final int DIGEST_LENGTH = 20;
8614 private int H1, H2, H3, H4, H5;
8616 private int[] X = new int[80];
8620 * Standard constructor
8628 * Copy constructor. This will copy the state of the provided
8631 public SHA1Digest(SHA1Digest t)
8641 System.arraycopy(t.X, 0, X, 0, t.X.length);
8645 public String getAlgorithmName()
8650 public int getDigestSize()
8652 return DIGEST_LENGTH;
8655 protected void processWord(
8659 X[xOff++] = ((in[inOff] & 0xff) << 24) | ((in[inOff + 1] & 0xff) << 16)
8660 | ((in[inOff + 2] & 0xff) << 8) | ((in[inOff + 3] & 0xff));
8668 private void unpackWord(
8673 out[outOff] = (byte)(word >>> 24);
8674 out[outOff + 1] = (byte)(word >>> 16);
8675 out[outOff + 2] = (byte)(word >>> 8);
8676 out[outOff + 3] = (byte)word;
8679 protected void processLength(
8687 X[14] = (int)(bitLength >>> 32);
8688 X[15] = (int)(bitLength & 0xffffffff);
8697 unpackWord(H1, out, outOff);
8698 unpackWord(H2, out, outOff + 4);
8699 unpackWord(H3, out, outOff + 8);
8700 unpackWord(H4, out, outOff + 12);
8701 unpackWord(H5, out, outOff + 16);
8705 return DIGEST_LENGTH;
8709 * reset the chaining variables
8722 for (int i = 0; i != X.length; i++)
8729 // Additive constants
8731 private static final int Y1 = 0x5a827999;
8732 private static final int Y2 = 0x6ed9eba1;
8733 private static final int Y3 = 0x8f1bbcdc;
8734 private static final int Y4 = 0xca62c1d6;
8741 return ((u & v) | ((~u) & w));
8757 return ((u & v) | (u & w) | (v & w));
8760 private int rotateLeft(
8764 return (x << n) | (x >>> (32 - n));
8767 protected void processBlock()
8770 // expand 16 word block into 80 word block.
8772 for (int i = 16; i <= 79; i++)
8774 X[i] = rotateLeft((X[i - 3] ^ X[i - 8] ^ X[i - 14] ^ X[i - 16]), 1);
8778 // set up working variables.
8789 for (int j = 0; j <= 19; j++)
8791 int t = rotateLeft(A, 5) + f(B, C, D) + E + X[j] + Y1;
8795 C = rotateLeft(B, 30);
8803 for (int j = 20; j <= 39; j++)
8805 int t = rotateLeft(A, 5) + h(B, C, D) + E + X[j] + Y2;
8809 C = rotateLeft(B, 30);
8817 for (int j = 40; j <= 59; j++)
8819 int t = rotateLeft(A, 5) + g(B, C, D) + E + X[j] + Y3;
8823 C = rotateLeft(B, 30);
8831 for (int j = 60; j <= 79; j++)
8833 int t = rotateLeft(A, 5) + h(B, C, D) + E + X[j] + Y4;
8837 C = rotateLeft(B, 30);
8849 // reset the offset and clean out the word buffer.
8852 for (int i = 0; i != X.length; i++)
8862 * this does your basic PKCS 1 v1.5 padding - whether or not you should be using this
8863 * depends on your application - see PKCS1 Version 2 for details.
8866 implements AsymmetricBlockCipher
8868 private static int HEADER_LENGTH = 10;
8870 private Random random;
8871 private AsymmetricBlockCipher engine;
8872 private boolean forEncryption;
8873 private boolean forPrivateKey;
8875 public PKCS1Encoding(
8876 AsymmetricBlockCipher cipher)
8878 this.engine = cipher;
8881 public AsymmetricBlockCipher getUnderlyingCipher()
8887 boolean forEncryption,
8888 CipherParameters param)
8890 AsymmetricKeyParameter kParam;
8892 if (param instanceof ParametersWithRandom)
8894 ParametersWithRandom rParam = (ParametersWithRandom)param;
8896 this.random = rParam.getRandom();
8897 kParam = (AsymmetricKeyParameter)rParam.getParameters();
8901 this.random = new Random();
8902 kParam = (AsymmetricKeyParameter)param;
8905 engine.init(forEncryption, kParam);
8907 this.forPrivateKey = kParam.isPrivate();
8908 this.forEncryption = forEncryption;
8911 public int getInputBlockSize()
8913 int baseBlockSize = engine.getInputBlockSize();
8917 return baseBlockSize - HEADER_LENGTH;
8921 return baseBlockSize;
8925 public int getOutputBlockSize()
8927 int baseBlockSize = engine.getOutputBlockSize();
8931 return baseBlockSize;
8935 return baseBlockSize - HEADER_LENGTH;
8939 public byte[] processBlock(
8943 throws InvalidCipherTextException
8947 return encodeBlock(in, inOff, inLen);
8951 return decodeBlock(in, inOff, inLen);
8955 private byte[] encodeBlock(
8959 throws InvalidCipherTextException
8961 byte[] block = new byte[engine.getInputBlockSize()];
8965 block[0] = 0x01; // type code 1
8967 for (int i = 1; i != block.length - inLen - 1; i++)
8969 block[i] = (byte)0xFF;
8974 random.nextBytes(block); // random fill
8976 block[0] = 0x02; // type code 2
8979 // a zero byte marks the end of the padding, so all
8980 // the pad bytes must be non-zero.
8982 for (int i = 1; i != block.length - inLen - 1; i++)
8984 while (block[i] == 0)
8986 block[i] = (byte)random.nextInt();
8991 block[block.length - inLen - 1] = 0x00; // mark the end of the padding
8992 System.arraycopy(in, inOff, block, block.length - inLen, inLen);
8994 return engine.processBlock(block, 0, block.length);
8998 * @exception InvalidCipherTextException if the decrypted block is not in PKCS1 format.
9000 private byte[] decodeBlock(
9004 throws InvalidCipherTextException
9006 byte[] block = engine.processBlock(in, inOff, inLen);
9008 if (block.length < getOutputBlockSize())
9010 throw new InvalidCipherTextException("block truncated");
9013 if (block[0] != 1 && block[0] != 2)
9015 throw new InvalidCipherTextException("unknown block type");
9019 // find and extract the message block.
9023 for (start = 1; start != block.length; start++)
9025 if (block[start] == 0)
9031 start++; // data should start at the next byte
9033 if (start >= block.length || start < HEADER_LENGTH)
9035 throw new InvalidCipherTextException("no data in block");
9038 byte[] result = new byte[block.length - start];
9040 System.arraycopy(block, start, result, 0, result.length);
9047 class RC4Engine implements StreamCipher
\r
9049 private final static int STATE_LENGTH = 256;
\r
9052 * variables to hold the state of the RC4 engine
\r
9053 * during encryption and decryption
\r
9056 private byte[] engineState = null;
\r
9057 private int x = 0;
\r
9058 private int y = 0;
\r
9059 private byte[] workingKey = null;
\r
9062 * initialise a RC4 cipher.
\r
9064 * @param forEncryption whether or not we are for encryption.
\r
9065 * @param params the parameters required to set up the cipher.
\r
9066 * @exception IllegalArgumentException if the params argument is
\r
9070 boolean forEncryption,
\r
9071 CipherParameters params
\r
9074 if (params instanceof KeyParameter)
\r
9077 * RC4 encryption and decryption is completely
\r
9078 * symmetrical, so the 'forEncryption' is
\r
9081 workingKey = ((KeyParameter)params).getKey();
\r
9082 setKey(workingKey);
\r
9087 throw new IllegalArgumentException("invalid parameter passed to RC4 init - " + params.getClass().getName());
\r
9090 public String getAlgorithmName()
\r
9095 public byte returnByte(byte in)
\r
9097 x = (x + 1) & 0xff;
\r
9098 y = (engineState[x] + y) & 0xff;
\r
9101 byte tmp = engineState[x];
\r
9102 engineState[x] = engineState[y];
\r
9103 engineState[y] = tmp;
\r
9106 return (byte)(in ^ engineState[(engineState[x] + engineState[y]) & 0xff]);
\r
9109 public void processBytes(
\r
9117 if ((inOff + len) > in.length)
\r
9119 throw new DataLengthException("input buffer too short");
\r
9122 if ((outOff + len) > out.length)
\r
9124 throw new DataLengthException("output buffer too short");
\r
9127 for (int i = 0; i < len ; i++)
\r
9129 x = (x + 1) & 0xff;
\r
9130 y = (engineState[x] + y) & 0xff;
\r
9133 byte tmp = engineState[x];
\r
9134 engineState[x] = engineState[y];
\r
9135 engineState[y] = tmp;
\r
9138 out[i+outOff] = (byte)(in[i + inOff]
\r
9139 ^ engineState[(engineState[x] + engineState[y]) & 0xff]);
\r
9143 public void reset()
\r
9145 setKey(workingKey);
\r
9148 // Private implementation
\r
9150 private void setKey(byte[] keyBytes)
\r
9152 workingKey = keyBytes;
\r
9154 // System.out.println("the key length is ; "+ workingKey.length);
\r
9159 if (engineState == null)
\r
9161 engineState = new byte[STATE_LENGTH];
\r
9164 // reset the state of the engine
\r
9165 for (int i=0; i < STATE_LENGTH; i++)
\r
9167 engineState[i] = (byte)i;
\r
9173 for (int i=0; i < STATE_LENGTH; i++)
\r
9175 i2 = ((keyBytes[i1] & 0xff) + engineState[i] + i2) & 0xff;
\r
9176 // do the byte-swap inline
\r
9177 byte tmp = engineState[i];
\r
9178 engineState[i] = engineState[i2];
\r
9179 engineState[i2] = tmp;
\r
9180 i1 = (i1+1) % keyBytes.length;
\r
9188 * this does your basic RSA algorithm.
9191 implements AsymmetricBlockCipher
9193 private RSAKeyParameters key;
9194 private boolean forEncryption;
9197 * initialise the RSA engine.
9199 * @param forEncryption true if we are encrypting, false otherwise.
9200 * @param param the necessary RSA key parameters.
9203 boolean forEncryption,
9204 CipherParameters param)
9206 this.key = (RSAKeyParameters)param;
9207 this.forEncryption = forEncryption;
9211 * Return the maximum size for an input block to this engine.
9212 * For RSA this is always one byte less than the key size on
9213 * encryption, and the same length as the key size on decryption.
9215 * @return maximum size for an input block.
9217 public int getInputBlockSize()
9219 int bitSize = key.getModulus().bitLength();
9223 return (bitSize + 7) / 8 - 1;
9227 return (bitSize + 7) / 8;
9232 * Return the maximum size for an output block to this engine.
9233 * For RSA this is always one byte less than the key size on
9234 * decryption, and the same length as the key size on encryption.
9236 * @return maximum size for an output block.
9238 public int getOutputBlockSize()
9240 int bitSize = key.getModulus().bitLength();
9244 return (bitSize + 7) / 8;
9248 return (bitSize + 7) / 8 - 1;
9253 * Process a single block using the basic RSA algorithm.
9255 * @param in the input array.
9256 * @param inOff the offset into the input buffer where the data starts.
9257 * @param inLen the length of the data to be processed.
9258 * @return the result of the RSA process.
9259 * @exception DataLengthException the input block is too large.
9261 public byte[] processBlock(
9266 if (inLen > (getInputBlockSize() + 1))
9268 throw new DataLengthException("input too large for RSA cipher.\n");
9270 else if (inLen == (getInputBlockSize() + 1) && (in[inOff] & 0x80) != 0)
9272 throw new DataLengthException("input too large for RSA cipher.\n");
9277 if (inOff != 0 || inLen != in.length)
9279 block = new byte[inLen];
9281 System.arraycopy(in, inOff, block, 0, inLen);
9288 BigInteger input = new BigInteger(1, block);
9291 if (key instanceof RSAPrivateCrtKeyParameters)
9294 // we have the extra factors, use the Chinese Remainder Theorem - the author
9295 // wishes to express his thanks to Dirk Bonekaemper at rtsffm.com for
9296 // advice regarding the expression of this.
9298 RSAPrivateCrtKeyParameters crtKey = (RSAPrivateCrtKeyParameters)key;
9300 BigInteger d = crtKey.getExponent();
9301 BigInteger p = crtKey.getP();
9302 BigInteger q = crtKey.getQ();
9303 BigInteger dP = crtKey.getDP();
9304 BigInteger dQ = crtKey.getDQ();
9305 BigInteger qInv = crtKey.getQInv();
9307 BigInteger mP, mQ, h, m;
9309 // mP = ((input mod p) ^ dP)) mod p
9310 mP = (input.remainder(p)).modPow(dP, p);
9312 // mQ = ((input mod q) ^ dQ)) mod q
9313 mQ = (input.remainder(q)).modPow(dQ, q);
9315 // h = qInv * (mP - mQ) mod p
9316 h = mP.subtract(mQ);
9317 h = h.multiply(qInv);
9318 h = h.mod(p); // mod (in Java) returns the positive residual
9324 output = m.toByteArray();
9328 output = input.modPow(
9329 key.getExponent(), key.getModulus()).toByteArray();
9334 if (output[0] == 0 && output.length > getOutputBlockSize()) // have ended up with an extra zero byte, copy down.
9336 byte[] tmp = new byte[output.length - 1];
9338 System.arraycopy(output, 1, tmp, 0, tmp.length);
9343 if (output.length < getOutputBlockSize()) // have ended up with less bytes than normal, lengthen
9345 byte[] tmp = new byte[getOutputBlockSize()];
9347 System.arraycopy(output, 0, tmp, tmp.length - output.length, output.length);
9354 if (output[0] == 0) // have ended up with an extra zero byte, copy down.
9356 byte[] tmp = new byte[output.length - 1];
9358 System.arraycopy(output, 1, tmp, 0, tmp.length);
9368 * this exception is thrown whenever we find something we don't expect in a
9371 class InvalidCipherTextException
9372 extends CryptoException
9377 public InvalidCipherTextException()
9382 * create a InvalidCipherTextException with the given message.
9384 * @param message the message to be carried with the exception.
9386 public InvalidCipherTextException(
9395 class DigestInputStream
9396 extends FilterInputStream
9398 protected Digest digest;
9400 public DigestInputStream(
9405 this.digest = digest;
9415 digest.update((byte)b);
9426 int n = in.read(b, off, len);
9429 digest.update(b, off, n);
9434 public Digest getDigest()
9442 class DigestOutputStream
9443 extends FilterOutputStream
9445 protected Digest digest;
9447 public DigestOutputStream(
9448 OutputStream stream,
9452 this.digest = digest;
9455 public void write(int b)
9458 digest.update((byte)b);
9468 digest.update(b, off, len);
9469 out.write(b, off, len);
9472 public Digest getDigest()
9480 * The base class for parameters to key generators.
9482 class KeyGenerationParameters
9484 private Random random;
9485 private int strength;
9488 * initialise the generator with a source of randomness
9489 * and a strength (in bits).
9491 * @param random the random byte source.
9492 * @param strength the size, in bits, of the keys we want to produce.
9494 public KeyGenerationParameters(
9498 this.random = random;
9499 this.strength = strength;
9503 * return the random source associated with this
9506 * @return the generators random source.
9508 public Random getRandom()
9514 * return the bit strength for keys produced by this generator,
9516 * @return the strength of the keys this generator produces (in bits).
9518 public int getStrength()
9525 class AsymmetricKeyParameter
9526 implements CipherParameters
9530 public AsymmetricKeyParameter(
9533 this.privateKey = privateKey;
9536 public boolean isPrivate()
9544 implements CipherParameters
9548 public KeyParameter(
9551 this(key, 0, key.length);
9554 public KeyParameter(
9559 this.key = new byte[keyLen];
9561 System.arraycopy(key, keyOff, this.key, 0, keyLen);
9564 public byte[] getKey()
9572 class ParametersWithRandom
9573 implements CipherParameters
9575 private Random random;
9576 private CipherParameters parameters;
9578 public ParametersWithRandom(
9579 CipherParameters parameters,
9582 this.random = random;
9583 this.parameters = parameters;
9586 public ParametersWithRandom(
9587 CipherParameters parameters)
9590 this.parameters = parameters;
9593 public Random getRandom()
9597 random = new Random();
9602 public CipherParameters getParameters()
9610 class RSAKeyParameters
9611 extends AsymmetricKeyParameter
9613 private BigInteger modulus;
9614 private BigInteger exponent;
9616 public RSAKeyParameters(
9619 BigInteger exponent)
9623 this.modulus = modulus;
9624 this.exponent = exponent;
9627 public BigInteger getModulus()
9632 public BigInteger getExponent()
9639 class RSAPrivateCrtKeyParameters
9640 extends RSAKeyParameters
9642 private BigInteger e;
9643 private BigInteger p;
9644 private BigInteger q;
9645 private BigInteger dP;
9646 private BigInteger dQ;
9647 private BigInteger qInv;
9652 public RSAPrivateCrtKeyParameters(
9654 BigInteger publicExponent,
9655 BigInteger privateExponent,
9662 super(true, modulus, privateExponent);
9664 this.e = publicExponent;
9672 public BigInteger getPublicExponent()
9677 public BigInteger getP()
9682 public BigInteger getQ()
9687 public BigInteger getDP()
9692 public BigInteger getDQ()
9697 public BigInteger getQInv()
9704 * the foundation class for the exceptions thrown by the crypto packages.
9706 class RuntimeCryptoException
9707 extends RuntimeException
9712 public RuntimeCryptoException()
9717 * create a RuntimeCryptoException with the given message.
9719 * @param message the message to be carried with the exception.
9721 public RuntimeCryptoException(
9729 * a wrapper for block ciphers with a single byte block size, so that they
9730 * can be treated like stream ciphers.
9732 class StreamBlockCipher
9733 implements StreamCipher
9735 private BlockCipher cipher;
9737 private byte[] oneByte = new byte[1];
9740 * basic constructor.
9742 * @param cipher the block cipher to be wrapped.
9743 * @exception IllegalArgumentException if the cipher has a block size other than
9746 public StreamBlockCipher(
9749 if (cipher.getBlockSize() != 1)
9751 throw new IllegalArgumentException("block cipher block size != 1.");
9754 this.cipher = cipher;
9758 * initialise the underlying cipher.
9760 * @param forEncryption true if we are setting up for encryption, false otherwise.
9761 * @param param the necessary parameters for the underlying cipher to be initialised.
9764 boolean forEncryption,
9765 CipherParameters params)
9767 cipher.init(forEncryption, params);
9771 * return the name of the algorithm we are wrapping.
9773 * @return the name of the algorithm we are wrapping.
9775 public String getAlgorithmName()
9777 return cipher.getAlgorithmName();
9781 * encrypt/decrypt a single byte returning the result.
9783 * @param in the byte to be processed.
9784 * @return the result of processing the input byte.
9786 public byte returnByte(
9791 cipher.processBlock(oneByte, 0, oneByte, 0);
9797 * process a block of bytes from in putting the result into out.
9799 * @param in the input byte array.
9800 * @param inOff the offset into the in array where the data to be processed starts.
9801 * @param len the number of bytes to be processed.
9802 * @param out the output buffer the processed bytes go into.
9803 * @param outOff the offset into the output byte array the processed data stars at.
9804 * @exception DataLengthException if the output buffer is too small.
9806 public void processBytes(
9812 throws DataLengthException
9814 if (outOff + len > out.length)
9816 throw new DataLengthException("output buffer too small in processBytes()");
9819 for (int i = 0; i != len; i++)
9821 cipher.processBlock(in, inOff + i, out, outOff + i);
9826 * reset the underlying cipher. This leaves it in the same state
9827 * it was at after the last init (if there was one).
9836 * the interface stream ciphers conform to.
9838 interface StreamCipher
9841 * Initialise the cipher.
9843 * @param forEncryption if true the cipher is initialised for
9844 * encryption, if false for decryption.
9845 * @param param the key and other data required by the cipher.
9846 * @exception IllegalArgumentException if the params argument is
9849 public void init(boolean forEncryption, CipherParameters params)
9850 throws IllegalArgumentException;
9853 * Return the name of the algorithm the cipher implements.
9855 * @return the name of the algorithm the cipher implements.
9857 public String getAlgorithmName();
9860 * encrypt/decrypt a single byte returning the result.
9862 * @param in the byte to be processed.
9863 * @return the result of processing the input byte.
9865 public byte returnByte(byte in);
9868 * process a block of bytes from in putting the result into out.
9870 * @param in the input byte array.
9871 * @param inOff the offset into the in array where the data to be processed starts.
9872 * @param len the number of bytes to be processed.
9873 * @param out the output buffer the processed bytes go into.
9874 * @param outOff the offset into the output byte array the processed data stars at.
9875 * @exception DataLengthException if the output buffer is too small.
9877 public void processBytes(byte[] in, int inOff, int len, byte[] out, int outOff)
9878 throws DataLengthException;
9881 * reset the cipher. This leaves it in the same state
9882 * it was at after the last init (if there was one).
9884 public void reset();
9889 private static final byte[] encodingTable =
9891 (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G',
9892 (byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N',
9893 (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U',
9894 (byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z',
9895 (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g',
9896 (byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n',
9897 (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u',
9899 (byte)'w', (byte)'x', (byte)'y', (byte)'z',
9900 (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6',
9901 (byte)'7', (byte)'8', (byte)'9',
9902 (byte)'+', (byte)'/'
9906 * encode the input data producong a base 64 encoded byte array.
9908 * @return a byte array containing the base 64 encoded data.
9910 public static byte[] encode(
9915 int modulus = data.length % 3;
9918 bytes = new byte[4 * data.length / 3];
9922 bytes = new byte[4 * ((data.length / 3) + 1)];
9925 int dataLength = (data.length - modulus);
9927 for (int i = 0, j = 0; i < dataLength; i += 3, j += 4)
9929 a1 = data[i] & 0xff;
9930 a2 = data[i + 1] & 0xff;
9931 a3 = data[i + 2] & 0xff;
9933 bytes[j] = encodingTable[(a1 >>> 2) & 0x3f];
9934 bytes[j + 1] = encodingTable[((a1 << 4) | (a2 >>> 4)) & 0x3f];
9935 bytes[j + 2] = encodingTable[((a2 << 2) | (a3 >>> 6)) & 0x3f];
9936 bytes[j + 3] = encodingTable[a3 & 0x3f];
9940 * process the tail end.
9947 case 0: /* nothing left to do */
9950 d1 = data[data.length - 1] & 0xff;
9951 b1 = (d1 >>> 2) & 0x3f;
9952 b2 = (d1 << 4) & 0x3f;
9954 bytes[bytes.length - 4] = encodingTable[b1];
9955 bytes[bytes.length - 3] = encodingTable[b2];
9956 bytes[bytes.length - 2] = (byte)'=';
9957 bytes[bytes.length - 1] = (byte)'=';
9960 d1 = data[data.length - 2] & 0xff;
9961 d2 = data[data.length - 1] & 0xff;
9963 b1 = (d1 >>> 2) & 0x3f;
9964 b2 = ((d1 << 4) | (d2 >>> 4)) & 0x3f;
9965 b3 = (d2 << 2) & 0x3f;
9967 bytes[bytes.length - 4] = encodingTable[b1];
9968 bytes[bytes.length - 3] = encodingTable[b2];
9969 bytes[bytes.length - 2] = encodingTable[b3];
9970 bytes[bytes.length - 1] = (byte)'=';
9978 * set up the decoding table.
9980 private static final byte[] decodingTable;
9984 decodingTable = new byte[128];
9986 for (int i = 'A'; i <= 'Z'; i++)
9988 decodingTable[i] = (byte)(i - 'A');
9991 for (int i = 'a'; i <= 'z'; i++)
9993 decodingTable[i] = (byte)(i - 'a' + 26);
9996 for (int i = '0'; i <= '9'; i++)
9998 decodingTable[i] = (byte)(i - '0' + 52);
10001 decodingTable['+'] = 62;
10002 decodingTable['/'] = 63;
10006 * decode the base 64 encoded input data.
10008 * @return a byte array representing the decoded data.
10010 public static byte[] decode(
10014 byte b1, b2, b3, b4;
10016 if (data[data.length - 2] == '=')
10018 bytes = new byte[(((data.length / 4) - 1) * 3) + 1];
10020 else if (data[data.length - 1] == '=')
10022 bytes = new byte[(((data.length / 4) - 1) * 3) + 2];
10026 bytes = new byte[((data.length / 4) * 3)];
10029 for (int i = 0, j = 0; i < data.length - 4; i += 4, j += 3)
10031 b1 = decodingTable[data[i]];
10032 b2 = decodingTable[data[i + 1]];
10033 b3 = decodingTable[data[i + 2]];
10034 b4 = decodingTable[data[i + 3]];
10036 bytes[j] = (byte)((b1 << 2) | (b2 >> 4));
10037 bytes[j + 1] = (byte)((b2 << 4) | (b3 >> 2));
10038 bytes[j + 2] = (byte)((b3 << 6) | b4);
10041 if (data[data.length - 2] == '=')
10043 b1 = decodingTable[data[data.length - 4]];
10044 b2 = decodingTable[data[data.length - 3]];
10046 bytes[bytes.length - 1] = (byte)((b1 << 2) | (b2 >> 4));
10048 else if (data[data.length - 1] == '=')
10050 b1 = decodingTable[data[data.length - 4]];
10051 b2 = decodingTable[data[data.length - 3]];
10052 b3 = decodingTable[data[data.length - 2]];
10054 bytes[bytes.length - 2] = (byte)((b1 << 2) | (b2 >> 4));
10055 bytes[bytes.length - 1] = (byte)((b2 << 4) | (b3 >> 2));
10059 b1 = decodingTable[data[data.length - 4]];
10060 b2 = decodingTable[data[data.length - 3]];
10061 b3 = decodingTable[data[data.length - 2]];
10062 b4 = decodingTable[data[data.length - 1]];
10064 bytes[bytes.length - 3] = (byte)((b1 << 2) | (b2 >> 4));
10065 bytes[bytes.length - 2] = (byte)((b2 << 4) | (b3 >> 2));
10066 bytes[bytes.length - 1] = (byte)((b3 << 6) | b4);
10073 * decode the base 64 encoded String data.
10075 * @return a byte array representing the decoded data.
10077 public static byte[] decode(
10081 byte b1, b2, b3, b4;
10083 if (data.charAt(data.length() - 2) == '=')
10085 bytes = new byte[(((data.length() / 4) - 1) * 3) + 1];
10087 else if (data.charAt(data.length() - 1) == '=')
10089 bytes = new byte[(((data.length() / 4) - 1) * 3) + 2];
10093 bytes = new byte[((data.length() / 4) * 3)];
10096 for (int i = 0, j = 0; i < data.length() - 4; i += 4, j += 3)
10098 b1 = decodingTable[data.charAt(i)];
10099 b2 = decodingTable[data.charAt(i + 1)];
10100 b3 = decodingTable[data.charAt(i + 2)];
10101 b4 = decodingTable[data.charAt(i + 3)];
10103 bytes[j] = (byte)((b1 << 2) | (b2 >> 4));
10104 bytes[j + 1] = (byte)((b2 << 4) | (b3 >> 2));
10105 bytes[j + 2] = (byte)((b3 << 6) | b4);
10108 if (data.charAt(data.length() - 2) == '=')
10110 b1 = decodingTable[data.charAt(data.length() - 4)];
10111 b2 = decodingTable[data.charAt(data.length() - 3)];
10113 bytes[bytes.length - 1] = (byte)((b1 << 2) | (b2 >> 4));
10115 else if (data.charAt(data.length() - 1) == '=')
10117 b1 = decodingTable[data.charAt(data.length() - 4)];
10118 b2 = decodingTable[data.charAt(data.length() - 3)];
10119 b3 = decodingTable[data.charAt(data.length() - 2)];
10121 bytes[bytes.length - 2] = (byte)((b1 << 2) | (b2 >> 4));
10122 bytes[bytes.length - 1] = (byte)((b2 << 4) | (b3 >> 2));
10126 b1 = decodingTable[data.charAt(data.length() - 4)];
10127 b2 = decodingTable[data.charAt(data.length() - 3)];
10128 b3 = decodingTable[data.charAt(data.length() - 2)];
10129 b4 = decodingTable[data.charAt(data.length() - 1)];
10131 bytes[bytes.length - 3] = (byte)((b1 << 2) | (b2 >> 4));
10132 bytes[bytes.length - 2] = (byte)((b2 << 4) | (b3 >> 2));
10133 bytes[bytes.length - 1] = (byte)((b3 << 6) | b4);