// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package netscape.security.pkcs; import java.io.IOException; import java.io.OutputStream; import java.security.cert.CertificateException; import java.util.Date; import java.util.Hashtable; import netscape.security.util.DerEncoder; import netscape.security.util.DerInputStream; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; import netscape.security.util.ObjectIdentifier; import netscape.security.x509.CertificateExtensions; /** * Class supporting any PKCS9 attribute except * ExtendedCertificateAttribute. Supports DER decoding and access to * attribute values, but not DER encoding or setting of values. * * @version 1.2 97/12/10 * @author Douglas Hoover */ public class PKCS9Attribute implements DerEncoder { /* * OIDs of PKCS #9 attribute types. */ private static final String RSADSI_str = "1.2.840.113549"; private static final String PKCS_str = RSADSI_str + ".1"; private static final String PKCS9_str = PKCS_str + ".9"; /** * Array of attribute OIDs defined in PKCS9, by number. */ static final ObjectIdentifier[] PKCS9_OIDS = //new ObjectIdentifier[10]; // There are some Obsolete(?) attribute identifiers. // This is mainly for extensionRequest (14) in pkcs10. // We just add the other 4 as by products. new ObjectIdentifier[15]; static { // static initializer for PKCS9_OIDS for (int i = 1; i < PKCS9_OIDS.length; i++) { PKCS9_OIDS[i] = new ObjectIdentifier(PKCS9_str + "." + i); } } public static final ObjectIdentifier EMAIL_ADDRESS_OID = PKCS9_OIDS[1]; public static final ObjectIdentifier UNSTRUCTURED_NAME_OID = PKCS9_OIDS[2]; public static final ObjectIdentifier CONTENT_TYPE_OID = PKCS9_OIDS[3]; public static final ObjectIdentifier MESSAGE_DIGEST_OID = PKCS9_OIDS[4]; public static final ObjectIdentifier SIGNING_TIME_OID = PKCS9_OIDS[5]; public static final ObjectIdentifier COUNTERSIGNATURE_OID = PKCS9_OIDS[6]; public static final ObjectIdentifier CHALLENGE_PASSWORD_OID = PKCS9_OIDS[7]; public static final ObjectIdentifier UNSTRUCTURED_ADDRESS_OID = PKCS9_OIDS[8]; public static final ObjectIdentifier EXTENDED_CERTIFICATE_ATTRIBUTES_OID = PKCS9_OIDS[9]; public static final ObjectIdentifier ISSUER_AND_SERIALNUMBER_OID = PKCS9_OIDS[10]; public static final ObjectIdentifier PASSWORD_CHECK_OID = PKCS9_OIDS[11]; public static final ObjectIdentifier PUBLIC_KEY_OID = PKCS9_OIDS[12]; public static final ObjectIdentifier SIGNING_DESCRIPTION_OID = PKCS9_OIDS[13]; public static final ObjectIdentifier EXTENSION_REQUEST_OID = PKCS9_OIDS[14]; public static final String EMAIL_ADDRESS_STR = "EmailAddress"; public static final String UNSTRUCTURED_NAME_STR = "UnstructuredName"; public static final String CONTENT_TYPE_STR = "ContentType"; public static final String MESSAGE_DIGEST_STR = "MessageDigest"; public static final String SIGNING_TIME_STR = "SigningTime"; public static final String COUNTERSIGNATURE_STR = "Countersignature"; public static final String CHALLENGE_PASSWORD_STR = "ChallengePassword"; public static final String UNSTRUCTURED_ADDRESS_STR = "UnstructuredAddress"; public static final String EXTENDED_CERTIFICATE_ATTRIBUTES_STR = "ExtendedCertificateAttributes"; public static final String ISSUER_AND_SERIALNUMBER_STR = "IssuerAndSerialNumber"; public static final String PASSWORD_CHECK_STR = "PasswordCheck"; public static final String PUBLIC_KEY_STR = "PublicKey"; public static final String SIGNING_DESCRIPTION_STR = "SigningDescription"; public static final String EXTENSION_REQUEST_STR = "ExtensionRequest"; /** * Hashtable mapping names and variant names of supported * attributes to their OIDs. This table contains all name forms * that occur in PKCS9, in lower case. */ private static final Hashtable NAME_OID_TABLE = new Hashtable( 28); static { // static initializer for PCKS9_NAMES NAME_OID_TABLE.put("emailaddress", PKCS9_OIDS[1]); NAME_OID_TABLE.put("unstructuredname", PKCS9_OIDS[2]); NAME_OID_TABLE.put("contenttype", PKCS9_OIDS[3]); NAME_OID_TABLE.put("messagedigest", PKCS9_OIDS[4]); NAME_OID_TABLE.put("signingtime", PKCS9_OIDS[5]); NAME_OID_TABLE.put("countersignature", PKCS9_OIDS[6]); NAME_OID_TABLE.put("challengepassword", PKCS9_OIDS[7]); NAME_OID_TABLE.put("unstructuredaddress", PKCS9_OIDS[8]); NAME_OID_TABLE.put("extendedcertificateattributes", PKCS9_OIDS[9]); NAME_OID_TABLE.put("issuerandserialNumber", PKCS9_OIDS[10]); NAME_OID_TABLE.put("passwordcheck", PKCS9_OIDS[11]); NAME_OID_TABLE.put("publickey", PKCS9_OIDS[12]); NAME_OID_TABLE.put("signingdescription", PKCS9_OIDS[13]); NAME_OID_TABLE.put("extensionrequest", PKCS9_OIDS[14]); }; /** * Hashtable mapping attribute OIDs defined in PKCS9 to the * corresponding attribute value type. */ private static final Hashtable OID_NAME_TABLE = new Hashtable( 14); static { OID_NAME_TABLE.put(PKCS9_OIDS[1], EMAIL_ADDRESS_STR); OID_NAME_TABLE.put(PKCS9_OIDS[2], UNSTRUCTURED_NAME_STR); OID_NAME_TABLE.put(PKCS9_OIDS[3], CONTENT_TYPE_STR); OID_NAME_TABLE.put(PKCS9_OIDS[4], MESSAGE_DIGEST_STR); OID_NAME_TABLE.put(PKCS9_OIDS[5], SIGNING_TIME_STR); OID_NAME_TABLE.put(PKCS9_OIDS[6], COUNTERSIGNATURE_STR); OID_NAME_TABLE.put(PKCS9_OIDS[7], CHALLENGE_PASSWORD_STR); OID_NAME_TABLE.put(PKCS9_OIDS[8], UNSTRUCTURED_ADDRESS_STR); OID_NAME_TABLE.put(PKCS9_OIDS[9], EXTENDED_CERTIFICATE_ATTRIBUTES_STR); OID_NAME_TABLE.put(PKCS9_OIDS[10], ISSUER_AND_SERIALNUMBER_STR); OID_NAME_TABLE.put(PKCS9_OIDS[11], PASSWORD_CHECK_STR); OID_NAME_TABLE.put(PKCS9_OIDS[12], PUBLIC_KEY_STR); OID_NAME_TABLE.put(PKCS9_OIDS[13], SIGNING_DESCRIPTION_STR); OID_NAME_TABLE.put(PKCS9_OIDS[14], EXTENSION_REQUEST_STR); } /** * Acceptable ASN.1 tags for DER encodings of values of PKCS9 * attributes, by index in PKCS9_OIDS. * Sets of acceptable tags are represented as arrays. */ private static final Byte[][] PKCS9_VALUE_TAGS = { null, { Byte.valueOf(DerValue.tag_IA5String) }, // EMailAddress { Byte.valueOf(DerValue.tag_IA5String) }, // UnstructuredName { Byte.valueOf(DerValue.tag_ObjectId) }, // ContentType { Byte.valueOf(DerValue.tag_OctetString) }, // MessageDigest { Byte.valueOf(DerValue.tag_UtcTime) }, // SigningTime { Byte.valueOf(DerValue.tag_Sequence) }, // Countersignature { Byte.valueOf(DerValue.tag_PrintableString), Byte.valueOf(DerValue.tag_T61String) }, // ChallengePassword { Byte.valueOf(DerValue.tag_PrintableString), Byte.valueOf(DerValue.tag_T61String) }, // UnstructuredAddress { Byte.valueOf(DerValue.tag_SetOf) }, // ExtendedCertificateAttributes null, //IssuerAndSerialNumber null, //PasswordCheck null, //PublicKey null, //SigningDescription { Byte.valueOf(DerValue.tag_Sequence) } //ExtensionRequest }; /** * Class types required for values for a given PKCS9 * attribute type. * *

* The following table shows the correspondence between attribute types and value component classes. * *

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
OIDAttribute Type NameKindValue Class
1.2.840.113549.1.9.1EmailAddressMultiple-valuedString[]
1.2.840.113549.1.9.2UnstructuredNameMultiple-valuedString
1.2.840.113549.1.9.3ContentTypeSingle-valuedObjectIdentifier
1.2.840.113549.1.9.4MessageDigestSingle-valuedbyte[]
1.2.840.113549.1.9.5SigningTimeSingle-valuedDate
1.2.840.113549.1.9.6CountersignatureMultiple-valuedSignerInfo
1.2.840.113549.1.9.7ChallengePasswordSingle-valuedString
1.2.840.113549.1.9.8UnstructuredAddressSingle-valuedString
1.2.840.113549.1.9.9ExtendedCertificateAttributesMultiple-valued(not supported)
1.2.840.113549.1.9.10IssuerAndSerialNumberSingle-valued(not supported)
1.2.840.113549.1.9.11PasswordCheckSingle-valued(not supported)
1.2.840.113549.1.9.12PublicKeySingle-valued(not supported)
1.2.840.113549.1.9.13SigningDescriptionSingle-valued(not supported)
1.2.840.113549.1.9.14ExtensionRequestSingle-valuedSequence
*/ private static final Class[] VALUE_CLASSES = new Class[15]; static { VALUE_CLASSES[0] = null; // not used VALUE_CLASSES[1] = String[].class; // EMailAddress VALUE_CLASSES[2] = String[].class; // UnstructuredName VALUE_CLASSES[3] = ObjectIdentifier.class; // ContentType VALUE_CLASSES[4] = byte[].class; // MessageDigest (byte[]) VALUE_CLASSES[5] = Date.class; // SigningTime VALUE_CLASSES[6] = SignerInfo[].class; // Countersignature VALUE_CLASSES[7] = String.class; // ChallengePassword VALUE_CLASSES[8] = String[].class; // UnstructuredAddress VALUE_CLASSES[9] = null; // ExtendedCertificateAttributes VALUE_CLASSES[10] = null; // IssuerAndSerialNumber VALUE_CLASSES[11] = null; // PasswordCheck VALUE_CLASSES[12] = null; // PublicKey VALUE_CLASSES[13] = null; // SigningDescription VALUE_CLASSES[14] = CertificateExtensions.class; // ExtensionRequest } /** * Array indicating which PKCS9 attributes are single-valued, * by index in PKCS9_OIDS. */ private static final boolean[] SINGLE_VALUED = { false, false, // EMailAddress false, // UnstructuredName true, // ContentType true, // MessageDigest true, // SigningTime false, // Countersignature true, // ChallengePassword false, // UnstructuredAddress false, // ExtendedCertificateAttributes true, // IssuerAndSerialNumber true, // PasswordCheck true, // PublicKey true, // SigningDescription true // ExtensionRequest }; /** * The OID of this attribute is PKCS9_OIDS[index]. */ private int index; /** * Value set of this attribute. Its class is given by VALUE_CLASSES[index]. */ private Object value; /** * Construct an attribute object from the attribute's OID and * value. If the attribute is single-valued, provide only one * value. If the attribute is * multiple-valued, provide an array containing all the values. * Arrays of length zero are accepted, though probably useless. * *

* The following table gives the class that value must have for a given attribute. * *

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
OIDAttribute Type NameKindValue Class
1.2.840.113549.1.9.1EmailAddressMultiple-valuedString[]
1.2.840.113549.1.9.2UnstructuredNameMultiple-valuedString[]
1.2.840.113549.1.9.3ContentTypeSingle-valuedObjectIdentifier
1.2.840.113549.1.9.4MessageDigestSingle-valuedbyte[]
1.2.840.113549.1.9.5SigningTimeSingle-valuedDate
1.2.840.113549.1.9.6CountersignatureMultiple-valuedSignerInfo[]
1.2.840.113549.1.9.7ChallengePasswordSingle-valuedString
1.2.840.113549.1.9.8UnstructuredAddressSingle-valuedString[]
1.2.840.113549.1.9.9ExtendedCertificateAttributesMultiple-valued(not supported)
1.2.840.113549.1.9.10IssuerAndSerialNumberSingle-valued(not supported)
1.2.840.113549.1.9.11PasswordCheckSingle-valued(not supported)
1.2.840.113549.1.9.12PublicKeySingle-valued(not supported)
1.2.840.113549.1.9.13SigningDescriptionSingle-valued(not supported)
1.2.840.113549.1.9.14ExtensionRequestSingle-valuedSequence
*/ public PKCS9Attribute(ObjectIdentifier oid, Object value) throws IllegalArgumentException { init(oid, value); } /** * Construct an attribute object from the attribute's name and * value. If the attribute is single-valued, provide only one * value. If the attribute is * multiple-valued, provide an array containing all the values. * Arrays of length zero are accepted, though probably useless. * *

* The following table gives the class that value must have for a given attribute. Reasonable variants * of these attributes are accepted; in particular, case does not matter. * *

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
OIDAttribute Type NameKindValue Class
1.2.840.113549.1.9.1EmailAddressMultiple-valuedString[]
1.2.840.113549.1.9.2UnstructuredNameMultiple-valuedString[]
1.2.840.113549.1.9.3ContentTypeSingle-valuedObjectIdentifier
1.2.840.113549.1.9.4MessageDigestSingle-valuedbyte[]
1.2.840.113549.1.9.5SigningTimeSingle-valuedDate
1.2.840.113549.1.9.6CountersignatureMultiple-valuedSignerInfo[]
1.2.840.113549.1.9.7ChallengePasswordSingle-valuedString
1.2.840.113549.1.9.8UnstructuredAddressSingle-valuedString[]
1.2.840.113549.1.9.9ExtendedCertificateAttributesMultiple-valued(not supported)
1.2.840.113549.1.9.10IssuerAndSerialNumberSingle-valued(not supported)
1.2.840.113549.1.9.11PasswordCheckSingle-valued(not supported)
1.2.840.113549.1.9.12PublicKeySingle-valued(not supported)
1.2.840.113549.1.9.13SigningDescriptionSingle-valued(not supported)
1.2.840.113549.1.9.14ExtensionRequestSingle-valuedSequence
* * @exception IllegalArgumentException * if the name is not recognized of the value has the wrong type. */ public PKCS9Attribute(String name, Object value) throws IllegalArgumentException { ObjectIdentifier oid = getOID(name); if (oid == null) throw new IllegalArgumentException( "Unrecognized attribute name " + name + " constructing PKCS9Attribute."); init(oid, value); } private void init(ObjectIdentifier oid, Object value) throws IllegalArgumentException { index = indexOf(oid, PKCS9_OIDS, 1); if (index == -1) throw new IllegalArgumentException( "Unsupported OID " + oid + " constructing PKCS9Attribute."); if (!VALUE_CLASSES[index].isInstance(value)) throw new IllegalArgumentException( "Wrong value class " + " for attribute " + oid + " constructing PKCS9Attribute; was " + value.getClass().toString() + ", should be " + VALUE_CLASSES[index].toString()); this.value = value; } /** * Construct a PKCS9Attribute from its encoding on an input * stream. * * @exception IOException on parsing error. */ public PKCS9Attribute(DerValue derVal) throws IOException { decode(derVal); } /** * Decode a PKCS9 attribute. * * @param val * the DerValue representing the DER encoding of the attribute. */ private void decode(DerValue derVal) throws IOException { DerInputStream derIn = new DerInputStream(derVal.toByteArray()); DerValue[] val = derIn.getSequence(2); if (derIn.available() != 0) throw new IOException("Excess data parsing PKCS9Attribute"); if (val.length != 2) throw new IOException("PKCS9Attribute doesn't have two components"); DerValue[] elems; // get the oid ObjectIdentifier oid = val[0].getOID(); index = indexOf(oid, PKCS9_OIDS, 1); Byte tag; if (index == -1) throw new IOException("Invalid OID for PKCS9 attribute: " + oid); elems = new DerInputStream(val[1].toByteArray()).getSet(1); // check single valued have only one value if (SINGLE_VALUED[index] && elems.length > 1) throwSingleValuedException(); // check for illegal element tags for (int i = 0; i < elems.length; i++) { tag = Byte.valueOf(elems[i].tag); if (indexOf(tag, PKCS9_VALUE_TAGS[index], 0) == -1) throwTagException(tag); } switch (index) { case 1: // email address case 2: // unstructured name case 8: // unstructured address { // open scope String[] values = new String[elems.length]; for (int i = 0; i < elems.length; i++) values[i] = elems[i].getAsString(); value = values; } // close scope break; case 3: // content type value = elems[0].getOID(); break; case 4: // message digest value = elems[0].getOctetString(); break; case 5: // signing time value = (new DerInputStream(elems[0].toByteArray())).getUTCTime(); break; case 6: // countersignature { // open scope SignerInfo[] values = new SignerInfo[elems.length]; for (int i = 0; i < elems.length; i++) values[i] = new SignerInfo(elems[i].toDerInputStream()); value = values; } // close scope break; case 7: // challenge password value = elems[0].getAsString(); break; case 9: // extended-certificate attribute -- not // supported throw new IOException("PKCS9 extended-certificate " + "attribute not supported."); case 10: // IssuerAndSerialNumber attribute -- not // supported throw new IOException("PKCS9 IssuerAndSerialNumber " + "attribute not supported."); case 11: // passwordCheck attribute -- not // supported throw new IOException("PKCS9 passwordCheck " + "attribute not supported."); case 12: // PublicKey attribute -- not // supported throw new IOException("PKCS9 PublicKey " + "attribute not supported."); case 13: // SigningDescription attribute -- not // supported throw new IOException("PKCS9 SigningDescription " + "attribute not supported."); case 14: // ExtensionRequest attribute value = new CertificateExtensions(elems[0].toDerInputStream()); // break unnecessary default: // can't happen } } /** * Write the DER encoding of this attribute to an output stream. * *

* N.B.: This method always encodes values of ChallengePassword and UnstructuredAddress attributes as ASN.1 * PrintableStrings, without checking whether they should be encoded as T61Strings. */ public void derEncode(OutputStream out) throws IOException { DerOutputStream temp = new DerOutputStream(); temp.putOID(getOID()); switch (index) { case 1: // email address case 2: // unstructured name { // open scope String[] values = (String[]) value; DerOutputStream[] temps = new DerOutputStream[values.length]; for (int i = 0; i < values.length; i++) { temps[i] = new DerOutputStream(); temps[i].putIA5String(values[i]); } temp.putOrderedSetOf(DerValue.tag_Set, temps); } // close scope break; case 3: // content type { DerOutputStream temp2 = new DerOutputStream(); temp2.putOID((ObjectIdentifier) value); temp.write(DerValue.tag_Set, temp2.toByteArray()); } break; case 4: // message digest { DerOutputStream temp2 = new DerOutputStream(); temp2.putOctetString((byte[]) value); temp.write(DerValue.tag_Set, temp2.toByteArray()); } break; case 5: // signing time { DerOutputStream temp2 = new DerOutputStream(); temp2.putUTCTime((Date) value); temp.write(DerValue.tag_Set, temp2.toByteArray()); } break; case 6: // countersignature temp.putOrderedSetOf(DerValue.tag_Set, (DerEncoder[]) value); break; case 7: // challenge password { DerOutputStream temp2 = new DerOutputStream(); temp2.putPrintableString((String) value); temp.write(DerValue.tag_Set, temp2.toByteArray()); } break; case 8: // unstructured address { // open scope String[] values = (String[]) value; DerOutputStream[] temps = new DerOutputStream[values.length]; for (int i = 0; i < values.length; i++) { temps[i] = new DerOutputStream(); temps[i].putPrintableString(values[i]); } temp.putOrderedSetOf(DerValue.tag_Set, temps); } // close scope break; case 9: // extended-certificate attribute -- not // supported throw new IOException("PKCS9 extended-certificate " + "attribute not supported."); case 10: // IssuerAndSerialNumber attribute -- not // supported throw new IOException("PKCS9 IssuerAndSerialNumber " + "attribute not supported."); case 11: // passwordCheck attribute -- not // supported throw new IOException("PKCS9 passwordCheck " + "attribute not supported."); case 12: // PublicKey attribute -- not // supported throw new IOException("PKCS9 PublicKey " + "attribute not supported."); case 13: // SigningDescription attribute -- not // supported throw new IOException("PKCS9 SigningDescription " + "attribute not supported."); case 14: // ExtensionRequest attribute try { DerOutputStream temp2 = new DerOutputStream(); //temp2.putSequence((CertificateExtensions) value); ((CertificateExtensions) value).encode(temp2); temp.write(DerValue.tag_Sequence, temp2.toByteArray()); } catch (CertificateException e) { throw new IOException("PKCS9 extension attributes not encoded"); } // break unnecessary default: // can't happen } DerOutputStream derOut = new DerOutputStream(); derOut.write(DerValue.tag_Sequence, temp.toByteArray()); out.write(derOut.toByteArray()); } /** * Get the value of this attribute. If the attribute is * single-valued, return just the one value. If the attribute is * multiple-valued, return an array containing all the values. * It is possible for this array to be of length 0. * *

* The following table gives the class of the value returned, depending on the type of this attribute. * *

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
OIDAttribute Type NameKindValue Class
1.2.840.113549.1.9.1EmailAddressMultiple-valuedString[]
1.2.840.113549.1.9.2UnstructuredNameMultiple-valuedString[]
1.2.840.113549.1.9.3ContentTypeSingle-valuedObjectIdentifier
1.2.840.113549.1.9.4MessageDigestSingle-valuedbyte[]
1.2.840.113549.1.9.5SigningTimeSingle-valuedDate
1.2.840.113549.1.9.6CountersignatureMultiple-valuedSignerInfo[]
1.2.840.113549.1.9.7ChallengePasswordSingle-valuedString
1.2.840.113549.1.9.8UnstructuredAddressSingle-valuedString[]
1.2.840.113549.1.9.9ExtendedCertificateAttributesMultiple-valued(not supported)
1.2.840.113549.1.9.10IssuerAndSerialNumberSingle-valued(not supported)
1.2.840.113549.1.9.11PasswordCheckSingle-valued(not supported)
1.2.840.113549.1.9.12PublicKeySingle-valued(not supported)
1.2.840.113549.1.9.13SigningDescriptionSingle-valued(not supported)
1.2.840.113549.1.9.14ExtensionRequestSingle-valuedSequence
* */ public Object getValue() { return value; } /** * Show whether this attribute is single-valued. */ public boolean isSingleValued() { return SINGLE_VALUED[index]; } /** * Return the OID of this attribute. */ public ObjectIdentifier getOID() { return PKCS9_OIDS[index]; } /** * Return the name of this attribute. */ public String getName() { return OID_NAME_TABLE.get(PKCS9_OIDS[index]); } /** * Return the OID for a given attribute name or null if we don't recognize * the name. */ public static ObjectIdentifier getOID(String name) { return NAME_OID_TABLE.get(name.toLowerCase()); } /** * Return the attribute name for a given OID or null if we don't recognize * the oid. */ public static String getName(ObjectIdentifier oid) { return OID_NAME_TABLE.get(oid); } /** * Returns a string representation of this attribute. */ public String toString() { StringBuffer buf = new StringBuffer(100); buf.append("["); buf.append(OID_NAME_TABLE.get(PKCS9_OIDS[index])); buf.append(": "); if (SINGLE_VALUED[index]) { if (value instanceof byte[]) { // special case for octet string netscape.security.util.PrettyPrintFormat pp = new netscape.security.util.PrettyPrintFormat(" ", 20); String valuebits = pp.toHexString(((byte[]) value)); buf.append(valuebits); } else { buf.append(value.toString()); } buf.append("]"); return buf.toString(); } else { // multiple-valued boolean first = true; Object[] values = (Object[]) value; for (int j = 0; j < values.length; j++) { if (first) first = false; else buf.append(", "); buf.append(values[j].toString()); } return buf.toString(); } } /** * Beginning the search at start, find the first * index i such that a[i] = obj. * * @return the index, if found, and -1 otherwise. */ static int indexOf(Object obj, Object[] a, int start) { for (int i = start; i < a.length; i++) { if (obj.equals(a[i])) return i; } return -1; } /** * Throw an exception when there are multiple values for * a single-valued attribute. */ private void throwSingleValuedException() throws IOException { throw new IOException("Single-value attribute " + getOID() + " (" + getName() + ")" + " has multiple values."); } /** * Throw an exception when the tag on a value encoding is * wrong for the attribute whose value it is. */ private void throwTagException(Byte tag) throws IOException { Byte[] expectedTags = PKCS9_VALUE_TAGS[index]; StringBuffer msg = new StringBuffer(100); msg.append("Value of attribute "); msg.append(getOID().toString()); msg.append(" ("); msg.append(getName()); msg.append(") has wrong tag: "); msg.append(tag.toString()); msg.append(". Expected tags: "); msg.append(expectedTags[0].toString()); for (int i = 1; i < expectedTags.length; i++) { msg.append(", "); msg.append(expectedTags[i].toString()); } msg.append("."); throw new IOException(msg.toString()); } }