/** * /** The class encapsulates the ASN.1 DER decoding work with PolicyQualifierInfo structure (as * specified in RFC 3280 - Internet X.509 Public Key Infrastructure. Certificate and Certificate * Revocation List (CRL) Profile. http://www.ietf.org/rfc/rfc3280.txt): * * <pre> * PolicyQualifierInfo ::= SEQUENCE { * policyQualifierId PolicyQualifierId, * qualifier ANY DEFINED BY policyQualifierId } * * PolicyQualifierId ::= * OBJECT IDENTIFIER ( id-qt-cps | id-qt-unotice ) * * </pre> */ public final class PolicyQualifierInfo { // Contains only ASN1 DER decoder currently public static final ASN1Sequence ASN1 = new ASN1Sequence(new ASN1Type[] {ASN1Oid.getInstance(), ASN1Any.getInstance()}) {}; }
/** * The class encapsulates the ASN.1 DER encoding/decoding work with the Extension part of X.509 * certificate (as specified in RFC 3280 - Internet X.509 Public Key Infrastructure. Certificate and * Certificate Revocation List (CRL) Profile. http://www.ietf.org/rfc/rfc3280.txt): * * <pre> * Extension ::= SEQUENCE { * extnID OBJECT IDENTIFIER, * critical BOOLEAN DEFAULT FALSE, * extnValue OCTET STRING * } * </pre> */ public final class Extension { // critical constants public static final boolean CRITICAL = true; public static final boolean NON_CRITICAL = false; // constants: the extension OIDs // certificate extensions: static final int[] SUBJ_DIRECTORY_ATTRS = {2, 5, 29, 9}; static final int[] SUBJ_KEY_ID = {2, 5, 29, 14}; static final int[] KEY_USAGE = {2, 5, 29, 15}; static final int[] PRIVATE_KEY_USAGE_PERIOD = {2, 5, 29, 16}; static final int[] SUBJECT_ALT_NAME = {2, 5, 29, 17}; static final int[] ISSUER_ALTERNATIVE_NAME = {2, 5, 29, 18}; static final int[] BASIC_CONSTRAINTS = {2, 5, 29, 19}; static final int[] NAME_CONSTRAINTS = {2, 5, 29, 30}; static final int[] CRL_DISTR_POINTS = {2, 5, 29, 31}; static final int[] CERTIFICATE_POLICIES = {2, 5, 29, 32}; static final int[] POLICY_MAPPINGS = {2, 5, 29, 33}; static final int[] AUTH_KEY_ID = {2, 5, 29, 35}; static final int[] POLICY_CONSTRAINTS = {2, 5, 29, 36}; static final int[] EXTENDED_KEY_USAGE = {2, 5, 29, 37}; static final int[] FRESHEST_CRL = {2, 5, 29, 46}; static final int[] INHIBIT_ANY_POLICY = {2, 5, 29, 54}; static final int[] AUTHORITY_INFO_ACCESS = {1, 3, 6, 1, 5, 5, 7, 1, 1}; static final int[] SUBJECT_INFO_ACCESS = {1, 3, 6, 1, 5, 5, 7, 1, 11}; // crl extensions: static final int[] ISSUING_DISTR_POINT = {2, 5, 29, 28}; // crl entry extensions: static final int[] CRL_NUMBER = {2, 5, 29, 20}; static final int[] CERTIFICATE_ISSUER = {2, 5, 29, 29}; static final int[] INVALIDITY_DATE = {2, 5, 29, 24}; static final int[] REASON_CODE = {2, 5, 29, 21}; static final int[] ISSUING_DISTR_POINTS = {2, 5, 29, 28}; // the value of extnID field of the structure private final int[] extnID; private String extnID_str; // the value of critical field of the structure private final boolean critical; // the value of extnValue field of the structure private final byte[] extnValue; // the ASN.1 encoded form of Extension private byte[] encoding; // the raw (not decoded) value of extnValue field of the structure private byte[] rawExtnValue; // the decoded extension value protected ExtensionValue extnValueObject; // tells whether extension value has been decoded or not private boolean valueDecoded = false; public Extension(String extnID, boolean critical, ExtensionValue extnValueObject) { this.extnID_str = extnID; this.extnID = ObjectIdentifier.toIntArray(extnID); this.critical = critical; this.extnValueObject = extnValueObject; this.valueDecoded = true; this.extnValue = extnValueObject.getEncoded(); } public Extension(String extnID, boolean critical, byte[] extnValue) { this.extnID_str = extnID; this.extnID = ObjectIdentifier.toIntArray(extnID); this.critical = critical; this.extnValue = extnValue; } public Extension(int[] extnID, boolean critical, byte[] extnValue) { this.extnID = extnID; this.critical = critical; this.extnValue = extnValue; } public Extension(String extnID, byte[] extnValue) { this(extnID, NON_CRITICAL, extnValue); } public Extension(int[] extnID, byte[] extnValue) { this(extnID, NON_CRITICAL, extnValue); } private Extension( int[] extnID, boolean critical, byte[] extnValue, byte[] rawExtnValue, byte[] encoding, ExtensionValue decodedExtValue) { this(extnID, critical, extnValue); this.rawExtnValue = rawExtnValue; this.encoding = encoding; this.extnValueObject = decodedExtValue; this.valueDecoded = (decodedExtValue != null); } /** Returns the value of extnID field of the structure. */ public String getExtnID() { if (extnID_str == null) { extnID_str = ObjectIdentifier.toString(extnID); } return extnID_str; } /** Returns the value of critical field of the structure. */ public boolean getCritical() { return critical; } /** Returns the value of extnValue field of the structure. */ public byte[] getExtnValue() { return extnValue; } /** Returns the raw (undecoded octet string) value of extnValue field of the structure. */ public byte[] getRawExtnValue() { if (rawExtnValue == null) { rawExtnValue = ASN1OctetString.getInstance().encode(extnValue); } return rawExtnValue; } /** Returns ASN.1 encoded form of this X.509 Extension value. */ public byte[] getEncoded() { if (encoding == null) { encoding = Extension.ASN1.encode(this); } return encoding; } @Override public boolean equals(Object ext) { if (!(ext instanceof Extension)) { return false; } Extension extension = (Extension) ext; return Arrays.equals(extnID, extension.extnID) && (critical == extension.critical) && Arrays.equals(extnValue, extension.extnValue); } @Override public int hashCode() { return (Arrays.hashCode(extnID) * 37 + (critical ? 1 : 0)) * 37 + Arrays.hashCode(extnValue); } public ExtensionValue getDecodedExtensionValue() throws IOException { if (!valueDecoded) { decodeExtensionValue(); } return extnValueObject; } public KeyUsage getKeyUsageValue() { if (!valueDecoded) { try { decodeExtensionValue(); } catch (IOException ignored) { } } if (extnValueObject instanceof KeyUsage) { return (KeyUsage) extnValueObject; } else { return null; } } public BasicConstraints getBasicConstraintsValue() { if (!valueDecoded) { try { decodeExtensionValue(); } catch (IOException ignored) { } } if (extnValueObject instanceof BasicConstraints) { return (BasicConstraints) extnValueObject; } else { return null; } } private void decodeExtensionValue() throws IOException { if (valueDecoded) { return; } valueDecoded = true; if (Arrays.equals(extnID, SUBJ_KEY_ID)) { extnValueObject = SubjectKeyIdentifier.decode(extnValue); } else if (Arrays.equals(extnID, KEY_USAGE)) { extnValueObject = new KeyUsage(extnValue); } else if (Arrays.equals(extnID, SUBJECT_ALT_NAME)) { extnValueObject = new AlternativeName(AlternativeName.SUBJECT, extnValue); } else if (Arrays.equals(extnID, ISSUER_ALTERNATIVE_NAME)) { extnValueObject = new AlternativeName(AlternativeName.SUBJECT, extnValue); } else if (Arrays.equals(extnID, BASIC_CONSTRAINTS)) { extnValueObject = new BasicConstraints(extnValue); } else if (Arrays.equals(extnID, NAME_CONSTRAINTS)) { extnValueObject = NameConstraints.decode(extnValue); } else if (Arrays.equals(extnID, CERTIFICATE_POLICIES)) { extnValueObject = CertificatePolicies.decode(extnValue); } else if (Arrays.equals(extnID, AUTH_KEY_ID)) { extnValueObject = AuthorityKeyIdentifier.decode(extnValue); } else if (Arrays.equals(extnID, POLICY_CONSTRAINTS)) { extnValueObject = new PolicyConstraints(extnValue); } else if (Arrays.equals(extnID, EXTENDED_KEY_USAGE)) { extnValueObject = new ExtendedKeyUsage(extnValue); } else if (Arrays.equals(extnID, INHIBIT_ANY_POLICY)) { extnValueObject = new InhibitAnyPolicy(extnValue); } else if (Arrays.equals(extnID, CERTIFICATE_ISSUER)) { extnValueObject = new CertificateIssuer(extnValue); } else if (Arrays.equals(extnID, CRL_DISTR_POINTS)) { extnValueObject = CRLDistributionPoints.decode(extnValue); } else if (Arrays.equals(extnID, CERTIFICATE_ISSUER)) { extnValueObject = new ReasonCode(extnValue); } else if (Arrays.equals(extnID, INVALIDITY_DATE)) { extnValueObject = new InvalidityDate(extnValue); } else if (Arrays.equals(extnID, REASON_CODE)) { extnValueObject = new ReasonCode(extnValue); } else if (Arrays.equals(extnID, CRL_NUMBER)) { extnValueObject = new CRLNumber(extnValue); } else if (Arrays.equals(extnID, ISSUING_DISTR_POINTS)) { extnValueObject = IssuingDistributionPoint.decode(extnValue); } else if (Arrays.equals(extnID, AUTHORITY_INFO_ACCESS)) { extnValueObject = InfoAccessSyntax.decode(extnValue); } else if (Arrays.equals(extnID, SUBJECT_INFO_ACCESS)) { extnValueObject = InfoAccessSyntax.decode(extnValue); } } public void dumpValue(StringBuilder sb, String prefix) { sb.append("OID: ").append(getExtnID()).append(", Critical: ").append(critical).append('\n'); if (!valueDecoded) { try { decodeExtensionValue(); } catch (IOException ignored) { } } if (extnValueObject != null) { extnValueObject.dumpValue(sb, prefix); return; } // else: dump unparsed hex representation sb.append(prefix); if (Arrays.equals(extnID, SUBJ_DIRECTORY_ATTRS)) { sb.append("Subject Directory Attributes Extension"); } else if (Arrays.equals(extnID, SUBJ_KEY_ID)) { sb.append("Subject Key Identifier Extension"); } else if (Arrays.equals(extnID, KEY_USAGE)) { sb.append("Key Usage Extension"); } else if (Arrays.equals(extnID, PRIVATE_KEY_USAGE_PERIOD)) { sb.append("Private Key Usage Period Extension"); } else if (Arrays.equals(extnID, SUBJECT_ALT_NAME)) { sb.append("Subject Alternative Name Extension"); } else if (Arrays.equals(extnID, ISSUER_ALTERNATIVE_NAME)) { sb.append("Issuer Alternative Name Extension"); } else if (Arrays.equals(extnID, BASIC_CONSTRAINTS)) { sb.append("Basic Constraints Extension"); } else if (Arrays.equals(extnID, NAME_CONSTRAINTS)) { sb.append("Name Constraints Extension"); } else if (Arrays.equals(extnID, CRL_DISTR_POINTS)) { sb.append("CRL Distribution Points Extension"); } else if (Arrays.equals(extnID, CERTIFICATE_POLICIES)) { sb.append("Certificate Policies Extension"); } else if (Arrays.equals(extnID, POLICY_MAPPINGS)) { sb.append("Policy Mappings Extension"); } else if (Arrays.equals(extnID, AUTH_KEY_ID)) { sb.append("Authority Key Identifier Extension"); } else if (Arrays.equals(extnID, POLICY_CONSTRAINTS)) { sb.append("Policy Constraints Extension"); } else if (Arrays.equals(extnID, EXTENDED_KEY_USAGE)) { sb.append("Extended Key Usage Extension"); } else if (Arrays.equals(extnID, INHIBIT_ANY_POLICY)) { sb.append("Inhibit Any-Policy Extension"); } else if (Arrays.equals(extnID, AUTHORITY_INFO_ACCESS)) { sb.append("Authority Information Access Extension"); } else if (Arrays.equals(extnID, SUBJECT_INFO_ACCESS)) { sb.append("Subject Information Access Extension"); } else if (Arrays.equals(extnID, INVALIDITY_DATE)) { sb.append("Invalidity Date Extension"); } else if (Arrays.equals(extnID, CRL_NUMBER)) { sb.append("CRL Number Extension"); } else if (Arrays.equals(extnID, REASON_CODE)) { sb.append("Reason Code Extension"); } else { sb.append("Unknown Extension"); } sb.append('\n').append(prefix).append("Unparsed Extension Value:\n"); sb.append(Array.toString(extnValue, prefix)); } /** X.509 Extension encoder/decoder. */ public static final ASN1Sequence ASN1 = new ASN1Sequence( new ASN1Type[] { ASN1Oid.getInstance(), ASN1Boolean.getInstance(), new ASN1OctetString() { @Override public Object getDecodedObject(BerInputStream in) throws IOException { // first - decoded octet string, // second - raw encoding of octet string return new Object[] {super.getDecodedObject(in), in.getEncoded()}; } } }) { { setDefault(Boolean.FALSE, 1); } @Override protected Object getDecodedObject(BerInputStream in) throws IOException { Object[] values = (Object[]) in.content; int[] oid = (int[]) values[0]; byte[] extnValue = (byte[]) ((Object[]) values[2])[0]; byte[] rawExtnValue = (byte[]) ((Object[]) values[2])[1]; ExtensionValue decodedExtValue = null; // decode Key Usage and Basic Constraints extension values if (Arrays.equals(oid, KEY_USAGE)) { decodedExtValue = new KeyUsage(extnValue); } else if (Arrays.equals(oid, BASIC_CONSTRAINTS)) { decodedExtValue = new BasicConstraints(extnValue); } return new Extension( (int[]) values[0], (Boolean) values[1], extnValue, rawExtnValue, in.getEncoded(), decodedExtValue); } @Override protected void getValues(Object object, Object[] values) { Extension ext = (Extension) object; values[0] = ext.extnID; values[1] = (ext.critical) ? Boolean.TRUE : Boolean.FALSE; values[2] = ext.extnValue; } }; }
/** * The class encapsulates the ASN.1 DER encoding/decoding work with PolicyInformation structure * which is a subpart of certificatePolicies (as specified in RFC 3280 - Internet X.509 Public Key * Infrastructure. Certificate and Certificate Revocation List (CRL) Profile. * http://www.ietf.org/rfc/rfc3280.txt): * * <pre> * PolicyInformation ::= SEQUENCE { * policyIdentifier CertPolicyId, * policyQualifiers SEQUENCE SIZE (1..MAX) OF * PolicyQualifierInfo OPTIONAL * } * </pre> * * TODO: This class is not fully implemented, implemented only work with OIDs. */ public class PolicyInformation { // the value of policyIdentifier field of the structure private String policyIdentifier; // the ASN.1 encoded form of PolicyInformation private byte[] encoding; /** * TODO * * @param policyIdentifier: String */ public PolicyInformation(String policyIdentifier) { this.policyIdentifier = policyIdentifier; } /** * Returns the value of policyIdentifier field of the structure. * * @return policyIdentifier */ public String getPolicyIdentifier() { return policyIdentifier; } /** * Returns ASN.1 encoded form of this X.509 PolicyInformation value. * * @return a byte array containing ASN.1 encode form. */ public byte[] getEncoded() { if (encoding == null) { encoding = ASN1.encode(this); } return encoding; } /** Places the string representation of extension value into the StringBuffer object. */ public void dumpValue(StringBuffer buffer) { buffer .append("Policy Identifier [") // $NON-NLS-1$ .append(policyIdentifier) .append(']'); } /** ASN.1 DER X.509 PolicyInformation encoder/decoder class. */ public static final ASN1Sequence ASN1 = new ASN1Sequence(new ASN1Type[] {ASN1Oid.getInstance(), ASN1Any.getInstance()}) { { setOptional(1); } protected Object getDecodedObject(BerInputStream in) { Object[] values = (Object[]) in.content; return new PolicyInformation(ObjectIdentifier.toString((int[]) values[0])); } protected void getValues(Object object, Object[] values) { PolicyInformation pi = (PolicyInformation) object; values[0] = ObjectIdentifier.toIntArray(pi.policyIdentifier); } }; }