001: /*
002: * Title: Oyster Project
003: * Description: S/MIME email sending capabilities
004: * @Author Vladimir Radisic
005: * @Version 2.1.6
006: */
007:
008: package org.enhydra.oyster.der;
009:
010: import org.enhydra.oyster.exception.SMIMEException;
011: import org.enhydra.oyster.exception.ErrorStorage;
012:
013: /**
014: * DERObjectIdentifier is primitive type of DER encoded object which represents
015: * Object Identifier type in ASN.1 notation. A value (distinguishable from all
016: * other such values) which is associated with an information object. For
017: * example object identifier for RSA algorithm is 1.2.840.113549.1.1.1.
018: * Implemented object identifiers are stored in class IdentifierStorage.
019: */
020: public class DERObjectIdentifier extends DERObject {
021:
022: /**
023: * This constructor has two different forms, depend on parameter typeConstruction0,
024: * which can be: DOT_SEPARATED_ARRAY or NAME_STRING. If typeConstruction0 parameter
025: * is DOT_SEPARATED_ARRAY then id0 definition is represented by numbers separated
026: * with dots (example: "1.2.840.113549.1.1.1"). In the case of NAME_STRING, id0
027: * definition is name of object identifier (example: "RSA").
028: * @param id0 defines Object Identifier in representation determined by the
029: * second parameter - typeConstruction0.
030: * @param typeConstruction0 can take values DOT_SEPARATED_ARRAY and NAME_STRING
031: * @exception SMIMEException if wrong type of parameters are passed to the
032: * constructor. Also, exception could be thrown in super class constructor or
033: * in super class addContent method.
034: */
035: public DERObjectIdentifier(String id0, String typeConstruction0)
036: throws SMIMEException {
037: super (6);
038: byte[] contentID; // For storing content of ID identifiers byte string
039: if (typeConstruction0.equalsIgnoreCase("DOT_SEPARATED_ARRAY")) // Construction with dot separated string of numbers
040: {
041: int[] temp;
042: int[] dotPosition;
043: int j = -1, i = 0;
044: do // Counting number of dots to find out how many integers will contain Object Identificator string
045: {
046: j = id0.indexOf('.', j + 1);
047: i++;
048: } while (j != -1);
049: if (i == 1)
050: throw new SMIMEException(1008);
051: temp = new int[i];
052: dotPosition = new int[i - 1];
053: i = 0;
054: j = -1;
055: do // Filling dot position
056: {
057: j = id0.indexOf('.', j + 1);
058: if (j != -1)
059: dotPosition[i] = j;
060: i++;
061: } while (j != -1);
062: temp[0] = Integer.decode(id0.substring(0, dotPosition[0]))
063: .intValue(); // First number in Identificator object string
064: temp[temp.length - 1] = Integer
065: .decode(
066: id0
067: .substring(dotPosition[dotPosition.length - 1] + 1))
068: .intValue(); // Last number in Identificator object string
069: for (i = 1; i != temp.length - 1; i++)
070: temp[i] = Integer.decode(
071: id0.substring(dotPosition[i - 1] + 1,
072: dotPosition[i])).intValue(); // Numbers between first and last number in Identificator object string
073: contentID = formatID(temp);
074: super .addContent(contentID); // Formating DER value of Object identificator
075: } else if (typeConstruction0.equalsIgnoreCase("NAME_STRING")) {
076: contentID = formatID(IdentifierStorage.getID(id0
077: .toUpperCase()));
078: super .addContent(contentID); // Formating DER value of Object identificator
079: } else
080: throw new SMIMEException(1009);
081: }
082:
083: /**
084: * Array of numbers is used for construction of DERObjectIdentifier. Every number in
085: * array represents one number between dots in the object identifier string.
086: * @param arrayID0 array of given numbers (example: for RSA algorithm those
087: * numbers are 1, 2, 840, 113549, 1, 1, and 1).
088: * @exception SMIMEException if wrong type of parameters are passed to the
089: * constructor. Also, exception could be thrown in super class constructor or
090: * in super class addContent method.
091: */
092: public DERObjectIdentifier(int[] arrayID0) throws SMIMEException {
093: super (6);
094: super .addContent(formatID(arrayID0));
095: }
096:
097: /**
098: * Creats Object Identifier octet string from discret number identifiers
099: * @param id0 array of defined numbers for defined Object Identifier
100: * @return Byte array representation of the DER encoded content of the Object
101: * Identifier
102: * @exception SMIMEException in case that unknown type of object identifier is
103: * submited to constructors dealing with DOT_SEPARATED_ARRAY and NAME_STRING.
104: * Also, it can be caused by non SMIMEException which is:
105: * UnsupportedEncodingException.
106: */
107: private byte[] formatID(int[] id0) throws SMIMEException {
108: int[] temp = new int[id0.length - 1];
109: String s = new String();
110: byte[] returnByteArray = null;
111: if (id0[0] == -1)
112: throw new SMIMEException(1010);
113: temp[0] = 40 * id0[0] + id0[1]; // First byte is constructed from the first and second discret numbers (that`s a rule)
114: for (int i = 2; i != id0.length; i++)
115: temp[i - 1] = id0[i];
116: try {
117: for (int i = 0; i != temp.length; i++) {
118: int j = 1; // j: Number of required bits for particular element of array "temp"
119: for (int a = 1; (a * 2) <= temp[i]; j++)
120: // Counting number of required bits
121: a = a * 2;
122: j = (int) Math.ceil((double) j / 7); // j: Number of required bytes for particular element of array "temp"
123: byte[] tempElement = new byte[j];
124: for (j = tempElement.length - 1; j >= 0; j--) {
125: tempElement[j] = (byte) ((temp[i] >> (7 * (tempElement.length - 1 - j))) & 0x7F);
126: if (j != (tempElement.length - 1))
127: tempElement[j] = (byte) (tempElement[j] | (0x80));
128: }
129: s = s.concat(new String(tempElement, "ISO-8859-1"));
130: }
131: returnByteArray = s.getBytes("ISO-8859-1");
132: } catch (Exception e) {
133: throw new SMIMEException(e);
134: }
135: return returnByteArray;
136: }
137: }
|