// --- 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.x509; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.security.cert.CertificateException; import java.util.Enumeration; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; /** * A plain certattr set used by pkcs10 to parse an unknown attribute. * * @author Lily Hsiao */ public class ACertAttrSet implements CertAttrSet { protected DerValue mDerValue = null; public ACertAttrSet(DerValue derValue) throws IOException { mDerValue = derValue; } public DerValue getDerValue() { return mDerValue; } /** * Returns a short string describing this certificate attribute. * * @return value of this certificate attribute in * printable form. */ public String toString() { return "ACertAttrSet value " + (mDerValue == null ? "null" : "not null"); } /** * Encodes the attribute to the output stream in a format * that can be parsed by the decode method. * * @param out the OutputStream to encode the attribute to. * * @exception CertificateException on encoding or validity errors. * @exception IOException on other errors. */ public void encode(OutputStream out) throws CertificateException, IOException { mDerValue.encode((DerOutputStream) out); } /** * Decodes the attribute in the input stream. * * @param in the InputStream to read the encoded attribute from. * * @exception CertificateException on decoding or validity errors. * @exception IOException on other errors. */ public void decode(InputStream in) throws CertificateException, IOException { throw new IOException("not supported"); } /** * Sets an attribute value within this CertAttrSet. * * @param name the name of the attribute (e.g. "x509.info.key") * @param obj the attribute object. * * @exception CertificateException on attribute handling errors. * @exception IOException on other errors. */ public void set(String name, Object obj) throws CertificateException, IOException { throw new IOException("not supported"); } /** * Gets an attribute value for this CertAttrSet. * * @param name the name of the attribute to return. * * @exception CertificateException on attribute handling errors. * @exception IOException on other errors. */ public Object get(String name) throws CertificateException, IOException { throw new IOException("not supported"); } /** * Deletes an attribute value from this CertAttrSet. * * @param name the name of the attribute to delete. * * @exception CertificateException on attribute handling errors. * @exception IOException on other errors. */ public void delete(String name) throws CertificateException, IOException { throw new IOException("not supported"); } /** * Returns an enumeration of the names of the attributes existing within * this attribute. * * @return an enumeration of the attribute names. */ public Enumeration getAttributeNames() { return null; } /** * Returns the name (identifier) of this CertAttrSet. * * @return the name of this CertAttrSet. */ public String getName() { return "Generic Extension"; } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 9995 Content-Disposition: inline; filename="AVA.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "0c67492c476db781e4c1306331b5d915d14fc37c" // --- 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.x509; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; import java.nio.charset.UnsupportedCharsetException; 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; /** * X.500 Attribute-Value-Assertion (AVA): an attribute, as identified by * some attribute ID, has some particular value. Values are as a rule ASN.1 * printable strings. A conventional set of type IDs is recognized when * parsing (and generating) RFC 1779 syntax strings. * *

* AVAs are components of X.500 relative names. Think of them as being individual fields of a database record. The * attribute ID is how you identify the field, and the value is part of a particular record. * * @see X500Name * @see RDN * @see LdapDNStrConverter * * @version 1.14 * * @author David Brownell * @author Amit Kapoor * @author Hemma Prafullchandra */ // public ... when RDN is public and X.500Names can be // constructed using RDNs, and all three classes are cleaner public final class AVA implements DerEncoder { ObjectIdentifier oid; DerValue value; /** * Constructs an AVA from a Ldap DN string with one AVA component * using the global default LdapDNStrConverter. * * @see LdapDNStrConverter * @param avaString a Ldap DN string with one AVA component. */ public AVA(String avaString) throws IOException { AVA ava; ava = LdapDNStrConverter.getDefault().parseAVA(avaString); oid = ava.getOid(); value = ava.getValue(); } /** * Like AVA(String) with a DER encoding order given for Directory Strings. */ public AVA(String avaString, byte[] tags) throws IOException { AVA ava; ava = LdapDNStrConverter.getDefault().parseAVA(avaString, tags); oid = ava.getOid(); value = ava.getValue(); } /** * Constructs an AVA from a Ldap DN string containing one AVA * component using the specified LdapDNStrConverter. * * @see LdapDNStrConverter * @param avaString a Ldap DN string containing one AVA. * @param ldapDNStrConverter a LdapDNStrConverter */ public AVA(String avaString, LdapDNStrConverter ldapDNStrConverter) throws IOException { AVA ava; ava = ldapDNStrConverter.parseAVA(avaString); oid = ava.getOid(); value = ava.getValue(); } /** * Constructs an AVA from an OID and DerValue. * * @param type an ObjectIdentifier * @param val a DerValue */ public AVA(ObjectIdentifier type, DerValue val) throws IOException { oid = type; value = val; } /** * Constructs an AVA from an input stream of UTF8 bytes that form * a Ldap DN string. Then parse the Ldap DN string using the global * default LdapDNStrConverter.
* Parses an RFC 1779 style AVA string: CN=fee fie foe fum * or perhaps with quotes. Not all defined AVA tags are supported; * of current note are X.400 related ones (PRMD, ADMD, etc). * * This terminates at unescaped AVA separators ("+") or RDN * separators (",", ";"), or DN terminators (">"), and removes * cosmetic whitespace at the end of values. * * @see LdapDNStrConverter * @param in the input stream. */ public AVA(InputStream in) throws IOException { try { // convert from UTF8 bytes to java string then parse it. byte[] buffer = new byte[in.available()]; in.read(buffer); Charset charset = Charset.forName("UTF-8"); CharsetDecoder decoder = charset.newDecoder(); CharBuffer charBuffer = decoder.decode(ByteBuffer.wrap(buffer)); AVA a = LdapDNStrConverter.getDefault().parseAVA(charBuffer.toString()); oid = a.getOid(); value = a.getValue(); } catch (UnsupportedCharsetException e) { throw new IOException("UTF8 encoding not supported", e); } } /** * Constructs an AVA from a Der Input Stream. * * @param in the Der Input Stream. */ public AVA(DerInputStream in) throws IOException { DerValue assertion = in.getDerValue(); /* * Individual attribute value assertions are SEQUENCE of two values. * That'd be a "struct" outside of ASN.1. */ if (assertion.tag != DerValue.tag_Sequence) throw new CertParseError("X500 AVA, not a sequence"); ObjectIdentifier o = assertion.data.getOID(); oid = X500NameAttrMap.getDefault().getOid(o); if (oid == null) { // NSCP #329837 // if this OID is not recongized in our map (table), // it is fine. we just store it as regular OID. oid = o; } value = assertion.data.getDerValue(); if (assertion.data.available() != 0) throw new CertParseError("AVA, extra bytes = " + assertion.data.available()); } // other public methods. /** * Returns true if another AVA has the same OID and DerValue. * * @param other the other AVA. * @return ture iff other AVA has same oid and value. */ public boolean equals(AVA other) { return oid.equals(other.oid) && value.equals(other.value); } /** * Compares the AVA with an Object, returns true if the object is * an AVA and has the same OID and value. * * @param other the other object. * @return true iff other object is an AVA and has same oid and value. */ public boolean equals(Object other) { if (other instanceof AVA) return equals((AVA) other); else return false; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((oid == null) ? 0 : oid.hashCode()); result = prime * result + ((value == null) ? 0 : value.hashCode()); return result; } /** * Encodes the AVA to a Der output stream. * AVAs are encoded as a SEQUENCE of two elements. * * @param out The Der output stream. */ public void encode(DerOutputStream out) throws IOException { derEncode(out); } /** * DER encode this object onto an output stream. * Implements the DerEncoder interface. * * @param out * the output stream on which to write the DER encoding. * * @exception IOException on encoding error. */ public void derEncode(OutputStream out) throws IOException { try (DerOutputStream tmp2 = new DerOutputStream()) { DerOutputStream tmp = new DerOutputStream(); tmp.putOID(oid); value.encode(tmp); tmp2.write(DerValue.tag_Sequence, tmp); out.write(tmp2.toByteArray()); } } /** * Returns a Ldap DN string with one AVA component using * the global default LdapDNStrConverter. * * @return a Ldap DN string * @exception IOException if an error occurs during conversion. * @see LdapDNStrConverter */ public String toLdapDNString() throws IOException { LdapDNStrConverter v = LdapDNStrConverter.getDefault(); return v.encodeAVA(this); } /** * Returns a Ldap DN string with one AVA component using the specified * LdapDNStrConverter. * * @return a Ldap DN string * @param ldapDNStrConverter a Ldap DN String Converter * @exception IOException if an error occurs during the conversion. * @see LdapDNStrConverter */ public String toLdapDNString(LdapDNStrConverter ldapDNStrConverter) throws IOException { return ldapDNStrConverter.encodeAVA(this); } /** * Returns a Ldap DN string with the AVA component using the global * default LdapDNStrConverter, or null if an error occurs in conversion. * * @return a Ldap DN string containing the AVA, or null if an * error occurs in the conversion. */ public String toString() { String s; try { // NOTE that a LdapDNString is returned here to match the // original source from sun. Could also return the raw value // (before Ldap escaping) here. s = toLdapDNString(); } catch (IOException e) { return null; } return s; } /** * Returns the OID in the AVA. * * @return the ObjectIdentifier in this AVA. */ public ObjectIdentifier getOid() { return oid; } /** * Returns the value in this AVA as a DerValue * * @return attribute value in this AVA. */ public DerValue getValue() { return value; } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 3165 Content-Disposition: inline; filename="AVAValueConverter.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "50ccd4d8aed237f8405e5c2f78399fa944e4d7ae" // --- 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.x509; import java.io.IOException; import netscape.security.util.DerValue; /** * Interface for classes that convert a attribute value string to a * DER encoded ASN.1 value and vice versa. * The converters are associated with attribute types, such as * directory string, ia5string, etc. * *

* For example, to convert a string, such as an organization name for the "O" attribute to a DerValue, the "O" attribute * is mapped to the DirStrConverter which is used to convert the organization name to a DER encoded Directory String * which is a DerValue of a ASN.1 PrintableString, T.61String or UniversalString for the organization name. * * @author Lily Hsiao, Slava Galperin at Netscape Communications, Inc. */ public interface AVAValueConverter { /** * Converts a string to a DER encoded attribute value. * * @param valueString An AVA value string not encoded in any form. * * @return A DerValue object. * * @exception IOException if an error occurs during the conversion. */ public DerValue getValue(String valueString) throws IOException; /** * Converts a string to a DER encoded attribute value. * Specify the order of DER tags to use if more than one encoding is * possible. Currently Directory Strings can have different order * for backwards compatibility. By 2003 all should be UTF8String. * * @param valueString An AVA value string not encoded in any form. * * @return A DerValue object. * * @exception IOException if an error occurs during the conversion. */ public DerValue getValue(String valueString, byte[] tags) throws IOException; /** * Converts a BER encoded value to a DER encoded attribute value. * * @param berStream A byte array of the BER encoded AVA value. * @return A DerValue object. */ public DerValue getValue(byte[] berStream) throws IOException; /** * Converts a DER encoded value to a string, not encoded in any form. * * @param avaValue A DerValue object. * * @return A string for the value or null if it can't be converted. * * @exception IOException if an error occurs during the conversion. */ public String getAsString(DerValue avaValue) throws IOException; } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 6672 Content-Disposition: inline; filename="AlgIdDSA.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "3c071cea7ba1171078a1af00159181e06c5a5be6" // --- 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.x509; import java.io.IOException; import java.math.BigInteger; import java.security.ProviderException; import java.security.interfaces.DSAParams; import netscape.security.util.BigInt; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; /** * This class identifies DSS/DSA Algorithm variants, which are distinguished * by using different algorithm parameters P, Q, G. It uses the * NIST/IETF standard DER encoding. These are used to implement the Digital * Signature Standard (DSS), FIPS 186. * *

* NOTE: At this time, DSS/DSA Algorithm IDs must always * include these parameters. Use of DSS/DSA in modes where parameters are * either implicit (e.g. a default applicable to a site or a larger scope), * or are derived from some Certificate Authority's DSS certificate, is * not currently supported. * * @version 1.31 * @author David Brownell */ public final class AlgIdDSA extends AlgorithmId implements DSAParams { /** * */ private static final long serialVersionUID = 5978220691806461631L; /* * The three unsigned integer parameters. */ private BigInteger p, q, g; /** Returns the DSS/DSA parameter "P" */ public BigInteger getP() { return p; } /** Returns the DSS/DSA parameter "Q" */ public BigInteger getQ() { return q; } /** Returns the DSS/DSA parameter "G" */ public BigInteger getG() { return g; } AlgIdDSA(DerValue val) throws IOException { super(val.getOID()); } /** * Construct an AlgIdDSA from an X.509 encoded byte array. */ public AlgIdDSA(byte[] encodedAlg) throws IOException { super(new DerValue(encodedAlg).getOID()); } /** * Constructs a DSS/DSA Algorithm ID from unsigned integers that * define the algorithm parameters. Those integers are encoded * as big-endian byte arrays. * * @param p the DSS/DSA paramter "P" * @param q the DSS/DSA paramter "Q" * @param g the DSS/DSA paramter "G" */ public AlgIdDSA(byte p[], byte q[], byte g[]) throws IOException { this(new BigInteger(1, p), new BigInteger(1, q), new BigInteger(1, g)); } /** * Constructs a DSS/DSA Algorithm ID from numeric parameters. * * @param p the DSS/DSA paramter "P" * @param q the DSS/DSA paramter "Q" * @param g the DSS/DSA paramter "G" */ public AlgIdDSA(BigInteger p, BigInteger q, BigInteger g) { super(DSA_oid); try { this.p = p; this.q = q; this.g = g; initializeParams(); } catch (IOException e) { /* this should not happen */ throw new ProviderException("Construct DSS/DSA Algorithm ID"); } } /** * Returns "DSA", indicating the Digital Signature Algorithm (DSA) as * defined by the Digital Signature Standard (DSS), FIPS 186. */ public String getName() { return "DSA"; } /* * For algorithm IDs which haven't been created from a DER encoded * value, "params" must be created. */ private void initializeParams() throws IOException { try (DerOutputStream out = new DerOutputStream()) { out.putInteger(new BigInt(p.toByteArray())); out.putInteger(new BigInt(q.toByteArray())); out.putInteger(new BigInt(g.toByteArray())); params = new DerValue(DerValue.tag_Sequence, out.toByteArray()); } } /** * Parses algorithm parameters P, Q, and G. They're found * in the "params" member, which never needs to be changed. */ protected void decodeParams() throws IOException { if (params == null || params.tag != DerValue.tag_Sequence) throw new IOException("DSA alg parsing error"); params.data.reset(); this.p = params.data.getInteger().toBigInteger(); this.q = params.data.getInteger().toBigInteger(); this.g = params.data.getInteger().toBigInteger(); if (params.data.available() != 0) throw new IOException("AlgIdDSA params, extra=" + params.data.available()); } /* * Returns a formatted string describing the parameters. */ public String toString() { return paramsToString(); } /* * Returns a string describing the parameters. */ protected String paramsToString() { return "\n p:\n" + (new BigInt(p)).toString() + "\n q:\n" + (new BigInt(q)).toString() + "\n g:\n" + (new BigInt(g)).toString() + "\n"; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((g == null) ? 0 : g.hashCode()); result = prime * result + ((p == null) ? 0 : p.hashCode()); result = prime * result + ((q == null) ? 0 : q.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (!super.equals(obj)) return false; if (getClass() != obj.getClass()) return false; AlgIdDSA other = (AlgIdDSA) obj; if (g == null) { if (other.g != null) return false; } else if (!g.equals(other.g)) return false; if (p == null) { if (other.p != null) return false; } else if (!p.equals(other.p)) return false; if (q == null) { if (other.q != null) return false; } else if (!q.equals(other.q)) return false; return true; } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 30500 Content-Disposition: inline; filename="AlgorithmId.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "a89843e0a1fd5dcd4da299758e615a76625019b0" // --- 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.x509; import java.io.IOException; import java.io.OutputStream; import java.io.Serializable; import java.security.AlgorithmParameters; import java.security.NoSuchAlgorithmException; 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; /** * This class identifies algorithms, such as cryptographic transforms, each * of which may be associated with parameters. Instances of this base class * are used when this runtime environment has no special knowledge of the * algorithm type, and may also be used in other cases. Equivalence is * defined according to OID and (where relevant) parameters. * *

* Subclasses may be used, for example when when the algorithm ID has associated parameters which some code (e.g. code * using public keys) needs to have parsed. Two examples of such algorithms are Diffie-Hellman key exchange, and the * Digital Signature Standard Algorithm (DSS/DSA). * *

* The OID constants defined in this class correspond to some widely used algorithms, for which conventional string * names have been defined. This class is not a general repository for OIDs, or for such string names. Note that the * mappings between algorithm IDs and algorithm names is not one-to-one. * * @version 1.70 * * @author David Brownell * @author Amit Kapoor * @author Hemma Prafullchandra */ public class AlgorithmId implements Serializable, DerEncoder { /** use serialVersionUID from JDK 1.1. for interoperability */ private static final long serialVersionUID = 7205873507486557157L; /** * The object identitifer being used for this algorithm. */ private ObjectIdentifier algid = null; // The (parsed) parameters private AlgorithmParameters algParams; /** * Parameters for this algorithm. These are stored in unparsed * DER-encoded form; subclasses can be made to automaticaly parse * them so there is fast access to these parameters. */ protected DerValue params = null; protected String paramsString = null; public AlgorithmParameters getParameters() { return this.algParams; } public String getParametersString() { return this.paramsString; } public void setParametersString(String paramStr) { this.paramsString = paramStr; } /** * Returns one of the algorithm IDs most commonly associated * with this algorithm name. * * @param algname the name being used * @exception NoSuchAlgorithmException on error. */ public static AlgorithmId get(String algname) throws NoSuchAlgorithmException { ObjectIdentifier oid = algOID(algname); if (oid == null) throw new NoSuchAlgorithmException("unrecognized algorithm name: " + algname); return new AlgorithmId(oid); } /** * Parse (unmarshal) an ID from a DER sequence input value. This form * parsing might be used when expanding a value which has already been * partially unmarshaled as a set or sequence member. * * @exception IOException on error. * @param val the input value, which contains the algid and, if * there are any parameters, those parameters. * @return an ID for the algorithm. If the system is configured * appropriately, this may be an instance of a class * with some kind of special support for this algorithm. * In that case, you may "narrow" the type of the ID. */ public static AlgorithmId parse(DerValue val) throws IOException { if (val.tag != DerValue.tag_Sequence) throw new IOException("algid parse error, not a sequence"); /* * Get the algorithm ID and any parameters. */ ObjectIdentifier algid; DerValue params; DerInputStream in = val.toDerInputStream(); algid = in.getOID(); if (in.available() == 0) params = null; else { params = in.getDerValue(); if (params.tag == DerValue.tag_Null) params = null; } /* * Figure out what class (if any) knows about this oid's * parameters. Make one, and give it the data to decode. */ AlgorithmId alg = new AlgorithmId(algid, params); if (params != null) alg.decodeParams(); /* * Set the raw params string in case * higher level code might want the info */ String paramStr = null; if (params != null) { paramStr = params.toString(); } alg.setParametersString(paramStr); return alg; } public static AlgorithmId parse(byte[] val) throws IOException { return null; } /** * Constructs a parameterless algorithm ID. * * @param oid the identifier for the algorithm */ public AlgorithmId(ObjectIdentifier oid) { algid = oid; } private AlgorithmId(ObjectIdentifier oid, DerValue params) throws IOException { this.algid = oid; this.params = params; if (this.params != null) decodeParams(); } /** * Constructs an algorithm ID which will be initialized * separately, for example by deserialization. * * @deprecated use one of the other constructors. */ public AlgorithmId() { } protected void decodeParams() throws IOException { try { this.algParams = AlgorithmParameters.getInstance (this.algid.toString()); } catch (NoSuchAlgorithmException e) { /* * This algorithm parameter type is not supported, so we cannot * parse the parameters. */ this.algParams = null; return; } // Decode (parse) the parameters this.algParams.init(this.params.toByteArray()); } /** * Marshal a DER-encoded "AlgorithmID" sequence on the DER stream. */ public final void encode(DerOutputStream out) throws IOException { derEncode(out); } /** * DER encode this object onto an output stream. * Implements the DerEncoder interface. * * @param out * the output stream on which to write the DER encoding. * * @exception IOException on encoding error. */ public void derEncode(OutputStream out) throws IOException { try (DerOutputStream tmp = new DerOutputStream()) { DerOutputStream bytes = new DerOutputStream(); bytes.putOID(algid); // omit parameter field for ECDSA if (!algid.equals(sha224WithEC_oid) && !algid.equals(sha256WithEC_oid) && !algid.equals(sha384WithEC_oid) && !algid.equals(sha512WithEC_oid)) { if (params == null) { bytes.putNull(); } else bytes.putDerValue(params); } tmp.write(DerValue.tag_Sequence, bytes); out.write(tmp.toByteArray()); } } // XXXX cleaning required /** * Returns the DER-encoded X.509 AlgorithmId as a byte array. */ public final byte[] encode() throws IOException { try (DerOutputStream out = new DerOutputStream()) { DerOutputStream bytes = new DerOutputStream(); bytes.putOID(algid); // omit parameter field for ECDSA if (!algid.equals(sha224WithEC_oid) && !algid.equals(sha256WithEC_oid) && !algid.equals(sha384WithEC_oid) && !algid.equals(sha512WithEC_oid)) { if (params == null) { bytes.putNull(); } else bytes.putDerValue(params); } out.write(DerValue.tag_Sequence, bytes); return out.toByteArray(); } } /** * Returns list of signing algorithms for a key algorithm such as * RSA or DSA. */ public static String[] getSigningAlgorithms(AlgorithmId alg) { ObjectIdentifier algOid = alg.getOID(); //System.out.println("Key Alg oid "+algOid.toString()); if (algOid.equals(DSA_oid) || algOid.equals(DSA_OIW_oid)) { return DSA_SIGNING_ALGORITHMS; } else if (algOid.equals(RSA_oid) || algOid.equals(RSAEncryption_oid)) { return RSA_SIGNING_ALGORITHMS; } else if (algOid.equals(ANSIX962_EC_Public_Key_oid) || algOid.equals(ANSIX962_SHA1_With_EC_oid)) { return EC_SIGNING_ALGORITHMS; } else { return null; } } /* * Translates from some common algorithm names to the * OID with which they're usually associated ... this mapping * is the reverse of the one below, except in those cases * where synonyms are supported or where a given algorithm * is commonly associated with multiple OIDs. */ private static ObjectIdentifier algOID(String name) { // Digesting algorithms if (name.equals("MD5")) return AlgorithmId.MD5_oid; if (name.equals("MD2")) return AlgorithmId.MD2_oid; if (name.equals("SHA") || name.equals("SHA1") || name.equals("SHA-1")) return AlgorithmId.SHA_oid; if (name.equals("SHA256") || name.equals("SHA-256")) return AlgorithmId.SHA256_oid; if (name.equals("SHA512") || name.equals("SHA-512")) return AlgorithmId.SHA512_oid; // Various public key algorithms if (name.equals("RSA")) return AlgorithmId.RSA_oid; if (name.equals("RSAEncryption")) return AlgorithmId.RSAEncryption_oid; if (name.equals("Diffie-Hellman") || name.equals("DH")) return AlgorithmId.DH_oid; if (name.equals("DSA")) return AlgorithmId.DSA_oid; // Common signature types if (name.equals("SHA1withEC") || name.equals("SHA1/EC") || name.equals("1.2.840.10045.4.1")) return AlgorithmId.sha1WithEC_oid; if (name.equals("SHA224withEC") || name.equals("SHA224/EC") || name.equals("1.2.840.10045.4.3.1")) return AlgorithmId.sha224WithEC_oid; if (name.equals("SHA256withEC") || name.equals("SHA256/EC") || name.equals("1.2.840.10045.4.3.2")) return AlgorithmId.sha256WithEC_oid; if (name.equals("SHA384withEC") || name.equals("SHA384/EC") || name.equals("1.2.840.10045.4.3.3")) return AlgorithmId.sha384WithEC_oid; if (name.equals("SHA512withEC") || name.equals("SHA512/EC") || name.equals("1.2.840.10045.4.3.4")) return AlgorithmId.sha512WithEC_oid; if (name.equals("SHA1withRSA") || name.equals("SHA1/RSA") || name.equals("1.2.840.113549.1.1.5")) return AlgorithmId.sha1WithRSAEncryption_oid; if (name.equals("SHA256withRSA") || name.equals("SHA256/RSA") || name.equals("1.2.840.113549.1.1.11")) return AlgorithmId.sha256WithRSAEncryption_oid; if (name.equals("SHA384withRSA") || name.equals("SHA384/RSA") || name.equals("1.2.840.113549.1.1.12")) return AlgorithmId.sha384WithRSAEncryption_oid; if (name.equals("SHA512withRSA") || name.equals("SHA512/RSA") || name.equals("1.2.840.113549.1.1.13")) return AlgorithmId.sha512WithRSAEncryption_oid; if (name.equals("MD5withRSA") || name.equals("MD5/RSA")) return AlgorithmId.md5WithRSAEncryption_oid; if (name.equals("MD2withRSA") || name.equals("MD2/RSA")) return AlgorithmId.md2WithRSAEncryption_oid; if (name.equals("SHAwithDSA") || name.equals("SHA1withDSA") || name.equals("SHA/DSA") || name.equals("SHA1/DSA")) return AlgorithmId.sha1WithDSA_oid; return null; } /* * For the inevitable cases where key or signature types are not * configured in an environment which encounters such keys or * signatures, we still attempt to provide user-friendly names * for some of the most common algorithms. Subclasses can of * course override getName(). * * Wherever possible, the names are those defined by the IETF. * Such names are noted below. */ private String algName() { // Common message digest algorithms if (algid.equals(AlgorithmId.MD5_oid)) return "MD5"; // RFC 1423 if (algid.equals(AlgorithmId.MD2_oid)) return "MD2"; // RFC 1423 if (algid.equals(AlgorithmId.SHA_oid)) return "SHA"; if (algid.equals(AlgorithmId.SHA256_oid)) return "SHA256"; if (algid.equals(AlgorithmId.SHA384_oid)) return "SHA384"; if (algid.equals(AlgorithmId.SHA512_oid)) return "SHA512"; // Common key types if (algid.equals(AlgorithmId.ANSIX962_EC_Public_Key_oid)) return "EC"; if (algid.equals(AlgorithmId.RSAEncryption_oid) || algid.equals(AlgorithmId.RSA_oid)) return "RSA"; if (algid.equals(AlgorithmId.DH_oid) || algid.equals(AlgorithmId.DH_PKIX_oid)) return "Diffie-Hellman"; if (algid.equals(AlgorithmId.DSA_oid) || algid.equals(AlgorithmId.DSA_OIW_oid)) return "DSA"; // Common signature types if (algid.equals(AlgorithmId.sha1WithEC_oid)) return "SHA1withEC"; if (algid.equals(AlgorithmId.sha256WithEC_oid)) return "SHA256withEC"; if (algid.equals(AlgorithmId.sha384WithEC_oid)) return "SHA384withEC"; if (algid.equals(AlgorithmId.sha512WithEC_oid)) return "SHA512withEC"; if (algid.equals(AlgorithmId.md5WithRSAEncryption_oid)) return "MD5withRSA"; if (algid.equals(AlgorithmId.md2WithRSAEncryption_oid)) return "MD2withRSA"; if (algid.equals(AlgorithmId.sha1WithRSAEncryption_oid)) return "SHA1withRSA"; if (algid.equals(AlgorithmId.sha256WithRSAEncryption_oid)) return "SHA256withRSA"; if (algid.equals(AlgorithmId.sha384WithRSAEncryption_oid)) return "SHA384withRSA"; if (algid.equals(AlgorithmId.sha512WithRSAEncryption_oid)) return "SHA512withRSA"; if (algid.equals(AlgorithmId.sha1WithDSA_oid) || algid.equals(AlgorithmId.sha1WithDSA_OIW_oid) || algid.equals(AlgorithmId.shaWithDSA_OIW_oid)) return "SHA1withDSA"; // default returns a dot-notation ID return "OID." + algid.toString(); } /** * Returns the ISO OID for this algorithm. This is usually converted * to a string and used as part of an algorithm name, for example * "OID.1.3.14.3.2.13" style notation. Use the getName call when you do not need to ensure cross-system * portability * of algorithm names, or need a user friendly name. */ final public ObjectIdentifier getOID() { return algid; } /** * Returns a name for the algorithm which may be more intelligible * to humans than the algorithm's OID, but which won't necessarily * be comprehensible on other systems. For example, this might * return a name such as "MD5withRSA" for a signature algorithm on * some systems. It also returns names like "OID.1.2.3.4", when * no particular name for the algorithm is known. */ public String getName() { return algName(); } /** * Returns a string describing the algorithm and its parameters. */ public String toString() { return (algName() + paramsToString()); } /** * Returns the DER encoded parameter, which can then be * used to initialize java.security.AlgorithmParamters. * * @return DER encoded parameters, or null not present. */ public byte[] getEncodedParams() throws IOException { if (params == null) return null; else return params.toByteArray(); } /** * Provides a human-readable description of the algorithm parameters. * This may be redefined by subclasses which parse those parameters. */ protected String paramsToString() { if (params == null) { return ""; } else if (algParams != null) { return algParams.toString(); } else { return ", params unparsed"; } } /** * Returns true iff the argument indicates the same algorithm * with the same parameters. */ public boolean equals(AlgorithmId other) { if (!algid.equals(other.algid)) return false; else if (params == null && other.params == null) return true; else if (params == null) return false; else return params.equals(other.params); } /** * Compares this AlgorithmID to another. If algorithm parameters are * available, they are compared. Otherwise, just the object IDs * for the algorithm are compared. * * @param other preferably an AlgorithmId, else an ObjectIdentifier */ public boolean equals(Object other) { if (other instanceof AlgorithmId) return equals((AlgorithmId) other); else if (other instanceof ObjectIdentifier) return equals((ObjectIdentifier) other); else return false; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((algParams == null) ? 0 : algParams.hashCode()); result = prime * result + ((algid == null) ? 0 : algid.hashCode()); result = prime * result + ((params == null) ? 0 : params.hashCode()); result = prime * result + ((paramsString == null) ? 0 : paramsString.hashCode()); return result; } /** * Compares two algorithm IDs for equality. Returns true iff * they are the same algorithm, ignoring algorithm parameters. */ public final boolean equals(ObjectIdentifier id) { return algid.equals(id); } /*****************************************************************/ /* * HASHING ALGORITHMS */ private static final int MD2_data[] = { 1, 2, 840, 113549, 2, 2 }; private static final int MD5_data[] = { 1, 2, 840, 113549, 2, 5 }; // sha = { 1, 3, 14, 3, 2, 18 }; private static final int SHA1_OIW_data[] = { 1, 3, 14, 3, 2, 26 }; private static final int SHA256_data[] = { 2, 16, 840, 1, 101, 3, 4, 2, 1 }; private static final int SHA384_data[] = { 2, 16, 840, 1, 101, 3, 4, 2, 2 }; private static final int SHA512_data[] = { 2, 16, 840, 1, 101, 3, 4, 2, 3 }; /** * Algorithm ID for the MD2 Message Digest Algorthm, from RFC 1319. * OID = 1.2.840.113549.2.2 */ public static final ObjectIdentifier MD2_oid = new ObjectIdentifier(MD2_data); /** * Algorithm ID for the MD5 Message Digest Algorthm, from RFC 1321. * OID = 1.2.840.113549.2.5 */ public static final ObjectIdentifier MD5_oid = new ObjectIdentifier(MD5_data); /** * Algorithm ID for the SHA1 Message Digest Algorithm, from FIPS 180-1. * This is sometimes called "SHA", though that is often confusing since * many people refer to FIPS 180 (which has an error) as defining SHA. * OID = 1.3.14.3.2.26 */ public static final ObjectIdentifier SHA_oid = new ObjectIdentifier(SHA1_OIW_data); public static final ObjectIdentifier SHA256_oid = new ObjectIdentifier(SHA256_data); public static final ObjectIdentifier SHA384_oid = new ObjectIdentifier(SHA384_data); public static final ObjectIdentifier SHA512_oid = new ObjectIdentifier(SHA512_data); /* * COMMON PUBLIC KEY TYPES */ private static final int DH_data[] = { 1, 2, 840, 113549, 1, 3, 1 }; private static final int DH_PKIX_data[] = { 1, 2, 840, 10046, 2, 1 }; private static final int DSA_OIW_data[] = { 1, 3, 14, 3, 2, 12 }; private static final int DSA_PKIX_data[] = { 1, 2, 840, 10040, 4, 1 }; private static final int RSA_data[] = { 1, 2, 5, 8, 1, 1 }; private static final int RSAEncryption_data[] = { 1, 2, 840, 113549, 1, 1, 1 }; private static final int ANSI_X962_public_key_data[] = { 1, 2, 840, 10045, 2, 1 }; private static final int ANSI_X962_sha1_with_ec_data[] = { 1, 2, 840, 10045, 4, 1 }; public static final ObjectIdentifier ANSIX962_EC_Public_Key_oid = new ObjectIdentifier(ANSI_X962_public_key_data); public static final ObjectIdentifier ANSIX962_SHA1_With_EC_oid = new ObjectIdentifier(ANSI_X962_sha1_with_ec_data); /* * Note the preferred OIDs are named simply with no "OIW" or * "PKIX" in them, even though they may point to data from these * specs; e.g. SHA_oid, DH_oid, DSA_oid, SHA1WithDSA_oid... */ /** * Algorithm ID for Diffie Hellman Key agreement, from PKCS #3. * Parameters include public values P and G, and may optionally specify * the length of the private key X. Alternatively, algorithm parameters * may be derived from another source such as a Certificate Authority's * certificate. * OID = 1.2.840.113549.1.3.1 */ public static final ObjectIdentifier DH_oid = new ObjectIdentifier(DH_data); /** * Algorithm ID for the Diffie Hellman Key Agreement (DH), from the * IETF PKIX IPKI Part I. * Parameters may include public values P and G. * OID = 1.2.840.10046.2.1 */ public static final ObjectIdentifier DH_PKIX_oid = new ObjectIdentifier(DH_PKIX_data); /** * Algorithm ID for the Digital Signing Algorithm (DSA), from the * NIST OIW Stable Agreements part 12. * Parameters may include public values P, Q, and G; or these may be * derived from * another source such as a Certificate Authority's certificate. * OID = 1.3.14.3.2.12 */ public static final ObjectIdentifier DSA_OIW_oid = new ObjectIdentifier(DSA_OIW_data); /** * Algorithm ID for the Digital Signing Algorithm (DSA), from the * IETF PKIX IPKI Part I. * Parameters may include public values P, Q, and G; or these may be * derived from * another source such as a Certificate Authority's certificate. * OID = 1.2.840.10040.4.1 */ public static final ObjectIdentifier DSA_oid = new ObjectIdentifier(DSA_PKIX_data); /** * Algorithm ID for RSA keys used for any purpose, as defined in X.509. * The algorithm parameter is a single value, the number of bits in the * public modulus. * OID = 1.2.5.8.1.1 */ public static final ObjectIdentifier RSA_oid = new ObjectIdentifier(RSA_data); /** * Algorithm ID for RSA keys used with RSA encryption, as defined * in PKCS #1. There are no parameters associated with this algorithm. * OID = 1.2.840.113549.1.1.1 */ public static final ObjectIdentifier RSAEncryption_oid = new ObjectIdentifier(RSAEncryption_data); /* * COMMON SIGNATURE ALGORITHMS */ private static final int sha1WithEC_data[] = { 1, 2, 840, 10045, 4, 1 }; private static final int sha224WithEC_data[] = { 1, 2, 840, 10045, 4, 3, 1 }; private static final int sha256WithEC_data[] = { 1, 2, 840, 10045, 4, 3, 2 }; private static final int sha384WithEC_data[] = { 1, 2, 840, 10045, 4, 3, 3 }; private static final int sha512WithEC_data[] = { 1, 2, 840, 10045, 4, 3, 4 }; private static final int md2WithRSAEncryption_data[] = { 1, 2, 840, 113549, 1, 1, 2 }; private static final int md5WithRSAEncryption_data[] = { 1, 2, 840, 113549, 1, 1, 4 }; private static final int sha1WithRSAEncryption_data[] = { 1, 2, 840, 113549, 1, 1, 5 }; private static final int sha256WithRSAEncryption_data[] = { 1, 2, 840, 113549, 1, 1, 11 }; private static final int sha384WithRSAEncryption_data[] = { 1, 2, 840, 113549, 1, 1, 12 }; private static final int sha512WithRSAEncryption_data[] = { 1, 2, 840, 113549, 1, 1, 13 }; private static final int sha1WithRSAEncryption_OIW_data[] = { 1, 3, 14, 3, 2, 29 }; private static final int shaWithDSA_OIW_data[] = { 1, 3, 14, 3, 2, 13 }; private static final int sha1WithDSA_OIW_data[] = { 1, 3, 14, 3, 2, 27 }; private static final int dsaWithSHA1_PKIX_data[] = { 1, 2, 840, 10040, 4, 3 }; public static final ObjectIdentifier sha1WithEC_oid = new ObjectIdentifier(sha1WithEC_data); public static final ObjectIdentifier sha224WithEC_oid = new ObjectIdentifier(sha224WithEC_data); public static final ObjectIdentifier sha256WithEC_oid = new ObjectIdentifier(sha256WithEC_data); public static final ObjectIdentifier sha384WithEC_oid = new ObjectIdentifier(sha384WithEC_data); public static final ObjectIdentifier sha512WithEC_oid = new ObjectIdentifier(sha512WithEC_data); /** * Identifies a signing algorithm where an MD2 digest is encrypted * using an RSA private key; defined in PKCS #1. Use of this * signing algorithm is discouraged due to MD2 vulnerabilities. * OID = 1.2.840.113549.1.1.2 */ public static final ObjectIdentifier md2WithRSAEncryption_oid = new ObjectIdentifier(md2WithRSAEncryption_data); /** * Identifies a signing algorithm where an MD5 digest is * encrypted using an RSA private key; defined in PKCS #1. * OID = 1.2.840.113549.1.1.4 */ public static final ObjectIdentifier md5WithRSAEncryption_oid = new ObjectIdentifier(md5WithRSAEncryption_data); /** * The proper one for sha1/rsa */ public static final ObjectIdentifier sha1WithRSAEncryption_oid = new ObjectIdentifier(sha1WithRSAEncryption_data); /** * The proper one for sha256/rsa */ public static final ObjectIdentifier sha256WithRSAEncryption_oid = new ObjectIdentifier(sha256WithRSAEncryption_data); /** * The proper one for sha384/rsa */ public static final ObjectIdentifier sha384WithRSAEncryption_oid = new ObjectIdentifier(sha384WithRSAEncryption_data); /** * The proper one for sha512/rsa */ public static final ObjectIdentifier sha512WithRSAEncryption_oid = new ObjectIdentifier(sha512WithRSAEncryption_data); /** * Identifies a signing algorithm where an SHA1 digest is * encrypted using an RSA private key; defined in NIST OIW. * OID = 1.3.14.3.2.29 */ public static final ObjectIdentifier sha1WithRSAEncryption_OIW_oid = new ObjectIdentifier(sha1WithRSAEncryption_OIW_data); /** * Identifies the FIPS 186 "Digital Signature Standard" (DSS), where a * SHA digest is signed using the Digital Signing Algorithm (DSA). * This should not be used. * OID = 1.3.14.3.2.13 */ public static final ObjectIdentifier shaWithDSA_OIW_oid = new ObjectIdentifier(shaWithDSA_OIW_data); /** * Identifies the FIPS 186 "Digital Signature Standard" (DSS), where a * SHA1 digest is signed using the Digital Signing Algorithm (DSA). * OID = 1.3.14.3.2.27 */ public static final ObjectIdentifier sha1WithDSA_OIW_oid = new ObjectIdentifier(sha1WithDSA_OIW_data); /** * Identifies the FIPS 186 "Digital Signature Standard" (DSS), where a * SHA1 digest is signed using the Digital Signing Algorithm (DSA). * OID = 1.2.840.10040.4.3 */ public static final ObjectIdentifier sha1WithDSA_oid = new ObjectIdentifier(dsaWithSHA1_PKIX_data); /** * Supported signing algorithms for a DSA key. */ public static final String[] DSA_SIGNING_ALGORITHMS = new String[] { "SHA1withDSA" }; /** * Supported signing algorithms for a RSA key. */ public static final String[] RSA_SIGNING_ALGORITHMS = new String[] { "SHA1withRSA", "SHA256withRSA", "SHA384withRSA", "SHA512withRSA", "MD5withRSA", "MD2withRSA" }; public static final String[] EC_SIGNING_ALGORITHMS = new String[] { "SHA1withEC", "SHA256withEC", "SHA384withEC", "SHA512withEC" }; /** * All supported signing algorithms. */ public static final String[] ALL_SIGNING_ALGORITHMS = new String[] { "SHA1withRSA", "MD5withRSA", "MD2withRSA", "SHA1withDSA", "SHA256withRSA", "SHA384withRSA", "SHA512withRSA", "SHA1withEC", "SHA256withEC", "SHA384withEC", "SHA512withEC" }; } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 10519 Content-Disposition: inline; filename="Attribute.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "d11d6f3d268057d5b05ee5fbcd4db856ff58b558" // --- 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.x509; import java.io.IOException; import java.io.OutputStream; import java.io.Serializable; import java.util.Enumeration; import java.util.Vector; import netscape.security.util.DerEncoder; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; import netscape.security.util.ObjectIdentifier; /** * An attribute, as identified by some attribute ID, has some particular values. * Values are as a rule ASN.1 printable strings. A conventional set of type IDs * is recognized when parsing. The following shows the syntax: * *

 *
 *    Attribute	::= SEQUENCE {
 * type		AttributeType,
 * 	value		SET OF AttributeValue
 *              	-- at least one value is required --}
 *
 *    AttributeType	::= OBJECT IDENTIFIER
 *
 *    AttributeValue	::= ANY
 *
 * 
* * Refer to draft-ietf-pkix-ipki-part1-11 for the support attributes listed on * page 96 of the internet draft. The are listed here for easy reference: name, * common name, surname, given name, initials, generation qualifier, dn qualifier, * country name, locality name, state or province name, organization name, organization * unit name, title, pkcs9 email. Not all the attributes are supported. Please check * the X500NameAttrMap for defined attributes. * * @author Christine Ho */ public final class Attribute implements Serializable, DerEncoder { /** * */ private static final long serialVersionUID = -931486084625476764L; //private variables ObjectIdentifier oid; Vector valueSet = new Vector(); transient protected X500NameAttrMap attrMap; //========== CONSTRUCTOR ================================== /** * Construct an attribute from attribute type and attribute value * * @param oid the object identifier of the attribute type * @param value the value string */ public Attribute(ObjectIdentifier oid, String value) throws IOException { //pre-condition verification if ((oid == null) || (value == null)) throw new IOException("Invalid Input - null passed"); attrMap = X500NameAttrMap.getDefault(); this.oid = oid; valueSet.addElement(value); } /** * Construct an attribute from attribute type and attribute values * * @param oid the object identifier of the attribute type * @param values String value vector */ public Attribute(ObjectIdentifier oid, Vector values) throws IOException { //pre-condition verification if ((oid == null) || (values == null)) throw new IOException("Invalid Input - null passed"); attrMap = X500NameAttrMap.getDefault(); this.oid = oid; //copy the value into the valueSet list Enumeration vals = values.elements(); while (vals.hasMoreElements()) { valueSet.addElement(vals.nextElement()); } } /** * Construct an attribute from attribute type and attribute values * * @param oid attribute type string CN,OU,O,C,L,TITLE,ST,STREET,UID,MAIL,E,DC * @param values String value vector */ public Attribute(String attr, Vector values) throws IOException { //pre-condition verification if ((attr == null) || (values == null)) throw new IOException("Invalid Input - null passed"); ObjectIdentifier identifier = null; try { identifier = new ObjectIdentifier(attr); } catch (Exception e) { } ObjectIdentifier id = identifier; if (identifier == null) { attrMap = X500NameAttrMap.getDefault(); id = attrMap.getOid(attr); if (id == null) throw new IOException("Attr is not supported - does not contain in attr map"); } this.oid = id; //copy the value into the valueSet list Enumeration vals = values.elements(); while (vals.hasMoreElements()) { valueSet.addElement(vals.nextElement()); } } /** * Construct an attribute from a der encoded object. This der * der encoded value should represent the attribute object. * * @param value the attribute object in der encode form. */ public Attribute(DerValue val) throws IOException { //pre-condition verification if (val == null) throw new IOException("Invalid Input - null passed"); attrMap = X500NameAttrMap.getDefault(); decodeThis(val); } //========== PUBLIC METHODS ================================== /** * Returns the OID in the Attribute. * * @return the ObjectIdentifier in this Attribute. */ public ObjectIdentifier getOid() { return oid; } /** * Returns enumeration of values in this attribute. * * @return Enumeration of values of this Attribute. */ public Enumeration getValues() { if (valueSet == null) return null; return valueSet.elements(); } /** * Encodes the Attribute to a Der output stream. * Attribute are encoded as a SEQUENCE of two elements. * * @param out The Der output stream. */ public void encode(DerOutputStream out) throws IOException { encodeThis(out); } /** * DER encode this object onto an output stream. * Implements the DerEncoder interface. * * @param out * the output stream on which to write the DER encoding. * * @exception IOException on encoding error. */ public void derEncode(OutputStream out) throws IOException { encodeThis(out); } /** * Prints a string version of this extension. */ public String toString() { String theoid = "Attribute: " + oid + "\n"; StringBuffer values = new StringBuffer("Values: "); Enumeration n = valueSet.elements(); if (n.hasMoreElements()) { values.append(n.nextElement()); while (n.hasMoreElements()) values.append("," + n.nextElement()); } return theoid + values.toString() + "\n"; } //========== PRIVATE METHODS ================================== //encode the attribute object private void encodeThis(OutputStream out) throws IOException { try (DerOutputStream tmp2 = new DerOutputStream()) { DerOutputStream tmp = new DerOutputStream(); tmp.putOID(oid); encodeValueSet(tmp); tmp2.write(DerValue.tag_Sequence, tmp); out.write(tmp2.toByteArray()); } } //encode the attribute object private void encodeValueSet(OutputStream out) throws IOException { try (DerOutputStream tmp2 = new DerOutputStream()) { DerOutputStream tmp = new DerOutputStream(); //get the attribute converter AVAValueConverter converter = attrMap.getValueConverter(oid); if (converter == null) { converter = new GenericValueConverter(); //throw new IOException("Converter not found: unsupported attribute type"); } //loop through all the values and encode Enumeration vals = valueSet.elements(); while (vals.hasMoreElements()) { String val = vals.nextElement(); DerValue derobj = converter.getValue(val); derobj.encode(tmp); } tmp2.write(DerValue.tag_SetOf, tmp); out.write(tmp2.toByteArray()); } } //decode the attribute object private void decodeThis(DerValue val) throws IOException { //pre-condition verification if (val == null) { throw new IOException("Invalid Input - null passed."); } if (val.tag != DerValue.tag_Sequence) { throw new IOException("Invalid encoding for Attribute."); } if (val.data.available() == 0) { throw new IOException("No data available in " + "passed DER encoded value."); } this.oid = val.data.getDerValue().getOID(); if (val.data.available() == 0) { throw new IOException("Invalid encoding for Attribute - value missing"); } decodeValueSet(val.data.getDerValue()); if (this.oid == null) throw new IOException("Invalid encoding for Attribute - OID missing"); } //decode the attribute value set private void decodeValueSet(DerValue val) throws IOException { //pre-condition verification if (val == null) { throw new IOException("Invalid Input - null passed."); } AVAValueConverter converter = attrMap.getValueConverter(this.oid); if (converter == null) { converter = new GenericValueConverter(); //throw new IOException("Attribute is not supported - not in attr map"); } if (val.tag != DerValue.tag_SetOf) { throw new IOException("Invalid encoding for Attribute Value Set."); } if (val.data.available() == 0) { throw new IOException("No data available in " + "passed DER encoded attribute value set."); } //get the value set while (val.data.available() != 0) { DerValue value = val.data.getDerValue(); valueSet.addElement(converter.getAsString(value)); } } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 12164 Content-Disposition: inline; filename="AuthorityKeyIdentifierExtension.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "a71a3b69ae289868975044a180e89e4448d70640" // --- 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.x509; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Array; import java.util.Enumeration; import java.util.Vector; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; /** * This class represents the Authority Key Identifier Extension. * *

* The authority key identifier extension provides a means of identifying the particular public key used to sign a * certificate. This extension would be used where an issuer has multiple signing keys (either due to multiple * concurrent key pairs or due to changeover). *

* The ASN.1 syntax for this is: * *

 * AuthorityKeyIdentifier ::= SEQUENCE {
 *    keyIdentifier             [0] KeyIdentifier           OPTIONAL,
 *    authorityCertIssuer       [1] GeneralNames            OPTIONAL,
 *    authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL
 * }
 * KeyIdentifier ::= OCTET STRING
 * 
* * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.9 * @see Extension * @see CertAttrSet */ public class AuthorityKeyIdentifierExtension extends Extension implements CertAttrSet { /** * */ private static final long serialVersionUID = -157913621972354170L; /** * Identifier for this attribute, to be used with the * get, set, delete methods of Certificate, x509 type. */ public static final String IDENT = "x509.info.extensions.AuthorityKeyIdentifier"; /** * Attribute names. */ public static final String NAME = "AuthorityKeyIdentifier"; public static final String KEY_ID = "key_id"; public static final String AUTH_NAME = "auth_name"; public static final String SERIAL_NUMBER = "serial_number"; // Private data members private static final byte TAG_ID = 0; private static final byte TAG_NAMES = 1; private static final byte TAG_SERIAL_NUM = 2; private KeyIdentifier id = null; private GeneralNames names = null; private SerialNumber serialNum = null; // Encode only the extension value private void encodeThis() throws IOException { try (DerOutputStream tmp = new DerOutputStream(); DerOutputStream seq = new DerOutputStream()) { if (id != null) { DerOutputStream tmp1 = new DerOutputStream(); id.encode(tmp1); tmp.writeImplicit(DerValue.createTag(DerValue.TAG_CONTEXT, false, TAG_ID), tmp1); } try { if (names != null) { DerOutputStream tmp1 = new DerOutputStream(); names.encode(tmp1); tmp.writeImplicit(DerValue.createTag(DerValue.TAG_CONTEXT, true, TAG_NAMES), tmp1); } } catch (Exception e) { throw new IOException(e); } if (serialNum != null) { DerOutputStream tmp1 = new DerOutputStream(); serialNum.encode(tmp1); tmp.writeImplicit(DerValue.createTag(DerValue.TAG_CONTEXT, false, TAG_SERIAL_NUM), tmp1); } seq.write(DerValue.tag_Sequence, tmp); this.extensionValue = seq.toByteArray(); } } /** * Exposed critical parameter. 99/11/03 */ public AuthorityKeyIdentifierExtension(boolean critical, KeyIdentifier kid, GeneralNames name, SerialNumber sn) throws IOException { this.id = kid; this.names = name; this.serialNum = sn; this.extensionId = PKIXExtensions.AuthorityKey_Id; this.critical = critical; encodeThis(); } /** * The default constructor for this extension. Null parameters make * the element optional (not present). * * @param id the KeyIdentifier associated with this extension. * @param names the GeneralNames associated with this extension * @param serialNum the CertificateSerialNumber associated with * this extension. * @exception IOException on error. */ public AuthorityKeyIdentifierExtension(KeyIdentifier kid, GeneralNames name, SerialNumber sn) throws IOException { this.id = kid; this.names = name; this.serialNum = sn; this.extensionId = PKIXExtensions.AuthorityKey_Id; this.critical = false; encodeThis(); } /** * Create the extension from the passed DER encoded value of the same. * * @param critical true if the extension is to be treated as critical. * @param value Array of DER encoded bytes of the actual value. * @exception IOException on error. */ public AuthorityKeyIdentifierExtension(Boolean critical, Object value) throws IOException { this.extensionId = PKIXExtensions.AuthorityKey_Id; this.critical = critical.booleanValue(); if (!(value instanceof byte[])) throw new IOException("Illegal argument type"); int len = Array.getLength(value); byte[] extValue = new byte[len]; System.arraycopy(value, 0, extValue, 0, len); this.extensionValue = extValue; DerValue val = new DerValue(extValue); if (val.tag != DerValue.tag_Sequence) { throw new IOException("Invalid encoding for " + "AuthorityKeyIdentifierExtension."); } // NB. this is always encoded with the IMPLICIT tag // The checks only make sense if we assume implicit tagging, // with explicit tagging the form is always constructed. while (val.data.available() != 0) { DerValue opt = val.data.getDerValue(); if (opt.isContextSpecific(TAG_ID) && !opt.isConstructed()) { if (id != null) throw new IOException("Duplicate KeyIdentifier in " + "AuthorityKeyIdentifier."); opt.resetTag(DerValue.tag_OctetString); id = new KeyIdentifier(opt); } else if (opt.isContextSpecific(TAG_NAMES) && opt.isConstructed()) { if (names != null) throw new IOException("Duplicate GeneralNames in " + "AuthorityKeyIdentifier."); try { opt.resetTag(DerValue.tag_Sequence); names = new GeneralNames(opt); } catch (GeneralNamesException e) { throw new IOException(e); } } else if (opt.isContextSpecific(TAG_SERIAL_NUM) && !opt.isConstructed()) { if (serialNum != null) throw new IOException("Duplicate SerialNumber in " + "AuthorityKeyIdentifier."); opt.resetTag(DerValue.tag_Integer); serialNum = new SerialNumber(opt); } else throw new IOException("Invalid encoding of " + "AuthorityKeyIdentifierExtension."); } } /** * Return the object as a string. */ public String toString() { String s = super.toString() + "AuthorityKeyIdentifier [\n"; if (id != null) { s += id.toString(); } if (names != null) { s += names.toString() + "\n"; } if (serialNum != null) { s += serialNum.toString() + "\n"; } return (s + "]\n"); } /** * Decode the extension from the InputStream. * * @param in the InputStream to unmarshal the contents from. * @exception IOException on decoding or validity errors. */ public void decode(InputStream in) throws IOException { throw new IOException("Method not to be called directly."); } /** * Write the extension to the OutputStream. * * @param out the OutputStream to write the extension to. * @exception IOException on error. */ public void encode(OutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); if (this.extensionValue == null) { extensionId = PKIXExtensions.AuthorityKey_Id; critical = false; encodeThis(); } super.encode(tmp); out.write(tmp.toByteArray()); } /** * Set the attribute value. */ public void set(String name, Object obj) throws IOException { clearValue(); if (name.equalsIgnoreCase(KEY_ID)) { if (!(obj instanceof KeyIdentifier)) { throw new IOException("Attribute value should be of " + "type KeyIdentifier."); } id = (KeyIdentifier) obj; } else if (name.equalsIgnoreCase(AUTH_NAME)) { if (!(obj instanceof GeneralNames)) { throw new IOException("Attribute value should be of " + "type GeneralNames."); } names = (GeneralNames) obj; } else if (name.equalsIgnoreCase(SERIAL_NUMBER)) { if (!(obj instanceof SerialNumber)) { throw new IOException("Attribute value should be of " + "type SerialNumber."); } serialNum = (SerialNumber) obj; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:AuthorityKeyIdentifier."); } } /** * Get the attribute value. */ public Object get(String name) throws IOException { if (name.equalsIgnoreCase(KEY_ID)) { return (id); } else if (name.equalsIgnoreCase(AUTH_NAME)) { return (names); } else if (name.equalsIgnoreCase(SERIAL_NUMBER)) { return (serialNum); } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:AuthorityKeyIdentifier."); } } /** * Delete the attribute value. */ public void delete(String name) throws IOException { if (name.equalsIgnoreCase(KEY_ID)) { id = null; } else if (name.equalsIgnoreCase(AUTH_NAME)) { names = null; } else if (name.equalsIgnoreCase(SERIAL_NUMBER)) { serialNum = null; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:AuthorityKeyIdentifier."); } } /** * Return an enumeration of names of attributes existing within this * attribute. */ public Enumeration getAttributeNames() { Vector elements = new Vector(); elements.addElement(KEY_ID); elements.addElement(AUTH_NAME); elements.addElement(SERIAL_NUMBER); return (elements.elements()); } /** * Return the name of this attribute. */ public String getName() { return (NAME); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 9579 Content-Disposition: inline; filename="BasicConstraintsExtension.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "38e34223d575157643085656397d9607613f2242" // --- 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.x509; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Array; import java.util.Enumeration; import java.util.Vector; import netscape.security.util.BigInt; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; /** * This class represents the Basic Constraints Extension. * *

* The basic constraints extension identifies whether the subject of the certificate is a CA and how deep a * certification path may exist through that CA. * *

 * The ASN.1 syntax for this extension is:
 * BasicConstraints ::= SEQUENCE {
 *     cA                BOOLEAN DEFAULT FALSE,
 *     pathLenConstraint INTEGER (0..MAX) OPTIONAL
 * }
 * 
* * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.7 * @see CertAttrSet * @see Extension */ public class BasicConstraintsExtension extends Extension implements CertAttrSet { /** * */ private static final long serialVersionUID = 6213957094939885889L; /** * Identifier for this attribute, to be used with the * get, set, delete methods of Certificate, x509 type. */ public static final String IDENT = "x509.info.extensions.BasicConstraints"; /** * Attribute names. */ public static final String NAME = "BasicConstraints"; public static final String IS_CA = "is_ca"; public static final String PATH_LEN = "path_len"; // Private data members private boolean ca = false; private int pathLen = -1; // Encode this extension value private void encodeThis() throws IOException { try (DerOutputStream out = new DerOutputStream()) { DerOutputStream tmp = new DerOutputStream(); if (ca) { tmp.putBoolean(ca); } if (pathLen >= 0) { tmp.putInteger(new BigInt(pathLen)); } out.write(DerValue.tag_Sequence, tmp); this.extensionValue = out.toByteArray(); } } /** * Default constructor for this object. * * @param ca true, if the subject of the Certificate is a CA. * @param len specifies the depth of the certification path. */ public BasicConstraintsExtension(boolean ca, int len) throws IOException { this.ca = ca; this.pathLen = len; this.extensionId = PKIXExtensions.BasicConstraints_Id; if (ca) { critical = true; } else { critical = false; } encodeThis(); } /** * Default constructor for this object. * * @param ca true, if the subject of the Certificate is a CA. * @param len specifies the depth of the certification path. */ public BasicConstraintsExtension(boolean ca, boolean critical, int len) throws IOException { this.ca = ca; this.pathLen = len; this.extensionId = PKIXExtensions.BasicConstraints_Id; this.critical = critical; encodeThis(); } /** * Create the extension from the passed DER encoded value of the same. * * @param extension the DER encoded value of the extension. * @exception IOException on error. */ public BasicConstraintsExtension(Boolean critical, Object value) throws IOException { this.extensionId = PKIXExtensions.BasicConstraints_Id; this.critical = critical.booleanValue(); if (value instanceof byte[]) { int len = Array.getLength(value); byte[] extValue = new byte[len]; System.arraycopy(value, 0, extValue, 0, len); this.extensionValue = extValue; DerValue val = new DerValue(extValue); if (val.tag != DerValue.tag_Sequence) { throw new IOException("Invalid encoding of BasicConstraints"); } // non-CA cert with no limit to certification path length if (val.data == null || val.data.available() < 1) { this.ca = false; this.pathLen = -1; return; } DerValue opt = val.data.getDerValue(); if (opt.tag != DerValue.tag_Boolean) { this.ca = false; } else { this.ca = true; if (val.data.available() != 0) { opt = val.data.getDerValue(); } else { this.pathLen = -1; return; } } if (opt.tag != DerValue.tag_Integer) { throw new IOException("Invalid encoding of BasicConstraints"); } this.pathLen = (opt.getInteger()).toInt(); /* * Activate this check once again after PKIX profiling * is a standard and this check no longer imposes an * interoperability barrier. * if (ca) { * if (!this.critical) { * throw new IOException("Criticality cannot be false for CA."); * } * } */ } else throw new IOException("Invalid argument type"); } /** * Return user readable form of extension. */ public String toString() { String s = super.toString() + "BasicConstraints:[\n"; s += ((ca) ? ("CA:true") : ("CA:false")) + "\n"; if (pathLen >= 0) { s += "PathLen:" + pathLen + "\n"; } else { s += "PathLen: undefined\n"; } return (s + "]\n"); } /** * Decode the extension from the InputStream. * * @param in the InputStream to unmarshal the contents from. * @exception IOException on decoding or validity errors. */ public void decode(InputStream in) throws IOException { throw new IOException("Method not to be called directly."); } /** * Encode this extension value to the output stream. * * @param out the DerOutputStream to encode the extension to. */ public void encode(OutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); if (extensionValue == null) { this.extensionId = PKIXExtensions.BasicConstraints_Id; /* #57286 - so that profile can set critiality */ /* if (ca) { critical = true; } else { critical = false; } */ encodeThis(); } super.encode(tmp); out.write(tmp.toByteArray()); } /** * Set the attribute value. */ public void set(String name, Object obj) throws IOException { clearValue(); if (name.equalsIgnoreCase(IS_CA)) { if (!(obj instanceof Boolean)) { throw new IOException("Attribute value should be of type Boolean."); } ca = ((Boolean) obj).booleanValue(); } else if (name.equalsIgnoreCase(PATH_LEN)) { if (!(obj instanceof Integer)) { throw new IOException("Attribute value should be of type Integer."); } pathLen = ((Integer) obj).intValue(); } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:BasicConstraints."); } } /** * Get the attribute value. */ public Object get(String name) throws IOException { if (name.equalsIgnoreCase(IS_CA)) { return (Boolean.valueOf(ca)); } else if (name.equalsIgnoreCase(PATH_LEN)) { return (Integer.valueOf(pathLen)); } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:BasicConstraints."); } } /** * Delete the attribute value. */ public void delete(String name) throws IOException { if (name.equalsIgnoreCase(IS_CA)) { ca = false; } else if (name.equalsIgnoreCase(PATH_LEN)) { pathLen = -1; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:BasicConstraints."); } } /** * Return an enumeration of names of attributes existing within this * attribute. */ public Enumeration getAttributeNames() { Vector elements = new Vector(); elements.addElement(IS_CA); elements.addElement(PATH_LEN); return (elements.elements()); } /** * Return the name of this attribute. */ public String getName() { return (NAME); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 1816 Content-Disposition: inline; filename="CPSuri.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "b39f04895c272a540d7eab683c2043cb695c86bc" // --- 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.x509; import java.io.IOException; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; /** * Represent the CPSuri Qualifier. * * CPSuri ::= IA5String; * * @author Thomas Kwan */ public class CPSuri extends Qualifier { /** * */ private static final long serialVersionUID = -2814961293159006960L; private String mURI = null; /** * Create a PolicyQualifierInfo * * @param id the ObjectIdentifier for the policy id. */ public CPSuri(String uri) { mURI = uri; } public CPSuri(DerValue val) throws IOException { mURI = val.getIA5String(); } /** * Write the PolicyQualifier to the DerOutputStream. * * @param out the DerOutputStream to write the object to. * @exception IOException on errors. */ public void encode(DerOutputStream out) throws IOException { out.putIA5String(mURI); } public String getURI() { return mURI; } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 17573 Content-Disposition: inline; filename="CRLDistributionPoint.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "7c591aee5862f14c6e22bdc80d82f6d45c24d633" // --- 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.x509; import java.io.ByteArrayOutputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import netscape.security.util.BitArray; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; import org.mozilla.jss.asn1.ANY; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Util; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.BIT_STRING; import org.mozilla.jss.asn1.EXPLICIT; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; /** *
 * DistributionPoint ::= SEQUENCE {
 *      distributionPoint       [0]     DistributionPointName OPTIONAL,
 *      reasons                 [1]     ReasonFlags OPTIONAL,
 *      cRLIssuer               [2]     GeneralNames OPTIONAL }
 *
 * DistributionPointName ::= CHOICE {
 *      fullName                [0]     GeneralNames,
 *      nameRelativeToCRLIssuer [1]     RelativeDistinguishedName }
 *
 * ReasonFlags ::= BIT STRING {
 *      unused                  (0),
 *      keyCompromise           (1),
 *      cACompromise            (2),
 *      affiliationChanged      (3),
 *      superseded              (4),
 *      cessationOfOperation    (5),
 *      certificateHold         (6) }
 * 
*/ public class CRLDistributionPoint implements ASN1Value { // at most one of the two following may be specified: private GeneralNames fullName; private RDN relativeName; // cache encoding of fullName private ANY fullNameEncoding; private BitArray reasons; // optional, may be null private GeneralNames CRLIssuer; // optional, may be null private ANY CRLIssuerEncoding; // default constructor does nothing. /** * Returns the fullName of the DistributionPointName, which may be null. */ public GeneralNames getFullName() { return fullName; } /** * Returns the relativeName of the DistributionPointName, which may be null. */ public RDN getRelativeName() { return relativeName; } /** * Sets the fullName of the DistributionPointName. It may be set to null. * If it is set to a non-null value, relativeName will be * set to null, because at most one of these two attributes * can be specified at a time. * * @exception GeneralNamesException If an error occurs encoding the * name. */ public void setFullName(GeneralNames fullName) throws GeneralNamesException, IOException { this.fullName = fullName; if (fullName != null) { // encode the name to catch any problems with it DerOutputStream derOut = new DerOutputStream(); fullName.encode(derOut); try { ANY raw = new ANY(derOut.toByteArray()); ByteArrayOutputStream bos = new ByteArrayOutputStream(); raw.encodeWithAlternateTag(Tag.get(0), bos); fullNameEncoding = new ANY(bos.toByteArray()); } catch (InvalidBERException e) { // assume this won't happen, since it would imply a bug // in DerOutputStream throw new GeneralNamesException(e.toString()); } this.relativeName = null; } } /** * Sets the relativeName of the DistributionPointName. It may be set to null. * If it is set to a non-null value, fullName will be * set to null, because at most one of these two attributes * can be specified at a time. */ public void setRelativeName(RDN relativeName) { this.relativeName = relativeName; if (relativeName != null) { this.fullName = null; } } /** * Returns the reason flags for this distribution point. May be null. */ public BitArray getReasons() { return reasons; } /** * Sets the reason flags for this distribution point. May be set to null. */ public void setReasons(BitArray reasons) { this.reasons = reasons; } /** * Returns the CRLIssuer for the CRL at this distribution point. * May be null. */ public GeneralNames getCRLIssuer() { return CRLIssuer; } /** * Sets the CRLIssuer for the CRL at this distribution point. * May be set to null. * * @exception GeneralNamesException If an error occurs encoding the name. */ public void setCRLIssuer(GeneralNames CRLIssuer) throws GeneralNamesException, IOException { this.CRLIssuer = CRLIssuer; if (CRLIssuer != null) { // encode the name to catch any problems with it DerOutputStream derOut = new DerOutputStream(); CRLIssuer.encode(derOut); try { ANY raw = new ANY(derOut.toByteArray()); ByteArrayOutputStream bos = new ByteArrayOutputStream(); raw.encodeWithAlternateTag(Tag.get(2), bos); CRLIssuerEncoding = new ANY(bos.toByteArray()); } catch (InvalidBERException e) { throw new GeneralNamesException(e.toString()); } } } ///////////////////////////////////////////////////////////// // DER encoding ///////////////////////////////////////////////////////////// private static final Tag TAG = SEQUENCE.TAG; public Tag getTag() { return TAG; } public void encode(OutputStream ostream) throws IOException { encode(TAG, ostream); } public void encode(Tag implicitTag, OutputStream ostream) throws IOException { SEQUENCE seq = new SEQUENCE(); DerOutputStream derOut; try { // Encodes the DistributionPointName. Because DistributionPointName // is a CHOICE, the [0] tag is forced to be EXPLICIT. if (fullName != null) { EXPLICIT distPoint = new EXPLICIT(Tag.get(0), fullNameEncoding); seq.addElement(distPoint); } else if (relativeName != null) { derOut = new DerOutputStream(); relativeName.encode(derOut); ANY rn = new ANY(derOut.toByteArray()); EXPLICIT raw = new EXPLICIT(Tag.get(1), rn); ByteArrayOutputStream bos = new ByteArrayOutputStream(); raw.encode(bos); ANY distPointName = new ANY(bos.toByteArray()); EXPLICIT distPoint = new EXPLICIT(Tag.get(0), distPointName); seq.addElement(distPoint); } // Encodes the ReasonFlags. if (reasons != null) { derOut = new DerOutputStream(); derOut.putUnalignedBitString(reasons); ANY raw = new ANY(derOut.toByteArray()); ByteArrayOutputStream bos = new ByteArrayOutputStream(); raw.encodeWithAlternateTag(Tag.get(1), bos); ANY reasonEncoding = new ANY(bos.toByteArray()); seq.addElement(Tag.get(1), reasonEncoding); } // Encodes the CRLIssuer if (CRLIssuer != null) { seq.addElement(Tag.get(2), CRLIssuerEncoding); } seq.encode(implicitTag, ostream); } catch (InvalidBERException e) { // this shouldn't happen unless there is a bug in one of // the Sun encoding classes throw new IOException(e.toString()); } } // Template singleton private static Template templateInstance = new Template(); /** * Returns an instance of a template for decoding a CRLDistributionPoint. */ public static Template getTemplate() { return templateInstance; } public static void main(String args[]) throws GeneralNamesException, IOException, InvalidBERException { ByteArrayOutputStream bos = null; FileOutputStream fos = null; try { if (args.length != 1) { System.out.println("Usage: CRLDistributionPoint "); System.exit(-1); } bos = new ByteArrayOutputStream(); SEQUENCE cdps = new SEQUENCE(); // URI only CRLDistributionPoint cdp = new CRLDistributionPoint(); URIName uri = new URIName("http://www.mycrl.com/go/here"); GeneralNames generalNames = new GeneralNames(); generalNames.addElement(uri); cdp.setFullName(generalNames); cdps.addElement(cdp); // DN only cdp = new CRLDistributionPoint(); X500Name dn = new X500Name("CN=Otis Smith,E=otis@fedoraproject.org" + ",OU=Certificate Server,O=Fedora,C=US"); generalNames = new GeneralNames(); generalNames.addElement(dn); cdp.setFullName(generalNames); cdps.addElement(cdp); // DN + reason BitArray ba = new BitArray(5, new byte[] { (byte) 0x28 }); cdp = new CRLDistributionPoint(); cdp.setFullName(generalNames); cdp.setReasons(ba); cdps.addElement(cdp); // relative DN + reason + crlIssuer cdp = new CRLDistributionPoint(); RDN rdn = new RDN("OU=foobar dept"); cdp.setRelativeName(rdn); cdp.setReasons(ba); cdp.setCRLIssuer(generalNames); cdps.addElement(cdp); cdps.encode(bos); byte[] encoded = bos.toByteArray(); fos = new FileOutputStream(args[0]); fos.write(encoded); SEQUENCE.OF_Template seqt = new SEQUENCE.OF_Template(getTemplate()); cdps = (SEQUENCE) ASN1Util.decode(seqt, encoded); int size = cdps.size(); System.out.println("Total number of CDPs: " + size); for (int i = 0; i < size; i++) { System.out.println("\nCDP " + i); cdp = (CRLDistributionPoint) cdps.elementAt(i); GeneralNames gn = cdp.getFullName(); if (gn == null) { System.out.println("No full name"); } else { System.out.println(gn); } rdn = cdp.getRelativeName(); if (rdn == null) { System.out.println("No relative name"); } else { System.out.println(rdn); } if (cdp.getReasons() == null) { System.out.println("No reasons"); } else { System.out.println(cdp.getReasons()); } gn = cdp.getCRLIssuer(); if (gn == null) { System.out.println("No cRLIssuer"); } else { System.out.println(gn); } } System.out.println("Done"); } finally { if (bos != null) { bos.close(); } if (fos != null) { fos.close(); } if (fos != null) { fos.close(); } } } /** * Template for decoding CRLDistributionPoint. */ public static class Template implements ASN1Template { public boolean tagMatch(Tag tag) { return TAG.equals(tag); } public ASN1Value decode(InputStream istream) throws IOException, InvalidBERException { return decode(TAG, istream); } public ASN1Value decode(Tag implicitTag, InputStream istream) throws IOException, InvalidBERException { CRLDistributionPoint cdp = new CRLDistributionPoint(); // // construct the top-level sequence // SEQUENCE.Template seqt = SEQUENCE.getTemplate(); // distributionPoint seqt.addOptionalElement( new EXPLICIT.Template(Tag.get(0), ANY.getTemplate())); // reasons seqt.addOptionalElement(Tag.get(1), BIT_STRING.getTemplate()); // cRLIssuer // This will have a tag of 2, but we can't say that here // because ANYs can't have implicit tags. We don't need to say // it, because we do check the tags on the other two elements // in the sequence, so we'll know if we get this one. seqt.addOptionalElement(ANY.getTemplate()); // // decode the top-level sequence // SEQUENCE top = (SEQUENCE) seqt.decode(implicitTag, istream); // decode the distribution point name if (top.elementAt(0) != null) { EXPLICIT exp = (EXPLICIT) top.elementAt(0); ANY distPoint = (ANY) exp.getContent(); if (distPoint.getTag().equals(Tag.get(0))) { // fullName try { DerValue dv = new DerValue(distPoint.getEncoded()); //toFile("encodedFullName", distPoint.getEncoded()); dv.resetTag(DerValue.tag_Sequence); cdp.setFullName(new GeneralNames(dv)); } catch (GeneralNamesException e) { throw new InvalidBERException("fullName: " + e.toString()); } catch (IOException e) { throw new InvalidBERException("fullName: " + e.toString()); } } else if (distPoint.getTag().equals(Tag.get(1))) { // relative name try { DerValue dv = new DerValue(distPoint.getEncoded()); /* dv is as follows: 0 12: [1] { 2 10: SET { 4 8: SEQUENCE { 6 3: OBJECT IDENTIFIER commonName (2 5 4 3) 11 1: PrintableString 'x' : } : } : } */ dv = dv.data.getDerValue(); // skipping the tag /* after the skipping, we have: 0 10: SET { 2 8: SEQUENCE { 4 3: OBJECT IDENTIFIER commonName (2 5 4 3) 9 1: PrintableString 'x' : } : } */ dv.resetTag(DerValue.tag_Set); cdp.setRelativeName(new RDN(dv)); } catch (IOException e) { throw new InvalidBERException("relativeName " + e.toString()); } } else { throw new InvalidBERException( "Unknown tag " + distPoint.getTag() + " in distributionPoint"); } } // decode the reasons if (top.elementAt(1) != null) { BIT_STRING bs = (BIT_STRING) top.elementAt(1); byte[] bits = bs.getBits(); cdp.setReasons( new BitArray((bits.length * 8) - bs.getPadCount(), bits)); } // decode the cRLIssuer if (top.elementAt(2) != null) { ANY issuer = (ANY) top.elementAt(2); if (!issuer.getTag().equals(Tag.get(2))) { throw new InvalidBERException("Invalid tag " + issuer.getTag()); } try { DerValue dv = new DerValue(issuer.getEncoded()); dv.resetTag(DerValue.tag_Sequence); cdp.setCRLIssuer(new GeneralNames(dv)); } catch (GeneralNamesException e) { throw new InvalidBERException("cRLIssuer " + e.toString()); } catch (IOException e) { throw new InvalidBERException("cRLIssuer " + e.toString()); } } return cdp; } } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 13152 Content-Disposition: inline; filename="CRLDistributionPointsExtension.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "0cd6505c39fb75768b7362d2bf76318fa168b0ea" // --- 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.x509; import java.io.BufferedOutputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.security.cert.CertificateException; import java.util.Enumeration; import java.util.Hashtable; import java.util.Vector; import org.mozilla.jss.asn1.ASN1Util; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.SEQUENCE; import netscape.security.util.BitArray; import netscape.security.util.DerOutputStream; /** * An extension that tells applications where to find the CRL for * this certificate. * *
 * cRLDistributionPoints ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint
 *
 * DistributionPoint ::= SEQUENCE {
 *      distributionPoint       [0]     DistributionPointName OPTIONAL,
 *      reasons                 [1]     ReasonFlags OPTIONAL,
 *      cRLIssuer               [2]     GeneralNames OPTIONAL }
 *
 * DistributionPointName ::= CHOICE {
 *      fullName                [0]     GeneralNames,
 *      nameRelativeToCRLIssuer [1]     RelativeDistinguishedName }
 *
 * ReasonFlags ::= BIT STRING {
 *      unused                  (0),
 *      keyCompromise           (1),
 *      cACompromise            (2),
 *      affiliationChanged      (3),
 *      superseded              (4),
 *      cessationOfOperation    (5),
 *      certificateHold         (6) }
 * 
*/ public class CRLDistributionPointsExtension extends Extension implements CertAttrSet { /** * */ private static final long serialVersionUID = 8551761833349709229L; // vector of CRLDistributionPoint private SEQUENCE distributionPoints = new SEQUENCE(); // Cached DER-encoding to improve performance. private byte[] cachedEncoding = null; /** * This constructor is called by the CertificateExtensions class to decode * an extension whose OID indicates it is a CRLDistributionsPoints * extension. */ public CRLDistributionPointsExtension(Boolean critical, Object value) //throws IOException { try { this.extensionId = PKIXExtensions.CRLDistributionPoints_Id; this.critical = critical.booleanValue(); this.extensionValue = ((byte[]) value).clone(); // decode the value try { SEQUENCE.OF_Template seqOfCRLDP = new SEQUENCE.OF_Template(CRLDistributionPoint.getTemplate()); distributionPoints = (SEQUENCE) ASN1Util.decode(seqOfCRLDP, extensionValue); } catch (InvalidBERException e) { throw new IOException("Invalid BER-encoding: " + e, e); } } catch (IOException e) { System.out.println("Big error"); System.out.println(e); e.printStackTrace(); //throw e; } } /** * The Object Identifier for this extension. */ public static final String OID = "2.5.29.31"; /** * Creates a new CRLDistributionPoints extension, with the given * distribution point as the first element. */ public CRLDistributionPointsExtension(CRLDistributionPoint dp) { this.extensionId = PKIXExtensions.CRLDistributionPoints_Id; this.critical = false; distributionPoints.addElement(dp); } /** * Adds an additional distribution point to the end of the sequence. */ public void addPoint(CRLDistributionPoint dp) { distributionPoints.addElement(dp); cachedEncoding = null; } /** * Returns the number of distribution points in the sequence. */ public int getNumPoints() { return distributionPoints.size(); } /** * Returns the DistributionPoint at the given index in the sequence. */ public CRLDistributionPoint getPointAt(int index) { return (CRLDistributionPoint) distributionPoints.elementAt(index); } /** * Sets the criticality of this extension. PKIX dictates that this * extension SHOULD NOT be critical, so applications can make it critical * if they have a very good reason. By default, the extension is not * critical. */ public void setCritical(boolean critical) { this.critical = critical; } /** * Encodes this extension to the given DerOutputStream. * This method re-encodes each time it is called, so it is not very * efficient. */ public void encode(DerOutputStream out) throws IOException { extensionValue = ASN1Util.encode(distributionPoints); super.encode(out); } /** * Should be called if any change is made to this data structure * so that the cached DER encoding can be discarded. */ public void flushCachedEncoding() { cachedEncoding = null; } ///////////////////////////////////////////////////////////// // CertAttrSet interface // This interface is not really appropriate for this extension // because it is so complicated. Therefore, we only provide a // minimal implementation. ///////////////////////////////////////////////////////////// public static final String NAME = "CRLDistributionPoints"; @Override public String toString() { return NAME; } /** * DER-encodes this extension to the given OutputStream. */ public void encode(OutputStream ostream) throws CertificateException, IOException { if (cachedEncoding == null) { // only re-encode if necessary DerOutputStream tmp = new DerOutputStream(); encode(tmp); cachedEncoding = tmp.toByteArray(); } ostream.write(cachedEncoding); } public void decode(InputStream in) throws CertificateException, IOException { throw new IOException("Not supported"); } public void set(String name, Object obj) throws CertificateException, IOException { throw new IOException("Attribute name not recognized by " + "CertAttrSet:CRLDistributionPointsExtension"); } public Object get(String name) throws CertificateException, IOException { throw new IOException("Attribute name not recognized by " + "CertAttrSet:CRLDistributionPointsExtension"); } public void delete(String name) throws CertificateException, IOException { throw new IOException("Attribute name not recognized by " + "CertAttrSet:CRLDistributionPointsExtension"); } /* * TODO use an empty collection to generate these */ public Enumeration getAttributeNames() { return (new Vector()).elements(); } public String getName() { return NAME; } /** * Test driver. */ public static void main(String args[]) { BufferedOutputStream bos = null; try { if (args.length != 1) { System.out.println("Usage: CRLDistributionPointsExtentions " + ""); System.exit(-1); } bos = new BufferedOutputStream( new FileOutputStream(args[0])); // URI only CRLDistributionPoint cdp = new CRLDistributionPoint(); URIName uri = new URIName("http://www.mycrl.com/go/here"); GeneralNames generalNames = new GeneralNames(); generalNames.addElement(uri); cdp.setFullName(generalNames); CRLDistributionPointsExtension crldpExt = new CRLDistributionPointsExtension(cdp); // DN only cdp = new CRLDistributionPoint(); X500Name dn = new X500Name("CN=Otis Smith,E=otis@fedoraproject.org" + ",OU=Certificate Server,O=Fedora,C=US"); generalNames = new GeneralNames(); generalNames.addElement(dn); cdp.setFullName(generalNames); crldpExt.addPoint(cdp); // DN + reason BitArray ba = new BitArray(5, new byte[] { (byte) 0x28 }); cdp = new CRLDistributionPoint(); cdp.setFullName(generalNames); cdp.setReasons(ba); crldpExt.addPoint(cdp); // relative DN + reason + crlIssuer cdp = new CRLDistributionPoint(); RDN rdn = new RDN("OU=foobar dept"); cdp.setRelativeName(rdn); cdp.setReasons(ba); cdp.setCRLIssuer(generalNames); crldpExt.addPoint(cdp); crldpExt.setCritical(true); crldpExt.encode(bos); } catch (Exception e) { e.printStackTrace(); } finally { if (bos != null) { try { bos.close(); } catch (IOException e) { e.printStackTrace(); } } } } /** * Represents a reason that a cert may be revoked. These reasons are * expressed in a ReasonFlags bit string. */ public static class Reason { private String name; private byte bitMask; private Reason() { } private Reason(String name, byte bitMask) { this.name = name; this.bitMask = bitMask; map.put(name, this); list.addElement(this); } private static Hashtable map = new Hashtable(); private static Vector list = new Vector(); public static Reason fromString(String name) { return map.get(name); } public String getName() { return name; } public byte getBitMask() { return bitMask; } /** * Given a bit array representing reason flags, extracts the reasons * and returns them as an array. * * @param bitFlags A bit vector containing reason flags. * @return An array of reasons contained in the bit vector. * May be zero-length but will not be null. */ public static Reason[] bitArrayToReasonArray(byte bitFlags) { return bitArrayToReasonArray(new byte[] { bitFlags }); } /** * Given a bit array representing reason flags, extracts the reasons * and returns them as an array. Currently, only the first byte * of the bitflags are examined. * * @param bitFlags A bit vector containing reason flags. The format * is big-endian (MSB first). Only the first byte is examined. * @return An array of reasons contained in the bit vector. * May be zero-length but will not be null. */ public static Reason[] bitArrayToReasonArray(byte[] bitFlags) { byte first = bitFlags[0]; int size = list.size(); Vector result = new Vector(); for (int i = 0; i < size; i++) { Reason r = list.elementAt(i); byte b = r.getBitMask(); if ((first & b) != 0) { result.addElement(r); } } size = result.size(); Reason[] retval = new Reason[size]; for (int i = 0; i < size; i++) { retval[i] = result.elementAt(i); } return retval; } public static final Reason UNUSED = new Reason("unused", (byte) 0x80); public static final Reason KEY_COMPROMISE = new Reason("keyCompromise", (byte) 0x40); public static final Reason CA_COMPROMISE = new Reason("cACompromise", (byte) 0x20); public static final Reason AFFILIATION_CHANGED = new Reason("affiliationChanged", (byte) 0x10); public static final Reason SUPERSEDED = new Reason("superseded", (byte) 0x08); public static final Reason CESSATION_OF_OPERATION = new Reason("cessationOfOperation", (byte) 0x04); public static final Reason CERTIFICATE_HOLD = new Reason("certificateHold", (byte) 0x02); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 8893 Content-Disposition: inline; filename="CRLExtensions.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "d9eaffd89de7b1b8e94c128f63ad788c4547f7fd" // --- 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.x509; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Array; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.security.cert.CRLException; import java.security.cert.CertificateException; import java.util.Enumeration; import java.util.Hashtable; import java.util.Vector; import netscape.security.util.DerInputStream; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; /** * This class defines the CRL Extensions. * * @author Hemma Prafullchandra * @version 1.4 */ public class CRLExtensions extends Vector { /** * */ private static final long serialVersionUID = 365767738692986418L; private Hashtable map; // Parse the encoded extension private void parseExtension(Extension ext) throws X509ExtensionException { try { Class extClass = OIDMap.getClass(ext.getExtensionId()); if (extClass == null) { // Unsupported extension if (ext.isCritical()) { throw new IOException("Unsupported CRITICAL extension: " + ext.getExtensionId()); } else { map.put(ext.getExtensionId().toString(), ext); addElement(ext); return; } } Class[] params = { Boolean.class, Object.class }; Constructor cons = extClass.getConstructor(params); byte[] extData = ext.getExtensionValue(); int extLen = extData.length; Object value = Array.newInstance(byte.class, extLen); for (int i = 0; i < extLen; i++) { Array.setByte(value, i, extData[i]); } Object[] passed = new Object[] { Boolean.valueOf(ext.isCritical()), value }; CertAttrSet crlExt = (CertAttrSet) cons.newInstance(passed); map.put(crlExt.getName(), (Extension) crlExt); addElement((Extension) crlExt); } catch (InvocationTargetException invk) { throw new X509ExtensionException( invk.getTargetException().getMessage()); } catch (Exception e) { throw new X509ExtensionException(e.toString()); } } /** * Default constructor. */ public CRLExtensions() { map = new Hashtable(); } /** * Create the object, decoding the values from the passed DER stream. * * @param in the DerInputStream to read the Extension from. * @exception CRLException on decoding errors. * @exception X509ExtensionException on extension handling errors. */ public CRLExtensions(DerInputStream in) throws CRLException, X509ExtensionException { map = new Hashtable(); try { DerValue[] exts = in.getSequence(5); for (int i = 0; i < exts.length; i++) { Extension ext = new Extension(exts[i]); parseExtension(ext); } } catch (IOException e) { throw new CRLException("Parsing error: " + e.toString()); } } /** * Decode the extensions from the InputStream. * * @param in the InputStream to unmarshal the contents from. * @exception CRLException on decoding or validity errors. * @exception X509ExtensionException on extension handling errors. */ public void decode(InputStream in) throws CRLException, X509ExtensionException { try { DerValue val = new DerValue(in); DerInputStream str = val.toDerInputStream(); map = new Hashtable(); DerValue[] exts = str.getSequence(5); for (int i = 0; i < exts.length; i++) { Extension ext = new Extension(exts[i]); parseExtension(ext); } } catch (IOException e) { throw new CRLException("Parsing error: " + e.toString()); } } /** * Encode the extensions in DER form to the stream. * * @param out the DerOutputStream to marshal the contents to. * @param isExplicit the tag indicating whether this is an entry * extension or a CRL extension. * @exception CRLException on encoding errors. */ public void encode(OutputStream out, boolean isExplicit) throws CRLException { try (DerOutputStream tmp = new DerOutputStream()) { // #381559 if (size() == 0) return; DerOutputStream extOut = new DerOutputStream(); for (int i = 0; i < size(); i++) { Object thisOne = elementAt(i); if (thisOne instanceof CertAttrSet) ((CertAttrSet) thisOne).encode(extOut); else if (thisOne instanceof Extension) ((Extension) thisOne).encode(extOut); else throw new CRLException("Illegal extension object"); } DerOutputStream seq = new DerOutputStream(); seq.write(DerValue.tag_Sequence, extOut); if (isExplicit) { tmp.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0), seq); out.write(tmp.toByteArray()); } else { out.write(seq.toByteArray()); } } catch (IOException e) { throw new CRLException("Encoding error: " + e.toString()); } catch (CertificateException e) { throw new CRLException("Encoding error: " + e.toString()); } } /** * Get the extension with this alias. * * @param alias the identifier string for the extension to retrieve. * @exception X509ExtensionException on extension handling errors. */ public Extension get(String alias) throws X509ExtensionException { X509AttributeName attr = new X509AttributeName(alias); String name; String id = attr.getPrefix(); if (id.equalsIgnoreCase(X509CertImpl.NAME)) { // fully qualified int index = alias.lastIndexOf("."); name = alias.substring(index + 1); } else name = alias; Extension ext = map.get(name); if (ext == null) throw new X509ExtensionException("No extension found with name: " + alias); return ext; } /** * Set the extension value with this alias. * * @param alias the identifier string for the extension to set. * @param obj the Object to set the extension identified by the * alias. * @exception IOException on errors. */ public void set(String alias, Extension obj) throws IOException { map.put(alias, obj); addElement(obj); } /** * Return an enumeration of names of the extensions. * * @return an enumeration of the names of the extensions in this CRL. */ public Enumeration getElements() { return (map.elements()); } @Override public int hashCode() { final int prime = 31; int result = super.hashCode(); result = prime * result + ((map == null) ? 0 : map.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (!super.equals(obj)) return false; if (getClass() != obj.getClass()) return false; CRLExtensions other = (CRLExtensions) obj; if (map == null) { if (other.map != null) return false; } else if (!map.equals(other.map)) return false; return true; } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 7319 Content-Disposition: inline; filename="CRLNumberExtension.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "f62a4f386fa63c102e53943d17c03902bf907e43" // --- 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.x509; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Array; import java.math.BigInteger; import java.util.Enumeration; import java.util.Vector; import netscape.security.util.BigInt; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; /** * Represent the CRL Number Extension. * *

* This extension, if present, conveys a monotonically increasing sequence number for each CRL issued by a given CA * through a specific CA X.500 Directory entry or CRL distribution point. This extension allows users to easily * determine when a particular CRL supersedes another CRL. * * @author Hemma Prafullchandra * @version 1.2 * @see Extension * @see CertAttrSet */ public class CRLNumberExtension extends Extension implements CertAttrSet { /** * */ private static final long serialVersionUID = 2992307666566322402L; /** * Attribute name. */ public static final String NAME = "CRLNumber"; public static final String NUMBER = "value"; private BigInt crlNumber = null; // Encode this extension value private void encodeThis() throws IOException { if (crlNumber == null) throw new IOException("Unintialized CRL number extension"); try (DerOutputStream os = new DerOutputStream()) { os.putInteger(this.crlNumber); this.extensionValue = os.toByteArray(); } } /** * Create a CRLNumberExtension with the integer value . * The criticality is set to false. * * @param crlNum the value to be set for the extension. */ public CRLNumberExtension(int crlNum) throws IOException { this.crlNumber = new BigInt(crlNum); this.extensionId = PKIXExtensions.CRLNumber_Id; this.critical = false; encodeThis(); } /** * Create a CRLNumberExtension with the BigInteger value . * The criticality is set to false. * * @param crlNum the value to be set for the extension. */ public CRLNumberExtension(BigInteger crlNum) throws IOException { this.crlNumber = new BigInt(crlNum); this.extensionId = PKIXExtensions.CRLNumber_Id; this.critical = false; encodeThis(); } /** * Create a CRLNumberExtension with the BigInteger value . * * @param critical true if the extension is to be treated as critical. * @param crlNum the value to be set for the extension. */ public CRLNumberExtension(Boolean critical, BigInteger crlNum) throws IOException { this.crlNumber = new BigInt(crlNum); this.extensionId = PKIXExtensions.CRLNumber_Id; this.critical = critical.booleanValue(); encodeThis(); } /** * Create the extension from the passed DER encoded value of the same. * * @param critical true if the extension is to be treated as critical. * @param value Array of DER encoded bytes of the actual value. * @exception IOException on error. */ public CRLNumberExtension(Boolean critical, Object value) throws IOException { this.extensionId = PKIXExtensions.CRLNumber_Id; this.critical = critical.booleanValue(); int len = Array.getLength(value); byte[] extValue = new byte[len]; for (int i = 0; i < len; i++) { extValue[i] = Array.getByte(value, i); } this.extensionValue = extValue; DerValue val = new DerValue(extValue); this.crlNumber = val.getInteger(); } /** * Set the attribute value. */ public void set(String name, Object obj) throws IOException { if (name.equalsIgnoreCase(NUMBER)) { if (!(obj instanceof BigInteger)) { throw new IOException("Attribute must be of type BigInteger."); } crlNumber = new BigInt((BigInteger) obj); } else { throw new IOException("Attribute name not recognized by" + " CertAttrSet:CRLNumber."); } } /** * Get the attribute value. */ public Object get(String name) throws IOException { if (name.equalsIgnoreCase(NUMBER)) { if (crlNumber == null) return null; else return crlNumber.toBigInteger(); } else { throw new IOException("Attribute name not recognized by" + " CertAttrSet:CRLNumber."); } } /** * Delete the attribute value. */ public void delete(String name) throws IOException { if (name.equalsIgnoreCase(NUMBER)) { crlNumber = null; } else { throw new IOException("Attribute name not recognized by" + " CertAttrSet:CRLNumber."); } } /** * Returns a printable representation of the CRLNumberExtension. */ public String toString() { String s = super.toString() + "CRL Number: " + ((crlNumber == null) ? "" : crlNumber.toString()) + "\n"; return (s); } /** * Decode the extension from the InputStream. * * @param in the InputStream to unmarshal the contents from. * @exception IOException on decoding or validity errors. */ public void decode(InputStream in) throws IOException { throw new IOException("Method not to be called directly."); } /** * Write the extension to the DerOutputStream. * * @param out the DerOutputStream to write the extension to. * @exception IOException on encoding errors. */ public void encode(OutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); if (this.extensionValue == null) { this.extensionId = PKIXExtensions.CRLNumber_Id; this.critical = false; encodeThis(); } super.encode(tmp); out.write(tmp.toByteArray()); } /** * Return an enumeration of names of attributes existing within this * attribute. */ public Enumeration getAttributeNames() { Vector elements = new Vector(); elements.addElement(NUMBER); return (elements.elements()); } /** * Return the name of this attribute. */ public String getName() { return (NAME); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 7853 Content-Disposition: inline; filename="CRLReasonExtension.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "b49dfa1db89febc557da37ff028bbfd4bff39232" // --- 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.x509; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Enumeration; import java.util.Vector; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; /** * Represent the CRLReason Extension of CRL entry. * *

* This extension, if present, defines the identifies the reason for the certificate revocation. * * @author galperin * @version $Revision$, $Date$ * @see Extension * @see CertAttrSet */ public final class CRLReasonExtension extends Extension implements CertAttrSet { /** * */ private static final long serialVersionUID = 4544973296866779535L; /** * Canned instances for all revocation reasons */ public static final CRLReasonExtension UNSPECIFIED = new CRLReasonExtension(RevocationReason.UNSPECIFIED); public static final CRLReasonExtension KEY_COMPROMISE = new CRLReasonExtension(RevocationReason.KEY_COMPROMISE); public static final CRLReasonExtension CA_COMPROMISE = new CRLReasonExtension(RevocationReason.CA_COMPROMISE); public static final CRLReasonExtension AFFILIATION_CHANGED = new CRLReasonExtension( RevocationReason.AFFILIATION_CHANGED); public static final CRLReasonExtension SUPERSEDED = new CRLReasonExtension(RevocationReason.SUPERSEDED); public static final CRLReasonExtension CESSATION_OF_OPERATION = new CRLReasonExtension( RevocationReason.CESSATION_OF_OPERATION); public static final CRLReasonExtension CERTIFICATE_HOLD = new CRLReasonExtension(RevocationReason.CERTIFICATE_HOLD); public static final CRLReasonExtension REMOVE_FROM_CRL = new CRLReasonExtension(RevocationReason.REMOVE_FROM_CRL); public static final CRLReasonExtension PRIVILEGE_WITHDRAWN = new CRLReasonExtension( RevocationReason.PRIVILEGE_WITHDRAWN); public static final CRLReasonExtension AA_COMPROMISE = new CRLReasonExtension(RevocationReason.AA_COMPROMISE); /** * Attribute names. */ public static final String NAME = "CRLReason"; public static final String REASON = "value"; private RevocationReason mReason = null; public RevocationReason getReason() { return mReason; } /** * Default constructor * */ public CRLReasonExtension() { this.extensionId = PKIXExtensions.ReasonCode_Id; this.critical = false; mReason = null; } /** * Create extension value for specific revocation reason * */ public CRLReasonExtension(RevocationReason reason) { this.extensionId = PKIXExtensions.ReasonCode_Id; this.critical = false; mReason = reason; } public CRLReasonExtension(Boolean critical, RevocationReason reason) throws IOException { this.extensionId = PKIXExtensions.ReasonCode_Id; this.critical = critical.booleanValue(); mReason = reason; } /** * Create the object from the passed DER encoded value. * * @param derVal the DerValue decoded from the stream. * @exception IOException on decoding errors. */ public CRLReasonExtension(Boolean critical, Object value) throws IOException { this.extensionId = PKIXExtensions.ReasonCode_Id; this.critical = critical.booleanValue(); byte[] extValue = ((byte[]) value).clone(); this.extensionValue = extValue; DerValue val = new DerValue(extValue); int reasonCode = val.getEnumerated(); mReason = RevocationReason.fromInt(reasonCode); if (mReason == null) throw new IOException("Unknown revocation reason value " + reasonCode); } /** * Set the attribute value. */ public void set(String name, Object obj) throws IOException { if (!(obj instanceof RevocationReason)) { throw new IOException("Attribute must be of type RevocationReason."); } if (name.equalsIgnoreCase(REASON)) { mReason = (RevocationReason) obj; } else { throw new IOException("Name not recognized by CRLReason"); } } /** * Get the attribute value. */ public Object get(String name) throws IOException { if (name.equalsIgnoreCase(REASON)) { return mReason; } else { throw new IOException("Name not recognized by CRLReason"); } } /** * Delete the attribute value. */ public void delete(String name) throws IOException { if (name.equalsIgnoreCase(REASON)) { mReason = null; } else { throw new IOException("Name not recognized by CRLReason"); } } /** * Returns a printable representation of the ReasonFlags. */ public String toString() { String s = super.toString() + "CRL Reason [" + mReason + "]\n"; return (s); } /** * Decode the extension from the InputStream. * * @param in the InputStream to unmarshal the contents from. * @exception IOException on decoding or validity errors. */ public void decode(InputStream in) throws IOException { throw new IOException("Method not to be called directly."); } // Encode this extension value private void encodeThis() throws IOException { if (mReason == null) throw new IOException("Unintialized CRLReason extension"); try (DerOutputStream os = new DerOutputStream()) { os.putEnumerated(mReason.toInt()); this.extensionValue = os.toByteArray(); } } /** * Write the extension to the DerOutputStream. * * @param out the OutputStream to write the extension to. * @exception IOException on encoding errors. */ public void encode(OutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); if (this.extensionValue == null) { encodeThis(); } super.encode(tmp); out.write(tmp.toByteArray()); } /** * Return an enumeration of names of attributes existing within this * attribute. */ public Enumeration getAttributeNames() { Vector elements = new Vector(); elements.addElement(REASON); return (elements.elements()); } /** * Return the name of this attribute. */ public String getName() { return (NAME); } public boolean equals(Object other) { if (this == other) return true; else if (other instanceof CRLReasonExtension) return ((CRLReasonExtension) other).mReason == mReason && ((CRLReasonExtension) other).critical == critical; else return false; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((mReason == null) ? 0 : mReason.hashCode()); return result; } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 11463 Content-Disposition: inline; filename="CertAndKeyGen.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "d2a8f2b6f45eee52592d0db1450efe1b7efa2469" // --- 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.x509; import java.io.IOException; import java.security.InvalidKeyException; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.SecureRandom; import java.security.Signature; import java.security.SignatureException; import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.Date; import netscape.security.pkcs.PKCS10; /** * Generate a pair of keys, and provide access to them. This class is * provided primarily for ease of use. * *

* This provides some simple certificate management functionality. Specifically, it allows you to create self-signed * X.509 certificates as well as PKCS 10 based certificate signing requests. * *

* Keys for some public key signature algorithms have algorithm parameters, such as DSS/DSA. Some sites' Certificate * Authorities adopt fixed algorithm parameters, which speeds up some operations including key generation and signing. * At this time, this interface * does not provide a way to provide such algorithm parameters, e.g. * by providing the CA certificate which includes those parameters. * *

* Also, note that at this time only signature-capable keys may be acquired through this interface. Diffie-Hellman keys, * used for secure key exchange, may be supported later. * * @author David Brownell * @author Hemma Prafullchandra * @version 1.44 * @see PKCS10 * @see X509CertImpl */ public final class CertAndKeyGen { /** * Creates a CertAndKeyGen object for a particular key type * and signature algorithm. * * @param keyType type of key, e.g. "RSA", "DSA" * @param sigAlg name of the signature algorithm, e.g. "MD5WithRSA", * "MD2WithRSA", "SHAwithDSA". * @exception NoSuchAlgorithmException on unrecognized algorithms. */ public CertAndKeyGen(String keyType, String sigAlg) throws NoSuchAlgorithmException { keyGen = KeyPairGenerator.getInstance(keyType); this.sigAlg = sigAlg; } /** * Sets the source of random numbers used when generating keys. * If you do not provide one, a system default facility is used. * You may wish to provide your own source of random numbers * to get a reproducible sequence of keys and signatures, or * because you may be able to take advantage of strong sources * of randomness/entropy in your environment. * * @deprecated All random numbers come from PKCS #11 now. */ public void setRandom(SecureRandom generator) { } // want "public void generate (X509Certificate)" ... inherit DSA/D-H param /** * Generates a random public/private key pair, with a given key * size. Different algorithms provide different degrees of security * for the same key size, because of the "work factor" involved in * brute force attacks. As computers become faster, it becomes * easier to perform such attacks. Small keys are to be avoided. * *

* Note that not all values of "keyBits" are valid for all algorithms, and not all public key algorithms are * currently supported for use in X.509 certificates. If the algorithm you specified does not produce X.509 * compatible keys, an invalid key exception is thrown. * * @param keyBits the number of bits in the keys. * @exception InvalidKeyException if the environment does not * provide X.509 public keys for this signature algorithm. */ public void generate(int keyBits) throws InvalidKeyException { KeyPair pair; try { keyGen.initialize(keyBits); pair = keyGen.generateKeyPair(); } catch (Exception e) { throw new IllegalArgumentException(e.getMessage()); } PublicKey publicKey = pair.getPublic(); if (publicKey instanceof X509Key) { this.publicKey = (X509Key) publicKey; } else { throw new InvalidKeyException("public key " + publicKey + " not an X509Key."); } privateKey = pair.getPrivate(); } /** * Returns the public key of the generated key pair. */ public X509Key getPublicKey() { return publicKey; } /** * Returns the private key of the generated key pair. * *

* Be extremely careful when handling private keys. * When private keys are not kept secret, they lose their ability * to securely authenticate specific entities ... that is a huge * security risk! */ public PrivateKey getPrivateKey() { return privateKey; } /** * Returns a self-signed X.509v1 certificate for the public key. * The certificate is immediately valid. * *

* Such certificates normally are used to identify a "Certificate Authority" (CA). Accordingly, they will not always * be accepted by other parties. However, such certificates are also useful when you are bootstrapping your security * infrastructure, or deploying system prototypes. * * @deprecated Use the new * * @param myname X.500 name of the subject (who is also the issuer) * @param validity how long the certificate should be valid, in seconds */ public X509Cert getSelfCert(X500Name myname, long validity) throws InvalidKeyException, SignatureException, NoSuchAlgorithmException { X509Certificate cert; try { cert = getSelfCertificate(myname, validity); return new X509Cert(cert.getEncoded()); } catch (CertificateException e) { throw new SignatureException(e.getMessage()); } catch (NoSuchProviderException e) { throw new NoSuchAlgorithmException(e.getMessage()); } catch (IOException e) { throw new SignatureException(e.getMessage()); } } /** * Returns a self-signed X.509v3 certificate for the public key. * The certificate is immediately valid. No extensions. * *

* Such certificates normally are used to identify a "Certificate Authority" (CA). Accordingly, they will not always * be accepted by other parties. However, such certificates are also useful when you are bootstrapping your security * infrastructure, or deploying system prototypes. * * @param myname X.500 name of the subject (who is also the issuer) * @param validity how long the certificate should be valid, in seconds * @exception CertificateException on certificate handling errors. * @exception InvalidKeyException on key handling errors. * @exception SignatureException on signature handling errors. * @exception NoSuchAlgorithmException on unrecognized algorithms. * @exception NoSuchProviderException on unrecognized providers. */ public X509Certificate getSelfCertificate(X500Name myname, long validity) throws CertificateException, InvalidKeyException, SignatureException, NoSuchAlgorithmException, NoSuchProviderException { X500Signer issuer; X509CertImpl cert; Date firstDate, lastDate; try { issuer = getSigner(myname); firstDate = new Date(); lastDate = new Date(); lastDate.setTime(lastDate.getTime() + validity * 1000); CertificateValidity interval = new CertificateValidity(firstDate, lastDate); X509CertInfo info = new X509CertInfo(); // Add all mandatory attributes info.set(X509CertInfo.VERSION, new CertificateVersion(CertificateVersion.V1)); info.set(X509CertInfo.SERIAL_NUMBER, new CertificateSerialNumber((int) (firstDate.getTime() / 1000))); AlgorithmId algID = issuer.getAlgorithmId(); info.set(X509CertInfo.ALGORITHM_ID, new CertificateAlgorithmId(algID)); info.set(X509CertInfo.SUBJECT, new CertificateSubjectName(myname)); info.set(X509CertInfo.KEY, new CertificateX509Key(publicKey)); info.set(X509CertInfo.VALIDITY, interval); info.set(X509CertInfo.ISSUER, new CertificateIssuerName(issuer.getSigner())); cert = new X509CertImpl(info); cert.sign(privateKey, algID.getName()); return cert; } catch (IOException e) { throw new CertificateEncodingException("getSelfCert: " + e.getMessage()); } } /** * Returns a PKCS #10 certificate request. The caller uses either PKCS10.print or * PKCS10.toByteArray operations on the result, to get the request in an appropriate * transmission format. * *

* PKCS #10 certificate requests are sent, along with some proof of identity, to Certificate Authorities (CAs) which * then issue X.509 public key certificates. * * @param myname X.500 name of the subject * @exception InvalidKeyException on key handling errors. * @exception SignatureException on signature handling errors. */ public PKCS10 getCertRequest(X500Name myname) throws InvalidKeyException, SignatureException { PKCS10 req = new PKCS10(publicKey); try { req.encodeAndSign(getSigner(myname)); } catch (CertificateException e) { throw new SignatureException(sigAlg + " CertificateException"); } catch (IOException e) { throw new SignatureException(sigAlg + " IOException"); } catch (NoSuchAlgorithmException e) { // "can't happen" throw new SignatureException(sigAlg + " unavailable?"); } return req; } private X500Signer getSigner(X500Name me) throws InvalidKeyException, NoSuchAlgorithmException { Signature signature = Signature.getInstance(sigAlg); signature.initSign(privateKey); return new X500Signer(signature, me); } private String sigAlg; private KeyPairGenerator keyGen; private X509Key publicKey; private PrivateKey privateKey; } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 4019 Content-Disposition: inline; filename="CertAttrSet.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "2dde4430ea2ef5460ca52b1f00f982b5acd60974" // --- 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.x509; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.security.cert.CertificateException; import java.util.Enumeration; /** * This interface defines the methods required of a certificate attribute. * Examples of X.509 certificate attributes are Validity, Issuer_Name, and * Subject Name. A CertAttrSet may compromise one attribute or many * attributes. *

* A CertAttrSet itself can also be comprised of other sub-sets. In the case of X.509 V3 certificates, for example, the * "extensions" attribute has subattributes, such as those for KeyUsage and AuthorityKeyIdentifier. * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.9 * @see CertificateException */ public interface CertAttrSet { /** * Returns a short string describing this certificate attribute. * * @return value of this certificate attribute in * printable form. */ String toString(); /** * Encodes the attribute to the output stream in a format * that can be parsed by the decode method. * * @param out the OutputStream to encode the attribute to. * * @exception CertificateException on encoding or validity errors. * @exception IOException on other errors. */ void encode(OutputStream out) throws CertificateException, IOException; /** * Decodes the attribute in the input stream. * * @param in the InputStream to read the encoded attribute from. * * @exception CertificateException on decoding or validity errors. * @exception IOException on other errors. */ void decode(InputStream in) throws CertificateException, IOException; /** * Sets an attribute value within this CertAttrSet. * * @param name the name of the attribute (e.g. "x509.info.key") * @param obj the attribute object. * * @exception CertificateException on attribute handling errors. * @exception IOException on other errors. */ void set(String name, Object obj) throws CertificateException, IOException; /** * Gets an attribute value for this CertAttrSet. * * @param name the name of the attribute to return. * * @exception CertificateException on attribute handling errors. * @exception IOException on other errors. */ Object get(String name) throws CertificateException, IOException; /** * Deletes an attribute value from this CertAttrSet. * * @param name the name of the attribute to delete. * * @exception CertificateException on attribute handling errors. * @exception IOException on other errors. */ void delete(String name) throws CertificateException, IOException; /** * Returns an enumeration of the names of the attributes existing within * this attribute. * * @return an enumeration of the attribute names. */ Enumeration getAttributeNames(); /** * Returns the name (identifier) of this CertAttrSet. * * @return the name of this CertAttrSet. */ String getName(); } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 5429 Content-Disposition: inline; filename="CertException.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "d9a6189255f9622b2c6201db8b96e7a901ff6a77" // --- 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.x509; /** * CertException indicates one of a variety of certificate problems. * * @version 1.18 * * @author David Brownell * @author Amit Kapoor * @author Hemma Prafullchandra */ public class CertException extends SecurityException { // Zero is reserved. /** * */ private static final long serialVersionUID = -4046189948107720588L; /** Indicates that the signature in the certificate is not valid. */ public static final int verf_INVALID_SIG = 1; /** Indicates that the certificate was revoked, and so is invalid. */ public static final int verf_INVALID_REVOKED = 2; /** Indicates that the certificate is not yet valid. */ public static final int verf_INVALID_NOTBEFORE = 3; /** Indicates that the certificate has expired and so is not valid. */ public static final int verf_INVALID_EXPIRED = 4; /** * Indicates that a certificate authority in the certification * chain is not trusted. */ public static final int verf_CA_UNTRUSTED = 5; /** Indicates that the certification chain is too long. */ public static final int verf_CHAIN_LENGTH = 6; /** Indicates an error parsing the ASN.1/DER encoding of the certificate. */ public static final int verf_PARSE_ERROR = 7; /** Indicates an error constructing a certificate or certificate chain. */ public static final int err_CONSTRUCTION = 8; /** Indicates a problem with the public key */ public static final int err_INVALID_PUBLIC_KEY = 9; /** Indicates a problem with the certificate version */ public static final int err_INVALID_VERSION = 10; /** Indicates a problem with the certificate format */ public static final int err_INVALID_FORMAT = 11; /** Indicates a problem with the certificate encoding */ public static final int err_ENCODING = 12; // Private data members private int verfCode; private String moreData; /** * Constructs a certificate exception using an error code * (verf_*) and a string describing the context * of the error. */ public CertException(int code, String moredata) { verfCode = code; moreData = moredata; } /** * Constructs a certificate exception using just an error code, * without a string describing the context. */ public CertException(int code) { verfCode = code; } /** * Returns the error code with which the exception was created. */ public int getVerfCode() { return verfCode; } /** * Returns a string describing the context in which the exception * was reported. */ public String getMoreData() { return moreData; } /** * Return a string corresponding to the error code used to create * this exception. */ public String getVerfDescription() { switch (verfCode) { case verf_INVALID_SIG: return "The signature in the certificate is not valid."; case verf_INVALID_REVOKED: return "The certificate has been revoked."; case verf_INVALID_NOTBEFORE: return "The certificate is not yet valid."; case verf_INVALID_EXPIRED: return "The certificate has expired."; case verf_CA_UNTRUSTED: return "The Authority which issued the certificate is not trusted."; case verf_CHAIN_LENGTH: return "The certificate path to a trusted authority is too long."; case verf_PARSE_ERROR: return "The certificate could not be parsed."; case err_CONSTRUCTION: return "There was an error when constructing the certificate."; case err_INVALID_PUBLIC_KEY: return "The public key was not in the correct format."; case err_INVALID_VERSION: return "The certificate has an invalid version number."; case err_INVALID_FORMAT: return "The certificate has an invalid format."; case err_ENCODING: return "Problem encountered while encoding the data."; default: return "Unknown code: " + verfCode; } } /** * Returns a string describing the certificate exception. */ public String toString() { return "[Certificate Exception: " + getMessage() + "]"; } /** * Returns a string describing the certificate exception. */ public String getMessage() { return getVerfDescription() + ((moreData != null) ? ("\n (" + moreData + ")") : ""); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 1318 Content-Disposition: inline; filename="CertParseError.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "dc4aa7b8fd84e65bbf55fbdc7201ce6d92ad4c54" // --- 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.x509; //back out these changes until backwards compatibility with //CertException is not an issue. //import java.security.CertificateException; /** * CertException indicates one of a variety of certificate problems. * * @version 1.7 * @author David Brownell */ class CertParseError extends CertException { /** * */ private static final long serialVersionUID = -7623327377774730807L; CertParseError(String where) { super(CertException.verf_PARSE_ERROR, where); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 5724 Content-Disposition: inline; filename="CertificateAlgorithmId.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "8e669b8f91df59f53938b139b47d8b259ffd8957" // --- 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.x509; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.OutputStream; import java.io.Serializable; import java.util.Enumeration; import java.util.Vector; import netscape.security.util.DerInputStream; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; /** * This class defines the AlgorithmId for the Certificate. * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.7 */ public class CertificateAlgorithmId implements CertAttrSet, Serializable { /** * */ private static final long serialVersionUID = 6084780721443376563L; private AlgorithmId algId; /** * Identifier for this attribute, to be used with the * get, set, delete methods of Certificate, x509 type. */ public static final String IDENT = "x509.info.algorithmID"; /** * Sub attributes name for this CertAttrSet. */ public static final String NAME = "algorithmID"; public static final String ALGORITHM = "algorithm"; /** * Default constructor for the certificate attribute. * * @param algId the Algorithm identifier */ public CertificateAlgorithmId(AlgorithmId algId) { this.algId = algId; } /** * Create the object, decoding the values from the passed DER stream. * * @param in the DerInputStream to read the serial number from. * @exception IOException on decoding errors. */ public CertificateAlgorithmId(DerInputStream in) throws IOException { DerValue val = in.getDerValue(); algId = AlgorithmId.parse(val); } /** * Create the object, decoding the values from the passed stream. * * @param in the InputStream to read the serial number from. * @exception IOException on decoding errors. */ public CertificateAlgorithmId(InputStream in) throws IOException { DerValue val = new DerValue(in); algId = AlgorithmId.parse(val); } /** * Return the algorithm identifier as user readable string. */ public String toString() { if (algId == null) return ""; return (algId.toString() + ", OID = " + (algId.getOID()).toString() + "\n"); } private void writeObject(ObjectOutputStream stream) throws IOException { encode(stream); } private void readObject(ObjectInputStream stream) throws IOException { decode(stream); } /** * Encode the algorithm identifier in DER form to the stream. * * @param out the DerOutputStream to marshal the contents to. * @exception IOException on errors. */ public void encode(OutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); algId.encode(tmp); out.write(tmp.toByteArray()); } /** * Decode the algorithm identifier from the passed stream. * * @param in the InputStream to unmarshal the contents from. * @exception IOException on errors. */ public void decode(InputStream in) throws IOException { DerValue derVal = new DerValue(in); algId = AlgorithmId.parse(derVal); } /** * Set the attribute value. */ public void set(String name, Object obj) throws IOException { if (!(obj instanceof AlgorithmId)) { throw new IOException("Attribute must be of type AlgorithmId."); } if (name.equalsIgnoreCase(ALGORITHM)) { algId = (AlgorithmId) obj; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:CertificateAlgorithmId."); } } /** * Get the attribute value. */ public Object get(String name) throws IOException { if (name.equalsIgnoreCase(ALGORITHM)) { return (algId); } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:CertificateAlgorithmId."); } } /** * Delete the attribute value. */ public void delete(String name) throws IOException { if (name.equalsIgnoreCase(ALGORITHM)) { algId = null; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:CertificateAlgorithmId."); } } /** * Return an enumeration of names of attributes existing within this * attribute. */ public Enumeration getAttributeNames() { Vector elements = new Vector(); elements.addElement(ALGORITHM); return (elements.elements()); } /** * Return the name of this attribute. */ public String getName() { return (NAME); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 3802 Content-Disposition: inline; filename="CertificateChain.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "1329217acd598afc7cac2a33692f74b898fcfc9b" // --- 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.x509; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.Serializable; import java.security.cert.X509Certificate; import netscape.security.pkcs.ContentInfo; import netscape.security.pkcs.PKCS7; import netscape.security.pkcs.SignerInfo; public class CertificateChain implements Serializable { public CertificateChain() { } /** * constructs a certificate chain from a certificate. * * @param cert a certificate */ public CertificateChain(X509Certificate cert) { mChain = new X509Certificate[1]; mChain[0] = cert; } /** * constructs a certificate chain from a X509 certificate array. * * @param chain a certificate array. */ public CertificateChain(X509Certificate[] chain) { mChain = chain.clone(); } /** * returns the certificate at specified index in chain. * * @param index the index. * @return the X509 certificate at the given index. */ public X509Certificate getCertificate(int index) { return mChain[index]; } /** * returns the first certificate in chain. * * @return the X509 certificate at the given index. */ public X509Certificate getFirstCertificate() { return mChain[0]; } /** * returns the certificate chain as an array of X509 certificates. * * @return an array of X509 Certificates. */ public X509Certificate[] getChain() { return mChain.clone(); } public void encode(OutputStream out) throws IOException { encode(out, true); } /** * encode in PKCS7 blob. */ public void encode(OutputStream out, boolean sort) throws IOException { PKCS7 p7 = new PKCS7(new AlgorithmId[0], new ContentInfo(new byte[0]), mChain, new SignerInfo[0]); p7.encodeSignedData(out, sort); } /** * decode from PKCS7 blob. */ public void decode(InputStream in) throws IOException { PKCS7 p7 = new PKCS7(in); mChain = p7.getCertificates(); } /** * for serialization */ private void writeObject(java.io.ObjectOutputStream out) throws IOException { encode(out); } /** * for serialization */ private void readObject(java.io.ObjectInputStream in) throws IOException { decode(in); } /** * Converts the certificate chain to a readable string. */ public String toString() { String s = "[\n"; if (mChain == null) return "[empty]"; StringBuffer tempBuffer = new StringBuffer(); for (int i = 0; i < mChain.length; i++) { tempBuffer.append(mChain[i].toString()); } s += tempBuffer.toString() + "]\n"; return s; } private X509Certificate[] mChain = null; } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 9632 Content-Disposition: inline; filename="CertificateExtensions.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "d76bfe196d2a1a7524e2d6015185237895418be3" // --- 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.x509; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.OutputStream; import java.io.Serializable; import java.lang.reflect.Array; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.security.cert.CertificateException; import java.util.Enumeration; import java.util.Hashtable; import java.util.Vector; import netscape.security.util.DerInputStream; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; /** * This class defines the Extensions attribute for the Certificate. * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.11 * @see CertAttrSet */ public class CertificateExtensions extends Vector implements CertAttrSet, Serializable { /** * */ private static final long serialVersionUID = -7172635300185788849L; /** * Identifier for this attribute, to be used with the * get, set, delete methods of Certificate, x509 type. */ public static final String IDENT = "x509.info.extensions"; /** * name */ public static final String NAME = "extensions"; private Hashtable map; // Parse the encoded extension public void parseExtension(Extension ext) throws IOException { try { @SuppressWarnings("unchecked") Class extClass = (Class) OIDMap.getClass(ext.getExtensionId()); if (extClass == null) { // Unsupported extension map.put(ext.getExtensionId().toString(), ext); addElement(ext); return; } Class[] params = { Boolean.class, Object.class }; Constructor cons = extClass.getConstructor(params); byte[] extData = ext.getExtensionValue(); int extLen = extData.length; Object value = Array.newInstance(byte.class, extLen); for (int i = 0; i < extLen; i++) { Array.setByte(value, i, extData[i]); } Object[] passed = new Object[] { Boolean.valueOf(ext.isCritical()), value }; CertAttrSet certExt = cons.newInstance(passed); if (certExt != null && certExt.getName() != null) { map.put(certExt.getName(), (Extension) certExt); addElement((Extension) certExt); } } catch (NoSuchMethodException e) { throw new IOException(e); } catch (InvocationTargetException e) { Throwable t = e.getTargetException(); if (t instanceof IOException) { throw (IOException)t; } throw new IOException(t); } catch (Exception e) { throw new IOException(e); } } /** * Default constructor for the certificate attribute. */ public CertificateExtensions() { map = new Hashtable(); } /** * Create the object, decoding the values from the passed DER stream. * * @param in the DerInputStream to read the Extension from. * @exception IOException on decoding errors. */ public CertificateExtensions(DerInputStream in) throws IOException { map = new Hashtable(); DerValue[] exts = in.getSequence(5); for (int i = 0; i < exts.length; i++) { Extension ext = new Extension(exts[i]); parseExtension(ext); } } /** * Decode the extensions from the InputStream. * * @param in the InputStream to unmarshal the contents from. * @exception IOException on decoding or validity errors. */ public void decode(InputStream in) throws IOException { DerValue val = new DerValue(in); DerInputStream str = val.toDerInputStream(); map = new Hashtable(); DerValue[] exts = str.getSequence(5); for (int i = 0; i < exts.length; i++) { Extension ext = new Extension(exts[i]); parseExtension(ext); } } /** * Decode the extensions from the InputStream. * * @param in the InputStream to unmarshal the contents from. * @exception IOException on decoding or validity errors. */ public void decodeEx(InputStream in) throws IOException { DerValue val = new DerValue(in); DerInputStream str = null; if (val.isConstructed() && val.isContextSpecific((byte) 3)) { str = val.data; } else { str = val.toDerInputStream(); } map = new Hashtable(); DerValue[] exts = str.getSequence(5); for (int i = 0; i < exts.length; i++) { Extension ext = new Extension(exts[i]); parseExtension(ext); } } private void writeObject(ObjectOutputStream stream) throws CertificateException, IOException { encode(stream); } private void readObject(ObjectInputStream stream) throws CertificateException, IOException { decodeEx(stream); } /** * Encode the extensions in DER form to the stream. * * @param out the DerOutputStream to marshal the contents to. * @exception CertificateException on encoding errors. * @exception IOException on errors. */ public void encode(OutputStream out) throws CertificateException, IOException { try (DerOutputStream tmp = new DerOutputStream()) { DerOutputStream extOut = new DerOutputStream(); for (int i = 0; i < size(); i++) { Object thisOne = elementAt(i); if (thisOne instanceof CertAttrSet) ((CertAttrSet) thisOne).encode(extOut); else if (thisOne instanceof Extension) ((Extension) thisOne).encode(extOut); else throw new CertificateException("Invalid extension object"); } DerOutputStream seq = new DerOutputStream(); seq.write(DerValue.tag_Sequence, extOut); tmp.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 3), seq); out.write(tmp.toByteArray()); } } /** * Set the attribute value. * * @param name the extension name used in the cache. * @param obj the object to set. * @exception IOException if the object could not be cached. */ public void set(String name, Object obj) throws IOException { map.put(name, (Extension) obj); addElement((Extension) obj); } /** * Get the attribute value. * * @param name the extension name used in the lookup. * @exception IOException if named extension is not found. */ public Object get(String name) throws IOException { Object obj = map.get(name); if (obj == null) { throw new IOException("No extension found with name " + name); } return (obj); } /** * Delete the attribute value. * * @param name the extension name used in the lookup. * @exception IOException if named extension is not found. */ public void delete(String name) throws IOException { Object obj = map.get(name); if (obj == null) { throw new IOException("No extension found with name " + name); } map.remove(name); removeElement(obj); } public Enumeration getNames() { return map.keys(); } /** * Return an enumeration of names of attributes existing within this * attribute. */ public Enumeration getAttributes() { return (map.elements()); } public Enumeration getAttributeNames() { return (map.keys()); } /** * Return the name of this attribute. */ public String getName() { return (NAME); } @Override public int hashCode() { final int prime = 31; int result = super.hashCode(); result = prime * result + ((map == null) ? 0 : map.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (!super.equals(obj)) return false; if (getClass() != obj.getClass()) return false; CertificateExtensions other = (CertificateExtensions) obj; if (map == null) { if (other.map != null) return false; } else if (!map.equals(other.map)) return false; return true; } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 7644 Content-Disposition: inline; filename="CertificateIssuerExtension.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "ae4c2093a7cdd39fe43233ad50f1ce8ab44ddf53" // --- 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.x509; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Array; import java.security.cert.CertificateException; import java.util.Enumeration; import java.util.Vector; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; /** * Represent the CRL Certificate Issuer Extension. * *

* This CRL entry extension identifies the certificate issuer associated with an entry in an indirect CRL, i.e. a CRL * that has the indirectCRL indicator set in its issuing distribution point extension. * * @see Extension * @see CertAttrSet */ public class CertificateIssuerExtension extends Extension implements CertAttrSet { /** * */ private static final long serialVersionUID = 8643788952936025986L; /** * Attribute name. */ public static final String NAME = "CertificateIssuer"; public static final String CERTIFICATE_ISSUER = "value"; /** * The Object Identifier for this extension. */ public static final String OID = "2.5.29.29"; // private data members GeneralNames names = null; static { try { OIDMap.addAttribute(CertificateIssuerExtension.class.getName(), OID, NAME); } catch (CertificateException e) { } } // Encode this extension private void encodeThis() throws IOException { DerOutputStream os = new DerOutputStream(); try { names.encode(os); } catch (GeneralNamesException e) { throw new IOException(e); } this.extensionValue = os.toByteArray(); } /** * Create a CertificateIssuerExtension with the passed GeneralNames * and criticality. * * @param critical true if the extension is to be treated as critical. * @param names the GeneralNames for the issuer. * @exception IOException on error. */ public CertificateIssuerExtension(Boolean critical, GeneralNames names) throws IOException { this.names = names; this.extensionId = PKIXExtensions.CertificateIssuer_Id; this.critical = critical.booleanValue(); encodeThis(); } /** * Create a CertificateIssuerExtension with the passed GeneralNames. * * @param names the GeneralNames for the issuer. * @exception IOException on error. */ public CertificateIssuerExtension(GeneralNames names) throws IOException { this.names = names; this.extensionId = PKIXExtensions.CertificateIssuer_Id; this.critical = true; encodeThis(); } /** * Create a default CertificateIssuerExtension. */ public CertificateIssuerExtension() { extensionId = PKIXExtensions.CertificateIssuer_Id; critical = false; names = new GeneralNames(); } /** * Create the extension from the passed DER encoded value. * * @param critical true if the extension is to be treated as critical. * @param value Array of DER encoded bytes of the actual value. * @exception IOException on error. */ public CertificateIssuerExtension(Boolean critical, Object value) throws IOException { this.extensionId = PKIXExtensions.CertificateIssuer_Id; this.critical = critical.booleanValue(); int len = Array.getLength(value); byte[] extValue = new byte[len]; for (int i = 0; i < len; i++) { extValue[i] = Array.getByte(value, i); } this.extensionValue = extValue; DerValue val = new DerValue(extValue); try { names = new GeneralNames(val); } catch (GeneralNamesException e) { throw new IOException("CertificateIssuerExtension: " + e, e); } } /** * Returns a printable representation of the CertificateIssuerName. */ public String toString() { if (names == null) return ""; String s = super.toString() + "CertificateIssuerName [\n" + names.toString() + "]\n"; return (s); } /** * Decode the extension from the InputStream. * * @param in the InputStream to unmarshal the contents from. * @exception IOException on decoding or validity errors. */ public void decode(InputStream in) throws IOException { throw new IOException("Method not to be called directly."); } /** * Write the extension to the OutputStream. * * @param out the OutputStream to write the extension to. * @exception IOException on encoding error. */ public void encode(OutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); if (extensionValue == null) { extensionId = PKIXExtensions.CertificateIssuer_Id; critical = false; encodeThis(); } super.encode(tmp); out.write(tmp.toByteArray()); } /** * Set the attribute value. */ public void set(String name, Object obj) throws IOException { if (name.equalsIgnoreCase(CERTIFICATE_ISSUER)) { if (!(obj instanceof GeneralNames)) { throw new IOException("Attribute value should be of" + " type GeneralNames."); } names = (GeneralNames) obj; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:CertificateIssuerName."); } } /** * Get the attribute value. */ public Object get(String name) throws IOException { if (name.equalsIgnoreCase(CERTIFICATE_ISSUER)) { return (names); } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:CertificateIssuerName."); } } /** * Delete the attribute value. */ public void delete(String name) throws IOException { if (name.equalsIgnoreCase(CERTIFICATE_ISSUER)) { names = null; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:CertificateIssuerName."); } } /** * Return an enumeration of names of attributes existing within this * attribute. */ public Enumeration getAttributeNames() { Vector elements = new Vector(); elements.addElement(CERTIFICATE_ISSUER); return (elements.elements()); } /** * Return the name of this attribute. */ public String getName() { return (NAME); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 5151 Content-Disposition: inline; filename="CertificateIssuerName.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "a075fdf56b2148267f477c00ab3d32353fd1df45" // --- 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.x509; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Enumeration; import java.util.Vector; import netscape.security.util.DerInputStream; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; /** * This class defines the X500Name attribute for the Certificate. * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.6 * @see CertAttrSet */ public class CertificateIssuerName implements CertAttrSet { /** * Identifier for this attribute, to be used with the * get, set, delete methods of Certificate, x509 type. */ public static final String IDENT = "x509.info.issuer"; /** * Sub attributes name for this CertAttrSet. */ public static final String NAME = "issuer"; public static final String DN_NAME = "dname"; // Private data member private X500Name dnName; /** * Default constructor for the certificate attribute. * * @param name the X500Name */ public CertificateIssuerName(X500Name name) { this.dnName = name; } /** * Create the object, decoding the values from the passed DER stream. * * @param in the DerInputStream to read the X500Name from. * @exception IOException on decoding errors. */ public CertificateIssuerName(DerInputStream in) throws IOException { dnName = new X500Name(in); } /** * Create the object, decoding the values from the passed stream. * * @param in the InputStream to read the X500Name from. * @exception IOException on decoding errors. */ public CertificateIssuerName(InputStream in) throws IOException { DerValue derVal = new DerValue(in); dnName = new X500Name(derVal); } /** * Return the name as user readable string. */ public String toString() { if (dnName == null) return ""; return (dnName.toString()); } /** * Encode the name in DER form to the stream. * * @param out the DerOutputStream to marshal the contents to. * @exception IOException on errors. */ public void encode(OutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); dnName.encode(tmp); out.write(tmp.toByteArray()); } /** * Decode the name in DER form from the stream. * * @param in the InputStream to marshal the contents from. * @exception IOException on errors. */ public void decode(InputStream in) throws IOException { DerValue derVal = new DerValue(in); dnName = new X500Name(derVal); } /** * Set the attribute value. */ public void set(String name, Object obj) throws IOException { if (!(obj instanceof X500Name)) { throw new IOException("Attribute must be of type X500Name."); } if (name.equalsIgnoreCase(DN_NAME)) { this.dnName = (X500Name) obj; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:CertificateIssuerName."); } } /** * Get the attribute value. */ public Object get(String name) throws IOException { if (name.equalsIgnoreCase(DN_NAME)) { return (dnName); } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:CertificateIssuerName."); } } /** * Delete the attribute value. */ public void delete(String name) throws IOException { if (name.equalsIgnoreCase(DN_NAME)) { dnName = null; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:CertificateIssuerName."); } } /** * Return an enumeration of names of attributes existing within this * attribute. */ public Enumeration getAttributeNames() { Vector elements = new Vector(); elements.addElement(DN_NAME); return (elements.elements()); } /** * Return the name of this attribute. */ public String getName() { return (NAME); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 5603 Content-Disposition: inline; filename="CertificateIssuerUniqueIdentity.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "af9c92b49fbb043f9f703bc631e9f6a40ae8e92d" // --- 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.x509; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Enumeration; import java.util.Vector; import netscape.security.util.DerInputStream; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; /** * This class defines the subject/issuer unique identity attribute * for the Certificate. * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.6 * @see CertAttrSet */ public class CertificateIssuerUniqueIdentity implements CertAttrSet { private UniqueIdentity id; /** * Identifier for this attribute, to be used with the * get, set, delete methods of Certificate, x509 type. */ public static final String IDENT = "x509.info.issuerID"; /** * Sub attributes name for this CertAttrSet. */ public static final String NAME = "issuerID"; public static final String ID = "id"; /** * Default constructor for the certificate attribute. * * @param key the UniqueIdentity */ public CertificateIssuerUniqueIdentity(UniqueIdentity id) { this.id = id; } /** * Create the object, decoding the values from the passed DER stream. * * @param in the DerInputStream to read the UniqueIdentity from. * @exception IOException on decoding errors. */ public CertificateIssuerUniqueIdentity(DerInputStream in) throws IOException { id = new UniqueIdentity(in); } /** * Create the object, decoding the values from the passed stream. * * @param in the InputStream to read the UniqueIdentity from. * @exception IOException on decoding errors. */ public CertificateIssuerUniqueIdentity(InputStream in) throws IOException { DerValue val = new DerValue(in); id = new UniqueIdentity(val); } /** * Create the object, decoding the values from the passed DER value. * * @param in the DerValue to read the UniqueIdentity from. * @exception IOException on decoding errors. */ public CertificateIssuerUniqueIdentity(DerValue val) throws IOException { id = new UniqueIdentity(val); } /** * Return the identity as user readable string. */ public String toString() { if (id == null) return ""; return (id.toString()); } /** * Decode the identity in DER form from the stream. * * @param in the InputStream to unmarshal the contents from. * @exception IOException on errors. */ public void decode(InputStream in) throws IOException { DerValue val = new DerValue(in); id = new UniqueIdentity(val); } /** * Encode the identity in DER form to the stream. * * @param out the DerOutputStream to marshal the contents to. * @exception IOException on errors. */ public void encode(OutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); id.encode(tmp, DerValue.createTag(DerValue.TAG_CONTEXT, false, (byte) 1)); out.write(tmp.toByteArray()); } /** * Set the attribute value. */ public void set(String name, Object obj) throws IOException { if (!(obj instanceof UniqueIdentity)) { throw new IOException("Attribute must be of type UniqueIdentity."); } if (name.equalsIgnoreCase(ID)) { id = (UniqueIdentity) obj; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet: CertificateIssuerUniqueIdentity."); } } /** * Get the attribute value. */ public Object get(String name) throws IOException { if (name.equalsIgnoreCase(ID)) { return (id); } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet: CertificateIssuerUniqueIdentity."); } } /** * Delete the attribute value. */ public void delete(String name) throws IOException { if (name.equalsIgnoreCase(ID)) { id = null; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet: CertificateIssuerUniqueIdentity."); } } /** * Return an enumeration of names of attributes existing within this * attribute. */ public Enumeration getAttributeNames() { Vector elements = new Vector(); elements.addElement(ID); return (elements.elements()); } /** * Return the name of this attribute. */ public String getName() { return (NAME); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 12021 Content-Disposition: inline; filename="CertificatePoliciesExtension.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "5bab03933b5accedc085e1062140ccf156f12606" // --- 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.x509; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Array; import java.util.Arrays; import java.util.Collections; import java.util.Enumeration; import java.util.Vector; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; import netscape.security.util.ObjectIdentifier; import com.netscape.cmsutil.util.Utils; /** * This class defines the Certificate Policies Extension. * *

* The certificate policies extension conatins a sequence of policy information terms, each of which consists of an * object identifier (OID) and optional qualifiers. These policy information terms indicate the policy under which the * certificate has been issued and the purposes for which the certificate may be used. Aplications with specific policy * requirements are expected to have a list of those policies which they will accept and to compare the policy OIDs in * the certificate to that list. If this extension is critical, the path validation software must be able to interpret * this extension, or must reject the certificate. * *

 * CertificatePolicies ::= SEQUENECE OF PolicyInformation
 * 
* * @author Christine Ho * @see Extension * @see CertAttrSet */ public class CertificatePoliciesExtension extends Extension implements CertAttrSet { /** * */ private static final long serialVersionUID = -3729294064061837367L; /** * Identifier for this attribute, to be used with the * get, set, delete methods of Certificate, x509 type. */ public static final String IDENT = "x509.info.extensions.CertificatePolicies"; /** * Attribute names. */ public static final String NAME = "CertificatePolicies"; public static final String INFOS = "infos"; // Private data members private Vector mInfos; // Encode this extension value private void encodeThis() throws IOException { try (DerOutputStream os = new DerOutputStream();) { DerOutputStream tmp = new DerOutputStream(); for (int i = 0; i < mInfos.size(); i++) { mInfos.elementAt(i).encode(tmp); } os.write(DerValue.tag_Sequence, tmp); extensionValue = os.toByteArray(); } } public CertificatePoliciesExtension(boolean critical, Vector infos) throws IOException { this.mInfos = infos; this.extensionId = PKIXExtensions.CertificatePolicies_Id; this.critical = critical; encodeThis(); } /** * Create a CertificatePolicies with the Vector of CertificatePolicyInfo. * * @param infos the Vector of CertificatePolicyInfo. */ public CertificatePoliciesExtension(Vector infos) throws IOException { this.mInfos = infos; this.extensionId = PKIXExtensions.CertificatePolicies_Id; this.critical = false; encodeThis(); } /** * Create a default CertificatePoliciesExtension. */ public CertificatePoliciesExtension() { this.extensionId = PKIXExtensions.CertificatePolicies_Id; critical = false; mInfos = new Vector(1, 1); } /** * Create the extension from the passed DER encoded value. * * @param critical true if the extension is to be treated as critical. * @param value Array of DER encoded bytes of the actual value. * @exception IOException on error. */ public CertificatePoliciesExtension(Boolean critical, Object value) throws IOException { this.extensionId = PKIXExtensions.CertificatePolicies_Id; this.critical = critical.booleanValue(); int len = Array.getLength(value); byte[] extValue = new byte[len]; for (int i = 0; i < len; i++) { extValue[i] = Array.getByte(value, i); } this.extensionValue = extValue; DerValue val = new DerValue(extValue); if (val.tag != DerValue.tag_Sequence) { throw new IOException("Invalid encoding for " + "CertificatePoliciesExtension."); } mInfos = new Vector(1, 1); while (val.data.available() != 0) { DerValue seq = val.data.getDerValue(); CertificatePolicyInfo info = new CertificatePolicyInfo(seq); mInfos.addElement(info); } } /** * Returns a printable representation of the policy extension. */ public String toString() { if (mInfos == null) return ""; String s = super.toString() + "Certificate Policies [\n" + mInfos.toString() + "]\n"; return (s); } /** * Write the extension to the OutputStream. * * @param out the OutputStream to write the extension to. * @exception IOException on encoding errors. */ public void encode(OutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); if (extensionValue == null) { extensionId = PKIXExtensions.CertificatePolicies_Id; critical = false; encodeThis(); } super.encode(tmp); out.write(tmp.toByteArray()); } /** * Decode the extension from the InputStream. * * @param in the InputStream to unmarshal the contents from. * @exception IOException on decoding or validity errors. */ public void decode(InputStream in) throws IOException { throw new IOException("Method not to be called directly."); } /** * Set the attribute value. */ @SuppressWarnings("unchecked") public void set(String name, Object obj) throws IOException { clearValue(); if (name.equalsIgnoreCase(INFOS)) { if (!(obj instanceof Vector)) { throw new IOException("Attribute value should be of" + " type Vector."); } mInfos = (Vector) obj; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:CertificatePoliciesExtension."); } } /** * Get the attribute value. */ public Object get(String name) throws IOException { if (name.equalsIgnoreCase(INFOS)) { return (mInfos); } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:CertificatePoliciesExtension."); } } /** * Delete the attribute value. */ public void delete(String name) throws IOException { if (name.equalsIgnoreCase(INFOS)) { mInfos = null; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:CertificatePoliciesExtension."); } } /** * Return an enumeration of attributes existing within this * attribute. */ public Enumeration> getAttributes() { Vector> elements = new Vector>(); elements.addElement(mInfos); return (elements.elements()); } private static final String[] NAMES = { INFOS }; @Override public Enumeration getAttributeNames() { // TODO Auto-generated method stub return Collections.enumeration(Arrays.asList(NAMES)); } /** * Return the name of this attribute. */ public String getName() { return (NAME); } public static void main(String args[]) { /** * From ASN.1 dump * * 0 30 133: SEQUENCE { * 3 30 45: . SEQUENCE { * 5 06 3: . . OBJECT IDENTIFIER '1 2 3 5' * 10 30 38: . . SEQUENCE { * 12 30 36: . . . SEQUENCE { * 14 06 8: . . . . OBJECT IDENTIFIER cps (1 3 6 1 5 5 7 2 1) * : . . . . . (PKIX policy qualifier) * 24 16 24: . . . . IA5String 'http://home.netscape.com' * : . . . . } * : . . . } * : . . } * 50 30 84: . SEQUENCE { * 52 06 2: . . OBJECT IDENTIFIER '2 3 5' * 56 30 78: . . SEQUENCE { * 58 30 36: . . . SEQUENCE { * 60 06 8: . . . . OBJECT IDENTIFIER cps (1 3 6 1 5 5 7 2 1) * : . . . . . (PKIX policy qualifier) * 70 16 24: . . . . IA5String 'http://home.netscape.com' * : . . . . } * 96 30 38: . . . SEQUENCE { * 98 06 8: . . . . OBJECT IDENTIFIER unotice (1 3 6 1 5 5 7 2 2) * : . . . . . (PKIX policy qualifier) * 108 30 26: . . . . SEQUENCE { * 110 30 16: . . . . . SEQUENCE { * 112 1E 8: . . . . . . BMPString (1993) '_..o.r.g' * 122 02 1: . . . . . . INTEGER 1 * 125 02 1: . . . . . . INTEGER 2 * : . . . . . . } * 128 1E 6: . . . . . BMPString (1993) '_..d.t' * : . . . . . } * : . . . . } * : . . . } * : . . } * : . } **/ CertificatePolicyId plcyId0 = new CertificatePolicyId( new ObjectIdentifier("1.2.3.5") ); PolicyQualifiers qualifiers0 = new PolicyQualifiers(); CPSuri cpsQualifier0 = new CPSuri("http://home.netscape.com"); PolicyQualifierInfo qualifierInfo0 = new PolicyQualifierInfo( PolicyQualifierInfo.QT_CPS, cpsQualifier0 ); qualifiers0.add(qualifierInfo0); CertificatePolicyInfo info0 = new CertificatePolicyInfo( plcyId0, qualifiers0); CertificatePolicyId plcyId1 = new CertificatePolicyId( new ObjectIdentifier("2.3.5") ); PolicyQualifiers qualifiers1 = new PolicyQualifiers(); DisplayText org1 = new DisplayText(DisplayText.tag_BMPString, "org"); int nums[] = { 1, 2 }; NoticeReference nr1 = new NoticeReference(org1, nums); DisplayText dt1 = new DisplayText(DisplayText.tag_BMPString, "dt"); UserNotice userNotice1 = new UserNotice(nr1, dt1); PolicyQualifierInfo qualifierInfo1 = new PolicyQualifierInfo( PolicyQualifierInfo.QT_UNOTICE, userNotice1 ); qualifiers1.add(qualifierInfo0); qualifiers1.add(qualifierInfo1); CertificatePolicyInfo info1 = new CertificatePolicyInfo( plcyId1, qualifiers1); Vector infos = new Vector(); infos.addElement(info0); infos.addElement(info1); try { CertificatePoliciesExtension ext = new CertificatePoliciesExtension(infos); // BASE64 encode the whole thing and write it to stdout System.out.println(Utils.base64encode(ext.getExtensionValue())); } catch (IOException e) { System.out.println(e.toString()); } } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 2470 Content-Disposition: inline; filename="CertificatePolicyId.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "d4af18c6aba33a1aaaaad1bd8651f97c5175fbdf" // --- 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.x509; import java.io.IOException; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; import netscape.security.util.ObjectIdentifier; /** * Represent the CertificatePolicyId ASN.1 object. * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.5 */ public class CertificatePolicyId implements java.io.Serializable { /** * */ private static final long serialVersionUID = -2376810529862707757L; private ObjectIdentifier id; /** * Create a CertificatePolicyId with the ObjectIdentifier. * * @param id the ObjectIdentifier for the policy id. */ public CertificatePolicyId(ObjectIdentifier id) { this.id = id; } /** * Create the object from its Der encoded value. * * @param val the DER encoded value for the same. */ public CertificatePolicyId(DerValue val) throws IOException { this.id = val.getOID(); } /** * Return the value of the CertificatePolicyId as an ObjectIdentifier. */ public ObjectIdentifier getIdentifier() { return (id); } /** * Returns a printable representation of the CertificatePolicyId. */ public String toString() { String s = "CertificatePolicyId: [" + id.toString() + "]\n"; return (s); } /** * Write the CertificatePolicyId to the DerOutputStream. * * @param out the DerOutputStream to write the object to. * @exception IOException on errors. */ public void encode(DerOutputStream out) throws IOException { out.putOID(id); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 3576 Content-Disposition: inline; filename="CertificatePolicyInfo.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "375cfbe7ce8f16ec8a5d862d92455b3d87a1ea5f" // --- 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.x509; import java.io.IOException; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; /** * Represent the CertificatePolicyInformation ASN.1 object. * * @author Christine Ho */ public class CertificatePolicyInfo implements java.io.Serializable { /** * */ private static final long serialVersionUID = -8516006396099280477L; private CertificatePolicyId mPolicyIdentifier; private PolicyQualifiers mPolicyQualifiers; /** * Create a CertificatePolicyInfo with the passed CertificatePolicyId's. * * @param id the CertificatePolicyId. */ public CertificatePolicyInfo(CertificatePolicyId id) { this.mPolicyIdentifier = id; this.mPolicyQualifiers = null; } public CertificatePolicyInfo(CertificatePolicyId id, PolicyQualifiers qualifiers) { this.mPolicyIdentifier = id; this.mPolicyQualifiers = qualifiers; } /** * Create the CertificatePolicyInfo from the DER encoded value. * * @param val the DER encoded value of the same. */ public CertificatePolicyInfo(DerValue val) throws IOException { if (val.tag != DerValue.tag_Sequence) { throw new IOException("Invalid encoding for CertificatePolicyInfo"); } mPolicyIdentifier = new CertificatePolicyId(val.data.getDerValue()); // The specification is not clear on whether qualifier is // optional or not. GTE CyberTrust Root certificate has // no qualifier. if (val.data.available() == 0) { mPolicyQualifiers = null; } else { mPolicyQualifiers = new PolicyQualifiers(val.data.getDerValue()); } } /** * return the policy identifier of the policy info */ public CertificatePolicyId getPolicyIdentifier() { return (mPolicyIdentifier); } public PolicyQualifiers getPolicyQualifiers() { return mPolicyQualifiers; } /** * Returns a printable representation of the CertificatePolicyId. */ public String toString() { String s = "CertificatePolicyInfo: [\n" + "PolicyIdentifier:" + mPolicyIdentifier.toString() + "]\n"; return (s); } /** * Write the CertificatePolicyInfo to the DerOutputStream. * * @param out the DerOutputStream to write the object to. * @exception IOException on errors. */ public void encode(DerOutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); mPolicyIdentifier.encode(tmp); if (mPolicyQualifiers != null) { mPolicyQualifiers.encode(tmp); } out.write(DerValue.tag_Sequence, tmp); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 3230 Content-Disposition: inline; filename="CertificatePolicyMap.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "aef43d3873de067b4ad397a17debf224b418bad2" // --- 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.x509; import java.io.IOException; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; /** * Represent the CertificatePolicyMap ASN.1 object. * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.5 */ public class CertificatePolicyMap { private CertificatePolicyId issuerDomain; private CertificatePolicyId subjectDomain; /** * Create a CertificatePolicyMap with the passed CertificatePolicyId's. * * @param issuer the CertificatePolicyId for the issuer CA. * @param subject the CertificatePolicyId for the subject CA. */ public CertificatePolicyMap(CertificatePolicyId issuer, CertificatePolicyId subject) { this.issuerDomain = issuer; this.subjectDomain = subject; } /** * Create the CertificatePolicyMap from the DER encoded value. * * @param val the DER encoded value of the same. */ public CertificatePolicyMap(DerValue val) throws IOException { if (val.tag != DerValue.tag_Sequence) { throw new IOException("Invalid encoding for CertificatePolicyMap"); } issuerDomain = new CertificatePolicyId(val.data.getDerValue()); subjectDomain = new CertificatePolicyId(val.data.getDerValue()); } /** * Return the issuer CA part of the policy map. */ public CertificatePolicyId getIssuerIdentifier() { return (issuerDomain); } /** * Return the subject CA part of the policy map. */ public CertificatePolicyId getSubjectIdentifier() { return (subjectDomain); } /** * Returns a printable representation of the CertificatePolicyId. */ public String toString() { String s = "CertificatePolicyMap: [\n" + "IssuerDomain:" + issuerDomain.toString() + "SubjectDomain:" + subjectDomain.toString() + "]\n"; return (s); } /** * Write the CertificatePolicyMap to the DerOutputStream. * * @param out the DerOutputStream to write the object to. * @exception IOException on errors. */ public void encode(DerOutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); issuerDomain.encode(tmp); subjectDomain.encode(tmp); out.write(DerValue.tag_Sequence, tmp); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 2588 Content-Disposition: inline; filename="CertificatePolicySet.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "7b6558df186c0efceb343228d25607a0526b4316" // --- 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.x509; import java.io.IOException; import java.util.Vector; import netscape.security.util.DerInputStream; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; /** * This class defines the certificate policy set ASN.1 object. * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.4 */ public class CertificatePolicySet { private Vector ids; /** * The default constructor for this class. * * @param ids the sequence of CertificatePolicyId's. */ public CertificatePolicySet(Vector ids) { this.ids = ids; } /** * Create the object from the DerValue. * * @param in the passed DerInputStream. * @exception IOException on decoding errors. */ public CertificatePolicySet(DerInputStream in) throws IOException { ids = new Vector(1, 1); DerValue[] seq = in.getSequence(5); for (int i = 0; i < seq.length; i++) { CertificatePolicyId id = new CertificatePolicyId(seq[i]); ids.addElement(id); } } /** * Return printable form of the object. */ public String toString() { String s = "CertificatePolicySet:[\n" + ids.toString() + "]\n"; return (s); } /** * Encode the policy set to the output stream. * * @param out the DerOutputStream to encode the data to. */ public void encode(DerOutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); for (int i = 0; i < ids.size(); i++) { ids.elementAt(i).encode(tmp); } out.write(DerValue.tag_Sequence, tmp); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 5774 Content-Disposition: inline; filename="CertificateSerialNumber.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "6dd353f16da65d7d95284f310c7ab259316c96d5" // --- 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.x509; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.math.BigInteger; import java.util.Enumeration; import java.util.Vector; import netscape.security.util.DerInputStream; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; /** * This class defines the SerialNumber attribute for the Certificate. * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.6 * @see CertAttrSet */ public class CertificateSerialNumber implements CertAttrSet { /** * Identifier for this attribute, to be used with the * get, set, delete methods of Certificate, x509 type. */ public static final String IDENT = "x509.info.serialNumber"; /** * Sub attributes name for this CertAttrSet. */ public static final String NAME = "serialNumber"; public static final String NUMBER = "number"; private SerialNumber serial; /** * Default constructor for the certificate attribute. * * @param serial the serial number for the certificate. */ public CertificateSerialNumber(BigInteger num) { this.serial = new SerialNumber(num); } /** * Default constructor for the certificate attribute. * * @param serial the serial number for the certificate. */ public CertificateSerialNumber(int num) { this.serial = new SerialNumber(num); } /** * Create the object, decoding the values from the passed DER stream. * * @param in the DerInputStream to read the serial number from. * @exception IOException on decoding errors. */ public CertificateSerialNumber(DerInputStream in) throws IOException { serial = new SerialNumber(in); } /** * Create the object, decoding the values from the passed stream. * * @param in the InputStream to read the serial number from. * @exception IOException on decoding errors. */ public CertificateSerialNumber(InputStream in) throws IOException { serial = new SerialNumber(in); } /** * Create the object, decoding the values from the passed DerValue. * * @param val the DER encoded value. * @exception IOException on decoding errors. */ public CertificateSerialNumber(DerValue val) throws IOException { serial = new SerialNumber(val); } /** * Return the serial number as user readable string. */ public String toString() { if (serial == null) return ""; return (serial.toString()); } /** * Encode the serial number in DER form to the stream. * * @param out the DerOutputStream to marshal the contents to. * @exception IOException on errors. */ public void encode(OutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); serial.encode(tmp); out.write(tmp.toByteArray()); } /** * Decode the serial number in DER form from the stream. * * @param in the InputStream to marshal the contents from. * @exception IOException on errors. */ public void decode(InputStream in) throws IOException { DerValue derVal = new DerValue(in); serial = new SerialNumber(derVal); } /** * Set the attribute value. */ public void set(String name, Object obj) throws IOException { if (!(obj instanceof SerialNumber)) { throw new IOException("Attribute must be of type SerialNumber."); } if (name.equalsIgnoreCase(NUMBER)) { serial = (SerialNumber) obj; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:CertificateSerialNumber."); } } /** * Get the attribute value. */ public Object get(String name) throws IOException { if (name.equalsIgnoreCase(NUMBER)) { return (serial); } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:CertificateSerialNumber."); } } /** * Delete the attribute value. */ public void delete(String name) throws IOException { if (name.equalsIgnoreCase(NUMBER)) { serial = null; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:CertificateSerialNumber."); } } /** * Return an enumeration of names of attributes existing within this * attribute. */ public Enumeration getAttributeNames() { Vector elements = new Vector(); elements.addElement(NUMBER); return (elements.elements()); } /** * Return the name of this attribute. */ public String getName() { return (NAME); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 5970 Content-Disposition: inline; filename="CertificateSubjectName.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "f8dfe41f84baa9150473eff37d9ef6055b5d4fd9" // --- 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.x509; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.OutputStream; import java.io.Serializable; import java.util.Enumeration; import java.util.Vector; import netscape.security.util.DerInputStream; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; /** * This class defines the X500Name attribute for the Certificate. * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.6 * @see CertAttrSet */ public class CertificateSubjectName implements CertAttrSet, Serializable { /** * */ private static final long serialVersionUID = 503643453152834350L; /** * Identifier for this attribute, to be used with the * get, set, delete methods of Certificate, x509 type. */ public static final String IDENT = "x509.info.subject"; /** * Sub attributes name for this CertAttrSet. */ public static final String NAME = "subject"; public static final String DN_NAME = "dname"; // Private data member private X500Name dnName; /** * Default constructor for the certificate attribute. * * @param name the X500Name */ public CertificateSubjectName(X500Name name) { this.dnName = name; } /** * Create the object, decoding the values from the passed DER stream. * * @param in the DerInputStream to read the X500Name from. * @exception IOException on decoding errors. */ public CertificateSubjectName(DerInputStream in) throws IOException { dnName = new X500Name(in); } /** * Create the object, decoding the values from the passed stream. * * @param in the InputStream to read the X500Name from. * @exception IOException on decoding errors. */ public CertificateSubjectName(InputStream in) throws IOException { DerValue derVal = new DerValue(in); dnName = new X500Name(derVal); } /** * Return the name as user readable string. */ public String toString() { if (dnName == null) return ""; return (dnName.toString()); } private void writeObject(ObjectOutputStream stream) throws IOException { encode(stream); } private void readObject(ObjectInputStream stream) throws IOException { decodeEx(stream); } /** * Encode the name in DER form to the stream. * * @param out the DerOutputStream to marshal the contents to. * @exception IOException on errors. */ public void encode(OutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); dnName.encode(tmp); out.write(tmp.toByteArray()); } /** * Decode the name in DER form from the stream. * * @param in the InputStream to marshal the contents from. * @exception IOException on errors. */ public void decodeEx(InputStream in) throws IOException { DerValue derVal = new DerValue(in); // dnName = new X500Name(derVal); dnName = new X500Name(derVal.toByteArray()); } /** * Decode the name in DER form from the stream. * * @param in the InputStream to marshal the contents from. * @exception IOException on errors. */ public void decode(InputStream in) throws IOException { DerValue derVal = new DerValue(in); dnName = new X500Name(derVal); } /** * Set the attribute value. */ public void set(String name, Object obj) throws IOException { if (!(obj instanceof X500Name)) { throw new IOException("Attribute must be of type X500Name."); } if (name.equalsIgnoreCase(DN_NAME)) { this.dnName = (X500Name) obj; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:CertificateSubjectName."); } } /** * Get the attribute value. */ public Object get(String name) throws IOException { if (name.equalsIgnoreCase(DN_NAME)) { return (dnName); } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:CertificateSubjectName."); } } /** * Delete the attribute value. */ public void delete(String name) throws IOException { if (name.equalsIgnoreCase(DN_NAME)) { dnName = null; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:CertificateSubjectName."); } } /** * Return an enumeration of names of attributes existing within this * attribute. */ public Enumeration getAttributeNames() { Vector elements = new Vector(); elements.addElement(DN_NAME); return (elements.elements()); } /** * Return the name of this attribute. */ public String getName() { return (NAME); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 5613 Content-Disposition: inline; filename="CertificateSubjectUniqueIdentity.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "9f9f9222cde0401003c7e21dc108240b0a575c5b" // --- 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.x509; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Enumeration; import java.util.Vector; import netscape.security.util.DerInputStream; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; /** * This class defines the subject/issuer unique identity attribute * for the Certificate. * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.6 * @see CertAttrSet */ public class CertificateSubjectUniqueIdentity implements CertAttrSet { /** * Identifier for this attribute, to be used with the * get, set, delete methods of Certificate, x509 type. */ public static final String IDENT = "x509.info.subjectID"; /** * Sub attributes name for this CertAttrSet. */ public static final String NAME = "subjectID"; public static final String ID = "id"; private UniqueIdentity id; /** * Default constructor for the certificate attribute. * * @param key the UniqueIdentity */ public CertificateSubjectUniqueIdentity(UniqueIdentity id) { this.id = id; } /** * Create the object, decoding the values from the passed DER stream. * * @param in the DerInputStream to read the UniqueIdentity from. * @exception IOException on decoding errors. */ public CertificateSubjectUniqueIdentity(DerInputStream in) throws IOException { id = new UniqueIdentity(in); } /** * Create the object, decoding the values from the passed stream. * * @param in the InputStream to read the UniqueIdentity from. * @exception IOException on decoding errors. */ public CertificateSubjectUniqueIdentity(InputStream in) throws IOException { DerValue val = new DerValue(in); id = new UniqueIdentity(val); } /** * Create the object, decoding the values from the passed DER value. * * @param in the DerValue to read the UniqueIdentity from. * @exception IOException on decoding errors. */ public CertificateSubjectUniqueIdentity(DerValue val) throws IOException { id = new UniqueIdentity(val); } /** * Return the identity as user readable string. */ public String toString() { if (id == null) return ""; return (id.toString()); } /** * Decode the identity in DER form from the stream. * * @param in the InputStream to unmarshal the contents from. * @exception IOException on errors. */ public void decode(InputStream in) throws IOException { DerValue val = new DerValue(in); id = new UniqueIdentity(val); } /** * Encode the identity in DER form to the stream. * * @param out the DerOutputStream to marshal the contents to. * @exception IOException on errors. */ public void encode(OutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); id.encode(tmp, DerValue.createTag(DerValue.TAG_CONTEXT, false, (byte) 2)); out.write(tmp.toByteArray()); } /** * Set the attribute value. */ public void set(String name, Object obj) throws IOException { if (!(obj instanceof UniqueIdentity)) { throw new IOException("Attribute must be of type UniqueIdentity."); } if (name.equalsIgnoreCase(ID)) { id = (UniqueIdentity) obj; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet: CertificateSubjectUniqueIdentity."); } } /** * Get the attribute value. */ public Object get(String name) throws IOException { if (name.equalsIgnoreCase(ID)) { return (id); } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet: CertificateSubjectUniqueIdentity."); } } /** * Delete the attribute value. */ public void delete(String name) throws IOException { if (name.equalsIgnoreCase(ID)) { id = null; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet: CertificateSubjectUniqueIdentity."); } } /** * Return an enumeration of names of attributes existing within this * attribute. */ public Enumeration getAttributeNames() { Vector elements = new Vector(); elements.addElement(ID); return (elements.elements()); } /** * Return the name of this attribute. */ public String getName() { return (NAME); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 10354 Content-Disposition: inline; filename="CertificateValidity.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "292dab7690ec4fe2f9aa985c9a444f1d5daa10d2" // --- 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.x509; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.OutputStream; import java.io.Serializable; import java.security.cert.CertificateExpiredException; import java.security.cert.CertificateNotYetValidException; import java.util.Date; import java.util.Enumeration; import java.util.Vector; import netscape.security.util.DerInputStream; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; /** * This class defines the interval for which the certificate is valid. * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.12 * @see CertAttrSet */ public class CertificateValidity implements CertAttrSet, Serializable { private static final long serialVersionUID = 8277703278213804194L; /** * Identifier for this attribute, to be used with the * get, set, delete methods of Certificate, x509 type. */ public static final String IDENT = "x509.info.validity"; /** * Sub attributes name for this CertAttrSet. */ public static final String NAME = "validity"; public static final String NOT_BEFORE = "notBefore"; public static final String NOT_AFTER = "notAfter"; private static final long YR_2050 = 2524636800000L; // Private data members private Date notBefore; private Date notAfter; // Returns the first time the certificate is valid. private Date getNotBefore() { return (new Date(notBefore.getTime())); } // Returns the last time the certificate is valid. private Date getNotAfter() { return (new Date(notAfter.getTime())); } // Construct the class from the DerValue private void construct(DerValue derVal) throws IOException { if (derVal.tag != DerValue.tag_Sequence) { throw new IOException("Invalid encoded CertificateValidity, " + "starting sequence tag missing."); } // check if UTCTime encoded or GeneralizedTime if (derVal.data.available() == 0) throw new IOException("No data encoded for CertificateValidity"); DerInputStream derIn = new DerInputStream(derVal.toByteArray()); DerValue[] seq = derIn.getSequence(2); if (seq.length != 2) throw new IOException("Invalid encoding for CertificateValidity"); if (seq[0].tag == DerValue.tag_UtcTime) { notBefore = derVal.data.getUTCTime(); } else if (seq[0].tag == DerValue.tag_GeneralizedTime) { notBefore = derVal.data.getGeneralizedTime(); } else { throw new IOException("Invalid encoding for CertificateValidity"); } if (seq[1].tag == DerValue.tag_UtcTime) { notAfter = derVal.data.getUTCTime(); } else if (seq[1].tag == DerValue.tag_GeneralizedTime) { notAfter = derVal.data.getGeneralizedTime(); } else { throw new IOException("Invalid encoding for CertificateValidity"); } } /** * Default constructor for the class. */ public CertificateValidity() { } /** * The default constructor for this class for the specified interval. * * @param notBefore the date and time before which the certificate * is not valid. * @param notAfter the date and time after which the certificate is * not valid. */ public CertificateValidity(Date notBefore, Date notAfter) { this.notBefore = notBefore; this.notAfter = notAfter; } /** * Create the object, decoding the values from the passed DER stream. * * @param in the DerInputStream to read the CertificateValidity from. * @exception IOException on decoding errors. */ public CertificateValidity(DerInputStream in) throws IOException { DerValue derVal = in.getDerValue(); construct(derVal); } /** * Return the validity period as user readable string. */ public String toString() { if (notBefore == null || notAfter == null) return ""; return ("Validity: [From: " + notBefore.toString() + ",\n To: " + notAfter.toString() + "]"); } /** * Decode the CertificateValidity period from the InputStream. * * @param in the InputStream to unmarshal the contents from. * @exception IOException on errors. */ public void decode(InputStream in) throws IOException { DerValue derVal = new DerValue(in); construct(derVal); } private void writeObject(ObjectOutputStream stream) throws IOException { encode(stream); } private void readObject(ObjectInputStream stream) throws IOException { decode(stream); } /** * Encode the CertificateValidity period in DER form to the stream. * * @param out the OutputStream to marshal the contents to. * @exception IOException on errors. */ public void encode(OutputStream out) throws IOException { // in cases where default constructor is used check for // null values if (notBefore == null || notAfter == null) { throw new IOException("CertAttrSet:CertificateValidity:" + " null values to encode.\n"); } try (DerOutputStream pair = new DerOutputStream(); DerOutputStream seq = new DerOutputStream()) { if (notBefore.getTime() < YR_2050) { pair.putUTCTime(notBefore); } else pair.putGeneralizedTime(notBefore); if (notAfter.getTime() < YR_2050) { pair.putUTCTime(notAfter); } else { pair.putGeneralizedTime(notAfter); } seq.write(DerValue.tag_Sequence, pair); out.write(seq.toByteArray()); } } /** * Set the attribute value. */ public void set(String name, Object obj) throws IOException { if (!(obj instanceof Date)) { throw new IOException("Attribute must be of type Date."); } if (name.equalsIgnoreCase(NOT_BEFORE)) { notBefore = (Date) obj; } else if (name.equalsIgnoreCase(NOT_AFTER)) { notAfter = (Date) obj; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet: CertificateValidity."); } } /** * Get the attribute value. */ public Object get(String name) throws IOException { if (name.equalsIgnoreCase(NOT_BEFORE)) { return (getNotBefore()); } else if (name.equalsIgnoreCase(NOT_AFTER)) { return (getNotAfter()); } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet: CertificateValidity."); } } /** * Delete the attribute value. */ public void delete(String name) throws IOException { if (name.equalsIgnoreCase(NOT_BEFORE)) { notBefore = null; } else if (name.equalsIgnoreCase(NOT_AFTER)) { notAfter = null; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet: CertificateValidity."); } } /** * Return an enumeration of names of attributes existing within this * attribute. */ public Enumeration getAttributeNames() { Vector elements = new Vector(); elements.addElement(NOT_BEFORE); elements.addElement(NOT_AFTER); return (elements.elements()); } /** * Return the name of this attribute. */ public String getName() { return (NAME); } /** * Verify that the current time is within the validity period. * * @exception CertificateExpiredException if the certificate has expired. * @exception CertificateNotYetValidException if the certificate is not * yet valid. */ public void valid() throws CertificateNotYetValidException, CertificateExpiredException { Date now = new Date(); valid(now); } /** * Verify that the passed time is within the validity period. * * @param now the Date against which to compare the validity * period. * * @exception CertificateExpiredException if the certificate has expired * with respect to the Date supplied. * @exception CertificateNotYetValidException if the certificate is not * yet valid with respect to the Date supplied. * */ public void valid(Date now) throws CertificateNotYetValidException, CertificateExpiredException { /* * we use the internal Dates rather than the passed in Date * because someone could override the Date methods after() * and before() to do something entirely different. */ if (notBefore.after(now)) { throw new CertificateNotYetValidException("NotBefore: " + notBefore.toString()); } if (notAfter.before(now)) { throw new CertificateExpiredException("NotAfter: " + notAfter.toString()); } } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 7334 Content-Disposition: inline; filename="CertificateVersion.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "a59542eb62b7f1ff41f2949b0b6fac933454fa9e" // --- 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.x509; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Enumeration; import java.util.Vector; import netscape.security.util.BigInt; import netscape.security.util.DerInputStream; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; /** * This class defines the version of the X509 Certificate. * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.8 * @see CertAttrSet */ public class CertificateVersion implements CertAttrSet { /** * X509Certificate Version 1 */ public static final int V1 = 0; /** * X509Certificate Version 2 */ public static final int V2 = 1; /** * X509Certificate Version 3 */ public static final int V3 = 2; /** * Identifier for this attribute, to be used with the * get, set, delete methods of Certificate, x509 type. */ public static final String IDENT = "x509.info.version"; /** * Sub attributes name for this CertAttrSet. */ public static final String NAME = "version"; public static final String VERSION = "number"; // Private data members int version = V1; // Returns the version number. private int getVersion() { return (version); } // Construct the class from the passed DerValue private void construct(DerValue derVal) throws IOException { if (derVal.isConstructed() && derVal.isContextSpecific()) { derVal = derVal.data.getDerValue(); version = derVal.getInteger().toInt(); if (derVal.data.available() != 0) { throw new IOException("X.509 version, bad format"); } } } /** * The default constructor for this class, * sets the version to 0 (i.e. X.509 version 1). */ public CertificateVersion() { version = V1; } /** * The constructor for this class for the required version. * * @param version the version for the certificate. * @exception IOException if the version is not valid. */ public CertificateVersion(int version) throws IOException { // check that it is a valid version if (version == V1 || version == V2 || version == V3) this.version = version; else { throw new IOException("X.509 Certificate version " + version + " not supported.\n"); } } /** * Create the object, decoding the values from the passed DER stream. * * @param in the DerInputStream to read the CertificateVersion from. * @exception IOException on decoding errors. */ public CertificateVersion(DerInputStream in) throws IOException { version = V1; DerValue derVal = in.getDerValue(); construct(derVal); } /** * Create the object, decoding the values from the passed stream. * * @param in the InputStream to read the CertificateVersion from. * @exception IOException on decoding errors. */ public CertificateVersion(InputStream in) throws IOException { version = V1; DerValue derVal = new DerValue(in); construct(derVal); } /** * Create the object, decoding the values from the passed DerValue. * * @param val the Der encoded value. * @exception IOException on decoding errors. */ public CertificateVersion(DerValue val) throws IOException { version = V1; construct(val); } /** * Return the version number of the certificate. */ public String toString() { return ("Version: V" + (version + 1)); } /** * Encode the CertificateVersion period in DER form to the stream. * * @param out the OutputStream to marshal the contents to. * @exception IOException on errors. */ public void encode(OutputStream out) throws IOException { // Nothing for default if (version == V1) { return; } try (DerOutputStream tmp = new DerOutputStream(); DerOutputStream seq = new DerOutputStream()) { tmp.putInteger(new BigInt(version)); seq.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0), tmp); out.write(seq.toByteArray()); } } /** * Decode the CertificateVersion period in DER form from the stream. * * @param in the InputStream to unmarshal the contents from. * @exception IOException on errors. */ public void decode(InputStream in) throws IOException { DerValue derVal = new DerValue(in); construct(derVal); } /** * Set the attribute value. */ public void set(String name, Object obj) throws IOException { if (!(obj instanceof Integer)) { throw new IOException("Attribute must be of type Integer."); } if (name.equalsIgnoreCase(VERSION)) { version = ((Integer) obj).intValue(); } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet: CertificateVersion."); } } /** * Get the attribute value. */ public Object get(String name) throws IOException { if (name.equalsIgnoreCase(VERSION)) { return (Integer.valueOf(getVersion())); } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet: CertificateVersion."); } } /** * Delete the attribute value. */ public void delete(String name) throws IOException { if (name.equalsIgnoreCase(VERSION)) { version = V1; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet: CertificateVersion."); } } /** * Return an enumeration of names of attributes existing within this * attribute. */ public Enumeration getAttributeNames() { Vector elements = new Vector(); elements.addElement(VERSION); return (elements.elements()); } /** * Return the name of this attribute. */ public String getName() { return (NAME); } /** * Compare versions. */ public int compare(int vers) { return (version - vers); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 5485 Content-Disposition: inline; filename="CertificateX509Key.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "0b6f250d9bdb61567ff26ffb6e803a78ba0075cf" // --- 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.x509; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.OutputStream; import java.io.Serializable; import java.util.Enumeration; import java.util.Vector; import netscape.security.util.DerInputStream; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; /** * This class defines the X509Key attribute for the Certificate. * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.5 * @see CertAttrSet */ public class CertificateX509Key implements CertAttrSet, Serializable { /** * */ private static final long serialVersionUID = 6718749024328681131L; /** * Identifier for this attribute, to be used with the * get, set, delete methods of Certificate, x509 type. */ public static final String IDENT = "x509.info.key"; /** * Sub attributes name for this CertAttrSet. */ public static final String NAME = "key"; public static final String KEY = "value"; // Private data member private X509Key key; /** * Default constructor for the certificate attribute. * * @param key the X509Key */ public CertificateX509Key(X509Key key) { this.key = key; } /** * Create the object, decoding the values from the passed DER stream. * * @param in the DerInputStream to read the X509Key from. * @exception IOException on decoding errors. */ public CertificateX509Key(DerInputStream in) throws IOException { DerValue val = in.getDerValue(); key = X509Key.parse(val); } /** * Create the object, decoding the values from the passed stream. * * @param in the InputStream to read the X509Key from. * @exception IOException on decoding errors. */ public CertificateX509Key(InputStream in) throws IOException { DerValue val = new DerValue(in); key = X509Key.parse(val); } /** * Return the key as printable string. */ public String toString() { if (key == null) return ""; return (key.toString()); } /** * Decode the key in DER form from the stream. * * @param in the InputStream to unmarshal the contents from * @exception IOException on decoding or validity errors. */ public void decode(InputStream in) throws IOException { DerValue val = new DerValue(in); key = X509Key.parse(val); } private void writeObject(ObjectOutputStream stream) throws IOException { encode(stream); } private void readObject(ObjectInputStream stream) throws IOException { decode(stream); } /** * Encode the key in DER form to the stream. * * @param out the OutputStream to marshal the contents to. * @exception IOException on errors. */ public void encode(OutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); key.encode(tmp); out.write(tmp.toByteArray()); } /** * Set the attribute value. */ public void set(String name, Object obj) throws IOException { if (!(obj instanceof X509Key)) { throw new IOException("Attribute must be of type X509Key."); } if (name.equalsIgnoreCase(KEY)) { this.key = (X509Key) obj; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet: CertificateX509Key."); } } /** * Get the attribute value. */ public Object get(String name) throws IOException { if (name.equalsIgnoreCase(KEY)) { return (key); } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet: CertificateX509Key."); } } /** * Delete the attribute value. */ public void delete(String name) throws IOException { if (name.equalsIgnoreCase(KEY)) { key = null; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet: CertificateX509Key."); } } /** * Return an enumeration of names of attributes existing within this * attribute. */ public Enumeration getAttributeNames() { Vector elements = new Vector(); elements.addElement(KEY); return (elements.elements()); } /** * Return the name of this attribute. */ public String getName() { return (NAME); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 2427 Content-Disposition: inline; filename="DNSName.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "2161adf3701a554040ca4afc5b0c39337ed8452a" // --- 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.x509; import java.io.IOException; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; /** * This class implements the DNSName as required by the GeneralNames * ASN.1 object. * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.4 */ public class DNSName implements GeneralNameInterface { /** * */ private static final long serialVersionUID = -2907649488092607056L; private String name; /** * Create the DNSName object from the passed encoded Der value. * * @param derValue the encoded DER DNSName. * @exception IOException on error. */ public DNSName(DerValue derValue) throws IOException { name = derValue.getIA5String(); } /** * Create the DNSName object with the specified name. * * @param name the DNSName. */ public DNSName(String name) { this.name = name; } /** * Return the type of the GeneralName. */ public int getType() { return (GeneralNameInterface.NAME_DNS); } /** * Encode the DNS name into the DerOutputStream. * * @param out the DER stream to encode the DNSName to. * @exception IOException on encoding errors. */ public void encode(DerOutputStream out) throws IOException { out.putIA5String(name); } /** * Convert the name into user readable string. */ public String toString() { return ("DNSName: " + name); } /** * Get the raw DNSName value. */ public String getValue() { return name; } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 7966 Content-Disposition: inline; filename="DeltaCRLIndicatorExtension.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "09400ef8e9630b89c0a724c689e5cf3730f9d2b4" // --- 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.x509; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Array; import java.math.BigInteger; import java.security.cert.CertificateException; import java.util.Enumeration; import java.util.Vector; import netscape.security.util.BigInt; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; /** * Represent the Delta CRL Indicator Extension. * *

* The delta CRL indicator is a critical CRL extension that identifies a delta-CRL. The value of BaseCRLNumber * identifies the CRL number of the base CRL that was used as the starting point in the generation of this delta- CRL. * The delta-CRL contains the changes between the base CRL and the current CRL issued along with the delta-CRL. * * @see Extension * @see CertAttrSet */ public class DeltaCRLIndicatorExtension extends Extension implements CertAttrSet { /** * */ private static final long serialVersionUID = 7182919216525364676L; /** * Attribute name. */ public static final String NAME = "DeltaCRLIndicator"; public static final String NUMBER = "value"; /** * The Object Identifier for this extension. */ public static final String OID = "2.5.29.27"; private BigInt baseCRLNumber = null; static { try { OIDMap.addAttribute(DeltaCRLIndicatorExtension.class.getName(), OID, NAME); } catch (CertificateException e) { } } // Encode this extension value private void encodeThis() throws IOException { if (baseCRLNumber == null) throw new IOException("Unintialized delta CRL indicator extension"); try (DerOutputStream os = new DerOutputStream()) { os.putInteger(this.baseCRLNumber); this.extensionValue = os.toByteArray(); } } /** * Create a DeltaCRLIndicatorExtension with the integer value. * The criticality is set to true. * * @param baseCRLNum the value to be set for the extension. */ public DeltaCRLIndicatorExtension(int baseCRLNum) throws IOException { this.baseCRLNumber = new BigInt(baseCRLNum); this.extensionId = PKIXExtensions.DeltaCRLIndicator_Id; this.critical = true; encodeThis(); } /** * Create a DeltaCRLIndicatorExtension with the BigInteger value. * The criticality is set to true. * * @param baseCRLNum the value to be set for the extension. */ public DeltaCRLIndicatorExtension(BigInteger baseCRLNum) throws IOException { this.baseCRLNumber = new BigInt(baseCRLNum); this.extensionId = PKIXExtensions.DeltaCRLIndicator_Id; this.critical = true; encodeThis(); } /** * Create a DeltaCRLIndicatorExtension with the BigInteger value. * * @param critical true if the extension is to be treated as critical. * @param baseCRLNum the value to be set for the extension. */ public DeltaCRLIndicatorExtension(Boolean critical, BigInteger baseCRLNum) throws IOException { this.baseCRLNumber = new BigInt(baseCRLNum); this.extensionId = PKIXExtensions.DeltaCRLIndicator_Id; this.critical = critical.booleanValue(); encodeThis(); } /** * Create the extension from the passed DER encoded value of the same. * * @param critical true if the extension is to be treated as critical. * @param value Array of DER encoded bytes of the actual value. * @exception IOException on error. */ public DeltaCRLIndicatorExtension(Boolean critical, Object value) throws IOException { this.extensionId = PKIXExtensions.DeltaCRLIndicator_Id; this.critical = critical.booleanValue(); int len = Array.getLength(value); byte[] extValue = new byte[len]; for (int i = 0; i < len; i++) { extValue[i] = Array.getByte(value, i); } this.extensionValue = extValue; DerValue val = new DerValue(extValue); this.baseCRLNumber = val.getInteger(); } /** * Set the attribute value. */ public void set(String name, Object obj) throws IOException { if (name.equalsIgnoreCase(NUMBER)) { if (!(obj instanceof BigInteger)) { throw new IOException("Attribute must be of type BigInteger."); } baseCRLNumber = new BigInt((BigInteger) obj); } else { throw new IOException("Attribute name not recognized by" + " CertAttrSet:DeltaCRLIndicator."); } } /** * Get the attribute value. */ public Object get(String name) throws IOException { if (name.equalsIgnoreCase(NUMBER)) { if (baseCRLNumber == null) return null; else return baseCRLNumber.toBigInteger(); } else { throw new IOException("Attribute name not recognized by" + " CertAttrSet:DeltaCRLIndicator."); } } /** * Delete the attribute value. */ public void delete(String name) throws IOException { if (name.equalsIgnoreCase(NUMBER)) { baseCRLNumber = null; } else { throw new IOException("Attribute name not recognized by" + " CertAttrSet:DeltaCRLIndicator."); } } /** * Returns a printable representation of the DeltaCRLIndicatorExtension. */ public String toString() { String s = super.toString() + "Delta CRL Indicator: " + ((baseCRLNumber == null) ? "" : baseCRLNumber.toString()) + "\n"; return (s); } /** * Decode the extension from the InputStream. * * @param in the InputStream to unmarshal the contents from. * @exception IOException on decoding or validity errors. */ public void decode(InputStream in) throws IOException { throw new IOException("Method not to be called directly."); } /** * Write the extension to the DerOutputStream. * * @param out the DerOutputStream to write the extension to. * @exception IOException on encoding errors. */ public void encode(OutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); if (this.extensionValue == null) { this.extensionId = PKIXExtensions.DeltaCRLIndicator_Id; this.critical = true; encodeThis(); } super.encode(tmp); out.write(tmp.toByteArray()); } /** * Return an enumeration of names of attributes existing within this * attribute. */ public Enumeration getAttributeNames() { Vector elements = new Vector(); elements.addElement(NUMBER); return (elements.elements()); } /** * Return the name of this attribute. */ public String getName() { return (NAME); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 6278 Content-Disposition: inline; filename="DirStrConverter.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "8b59808ecc168e7085b8f81ec452ab8a57dc1b0c" // --- 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.x509; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.CharacterCodingException; import java.nio.charset.CharsetEncoder; import netscape.security.util.ASN1CharStrConvMap; import netscape.security.util.DerValue; /** * A DirStrConverter converts a string to a DerValue of ASN.1 Directory String, * which is a CHOICE of Printable (subset of ASCII), T.61 (Teletex) or * Universal String (UCS-4), and vice versa. * *

* The string to DerValue conversion is done as follows. If the string has only PrintableString characters it is * converted to a ASN.1 Printable String using the PrintableString encoder from the global default ASN1CharStrConvMap. * If it has only characters covered in the PrintableString or T.61 character set it is converted to a ASN.1 T.61 string * using the T.61 encoder from the ASN1CharStrCovnMap. Otherwise it is converted to a ASN.1 UniversalString (UCS-4 * character set) which covers all characters. * * @see AVAValueConverter * @see ASN1CharStrConvMap * * @author Lily Hsiao, Slava Galperin at Netscape Communications, Inc. */ public class DirStrConverter implements AVAValueConverter { // public constructors /** * Constructs a DirStrConverter. */ public DirStrConverter() { } // public functions /** * Converts a string to a DER encoded ASN1 Directory String, which is a * CHOICE of PrintableString, T.61String or UniversalString. * The string is taken as is i.e. should not be in Ldap DN string syntax. * * @param ds a string representing a directory string value. * * @return a DerValue * * @exception IOException if the string cannot be converted, such as * when a UniversalString encoder * isn't available and the string contains * characters covered only in the universal * string (or UCS-4) character set. */ private static byte[] DefEncodingOrder = new byte[] { DerValue.tag_UTF8String, DerValue.tag_PrintableString, DerValue.tag_T61String, DerValue.tag_UniversalString }; public static synchronized void setDefEncodingOrder(byte[] defEncodingOrder) { DefEncodingOrder = defEncodingOrder; } public DerValue getValue(String ds) throws IOException { return getValue(ds, DefEncodingOrder); } /** * Like getValue(String) with specified DER tags as encoding order. */ public DerValue getValue(String valueString, byte[] tags) throws IOException { // try to convert to printable, then t61 the universal - // i.e. from minimal to the most liberal. if (tags == null || tags.length == 0) tags = DefEncodingOrder; for (int i = 0; i < tags.length; i++) { try { CharsetEncoder encoder = ASN1CharStrConvMap.getDefault().getEncoder(tags[i]); if (encoder == null) continue; CharBuffer charBuffer = CharBuffer.wrap(valueString.toCharArray()); ByteBuffer byteBuffer = encoder.encode(charBuffer); return new DerValue(tags[i], byteBuffer.array(), byteBuffer.arrayOffset(), byteBuffer.limit()); } catch (CharacterCodingException e) { continue; } } throw new IOException( "Cannot convert the directory string value to a ASN.1 type"); } /** * Creates a DerValue from a BER encoded value, obtained from for example * a attribute value in octothorpe form of a Ldap DN string. * Checks if the BER encoded value is legal for a DirectoryString. * * NOTE: currently only supports DER encoding for the BER encoded value. * * @param berStream Byte array of a BER encoded value. * * @return DerValue object. * * @exception IOException If the BER value cannot be converted to a * valid Directory String DER value. */ public DerValue getValue(byte[] berByteStream) throws IOException { DerValue value = new DerValue(berByteStream); /* if (value.tag != DerValue.tag_PrintableString && value.tag != DerValue.tag_T61String && value.tag != DerValue.tag_UniversalString) throw new IOException("Invalid Directory String AVA Value"); */ return value; } /** * Converts a DerValue to a string. * The string is not in any syntax, such as RFC1779 string syntax. * * @param avaValue a DerValue * @return a string if the value can be converted. * @exception IOException if a decoder needed for the * conversion is not available. */ public String getAsString(DerValue avaValue) throws IOException { /* if (avaValue.tag != DerValue.tag_PrintableString && avaValue.tag != DerValue.tag_BMPString && avaValue.tag != DerValue.tag_UniversalString && avaValue.tag != DerValue.tag_T61String) throw new IllegalArgumentException( "Invalid Directory String value"); // NOTE will return null if a decoder is not available. */ return avaValue.getASN1CharString(); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 2552 Content-Disposition: inline; filename="DisplayText.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "f0e712ff45b098ba76c2742138a73fae3de6a143" // --- 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.x509; import java.io.IOException; import java.io.Serializable; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; /** * Represent the DisplayText. * * DisplayText ::= CHOICE { * visibleString VisibleString (SIZE (1..200)), * bmpString BMPString (SIZE (1..200)), * utf8String UTF8String (SIZE (1..200)), * } * * @author Thomas Kwan */ public class DisplayText implements Serializable { private static final long serialVersionUID = -6521458152495173328L; /** Tag value indicating an ASN.1 "BMPString" value. */ public final static byte tag_IA5String = 0x16; public final static byte tag_BMPString = 0x1E; public final static byte tag_VisibleString = 0x1A; public final static byte tag_UTF8String = 0x0C; private byte mTag; private String mS = null; public DisplayText(byte tag, String s) { mTag = tag; mS = s; } public DisplayText(DerValue val) throws IOException { mTag = val.tag; mS = val.getAsString(); } /** * Write the DisplayText to the DerOutputStream. * * @param out the DerOutputStream to write the object to. * @exception IOException on errors. */ public void encode(DerOutputStream out) throws IOException { out.putStringType(mTag, mS); } public String getText() { return mS; } public String toString() { if (mTag == tag_IA5String) { return "IA5String: " + mS; } else if (mTag == tag_BMPString) { return "BMPString: " + mS; } else if (mTag == tag_VisibleString) { return "VisibleString: " + mS; } else { return "UTF8String: " + mS; } } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 5185 Content-Disposition: inline; filename="EDIPartyName.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "0efb1c59c7a258f61eeab600018a127abeff333e" // --- 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.x509; import java.io.IOException; import netscape.security.util.DerInputStream; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; /** * This class defines the EDIPartyName of the GeneralName choice. * The ASN.1 syntax for this is: * *

 * EDIPartyName ::= SEQUENCE {
 *     nameAssigner  [0]  DirectoryString OPTIONAL,
 *     partyName     [1]  DirectoryString }
 * 
* * @author Hemma Prafullchandra * @version 1.2 * @see GeneralName * @see GeneralNames * @see GeneralNameInterface */ public class EDIPartyName implements GeneralNameInterface { /** * */ private static final long serialVersionUID = -8669257424766789063L; // Private data members private static final byte TAG_ASSIGNER = 0; private static final byte TAG_PARTYNAME = 1; private String assigner = null; private String party = null; /** * Create the EDIPartyName object from the specified names. * * @param assignerName the name of the assigner * @param partyName the name of the EDI party. */ public EDIPartyName(String assignerName, String partyName) { this.assigner = assignerName; this.party = partyName; } /** * Create the EDIPartyName object from the specified name. * * @param partyName the name of the EDI party. */ public EDIPartyName(String partyName) { this.party = partyName; } /** * Create the EDIPartyName object from the passed encoded Der value. * * @param derValue the encoded DER EDIPartyName. * @exception IOException on error. */ public EDIPartyName(DerValue derValue) throws IOException { DerInputStream in = new DerInputStream(derValue.toByteArray()); DerValue[] seq = in.getSequence(2); int len = seq.length; if (len < 1 || len > 2) throw new IOException("Invalid encoding of EDIPartyName"); for (int i = 0; i < len; i++) { DerValue opt = seq[i]; if (opt.isContextSpecific(TAG_ASSIGNER) && !opt.isConstructed()) { if (assigner != null) throw new IOException("Duplicate nameAssigner found in" + " EDIPartyName"); opt = opt.data.getDerValue(); assigner = opt.getAsString(); } if (opt.isContextSpecific(TAG_PARTYNAME) && !opt.isConstructed()) { if (party != null) throw new IOException("Duplicate partyName found in" + " EDIPartyName"); opt = opt.data.getDerValue(); party = opt.getAsString(); } } } /** * Return the type of the GeneralName. */ public int getType() { return (GeneralNameInterface.NAME_EDI); } /** * Encode the EDI party name into the DerOutputStream. * * @param out the DER stream to encode the EDIPartyName to. * @exception IOException on encoding errors. */ public void encode(DerOutputStream out) throws IOException { DerOutputStream tagged = new DerOutputStream(); DerOutputStream tmp = new DerOutputStream(); if (assigner != null) { DerOutputStream tmp2 = new DerOutputStream(); // XXX - shd check is chars fit into PrintableString tmp2.putPrintableString(assigner); tagged.write(DerValue.createTag(DerValue.TAG_CONTEXT, false, TAG_ASSIGNER), tmp2); } if (party == null) { tagged.close(); tmp.close(); throw new IOException("Cannot have null partyName"); } // XXX - shd check is chars fit into PrintableString tmp.putPrintableString(party); tagged.write(DerValue.createTag(DerValue.TAG_CONTEXT, false, TAG_PARTYNAME), tmp); out.write(DerValue.tag_Sequence, tagged); } /** * Return the printable string. */ public String toString() { return ("EDIPartyName: " + ((assigner == null) ? "" : (" nameAssigner = " + assigner + ",")) + " partyName = " + party); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 6099 Content-Disposition: inline; filename="Extension.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "43bbafe8171e89185e07d35fa7a8b86971716cec" // --- 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.x509; import java.io.IOException; import java.io.Serializable; import netscape.security.util.DerInputStream; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; import netscape.security.util.ObjectIdentifier; /** * Represent a X509 Extension Attribute. * *

* Extensions are addiitonal attributes which can be inserted in a X509 v3 certificate. For example a * "Driving License Certificate" could have the driving license number as a extension. * *

* Extensions are represented as a sequence of the extension identifier (Object Identifier), a boolean flag stating * whether the extension is to be treated as being critical and the extension value itself (this is again a DER encoding * of the extension value). * *

 * ASN.1 definition of Extension:
 * Extension ::= SEQUENCE {
 * ExtensionId	OBJECT IDENTIFIER,
 * critical	BOOLEAN DEFAULT FALSE,
 * extensionValue	OCTET STRING
 * }
 * 
* * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.9 */ public class Extension implements Serializable { private static final long serialVersionUID = -643549610716024753L; protected ObjectIdentifier extensionId = null; protected boolean critical = false; protected byte[] extensionValue = null; /** * Default constructor. Used only by sub-classes. */ public Extension() { } /** * Constructs an extension from a DER encoded array of bytes. */ public Extension(DerValue derVal) throws IOException { DerInputStream in = derVal.toDerInputStream(); // Object identifier extensionId = in.getOID(); // If the criticality flag was false, it will not have been encoded. DerValue val = in.getDerValue(); if (val.tag == DerValue.tag_Boolean) { critical = val.getBoolean(); // Extension value (DER encoded) val = in.getDerValue(); extensionValue = val.getOctetString(); } else { critical = false; extensionValue = val.getOctetString(); } } /** * Constructs an Extension from individual components of ObjectIdentifier, * criticality and the DER encoded OctetString. * * @param extensionId the ObjectIdentifier of the extension * @param critical the boolean indicating if the extension is critical * @param extensionValue the DER encoded octet string of the value. */ public Extension(ObjectIdentifier extensionId, boolean critical, byte[] extensionValue) throws IOException { this.extensionId = extensionId; this.critical = critical; // passed in a DER encoded octet string, strip off the tag // and length DerValue inDerVal = new DerValue(extensionValue); this.extensionValue = inDerVal.getOctetString(); } /** * Constructs an Extension from another extension. To be used for * creating decoded subclasses. * * @param ext the extension to create from. */ public Extension(Extension ext) { this.extensionId = ext.extensionId; this.critical = ext.critical; this.extensionValue = ext.extensionValue; } /** * Write the extension to the DerOutputStream. * * @param out the DerOutputStream to write the extension to. * @exception IOException on encoding errors */ public void encode(DerOutputStream out) throws IOException { if (extensionId == null) throw new IOException("Null OID to encode for the extension!"); DerOutputStream bytes = new DerOutputStream(); bytes.putOID(extensionId); if (critical) bytes.putBoolean(critical); if (extensionValue != null) bytes.putOctetString(extensionValue); out.write(DerValue.tag_Sequence, bytes); } /** * Returns true if extension is critical. */ public boolean isCritical() { return (critical); } public void setCritical(boolean c) { critical = c; } public void clearValue() { extensionValue = null; } /** * Returns the ObjectIdentifier of the extension. */ public ObjectIdentifier getExtensionId() { return (extensionId); } public void setExtensionId(ObjectIdentifier oid) { extensionId = oid; } /** * Returns the extension value as an byte array for further processing. * Note, this is the raw DER value of the extension, not the DER * encoded octet string which is in the certificate. */ public byte[] getExtensionValue() { if (extensionValue == null) return null; byte[] dup = new byte[extensionValue.length]; System.arraycopy(extensionValue, 0, dup, 0, dup.length); return dup; } public void setExtensionValue(byte value[]) { extensionValue = value; } /** * Returns the Extension in user readable form. */ public String toString() { String s = "ObjectId: " + extensionId.toString(); if (critical) { s += " Criticality=true\n"; } else { s += " Criticality=false\n"; } return (s); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 8184 Content-Disposition: inline; filename="Extensions.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "9047f59c9c161bd86c483ab0476376272fc6c3f5" // --- 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.x509; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Array; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.security.cert.CertificateException; import java.util.Enumeration; import java.util.Hashtable; import java.util.Vector; import netscape.security.util.DerInputStream; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; /** * This class defines the Extensions attribute for the Certificate. * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.11 * @see CertAttrSet */ public class Extensions extends Vector implements CertAttrSet { /** * */ private static final long serialVersionUID = 4597917347772057433L; /** * Identifier for this attribute, to be used with the * get, set, delete methods of Certificate, x509 type. */ public static final String IDENT = "x509.info.extensions"; /** * name */ public static final String NAME = "extensions"; private Hashtable map; // Parse the encoded extension public void parseExtension(Extension ext) throws IOException { try { @SuppressWarnings("unchecked") Class extClass = (Class) OIDMap.getClass(ext.getExtensionId()); if (extClass == null) { // Unsupported extension if (ext.isCritical()) { throw new IOException("Unsupported CRITICAL extension: " + ext.getExtensionId()); } else { map.put(ext.getExtensionId().toString(), ext); addElement(ext); return; } } Class[] params = { Boolean.class, Object.class }; Constructor cons = extClass.getConstructor(params); byte[] extData = ext.getExtensionValue(); int extLen = extData.length; Object value = Array.newInstance(byte.class, extLen); for (int i = 0; i < extLen; i++) { Array.setByte(value, i, extData[i]); } Object[] passed = new Object[] { Boolean.valueOf(ext.isCritical()), value }; CertAttrSet certExt = cons.newInstance(passed); map.put(certExt.getName(), (Extension) certExt); addElement((Extension) certExt); } catch (NoSuchMethodException nosuch) { throw new IOException(nosuch.toString()); } catch (InvocationTargetException invk) { throw new IOException(invk.getTargetException().toString()); } catch (Exception e) { throw new IOException(e.toString()); } } /** * Default constructor for the certificate attribute. */ public Extensions() { map = new Hashtable(); } /** * Create the object, decoding the values from the passed DER stream. * * @param in the DerInputStream to read the Extension from. * @exception IOException on decoding errors. */ public Extensions(DerInputStream in) throws IOException { map = new Hashtable(); DerValue[] exts = in.getSequence(5); for (int i = 0; i < exts.length; i++) { Extension ext = new Extension(exts[i]); parseExtension(ext); } } /** * Decode the extensions from the InputStream. * * @param in the InputStream to unmarshal the contents from. * @exception IOException on decoding or validity errors. */ public void decode(InputStream in) throws IOException { DerValue val = new DerValue(in); DerInputStream str = val.toDerInputStream(); map = new Hashtable(); DerValue[] exts = str.getSequence(5); for (int i = 0; i < exts.length; i++) { Extension ext = new Extension(exts[i]); parseExtension(ext); } } /** * Encode the extensions in DER form to the stream. * * @param out the DerOutputStream to marshal the contents to. * @exception CertificateException on encoding errors. * @exception IOException on errors. */ public void encode(OutputStream out) throws CertificateException, IOException { DerOutputStream extOut = new DerOutputStream(); for (int i = 0; i < size(); i++) { Object thisOne = elementAt(i); if (thisOne instanceof CertAttrSet) ((CertAttrSet) thisOne).encode(extOut); else if (thisOne instanceof Extension) ((Extension) thisOne).encode(extOut); else throw new CertificateException("Invalid extension object"); } try (DerOutputStream seq = new DerOutputStream()) { seq.write(DerValue.tag_Sequence, extOut); out.write(seq.toByteArray()); } } /** * Set the attribute value. * * @param name the extension name used in the cache. * @param obj the object to set. * @exception IOException if the object could not be cached. */ public void set(String name, Object obj) throws IOException { map.put(name, (Extension) obj); addElement((Extension) obj); } /** * Get the attribute value. * * @param name the extension name used in the lookup. * @exception IOException if named extension is not found. */ public Object get(String name) throws IOException { Object obj = map.get(name); if (obj == null) { throw new IOException("No extension found with name " + name); } return (obj); } /** * Delete the attribute value. * * @param name the extension name used in the lookup. * @exception IOException if named extension is not found. */ public void delete(String name) throws IOException { Object obj = map.get(name); if (obj == null) { throw new IOException("No extension found with name " + name); } map.remove(name); removeElement(obj); } /** * Return an enumeration of names of attributes existing within this * attribute. */ public Enumeration getAttributeNames() { return map.keys(); } /** * Return the name of this attribute. */ public String getName() { return (NAME); } @Override public int hashCode() { final int prime = 31; int result = super.hashCode(); result = prime * result + ((map == null) ? 0 : map.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (!super.equals(obj)) return false; if (getClass() != obj.getClass()) return false; Extensions other = (Extensions) obj; if (map == null) { if (other.map != null) return false; } else if (!map.equals(other.map)) return false; return true; } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 13388 Content-Disposition: inline; filename="FreshestCRLExtension.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "c084956b5ecdcbe697ee78cb02bb81186b3a6d1c" // --- 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.x509; import java.io.BufferedOutputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.security.cert.CertificateException; import java.util.Enumeration; import java.util.Hashtable; import java.util.Vector; import org.mozilla.jss.asn1.ASN1Util; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.SEQUENCE; import netscape.security.util.BitArray; import netscape.security.util.DerOutputStream; /** * An extension that tells applications where to find * the latest (freshest) delta CRL for this certificate * or full CRL. * *
 * cRLDistributionPoints ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint
 *
 * DistributionPoint ::= SEQUENCE {
 *      distributionPoint       [0]     DistributionPointName OPTIONAL,
 *      reasons                 [1]     ReasonFlags OPTIONAL,
 *      cRLIssuer               [2]     GeneralNames OPTIONAL }
 *
 * DistributionPointName ::= CHOICE {
 *      fullName                [0]     GeneralNames,
 *      nameRelativeToCRLIssuer [1]     RelativeDistinguishedName }
 *
 * ReasonFlags ::= BIT STRING {
 *      unused                  (0),
 *      keyCompromise           (1),
 *      cACompromise            (2),
 *      affiliationChanged      (3),
 *      superseded              (4),
 *      cessationOfOperation    (5),
 *      certificateHold         (6) }
 * 
*/ public class FreshestCRLExtension extends Extension implements CertAttrSet { /** * */ private static final long serialVersionUID = -8040203589629281781L; // vector of CRLDistributionPoint private SEQUENCE distributionPoints = new SEQUENCE(); public FreshestCRLExtension() { this.extensionId = PKIXExtensions.FreshestCRL_Id; this.critical = false; } // Cached DER-encoding to improve performance. private byte[] cachedEncoding = null; // Attribute name public static final String NAME = "FreshestCRL"; // The Object Identifier for this extension. public static final String OID = "2.5.29.46"; static { try { OIDMap.addAttribute(FreshestCRLExtension.class.getName(), OID, NAME); } catch (CertificateException e) { } } /** * This constructor is called by the CertificateExtensions class to decode * an extension whose OID indicates it is a CRLDistributionsPoints * extension. */ public FreshestCRLExtension(Boolean critical, Object value) //throws IOException { try { this.extensionId = PKIXExtensions.FreshestCRL_Id; this.critical = critical.booleanValue(); this.extensionValue = ((byte[]) value).clone(); // decode the value try { SEQUENCE.OF_Template seqOfCRLDP = new SEQUENCE.OF_Template(CRLDistributionPoint.getTemplate()); distributionPoints = (SEQUENCE) ASN1Util.decode(seqOfCRLDP, extensionValue); } catch (InvalidBERException e) { throw new IOException("Invalid BER-encoding: " + e, e); } } catch (IOException e) { System.out.println("Big error"); System.out.println(e); e.printStackTrace(); //throw e; } } /** * Creates a new FreshestCRL extension, with the given * distribution point as the first element. */ public FreshestCRLExtension(CRLDistributionPoint dp) { this.extensionId = PKIXExtensions.FreshestCRL_Id; this.critical = false; distributionPoints.addElement(dp); } /** * Adds an additional distribution point to the end of the sequence. */ public void addPoint(CRLDistributionPoint dp) { distributionPoints.addElement(dp); cachedEncoding = null; } /** * Returns the number of distribution points in the sequence. */ public int getNumPoints() { return distributionPoints.size(); } /** * Returns the DistributionPoint at the given index in the sequence. */ public CRLDistributionPoint getPointAt(int index) { return (CRLDistributionPoint) distributionPoints.elementAt(index); } /** * Sets the criticality of this extension. PKIX dictates that this * extension SHOULD NOT be critical, so applications can make it critical * if they have a very good reason. By default, the extension is not * critical. */ public void setCritical(boolean critical) { this.critical = critical; } /** * Encodes this extension to the given DerOutputStream. * This method re-encodes each time it is called, so it is not very * efficient. */ public void encode(DerOutputStream out) throws IOException { extensionValue = ASN1Util.encode(distributionPoints); super.encode(out); } /** * Should be called if any change is made to this data structure * so that the cached DER encoding can be discarded. */ public void flushCachedEncoding() { cachedEncoding = null; } ///////////////////////////////////////////////////////////// // CertAttrSet interface // This interface is not really appropriate for this extension // because it is so complicated. Therefore, we only provide a // minimal implementation. ///////////////////////////////////////////////////////////// @Override public String toString() { return NAME; } /** * DER-encodes this extension to the given OutputStream. */ public void encode(OutputStream ostream) throws CertificateException, IOException { if (cachedEncoding == null) { // only re-encode if necessary DerOutputStream tmp = new DerOutputStream(); encode(tmp); cachedEncoding = tmp.toByteArray(); } ostream.write(cachedEncoding); } public void decode(InputStream in) throws CertificateException, IOException { throw new IOException("Not supported"); } public void set(String name, Object obj) throws CertificateException, IOException { throw new IOException("Attribute name not recognized by " + "CertAttrSet:FreshestCRLExtension"); } public Object get(String name) throws CertificateException, IOException { throw new IOException("Attribute name not recognized by " + "CertAttrSet:FreshestCRLExtension"); } public void delete(String name) throws CertificateException, IOException { throw new IOException("Attribute name not recognized by " + "CertAttrSet:FreshestCRLExtension"); } /* * TODO replacewith empty collection */ public Enumeration getAttributeNames() { return (new Vector()).elements(); } public String getName() { return NAME; } /** * Test driver. */ public static void main(String args[]) { BufferedOutputStream bos = null; try { if (args.length != 1) { System.out.println("Usage: FreshestCRLExtentions " + ""); System.exit(-1); } bos = new BufferedOutputStream( new FileOutputStream(args[0])); // URI only CRLDistributionPoint cdp = new CRLDistributionPoint(); URIName uri = new URIName("http://www.mycrl.com/go/here"); GeneralNames generalNames = new GeneralNames(); generalNames.addElement(uri); cdp.setFullName(generalNames); FreshestCRLExtension crldpExt = new FreshestCRLExtension(cdp); // DN only cdp = new CRLDistributionPoint(); X500Name dn = new X500Name("CN=Otis Smith,E=otis@fedoraproject.org" + ",OU=Certificate Server,O=Fedora,C=US"); generalNames = new GeneralNames(); generalNames.addElement(dn); cdp.setFullName(generalNames); crldpExt.addPoint(cdp); // DN + reason BitArray ba = new BitArray(5, new byte[] { (byte) 0x28 }); cdp = new CRLDistributionPoint(); cdp.setFullName(generalNames); cdp.setReasons(ba); crldpExt.addPoint(cdp); // relative DN + reason + crlIssuer cdp = new CRLDistributionPoint(); RDN rdn = new RDN("OU=foobar dept"); cdp.setRelativeName(rdn); cdp.setReasons(ba); cdp.setCRLIssuer(generalNames); crldpExt.addPoint(cdp); crldpExt.setCritical(true); crldpExt.encode(bos); } catch (Exception e) { e.printStackTrace(); } finally { if (bos != null) { try { bos.close(); } catch (IOException e) { e.printStackTrace(); } } } } /** * Represents a reason that a cert may be revoked. These reasons are * expressed in a ReasonFlags bit string. */ public static class Reason { private String name; private byte bitMask; private Reason() { } private Reason(String name, byte bitMask) { this.name = name; this.bitMask = bitMask; map.put(name, this); list.addElement(this); } private static Hashtable map = new Hashtable(); private static Vector list = new Vector(); public static Reason fromString(String name) { return map.get(name); } public String getName() { return name; } public byte getBitMask() { return bitMask; } /** * Given a bit array representing reason flags, extracts the reasons * and returns them as an array. * * @param bitFlags A bit vector containing reason flags. * @return An array of reasons contained in the bit vector. * May be zero-length but will not be null. */ public static Reason[] bitArrayToReasonArray(byte bitFlags) { return bitArrayToReasonArray(new byte[] { bitFlags }); } /** * Given a bit array representing reason flags, extracts the reasons * and returns them as an array. Currently, only the first byte * of the bitflags are examined. * * @param bitFlags A bit vector containing reason flags. The format * is big-endian (MSB first). Only the first byte is examined. * @return An array of reasons contained in the bit vector. * May be zero-length but will not be null. */ public static Reason[] bitArrayToReasonArray(byte[] bitFlags) { byte first = bitFlags[0]; int size = list.size(); Vector result = new Vector(); for (int i = 0; i < size; i++) { Reason r = list.elementAt(i); byte b = r.getBitMask(); if ((first & b) != 0) { result.addElement(r); } } size = result.size(); Reason[] retval = new Reason[size]; for (int i = 0; i < size; i++) { retval[i] = result.elementAt(i); } return retval; } public static final Reason UNUSED = new Reason("unused", (byte) 0x80); public static final Reason KEY_COMPROMISE = new Reason("keyCompromise", (byte) 0x40); public static final Reason CA_COMPROMISE = new Reason("cACompromise", (byte) 0x20); public static final Reason AFFILIATION_CHANGED = new Reason("affiliationChanged", (byte) 0x10); public static final Reason SUPERSEDED = new Reason("superseded", (byte) 0x08); public static final Reason CESSATION_OF_OPERATION = new Reason("cessationOfOperation", (byte) 0x04); public static final Reason CERTIFICATE_HOLD = new Reason("certificateHold", (byte) 0x02); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 7700 Content-Disposition: inline; filename="GeneralName.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "55b5bfcf304c0c8ccf893f9a6ef70d2e5c2ee0e2" // --- 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.x509; import java.io.IOException; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; /** * This class implements the ASN.1 GeneralName object class. *

* The ASN.1 syntax for this is: * *

 * GeneralName ::= CHOICE {
 *    otherName                       [0]     OtherName,
 *    rfc822Name                      [1]     IA5String,
 *    dNSName                         [2]     IA5String,
 *    x400Address                     [3]     ORAddress,
 *    directoryName                   [4]     Name,
 *    ediPartyName                    [5]     EDIPartyName,
 *    uniformResourceIdentifier       [6]     IA5String,
 *    iPAddress                       [7]     OCTET STRING,
 *    registeredID                    [8]     OBJECT IDENTIFIER
 * }
 * 
* * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.7 */ public class GeneralName implements GeneralNameInterface { /** * */ private static final long serialVersionUID = 2244101501095555042L; // Private data members private GeneralNameInterface name = null; /** * Default constructor for the class. * * @param name the selected CHOICE from the list. */ public GeneralName(GeneralNameInterface name) { this.name = name; } /** * Create the object from its DER encoded value. * * @param encName the DER encoded GeneralName. */ public GeneralName(DerValue encName) throws IOException { short tag = (byte) (encName.tag & 0x1f); // NB. this is always encoded with the IMPLICIT tag // The checks only make sense if we assume implicit tagging, // with explicit tagging the form is always constructed. switch (tag) { case GeneralNameInterface.NAME_RFC822: if (encName.isContextSpecific() && !encName.isConstructed()) { encName.resetTag(DerValue.tag_IA5String); name = new RFC822Name(encName); } else throw new IOException("Invalid encoding of RFC822 name"); break; case GeneralNameInterface.NAME_DNS: if (encName.isContextSpecific() && !encName.isConstructed()) { encName.resetTag(DerValue.tag_IA5String); name = new DNSName(encName); } else throw new IOException("Invalid encoding of DNS name"); break; case GeneralNameInterface.NAME_URI: if (encName.isContextSpecific() && !encName.isConstructed()) { encName.resetTag(DerValue.tag_IA5String); name = new URIName(encName); } else throw new IOException("Invalid encoding of URI"); break; case GeneralNameInterface.NAME_IP: if (encName.isContextSpecific() && !encName.isConstructed()) { encName.resetTag(DerValue.tag_OctetString); name = new IPAddressName(encName); } else throw new IOException("Invalid encoding of IP address"); break; case GeneralNameInterface.NAME_ANY: if (encName.isContextSpecific() && encName.isConstructed()) { encName.resetTag(DerValue.tag_OctetString); name = new OtherName(encName); } else throw new IOException("Invalid encoding of other name"); break; case GeneralNameInterface.NAME_OID: if (encName.isContextSpecific() && !encName.isConstructed()) { encName.resetTag(DerValue.tag_ObjectId); name = new OIDName(encName); } else throw new IOException("Invalid encoding of OID name"); break; case GeneralNameInterface.NAME_DIRECTORY: if (encName.isContextSpecific() && encName.isConstructed()) { // Unlike the other cases, DirectoryName is EXPLICITly // tagged, because the X.500 Name type is a CHOICE. // Therefore, the sequence is actually nested in the // content of this value. We'll pretend it's an octet // string so we can get at the content bytes. encName.resetTag(DerValue.tag_OctetString); byte[] content = encName.getOctetString(); name = new X500Name(content); } else throw new IOException("Invalid encoding of Directory name"); break; case GeneralNameInterface.NAME_EDI: if (encName.isContextSpecific() && encName.isConstructed()) { encName.resetTag(DerValue.tag_Sequence); name = new EDIPartyName(encName); } else throw new IOException("Invalid encoding of EDI name"); break; default: throw new IOException("Unrecognized GeneralName tag, (" + tag + ")"); } } /** * Return the type of the general name. */ public int getType() { return (name.getType()); } /** * Return the name as user readable string */ public String toString() { return (name.toString()); } /** * Encode the name to the specified DerOutputStream. * * @param out the DerOutputStream to encode the the GeneralName to. * @exception IOException on encoding errors. */ public void encode(DerOutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); name.encode(tmp); int nameType = name.getType(); boolean constructedForm; if (nameType == GeneralNameInterface.NAME_ANY || nameType == GeneralNameInterface.NAME_X400 || nameType == GeneralNameInterface.NAME_DIRECTORY || nameType == GeneralNameInterface.NAME_EDI) { constructedForm = true; } else { constructedForm = false; } if (nameType == GeneralNameInterface.NAME_DIRECTORY) { // EXPLICIT tag, because Name is a CHOICE type out.write(DerValue.createTag(DerValue.TAG_CONTEXT, constructedForm, (byte) nameType), tmp); } else { // IMPLICIT tag, the default out.writeImplicit(DerValue.createTag(DerValue.TAG_CONTEXT, constructedForm, (byte) nameType), tmp); } } /** * Unwrap this GeneralName until we reach something that is not * a GeneralName. */ public GeneralNameInterface unwrap() { if (this == name) return null; // can't happen, but just in case... if (name instanceof GeneralName) return ((GeneralName) name).unwrap(); else return name; } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 2032 Content-Disposition: inline; filename="GeneralNameInterface.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "7225ccc04d8a0bea0a8fb2bab0a103ce33e3a91d" // --- 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.x509; import java.io.IOException; import netscape.security.util.DerOutputStream; /** * This interface specifies the abstract methods which have to be * implemented by all the members of the GeneralNames ASN.1 object. * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.6 */ public interface GeneralNameInterface extends java.io.Serializable { /** * The list of names supported. */ public static final int NAME_ANY = 0; public static final int NAME_RFC822 = 1; public static final int NAME_DNS = 2; public static final int NAME_X400 = 3; public static final int NAME_DIRECTORY = 4; public static final int NAME_EDI = 5; public static final int NAME_URI = 6; public static final int NAME_IP = 7; public static final int NAME_OID = 8; /** * Return the type of the general name, as * defined above. */ int getType(); /** * Encode the name to the specified DerOutputStream. * * @param out the DerOutputStream to encode the GeneralName to. * @exception IOException thrown if the GeneralName could not be * encoded. */ void encode(DerOutputStream out) throws IOException; } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 5225 Content-Disposition: inline; filename="GeneralNames.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "08084764a260fa89f889ed1f7ec690ecf3dc285e" // --- 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.x509; import java.io.IOException; import java.util.Enumeration; import java.util.Vector; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; /** * This object class represents the GeneralNames type required in * X509 certificates. *

* The ASN.1 syntax for this is: * *

 * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
 * 
* * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.7 */ public class GeneralNames extends Vector { /** * */ private static final long serialVersionUID = 3204492869396713312L; /** * Create the GeneralNames, decoding from the passed DerValue. * * Caution when using this constructor. It may be broken! * Better to call addElement(gni) directly where gni is * a GeneralNameInterface object * * @param derVal the DerValue to construct the GeneralNames from. * @exception GeneralNamesException on decoding error. * @exception IOException on error. */ public GeneralNames(DerValue derVal) throws IOException, GeneralNamesException { if (derVal.tag != DerValue.tag_Sequence) { throw new IOException("Invalid encoding for GeneralNames."); } if (derVal.data.available() == 0) { throw new GeneralNamesException("No data available in " + "passed DER encoded value."); } // Decode all the GeneralName's while (derVal.data.available() != 0) { DerValue encName = derVal.data.getDerValue(); GeneralName name = new GeneralName(encName); addElement(name); } } /** * Create the GeneralNames * * @param names a non-empty array of names to put into the * generalNames */ public GeneralNames(GeneralNameInterface[] names) throws GeneralNamesException { if (names == null || names.length == 0) throw new GeneralNamesException("Cannot create empty GeneralNames"); for (int i = 0; i < names.length; i++) { addElement(names[i]); } } /** * The default constructor for this class. */ public GeneralNames() { super(1, 1); } /** * Write the extension to the DerOutputStream. * * @param out the DerOutputStream to write the extension to. * @exception GeneralNamesException on encoding error. * @exception IOException on error. */ public void encode(DerOutputStream out) throws IOException, GeneralNamesException { if (size() == 0) { return; } Enumeration names = elements(); DerOutputStream temp = new DerOutputStream(); while (names.hasMoreElements()) { Object obj = names.nextElement(); if (!(obj instanceof GeneralNameInterface)) { throw new GeneralNamesException("Element in GeneralNames " + "not of type GeneralName."); } GeneralNameInterface intf = (GeneralNameInterface) obj; if (obj instanceof GeneralName) { intf.encode(temp); } else { DerOutputStream gname = new DerOutputStream(); intf.encode(gname); int nameType = intf.getType(); // constructed form if (nameType == GeneralNameInterface.NAME_ANY || nameType == GeneralNameInterface.NAME_X400 || nameType == GeneralNameInterface.NAME_EDI) { temp.writeImplicit(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) nameType), gname); } else if (nameType == GeneralNameInterface.NAME_DIRECTORY) { // EXPLICIT tag because directoryName is a CHOICE temp.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) nameType), gname); } else // primitive form temp.writeImplicit(DerValue.createTag(DerValue.TAG_CONTEXT, false, (byte) nameType), gname); } } out.write(DerValue.tag_Sequence, temp); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 1516 Content-Disposition: inline; filename="GeneralNamesException.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "11c763fda223107e6d187517eb5d55a1f9830e9f" // --- 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.x509; import java.security.GeneralSecurityException; /** * Generic General Names Exception. * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.4 */ public class GeneralNamesException extends GeneralSecurityException { /** * */ private static final long serialVersionUID = -8320001725384815795L; /** * Constructs a GeneralNamesException with no detail message. */ public GeneralNamesException() { super(); } /** * Constructs the exception with the specified error message. * * @param message the requisite error message. */ public GeneralNamesException(String message) { super(message); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 5385 Content-Disposition: inline; filename="GeneralSubtree.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "4c20bb4ba38fbc6f97c61801c563935c4114f0d3" // --- 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.x509; import java.io.IOException; import java.io.Serializable; import netscape.security.util.BigInt; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; import netscape.security.util.PrettyPrintFormat; /** * Represent the GeneralSubtree ASN.1 object, whose syntax is: * *
 * GeneralSubtree ::= SEQUENCE {
 *    base             GeneralName,
 *    minimum  [0]     BaseDistance DEFAULT 0,
 *    maximum  [1]     BaseDistance OPTIONAL
 * }
 * BaseDistance ::= INTEGER (0..MAX)
 * 
* * @version 1.5 * @author Amit Kapoor * @author Hemma Prafullchandra */ public class GeneralSubtree implements Serializable { private static final long serialVersionUID = -2835481424013062770L; private static final byte TAG_MIN = 0; private static final byte TAG_MAX = 1; private static final int MIN_DEFAULT = 0; private GeneralName name; private int minimum = MIN_DEFAULT; private int maximum = -1; private transient PrettyPrintFormat pp = new PrettyPrintFormat(":"); /** * The default constructor for the class. * * @param name the GeneralName * @param min the minimum BaseDistance * @param max the maximum BaseDistance */ public GeneralSubtree(GeneralName name, int min, int max) { this.name = name; this.minimum = min; this.maximum = max; } /** * Create the object from its DER encoded form. * * @param val the DER encoded from of the same. */ public GeneralSubtree(DerValue val) throws IOException { if (val.tag != DerValue.tag_Sequence) { throw new IOException("Invalid encoding for GeneralSubtree."); } name = new GeneralName(val.data.getDerValue()); // NB. this is always encoded with the IMPLICIT tag // The checks only make sense if we assume implicit tagging, // with explicit tagging the form is always constructed. while (val.data.available() != 0) { DerValue opt = val.data.getDerValue(); if (opt.isContextSpecific(TAG_MIN) && !opt.isConstructed()) { opt.resetTag(DerValue.tag_Integer); minimum = (opt.getInteger()).toInt(); } else if (opt.isContextSpecific(TAG_MAX) && !opt.isConstructed()) { opt.resetTag(DerValue.tag_Integer); maximum = (opt.getInteger()).toInt(); } else throw new IOException("Invalid encoding of GeneralSubtree."); } } /** * Return a printable string of the GeneralSubtree. */ public String toString() { String s = "\n GeneralSubtree: [\n" + " GeneralName: " + ((name == null) ? "" : name.toString()) + "\n Minimum: " + minimum; if (maximum == -1) { s += "\t Maximum: undefined"; } else s += "\t Maximum: " + maximum; s += " ]\n"; return (s); } public String toPrint(int indent) { String s = "\n" + pp.indent(indent) + "GeneralSubtree: [\n" + pp.indent(indent + 2) + "GeneralName: " + ((name == null) ? "" : name.toString()) + "\n" + pp.indent(indent + 2) + "Minimum: " + minimum; if (maximum == -1) { s += "\n" + pp.indent(indent + 2) + "Maximum: undefined"; } else s += "\n" + pp.indent(indent + 2) + "Maximum: " + maximum; s += "]\n"; return (s); } /** * Encode the GeneralSubtree. * * @param out the DerOutputStream to encode this object to. */ public void encode(DerOutputStream out) throws IOException { DerOutputStream seq = new DerOutputStream(); name.encode(seq); if (minimum != MIN_DEFAULT) { DerOutputStream tmp = new DerOutputStream(); tmp.putInteger(new BigInt(minimum)); seq.writeImplicit(DerValue.createTag(DerValue.TAG_CONTEXT, false, TAG_MIN), tmp); } if (maximum != -1) { DerOutputStream tmp = new DerOutputStream(); tmp.putInteger(new BigInt(maximum)); seq.writeImplicit(DerValue.createTag(DerValue.TAG_CONTEXT, false, TAG_MAX), tmp); } out.write(DerValue.tag_Sequence, seq); } public GeneralName getGeneralName() { return name; } public int getMaxValue() { return maximum; } public int getMinValue() { return minimum; } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 3314 Content-Disposition: inline; filename="GeneralSubtrees.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "edbab7ee90b768a802c74e5f7b3ffd8639f100db" // --- 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.x509; import java.io.IOException; import java.io.Serializable; import java.util.Enumeration; import java.util.Vector; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; import netscape.security.util.PrettyPrintFormat; /** * Represent the GeneralSubtrees ASN.1 object. * * @version 1.4 * * @author Amit Kapoor * @author Hemma Prafullchandra */ public class GeneralSubtrees implements Serializable { private static final long serialVersionUID = 6308776640697100848L; private Vector trees; private transient PrettyPrintFormat pp = new PrettyPrintFormat(":"); /** * The default constructor for the class. * * @param trees the sequence of GeneralSubtree. */ public GeneralSubtrees(Vector trees) { this.trees = trees; } /** * Create the object from the passed DER encoded form. * * @param val the DER encoded form of the same. */ public GeneralSubtrees(DerValue val) throws IOException { trees = new Vector(1, 1); if (val.tag != DerValue.tag_Sequence) { throw new IOException("Invalid encoding of GeneralSubtrees."); } while (val.data.available() != 0) { DerValue opt = val.data.getDerValue(); GeneralSubtree tree = new GeneralSubtree(opt); trees.addElement(tree); } } /** * Return a printable string of the GeneralSubtree. */ public String toString() { String s = " GeneralSubtrees:\n" + trees.toString() + "\n"; return (s); } public String toPrint(int indent) { StringBuffer s = new StringBuffer(); GeneralSubtree element; for (Enumeration e = trees.elements(); e.hasMoreElements();) { element = e.nextElement(); s.append(pp.indent(indent + 4) + element.toPrint(indent) + "\n"); } return (s.toString()); } /** * Encode the GeneralSubtrees. * * @param out the DerOutputStrean to encode this object to. */ public void encode(DerOutputStream out) throws IOException { DerOutputStream seq = new DerOutputStream(); for (int i = 0; i < trees.size(); i++) { trees.elementAt(i).encode(seq); } out.write(DerValue.tag_Sequence, seq); } public Vector getSubtrees() { return trees; } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 5541 Content-Disposition: inline; filename="GenericValueConverter.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "f08ebcca515dd6f0751ed027cd01b95307e065ce" // --- 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.x509; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.CharacterCodingException; import java.nio.charset.CharsetEncoder; import netscape.security.util.ASN1CharStrConvMap; import netscape.security.util.DerValue; /** * A GenericValueConverter converts a string that is not associated with * a particular attribute to a DER encoded ASN.1 character string type. * Currently supports PrintableString, IA5String, BMPString T.61String and * Universal String. * *

* The conversion is done as follows. An encoder is obtained for the all the character sets from the global default * ASN1CharStrConvMap. The encoders are then used to convert the string to the smallest character set first -- * printableString. If the string contains characters outside of that character set, it is converted to the next * character set -- IA5String character set. If that is not enough it is converted to a BMPString, then Universal String * which contains all characters. * * @author Lily Hsiao, Slava Galperin at Netscape Communications, Inc. * */ public class GenericValueConverter implements AVAValueConverter { public GenericValueConverter() { } /** * Converts a string to a DER encoded ASN.1 primtable string, defined here * as a PrintableString, IA5String, T.61String, BMPString or * UniversalString. The string is not expected to be encoded in any form. * *

* If an encoder is not available for a character set that is needed to convert the string, the string cannot be * converted and an IOException is thrown. For example, if the string contains characters outside the * PrintableString character and only a PrintableString encoder is available then an IOException is thrown. * * @param s A string representing a generic attribute string value. * * @return The DER value of the attribute. * * @exception IOException if the string cannot be converted, such as * when an encoder needed is * unavailable. */ public DerValue getValue(String s) throws IOException { return getValue(s, null); } public DerValue getValue(String valueString, byte[] tags) throws IOException { // try to convert to printable, then t61 the universal - // i.e. from minimal coverage to the broadest. if (tags == null || tags.length == 0) tags = DefEncodingTags; for (int i = 0; i < tags.length; i++) { try { CharsetEncoder encoder = ASN1CharStrConvMap.getDefault().getEncoder(tags[i]); if (encoder == null) continue; CharBuffer charBuffer = CharBuffer.wrap(valueString.toCharArray()); ByteBuffer byteBuffer = encoder.encode(charBuffer); return new DerValue(tags[i], byteBuffer.array(), byteBuffer.arrayOffset(), byteBuffer.limit()); } catch (CharacterCodingException e) { continue; } } throw new IOException( "Cannot convert the string value to a ASN.1 type"); } /** * Creates a DerValue from the byte array of BER encoded value. * * NOTE: currently only supports DER encoding (a form of BER) on input . * * @param berStream Byte array of a BER encoded value. * * @return DerValue object. * * @exception IOException If the BER value cannot be converted to a * valid Directory String DER value. */ public DerValue getValue(byte[] berByteStream) throws IOException { // accepts any tag. DerValue value = new DerValue(berByteStream); return value; } /** * Converts a DerValue of ASN1 Character string type to a java string * (the string is not encoded in any form). * * @param avaValue A DerValue * @return A string representing the attribute value. * @exception IOException if a decoder needed for the * conversion is not available or if BER value * is not one of the ASN1 character string types * here. */ public String getAsString(DerValue avaValue) throws IOException { return avaValue.getASN1CharString(); } private static byte DefEncodingTags[] = { DerValue.tag_PrintableString, DerValue.tag_IA5String, DerValue.tag_BMPString, DerValue.tag_UTF8String, DerValue.tag_T61String, DerValue.tag_UniversalString }; } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 12621 Content-Disposition: inline; filename="HoldInstructionExtension.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "2a7c4af127572cb0400c83fe5cb6a0db595ffb39" // --- 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.x509; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Array; import java.security.cert.CertificateException; import java.util.Enumeration; import java.util.Vector; import netscape.security.util.DerInputStream; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; import netscape.security.util.ObjectIdentifier; /** * Represent the CRL Hold Instruction Code Extension. * *

* The hold instruction code is a non-critical CRL entry extension that provides a registered instruction identifier * which indicates the action to be taken after encountering a certificate that has been placed on hold. * * @see Extension * @see CertAttrSet */ public class HoldInstructionExtension extends Extension implements CertAttrSet { /** * */ private static final long serialVersionUID = -6706557233070964984L; /** * Attribute name. */ public static final String NAME = "HoldInstruction"; public static final String HOLD_INSTRUCTION = "value"; /** * The Object Identifier for this extension. */ public static final String OID = "2.5.29.23"; public static final String NONE_HOLD_INSTR_OID_STR = "1.2.840.10040.2.1"; public static final ObjectIdentifier NONE_HOLD_INSTR_OID = new ObjectIdentifier(NONE_HOLD_INSTR_OID_STR); public static final String CALL_ISSUER_HOLD_INSTR_OID_STR = "1.2.840.10040.2.2"; public static final ObjectIdentifier CALL_ISSUER_HOLD_INSTR_OID = new ObjectIdentifier(CALL_ISSUER_HOLD_INSTR_OID_STR); public static final String REJECT_HOLD_INSTR_OID_STR = "1.2.840.10040.2.3"; public static final ObjectIdentifier REJECT_HOLD_INSTR_OID = new ObjectIdentifier(REJECT_HOLD_INSTR_OID_STR); private ObjectIdentifier holdInstructionCodeOIDs[] = { NONE_HOLD_INSTR_OID, CALL_ISSUER_HOLD_INSTR_OID, REJECT_HOLD_INSTR_OID }; private ObjectIdentifier holdInstructionCodeOID = null; private String holdInstructionDescription[] = { "None", "Call Issuer", "Reject" }; static { try { OIDMap.addAttribute(HoldInstructionExtension.class.getName(), OID, NAME); } catch (CertificateException e) { } } private int getHoldInstructionCodeFromOID(ObjectIdentifier oid) { for (int i = 0; i < holdInstructionCodeOIDs.length; i++) { if (oid.equals(holdInstructionCodeOIDs[i])) return (i + 1); } return 0; } private String getHoldInstructionDescription(ObjectIdentifier oid) { String description = "Invalid"; if (oid != null) { int i = getHoldInstructionCodeFromOID(oid); if (i > 0 && i < 4) description = holdInstructionDescription[i - 1]; } return (description); } // Encode this extension value private void encodeThis() throws IOException { if (holdInstructionCodeOID == null) throw new IOException("Unintialized hold instruction extension"); try (DerOutputStream os = new DerOutputStream()) { os.putOID(holdInstructionCodeOID); this.extensionValue = os.toByteArray(); } } /** * Create a HoldInstructionExtension with the date. * The criticality is set to false. * * @param code the value to be set for the extension. */ public HoldInstructionExtension(int code) throws IOException { if (code < 1 || code > 3) throw new IOException("Invalid hold instruction code"); holdInstructionCodeOID = holdInstructionCodeOIDs[code - 1]; this.extensionId = PKIXExtensions.HoldInstructionCode_Id; this.critical = false; encodeThis(); } /** * Create a HoldInstructionExtension with the date. * The criticality is set to false. * * @param oidStr the value to be set for the extension. */ public HoldInstructionExtension(String oidStr) throws IOException { ObjectIdentifier oid = new ObjectIdentifier(oidStr); if (oid == null || getHoldInstructionCodeFromOID(oid) == 0) throw new IOException("Invalid hold instruction code"); holdInstructionCodeOID = oid; this.extensionId = PKIXExtensions.HoldInstructionCode_Id; this.critical = false; encodeThis(); } /** * Create a HoldInstructionExtension with the date. * The criticality is set to false. * * @param oid the value to be set for the extension. */ public HoldInstructionExtension(ObjectIdentifier oid) throws IOException { if (getHoldInstructionCodeFromOID(oid) == 0) throw new IOException("Invalid hold instruction code"); holdInstructionCodeOID = oid; this.extensionId = PKIXExtensions.HoldInstructionCode_Id; this.critical = false; encodeThis(); } /** * Create a HoldInstructionExtension with the date. * The criticality is set to false. * * @param critical true if the extension is to be treated as critical. * @param code the value to be set for the extension. */ public HoldInstructionExtension(Boolean critical, int code) throws IOException { if (code < 1 || code > 3) throw new IOException("Invalid hold instruction code"); holdInstructionCodeOID = holdInstructionCodeOIDs[code - 1]; this.extensionId = PKIXExtensions.HoldInstructionCode_Id; this.critical = critical.booleanValue(); encodeThis(); } /** * Create a HoldInstructionExtension with the date. * The criticality is set to false. * * @param critical true if the extension is to be treated as critical. * @param oidStr the value to be set for the extension. */ public HoldInstructionExtension(Boolean critical, String oidStr) throws IOException { ObjectIdentifier oid = new ObjectIdentifier(oidStr); if (oid == null || getHoldInstructionCodeFromOID(oid) == 0) throw new IOException("Invalid hold instruction code"); holdInstructionCodeOID = oid; this.extensionId = PKIXExtensions.HoldInstructionCode_Id; this.critical = critical.booleanValue(); encodeThis(); } /** * Create a HoldInstructionExtension with the date. * The criticality is set to false. * * @param critical true if the extension is to be treated as critical. * @param oid the value to be set for the extension. */ public HoldInstructionExtension(Boolean critical, ObjectIdentifier oid) throws IOException { if (getHoldInstructionCodeFromOID(oid) == 0) throw new IOException("Invalid hold instruction code"); holdInstructionCodeOID = oid; this.extensionId = PKIXExtensions.HoldInstructionCode_Id; this.critical = critical.booleanValue(); encodeThis(); } /** * Create the extension from the passed DER encoded value of the same. * * @param critical true if the extension is to be treated as critical. * @param value Array of DER encoded bytes of the actual value. * @exception IOException on error. */ public HoldInstructionExtension(Boolean critical, Object value) throws IOException { this.extensionId = PKIXExtensions.HoldInstructionCode_Id; this.critical = critical.booleanValue(); int len = Array.getLength(value); byte[] extValue = new byte[len]; for (int i = 0; i < len; i++) { extValue[i] = Array.getByte(value, i); } this.extensionValue = extValue; DerValue val = new DerValue(extValue); if (val.tag == DerValue.tag_ObjectId) { DerInputStream derInputStream = new DerInputStream(val.toByteArray()); holdInstructionCodeOID = derInputStream.getOID(); if (getHoldInstructionCodeFromOID(holdInstructionCodeOID) == 0) throw new IOException("Invalid encoding for HoldInstructionExtension"); } else { throw new IOException("Invalid encoding for HoldInstructionExtension"); } } /** * Get the hold instruction code. */ public ObjectIdentifier getHoldInstructionCode() { return holdInstructionCodeOID; } public String getHoldInstructionCodeDescription() { return getHoldInstructionDescription(holdInstructionCodeOID); } /** * Set the attribute value. */ public void set(String name, Object obj) throws IOException { if (name.equalsIgnoreCase(HOLD_INSTRUCTION)) { if (!(obj instanceof ObjectIdentifier)) { throw new IOException("Attribute must be of type String."); } holdInstructionCodeOID = (ObjectIdentifier) obj; } else { throw new IOException("Attribute name not recognized by" + " CertAttrSet:HoldInstructionCode."); } } /** * Get the attribute value. */ public Object get(String name) throws IOException { if (name.equalsIgnoreCase(HOLD_INSTRUCTION)) { return holdInstructionCodeOID; } else { throw new IOException("Attribute name not recognized by" + " CertAttrSet:HoldInstructionCode."); } } /** * Delete the attribute value. */ public void delete(String name) throws IOException { if (name.equalsIgnoreCase(HOLD_INSTRUCTION)) { holdInstructionCodeOID = null; } else { throw new IOException("Attribute name not recognized by" + " CertAttrSet:HoldInstructionCode."); } } /** * Returns a printable representation of the HoldInstructionExtension. */ public String toString() { String s = super.toString() + "Hold Instruction Code: " + getHoldInstructionDescription(holdInstructionCodeOID) + "\n"; return (s); } /** * Decode the extension from the InputStream. * * @param in the InputStream to unmarshal the contents from. * @exception IOException on decoding or validity errors. */ public void decode(InputStream in) throws IOException { throw new IOException("Method not to be called directly."); } /** * Write the extension to the DerOutputStream. * * @param out the DerOutputStream to write the extension to. * @exception IOException on encoding errors. */ public void encode(OutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); if (this.extensionValue == null) { this.extensionId = PKIXExtensions.HoldInstructionCode_Id; this.critical = true; encodeThis(); } super.encode(tmp); out.write(tmp.toByteArray()); } /** * Return an enumeration of names of attributes existing within this * attribute. */ public Enumeration getAttributeNames() { Vector elements = new Vector(); elements.addElement(HOLD_INSTRUCTION); return (elements.elements()); } /** * Return the name of this attribute. */ public String getName() { return (NAME); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 4255 Content-Disposition: inline; filename="IA5StringConverter.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "f01d090d15b2f104ab4504160a9ed4c3ab642f6f" // --- 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.x509; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.CharacterCodingException; import java.nio.charset.CharsetEncoder; import netscape.security.util.ASN1CharStrConvMap; import netscape.security.util.DerValue; /** * A AVAValueConverter that converts a IA5String attribute to a DerValue * and vice versa. An example an attribute that is a IA5String string is "E". * * @see AVAValueConverter * * @author Lily Hsiao, Slava Galperin at Netscape Communications, Inc. */ public class IA5StringConverter implements AVAValueConverter { // public constructors /* * Contructs a IA5String Converter. */ public IA5StringConverter() { } /* * Converts a string with ASN.1 IA5String characters to a DerValue. * * @param valueString a string with IA5String characters. * * @return a DerValue. * * @exception IOException if a IA5String encoder is not * available for the conversion. */ public DerValue getValue(String valueString) throws IOException { return getValue(valueString, null); } public DerValue getValue(String valueString, byte[] tags) throws IOException { try { CharsetEncoder encoder = ASN1CharStrConvMap.getDefault().getEncoder(DerValue.tag_IA5String); if (encoder == null) throw new IOException("No encoder for IA5String"); CharBuffer charBuffer = CharBuffer.wrap(valueString.toCharArray()); ByteBuffer byteBuffer = encoder.encode(charBuffer); return new DerValue(DerValue.tag_IA5String, byteBuffer.array(), byteBuffer.arrayOffset(), byteBuffer.limit()); } catch (CharacterCodingException e) { throw new IllegalArgumentException("Invalid IA5String AVA Value string"); } } /* * Converts a BER encoded value of IA5String to a DER encoded value. * Checks if the BER encoded value is a IA5String. * NOTE only DER encoding is currently supported on for the BER * encoded value. * * @param berStream a byte array of the BER encoded value. * * @return a DerValue. * * @exception IOException if the BER value cannot be converted * to a IA5String DER value. */ public DerValue getValue(byte[] berStream) throws IOException { DerValue value = new DerValue(berStream); if (value.tag == DerValue.tag_IA5String) return value; if (value.tag == DerValue.tag_PrintableString) return value; throw new IOException("Invalid IA5String AVA Value."); } /* * Converts a DerValue of IA5String to a java string with IA5String * characters. * * @param avaValue a DerValue. * * @return a string with IA5String characters. * * @exception IOException if the DerValue is not a IA5String i.e. * The DerValue cannot be converted to a string * with IA5String characters. */ public String getAsString(DerValue avaValue) throws IOException { if (avaValue.tag == DerValue.tag_IA5String) return avaValue.getIA5String(); if (avaValue.tag == DerValue.tag_PrintableString) return avaValue.getPrintableString(); throw new IOException("Invalid IA5String AVA Value."); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 9121 Content-Disposition: inline; filename="IPAddressName.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "bb27548a30a4cab9c30e656e99540dfa9e0bd0bf" // --- 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.x509; import java.io.IOException; import java.util.StringTokenizer; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; /** * This class implements the IPAddressName as required by the GeneralNames * ASN.1 object. * * @see GeneralName * @see GeneralNameInterface * @see GeneralNames * * @version 1.2 * * @author Amit Kapoor * @author Hemma Prafullchandra */ public class IPAddressName implements GeneralNameInterface { /** * */ private static final long serialVersionUID = -4240184399679453666L; private byte[] address; /** * Create the IPAddressName object from the passed encoded Der value. * * @param derValue the encoded DER IPAddressName. * @exception IOException on error. */ public IPAddressName(DerValue derValue) throws IOException { address = derValue.getOctetString(); } /** * Create the IPAddressName object with the specified name. * * @param name the IPAddressName. */ public IPAddressName(byte[] address) { this.address = address; } protected static final char IPv4_LEN = 4; protected static final char IPv6_LEN = 16; protected static final IPAddr IPv4 = new IPv4Addr(); protected static final IPAddr IPv6 = new IPv6Addr(); /** * Create the IPAddressName object with a string representing the * ip address and a string representing the netmask, with encoding * having ip address encoding followed by the netmask encoding. * This form is needed for name constraints extension. * * @param s the ip address in the format: n.n.n.n or x:x:x:x:x:x:x:x (RFC 1884) * @param netmask the netmask address in the format: n.n.n.n or x:x:x:x:x:x:x:x (RFC 1884) */ public IPAddressName(String s, String netmask) { // Based on PKIX RFC2459. IPAddress has // 8 bytes (instead of 4 bytes) in the // context of NameConstraints IPAddr ipAddr = null; if (s.indexOf(':') != -1) { ipAddr = IPv6; address = new byte[IPv6_LEN * 2]; } else { ipAddr = IPv4; address = new byte[IPv4_LEN * 2]; } StringTokenizer st = new StringTokenizer(s, ","); int numFilled = ipAddr.getIPAddr(st.nextToken(), address, 0); if (st.hasMoreTokens()) { ipAddr.getIPAddr(st.nextToken(), address, numFilled); } else { for (int i = numFilled; i < address.length; i++) address[i] = (byte) 0xff; } } /** * Create the IPAddressName object with a string representing the * ip address. * * @param s the ip address in the format: n.n.n.n or x:x:x:x:x:x:x:x */ public IPAddressName(String s) { IPAddr ipAddr = null; if (s.indexOf(':') != -1) { ipAddr = IPv6; address = new byte[IPv6_LEN]; } else { ipAddr = IPv4; address = new byte[IPv4_LEN]; } ipAddr.getIPAddr(s, address, 0); } /** * Return the type of the GeneralName. */ public int getType() { return (GeneralNameInterface.NAME_IP); } /** * Encode the IPAddress name into the DerOutputStream. * * @param out the DER stream to encode the IPAddressName to. * @exception IOException on encoding errors. */ public void encode(DerOutputStream out) throws IOException { out.putOctetString(address); } /** * Return a printable string of IPaddress */ public String toString() { if (address.length == 4) { return ("IPAddress: " + (address[0] & 0xff) + "." + (address[1] & 0xff) + "." + (address[2] & 0xff) + "." + (address[3] & 0xff)); } else { StringBuffer r = new StringBuffer("IPAddress: " + Integer.toHexString(address[0] & 0xff)); String hexString = Integer.toHexString(address[1] & 0xff); if (hexString.length() == 1) { r.append("0" + hexString); } else { r.append(hexString); } for (int i = 2; i < address.length;) { r.append(":" + Integer.toHexString(address[i] & 0xff)); hexString = Integer.toHexString(address[i + 1] & 0xff); if (hexString.length() == 1) { r.append("0" + hexString); } else { r.append(hexString); } i += 2; } return r.toString(); } } } interface IPAddr { public int getIPAddr(String s, byte[] address, int start); public int getLength(); } class IPv4Addr implements IPAddr { protected static final int IPv4_LEN = 4; /** * Gets an IP v4 address in the form n.n.n.n. */ public int getIPAddr(String s, byte[] address, int start) { StringTokenizer st = new StringTokenizer(s, "."); int nt = st.countTokens(); if (nt != IPv4_LEN) throw new InvalidIPAddressException(s); try { int end = start + nt; for (int i = start; i < end; i++) { Integer j = new Integer(st.nextToken()); address[i] = (byte) j.intValue(); } } catch (NumberFormatException e) { throw new InvalidIPAddressException(s); } return nt; } public int getLength() { return IPv4_LEN; } } class IPv6Addr implements IPAddr { /** * Gets an IP address in the forms as defined in RFC1884:
*

    *
  • x:x:x:x:x:x:x:x *
  • ...::xxx (using :: shorthand) *
  • ...:n.n.n.n (with n.n.n.n at the end) *
*/ public int getIPAddr(String s, byte[] address, int start) { int lastcolon = -2; int end = start + 16; int idx = start; for (int i = start; i < address.length; i++) address[i] = 0; if (s.indexOf('.') != -1) { // has n.n.n.n at the end lastcolon = s.lastIndexOf(':'); if (lastcolon == -1) throw new InvalidIPAddressException(s); end -= 4; IPAddressName.IPv4.getIPAddr( s.substring(lastcolon + 1), address, end); } try { String s1 = s; if (lastcolon != -2) s1 = s.substring(0, lastcolon + 1); int lastDoubleColon = s1.indexOf("::"); String l = s1, r = null; StringTokenizer lt = null, rt = null; if (lastDoubleColon != -1) { l = s1.substring(0, lastDoubleColon); r = s1.substring(lastDoubleColon + 2); if (l.length() == 0) l = null; if (r.length() == 0) r = null; } int at = 0; if (l != null) { lt = new StringTokenizer(l, ":", false); at += lt.countTokens(); } if (r != null) { rt = new StringTokenizer(r, ":", false); at += rt.countTokens(); } if (at > 8 || (lastcolon != -2 && (at > 6 || (lastDoubleColon == -1 && at != 6)))) throw new InvalidIPAddressException(s); if (l != null) { while (lt.hasMoreTokens()) { String tok = lt.nextToken(); int j = Integer.parseInt(tok, 16); address[idx++] = (byte) ((j >> 8) & 0xFF); address[idx++] = (byte) (j & 0xFF); } } if (r != null) { idx = end - (rt.countTokens() * 2); while (rt.hasMoreTokens()) { String tok = rt.nextToken(); int j = Integer.parseInt(tok, 16); address[idx++] = (byte) ((j >> 8) & 0xFF); address[idx++] = (byte) (j & 0xFF); } } } catch (NumberFormatException e) { throw new InvalidIPAddressException(s); } return 16; } public int getLength() { return 16; } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 1153 Content-Disposition: inline; filename="InvalidIPAddressException.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "f544df200696b924f05598ba43697e1aeab47ae5" // --- 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.x509; public class InvalidIPAddressException extends RuntimeException { /** * */ private static final long serialVersionUID = -1601934234587845028L; public InvalidIPAddressException() { super(); } public InvalidIPAddressException(String ip) { super("Invalid IP Address '" + ip + "'"); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 7813 Content-Disposition: inline; filename="InvalidityDateExtension.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "a0cf7e45bce05de446409a2af0fc92d3b6024fbf" // --- 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.x509; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Array; import java.security.cert.CertificateException; import java.util.Date; import java.util.Enumeration; import java.util.Vector; import netscape.security.util.DerInputStream; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; /** * Represent the CRL Invalidity Date Extension. * *

* This CRL entry extension, if present, provides the date on which it is known or suspected that the private key was * compromised or that the certificate otherwise became invalid. Invalidity date may be earlier than the revocation * date. * * @see Extension * @see CertAttrSet */ public class InvalidityDateExtension extends Extension implements CertAttrSet { /** * */ private static final long serialVersionUID = 2191026017389643053L; /** * Attribute name. */ public static final String NAME = "InvalidityDate"; public static final String INVALIDITY_DATE = "value"; /** * The Object Identifier for this extension. */ public static final String OID = "2.5.29.24"; private Date invalidityDate = null; static { try { OIDMap.addAttribute(InvalidityDateExtension.class.getName(), OID, NAME); } catch (CertificateException e) { } } // Encode this extension value private void encodeThis() throws IOException { if (invalidityDate == null) throw new IOException("Unintialized invalidity date extension"); try (DerOutputStream os = new DerOutputStream()) { os.putGeneralizedTime(this.invalidityDate); this.extensionValue = os.toByteArray(); } } /** * Create a InvalidityDateExtension with the date. * The criticality is set to false. * * @param dateOfInvalidity the value to be set for the extension. */ public InvalidityDateExtension(Date dateOfInvalidity) throws IOException { this.invalidityDate = dateOfInvalidity; this.extensionId = PKIXExtensions.InvalidityDate_Id; this.critical = false; encodeThis(); } /** * Create a InvalidityDateExtension with the date. * The criticality is set to false. * * @param critical true if the extension is to be treated as critical. * @param dateOfInvalidity the value to be set for the extension. */ public InvalidityDateExtension(Boolean critical, Date dateOfInvalidity) throws IOException { this.invalidityDate = dateOfInvalidity; this.extensionId = PKIXExtensions.InvalidityDate_Id; this.critical = critical.booleanValue(); encodeThis(); } /** * Create the extension from the passed DER encoded value of the same. * * @param critical true if the extension is to be treated as critical. * @param value Array of DER encoded bytes of the actual value. * @exception IOException on error. */ public InvalidityDateExtension(Boolean critical, Object value) throws IOException { this.extensionId = PKIXExtensions.InvalidityDate_Id; this.critical = critical.booleanValue(); int len = Array.getLength(value); byte[] extValue = new byte[len]; for (int i = 0; i < len; i++) { extValue[i] = Array.getByte(value, i); } this.extensionValue = extValue; DerValue val = new DerValue(extValue); if (val.tag == DerValue.tag_GeneralizedTime) { DerInputStream derInputStream = new DerInputStream(val.toByteArray()); this.invalidityDate = derInputStream.getGeneralizedTime(); } else { throw new IOException("Invalid encoding for InvalidityDateExtension"); } } /** * Get the invalidity date. */ public Date getInvalidityDate() { return invalidityDate; } /** * Set the attribute value. */ public void set(String name, Object obj) throws IOException { if (name.equalsIgnoreCase(INVALIDITY_DATE)) { if (!(obj instanceof Date)) { throw new IOException("Attribute must be of type Date."); } invalidityDate = (Date) obj; } else { throw new IOException("Attribute name not recognized by" + " CertAttrSet:InvalidityDate."); } } /** * Get the attribute value. */ public Object get(String name) throws IOException { if (name.equalsIgnoreCase(INVALIDITY_DATE)) { if (invalidityDate == null) return null; else return invalidityDate; } else { throw new IOException("Attribute name not recognized by" + " CertAttrSet:InvalidityDate."); } } /** * Delete the attribute value. */ public void delete(String name) throws IOException { if (name.equalsIgnoreCase(INVALIDITY_DATE)) { invalidityDate = null; } else { throw new IOException("Attribute name not recognized by" + " CertAttrSet:InvalidityDate."); } } /** * Returns a printable representation of the InvalidityDateExtension. */ public String toString() { String s = super.toString() + "Invalidity Date: " + ((invalidityDate == null) ? "" : invalidityDate.toString()) + "\n"; return (s); } /** * Decode the extension from the InputStream. * * @param in the InputStream to unmarshal the contents from. * @exception IOException on decoding or validity errors. */ public void decode(InputStream in) throws IOException { throw new IOException("Method not to be called directly."); } /** * Write the extension to the DerOutputStream. * * @param out the DerOutputStream to write the extension to. * @exception IOException on encoding errors. */ public void encode(OutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); if (this.extensionValue == null) { this.extensionId = PKIXExtensions.InvalidityDate_Id; this.critical = true; encodeThis(); } super.encode(tmp); out.write(tmp.toByteArray()); } /** * Return an enumeration of names of attributes existing within this * attribute. */ public Enumeration getAttributeNames() { Vector elements = new Vector(); elements.addElement(INVALIDITY_DATE); return (elements.elements()); } /** * Return the name of this attribute. */ public String getName() { return (NAME); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 7696 Content-Disposition: inline; filename="IssuerAlternativeNameExtension.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "469e4722b6064a81777cc26cc0afbda46b1f6c17" // --- 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.x509; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Array; import java.util.Enumeration; import java.util.Vector; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; /** * This represents the Issuer Alternative Name Extension. * * This extension, if present, allows the issuer to specify multiple * alternative names. * *

* Extensions are represented as a sequence of the extension identifier (Object Identifier), a boolean flag stating * whether the extension is to be treated as being critical and the extension value itself (this is again a DER encoding * of the extension value). * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.7 * @see Extension * @see CertAttrSet */ public class IssuerAlternativeNameExtension extends Extension implements CertAttrSet { /** * */ private static final long serialVersionUID = -269518027483586255L; /** * Identifier for this attribute, to be used with the * get, set, delete methods of Certificate, x509 type. */ public static final String IDENT = "x509.info.extensions.IssuerAlternativeName"; /** * Attribute names. */ public static final String NAME = "IssuerAlternativeName"; public static final String ISSUER_NAME = "issuer_name"; // private data members GeneralNames names; // Encode this extension private void encodeThis() throws IOException { DerOutputStream os = new DerOutputStream(); try { names.encode(os); } catch (GeneralNamesException e) { throw new IOException(e); } this.extensionValue = os.toByteArray(); } /** * Create a IssuerAlternativeNameExtension with the passed GeneralNames. * * @param critical true if the extension is to be treated as critical. * @param names the GeneralNames for the issuer. * @exception IOException on error. */ public IssuerAlternativeNameExtension(Boolean critical, GeneralNames names) throws IOException { this.names = names; this.extensionId = PKIXExtensions.IssuerAlternativeName_Id; this.critical = critical.booleanValue(); encodeThis(); } /** * Create a IssuerAlternativeNameExtension with the passed GeneralNames. * * @param names the GeneralNames for the issuer. * @exception IOException on error. */ public IssuerAlternativeNameExtension(GeneralNames names) throws IOException { this.names = names; this.extensionId = PKIXExtensions.IssuerAlternativeName_Id; this.critical = false; encodeThis(); } /** * Create a default IssuerAlternativeNameExtension. */ public IssuerAlternativeNameExtension() { extensionId = PKIXExtensions.IssuerAlternativeName_Id; critical = false; names = new GeneralNames(); } /** * Create the extension from the passed DER encoded value. * * @param critical true if the extension is to be treated as critical. * @param value Array of DER encoded bytes of the actual value. * @exception IOException on error. */ public IssuerAlternativeNameExtension(Boolean critical, Object value) throws IOException { this.extensionId = PKIXExtensions.IssuerAlternativeName_Id; this.critical = critical.booleanValue(); int len = Array.getLength(value); byte[] extValue = new byte[len]; for (int i = 0; i < len; i++) { extValue[i] = Array.getByte(value, i); } this.extensionValue = extValue; DerValue val = new DerValue(extValue); try { names = new GeneralNames(val); } catch (GeneralNamesException e) { throw new IOException("IssuerAlternativeNameExtension: " + e, e); } } /** * Returns a printable representation of the IssuerAlternativeName. */ public String toString() { if (names == null) return ""; String s = super.toString() + "IssuerAlternativeName [\n" + names.toString() + "]\n"; return (s); } /** * Decode the extension from the InputStream. * * @param in the InputStream to unmarshal the contents from. * @exception IOException on decoding or validity errors. */ public void decode(InputStream in) throws IOException { throw new IOException("Method not to be called directly."); } /** * Write the extension to the OutputStream. * * @param out the OutputStream to write the extension to. * @exception IOException on encoding error. */ public void encode(OutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); if (extensionValue == null) { extensionId = PKIXExtensions.IssuerAlternativeName_Id; critical = false; encodeThis(); } super.encode(tmp); out.write(tmp.toByteArray()); } /** * Set the attribute value. */ public void set(String name, Object obj) throws IOException { clearValue(); if (name.equalsIgnoreCase(ISSUER_NAME)) { if (!(obj instanceof GeneralNames)) { throw new IOException("Attribute value should be of" + " type GeneralNames."); } names = (GeneralNames) obj; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:IssuerAlternativeName."); } } /** * Get the attribute value. */ public Object get(String name) throws IOException { if (name.equalsIgnoreCase(ISSUER_NAME)) { return (names); } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:IssuerAlternativeName."); } } /** * Delete the attribute value. */ public void delete(String name) throws IOException { if (name.equalsIgnoreCase(ISSUER_NAME)) { names = null; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:IssuerAlternativeName."); } } /** * Return an enumeration of names of attributes existing within this * attribute. */ public Enumeration getAttributeNames() { Vector elements = new Vector(); elements.addElement(ISSUER_NAME); return (elements.elements()); } /** * Return the name of this attribute. */ public String getName() { return (NAME); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 11521 Content-Disposition: inline; filename="IssuingDistributionPoint.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "06638f2dd4eb070bf567554cf0fe33e355d2c57c" // --- 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.x509; import java.io.BufferedOutputStream; import java.io.ByteArrayOutputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import netscape.security.util.BitArray; import netscape.security.util.DerOutputStream; import org.mozilla.jss.asn1.ANY; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.BOOLEAN; import org.mozilla.jss.asn1.EXPLICIT; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; /** *

 * issuingDistributionPoint ::= SEQUENCE {
 *         distributionPoint       [0] DistributionPointName OPTIONAL,
 *         onlyContainsUserCerts   [1] BOOLEAN DEFAULT FALSE,
 *         onlyContainsCACerts     [2] BOOLEAN DEFAULT FALSE,
 *         onlySomeReasons         [3] ReasonFlags OPTIONAL,
 *         indirectCRL             [4] BOOLEAN DEFAULT FALSE }
 *
 * DistributionPointName ::= CHOICE {
 *         fullName                [0]     GeneralNames,
 *         nameRelativeToCRLIssuer [1]     RelativeDistinguishedName }
 *
 * ReasonFlags ::= BIT STRING {
 *         unused                  (0),
 *         keyCompromise           (1),
 *         cACompromise            (2),
 *         affiliationChanged      (3),
 *         superseded              (4),
 *         cessationOfOperation    (5),
 *         certificateHold         (6) }
 *
 * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
 *
 * GeneralName ::= CHOICE {
 *         otherName                       [0]     OtherName,
 *         rfc822Name                      [1]     IA5String,
 *         dNSName                         [2]     IA5String,
 *         x400Address                     [3]     ORAddress,
 *         directoryName                   [4]     Name,
 *         ediPartyName                    [5]     EDIPartyName,
 *         uniformResourceIdentifier       [6]     IA5String,
 *         iPAddress                       [7]     OCTET STRING,
 *         registeredID                    [8]     OBJECT IDENTIFIER}
 *
 * OtherName ::= SEQUENCE {
 *         type-id    OBJECT IDENTIFIER,
 *         value      [0] EXPLICIT ANY DEFINED BY type-id }
 *
 * EDIPartyName ::= SEQUENCE {
 *         nameAssigner            [0]     DirectoryString OPTIONAL,
 *         partyName               [1]     DirectoryString }
 *
 * RelativeDistinguishedName ::=
 *         SET OF AttributeTypeAndValue
 *
 * AttributeTypeAndValue ::= SEQUENCE {
 *         type     AttributeType,
 *         value    AttributeValue }
 *
 * AttributeType ::= OBJECT IDENTIFIER
 *
 * AttributeValue ::= ANY DEFINED BY AttributeType
 * 
* * See the documentation in CRLDistributionPoint for * the DistributionPointName and ReasonFlags ASN.1 types. */ public class IssuingDistributionPoint implements ASN1Value { // at most one of the following two may be specified. One or both can // be null. private GeneralNames fullName = null; private RDN relativeName = null; private boolean onlyContainsUserCerts = false; // DEFAULT FALSE private boolean onlyContainsCACerts = false; // DEFAULT FALSE private BitArray onlySomeReasons = null; // optional, may be null private boolean indirectCRL = false; // DEFAULT FALSE // cache encoding of fullName private ANY fullNameEncoding; /** * Returns the fullName of the DistributionPointName, which may be null. */ public GeneralNames getFullName() { return fullName; } /** * Returns the relativeName of the DistributionPointName, which may be null. */ public RDN getRelativeName() { return relativeName; } /** * Sets the fullName of the DistributionPointName. It may be set to null. * If it is set to a non-null value, relativeName will be * set to null, because at most one of these two attributes * can be specified at a time. * * @exception GeneralNamesException If an error occurs encoding the * name. */ public void setFullName(GeneralNames fullName) throws GeneralNamesException, IOException { this.fullName = fullName; if (fullName != null) { // encode the name to catch any problems with it DerOutputStream derOut = new DerOutputStream(); fullName.encode(derOut); try { ANY raw = new ANY(derOut.toByteArray()); ByteArrayOutputStream bos = new ByteArrayOutputStream(); raw.encodeWithAlternateTag(Tag.get(0), bos); fullNameEncoding = new ANY(bos.toByteArray()); } catch (InvalidBERException e) { // assume this won't happen, since it would imply a bug // in DerOutputStream throw new GeneralNamesException(e.toString()); } this.relativeName = null; } } /** * Sets the relativeName of the DistributionPointName. It may be set to null. * If it is set to a non-null value, fullName will be * set to null, because at most one of these two attributes * can be specified at a time. */ public void setRelativeName(RDN relativeName) { this.relativeName = relativeName; if (relativeName != null) { this.fullName = null; } } public boolean getOnlyContainsUserCerts() { return onlyContainsUserCerts; } public void setOnlyContainsUserCerts(boolean b) { onlyContainsUserCerts = b; } public boolean getOnlyContainsCACerts() { return onlyContainsCACerts; } public void setOnlyContainsCACerts(boolean b) { onlyContainsCACerts = b; } /** * Returns the reason flags for this distribution point. May be null. */ public BitArray getOnlySomeReasons() { return onlySomeReasons; } /** * Sets the reason flags for this distribution point. May be set to null. */ public void setOnlySomeReasons(BitArray reasons) { this.onlySomeReasons = reasons; } public boolean getIndirectCRL() { return indirectCRL; } public void setIndirectCRL(boolean b) { indirectCRL = b; } ///////////////////////////////////////////////////////////// // DER encoding ///////////////////////////////////////////////////////////// private static final Tag TAG = SEQUENCE.TAG; public Tag getTag() { return TAG; } public void encode(OutputStream ostream) throws IOException { encode(TAG, ostream); } public void encode(Tag implicitTag, OutputStream ostream) throws IOException { SEQUENCE seq = new SEQUENCE(); DerOutputStream derOut; try { // Encodes the DistributionPointName. Because DistributionPointName // is a CHOICE, the [0] tag is forced to be EXPLICIT. if (fullName != null) { EXPLICIT distPoint = new EXPLICIT(Tag.get(0), fullNameEncoding); seq.addElement(distPoint); } else if (relativeName != null) { derOut = new DerOutputStream(); relativeName.encode(derOut); ANY raw = new ANY(derOut.toByteArray()); ByteArrayOutputStream bos = new ByteArrayOutputStream(); raw.encodeWithAlternateTag(Tag.get(1), bos); ANY distPointName = new ANY(bos.toByteArray()); EXPLICIT distPoint = new EXPLICIT(Tag.get(0), distPointName); seq.addElement(distPoint); } if (onlyContainsUserCerts != false) { seq.addElement(Tag.get(1), new BOOLEAN(true)); } if (onlyContainsCACerts != false) { seq.addElement(Tag.get(2), new BOOLEAN(true)); } // Encodes the ReasonFlags. if (onlySomeReasons != null) { derOut = new DerOutputStream(); derOut.putUnalignedBitString(onlySomeReasons); ANY raw = new ANY(derOut.toByteArray()); ByteArrayOutputStream bos = new ByteArrayOutputStream(); raw.encodeWithAlternateTag(Tag.get(3), bos); ANY reasonEncoding = new ANY(bos.toByteArray()); seq.addElement(reasonEncoding); } if (indirectCRL != false) { seq.addElement(Tag.get(4), new BOOLEAN(true)); } seq.encode(implicitTag, ostream); } catch (InvalidBERException e) { // this shouldn't happen unless there is a bug in one of // the Sun encoding classes throw new IOException(e.toString()); } } public static void main(String args[]) { BufferedOutputStream bos = null; try { if (args.length != 1) { System.out.println("Usage: IssuingDistributionPoint "); System.exit(-1); } bos = new BufferedOutputStream( new FileOutputStream(args[0])); SEQUENCE idps = new SEQUENCE(); IssuingDistributionPoint idp = new IssuingDistributionPoint(); X500Name dn = new X500Name("CN=Skovw Wjasldk,E=nicolson@netscape.com" + ",OU=Certificate Server,O=Netscape,C=US"); GeneralNames generalNames = new GeneralNames(); generalNames.addElement(dn); idp.setFullName(generalNames); idps.addElement(idp); idp = new IssuingDistributionPoint(); URIName uri = new URIName("http://www.mycrl.com/go/here"); generalNames = new GeneralNames(); generalNames.addElement(uri); idp.setFullName(generalNames); idp.setOnlyContainsUserCerts(true); idp.setOnlyContainsCACerts(true); idp.setIndirectCRL(true); BitArray ba = new BitArray(5, new byte[] { (byte) 0x28 }); idp.setOnlySomeReasons(ba); idps.addElement(idp); idps.encode(bos); } catch (Exception e) { e.printStackTrace(); } finally { if (bos != null) { try { bos.close(); } catch (IOException e) { e.printStackTrace(); } } } } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 16819 Content-Disposition: inline; filename="IssuingDistributionPointExtension.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "d65dc44f0aefccd87d5db18253c93e252eb347a6" // --- 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.x509; import java.io.BufferedOutputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.security.cert.CertificateException; import java.util.Enumeration; import java.util.Vector; import org.mozilla.jss.asn1.ASN1Util; import netscape.security.util.BitArray; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; /** * A critical CRL extension that identifies the CRL distribution point * for a particular CRL * *
 * issuingDistributionPoint ::= SEQUENCE {
 *         distributionPoint       [0] DistributionPointName OPTIONAL,
 *         onlyContainsUserCerts   [1] BOOLEAN DEFAULT FALSE,
 *         onlyContainsCACerts     [2] BOOLEAN DEFAULT FALSE,
 *         onlySomeReasons         [3] ReasonFlags OPTIONAL,
 *         indirectCRL             [4] BOOLEAN DEFAULT FALSE }
 *
 * DistributionPointName ::= CHOICE {
 *         fullName                [0]     GeneralNames,
 *         nameRelativeToCRLIssuer [1]     RelativeDistinguishedName }
 *
 * ReasonFlags ::= BIT STRING {
 *         unused                  (0),
 *         keyCompromise           (1),
 *         cACompromise            (2),
 *         affiliationChanged      (3),
 *         superseded              (4),
 *         cessationOfOperation    (5),
 *         certificateHold         (6) }
 *
 * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
 *
 * GeneralName ::= CHOICE {
 *         otherName                       [0]     OtherName,
 *         rfc822Name                      [1]     IA5String,
 *         dNSName                         [2]     IA5String,
 *         x400Address                     [3]     ORAddress,
 *         directoryName                   [4]     Name,
 *         ediPartyName                    [5]     EDIPartyName,
 *         uniformResourceIdentifier       [6]     IA5String,
 *         iPAddress                       [7]     OCTET STRING,
 *         registeredID                    [8]     OBJECT IDENTIFIER}
 *
 * OtherName ::= SEQUENCE {
 *         type-id    OBJECT IDENTIFIER,
 *         value      [0] EXPLICIT ANY DEFINED BY type-id }
 *
 * EDIPartyName ::= SEQUENCE {
 *         nameAssigner            [0]     DirectoryString OPTIONAL,
 *         partyName               [1]     DirectoryString }
 *
 * RelativeDistinguishedName ::=
 *         SET OF AttributeTypeAndValue
 *
 * AttributeTypeAndValue ::= SEQUENCE {
 *         type     AttributeType,
 *         value    AttributeValue }
 *
 * AttributeType ::= OBJECT IDENTIFIER
 *
 * AttributeValue ::= ANY DEFINED BY AttributeType
 * 
*/ public class IssuingDistributionPointExtension extends Extension implements CertAttrSet { /** * */ private static final long serialVersionUID = -1281544042375527550L; /** * The Object Identifier for this extension. */ public static final String OID = "2.5.29.28"; /** * Attribute names. */ public static final String NAME = "IssuingDistributionPoint"; public static final String ISSUING_DISTRIBUTION_POINT = "issuing_distribution_point"; // Private data members private IssuingDistributionPoint issuingDistributionPoint = null; // Cached DER-encoding to improve performance. private byte[] cachedEncoding = null; static { try { OIDMap.addAttribute(IssuingDistributionPointExtension.class.getName(), OID, NAME); } catch (CertificateException e) { } } /** * This constructor is very important, since it will be called * by the system. */ public IssuingDistributionPointExtension(Boolean critical, Object value) throws IOException { this.extensionId = PKIXExtensions.IssuingDistributionPoint_Id; this.critical = critical.booleanValue(); this.extensionValue = ((byte[]) value).clone(); byte[] extValue = this.extensionValue; issuingDistributionPoint = new IssuingDistributionPoint(); DerValue val = new DerValue(extValue); if (val.tag != DerValue.tag_Sequence) { throw new IOException("Invalid encoding of IssuingDistributionPoint"); } while (val.data.available() != 0) { DerValue opt = val.data.getDerValue(); if (opt != null) { for (int i = 0; i < 5; i++) { if (opt.isContextSpecific((byte) i)) { if ((i == 0 && opt.isConstructed() && opt.data.available() != 0) || (i != 0 && (!opt.isConstructed()) && opt.data.available() != 0)) { if (i == 0) { DerValue opt1 = opt.data.getDerValue(); if (opt1 != null) { if (opt1.isContextSpecific((byte) 0)) { if (opt1.isConstructed() && opt1.data.available() != 0) { opt1.resetTag(DerValue.tag_Sequence); try { GeneralNames fullName = new GeneralNames(opt1); if (fullName != null) { issuingDistributionPoint.setFullName(fullName); } } catch (GeneralNamesException e) { throw new IOException("Invalid encoding of IssuingDistributionPoint " + e, e); } catch (IOException e) { throw new IOException("Invalid encoding of IssuingDistributionPoint " + e, e); } } else { throw new IOException("Invalid encoding of IssuingDistributionPoint"); } } else if (opt1.isContextSpecific((byte) 1)) { if (opt1.isConstructed() && opt1.data.available() != 0) { opt1.resetTag(DerValue.tag_Set); try { RDN relativeName = new RDN(opt1); if (relativeName != null) { issuingDistributionPoint.setRelativeName(relativeName); } } catch (IOException e) { throw new IOException("Invalid encoding of IssuingDistributionPoint " + e, e); } } else { throw new IOException("Invalid encoding of IssuingDistributionPoint"); } } } } else if (i == 3) { opt.resetTag(DerValue.tag_BitString); try { BitArray reasons = opt.getUnalignedBitString(); if (reasons == null) { throw new IOException("Unable to get the unaligned bit string."); } issuingDistributionPoint.setOnlySomeReasons(reasons); @SuppressWarnings("unused") byte[] a = reasons.toByteArray(); // check for errors } catch (IOException e) { throw new IOException("Invalid encoding of IssuingDistributionPoint " + e, e); } } else { opt.resetTag(DerValue.tag_Boolean); try { boolean b = opt.getBoolean(); if (i == 1) { issuingDistributionPoint.setOnlyContainsUserCerts(b); } else if (i == 2) { issuingDistributionPoint.setOnlyContainsCACerts(b); } else if (i == 4) { issuingDistributionPoint.setIndirectCRL(b); } } catch (IOException e) { throw new IOException("Invalid encoding of IssuingDistributionPoint " + e, e); } } } else { throw new IOException("Invalid encoding of IssuingDistributionPoint"); } } } } else { throw new IOException("Invalid encoding of IssuingDistributionPoint"); } } } /** * Creates a new IssuingDistributionPoint extension, with the given * issuing distribution point as the first element. */ public IssuingDistributionPointExtension(IssuingDistributionPoint idp) { this.extensionId = PKIXExtensions.IssuingDistributionPoint_Id; this.critical = true; issuingDistributionPoint = idp; } /** * Returns the issuing distribution point. */ public IssuingDistributionPoint getIssuingDistributionPoint() { return issuingDistributionPoint; } /** * Sets the criticality of this extension. PKIX dictates that this * extension SHOULD be critical, so applications can make it not critical * if they have a very good reason. By default, the extension is critical. */ public void setCritical(boolean critical) { this.critical = critical; } /** * Gets the criticality of this extension. PKIX dictates that this * extension SHOULD be critical, so by default, the extension is critical. */ public boolean getCritical(boolean critical) { return this.critical; } /** * Encodes this extension to the given DerOutputStream. * This method re-encodes each time it is called, so it is not very * efficient. */ public void encode(DerOutputStream out) throws IOException { extensionValue = ASN1Util.encode(issuingDistributionPoint); super.encode(out); } /** * Should be called if any change is made to this data structure * so that the cached DER encoding can be discarded. */ public void flushCachedEncoding() { cachedEncoding = null; } /** * Returns a printable representation of the IssuingDistributionPointExtension */ @Override public String toString() { return NAME; } /** * DER-encodes this extension to the given OutputStream. */ public void encode(OutputStream ostream) throws CertificateException, IOException { if (cachedEncoding == null) { // only re-encode if necessary DerOutputStream tmp = new DerOutputStream(); encode(tmp); cachedEncoding = tmp.toByteArray(); } ostream.write(cachedEncoding); } public void decode(InputStream in) throws CertificateException, IOException { throw new IOException("Not supported"); } public void set(String name, Object obj) throws CertificateException, IOException { if (name.equalsIgnoreCase(ISSUING_DISTRIBUTION_POINT)) { if (!(obj instanceof IssuingDistributionPoint)) { throw new IOException("Attribute value should be of type IssuingDistributionPoint."); } issuingDistributionPoint = (IssuingDistributionPoint) obj; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:IssuingDistributionPointExtension"); } } public Object get(String name) throws CertificateException, IOException { if (name.equalsIgnoreCase(ISSUING_DISTRIBUTION_POINT)) { return issuingDistributionPoint; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:IssuingDistributionPointExtension"); } } public void delete(String name) throws CertificateException, IOException { if (name.equalsIgnoreCase(ISSUING_DISTRIBUTION_POINT)) { issuingDistributionPoint = null; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:IssuingDistributionPointExtension"); } } public Enumeration getAttributeNames() { Vector elements = new Vector(); elements.addElement(ISSUING_DISTRIBUTION_POINT); return (elements.elements()); // return (new Vector()).elements(); } public String getName() { return NAME; } /** * Test driver. */ public static void main(String args[]) { BufferedOutputStream bos = null; try { if (args.length != 1) { System.out.println("Usage: IssuingDistributionPointExtension " + ""); System.exit(-1); } bos = new BufferedOutputStream( new FileOutputStream(args[0])); // URI only IssuingDistributionPoint idp = new IssuingDistributionPoint(); URIName uri = new URIName("http://www.mycrl.com/go/here"); GeneralNames generalNames = new GeneralNames(); generalNames.addElement(uri); idp.setFullName(generalNames); IssuingDistributionPointExtension idpExt = new IssuingDistributionPointExtension(idp); // DN only idp = new IssuingDistributionPoint(); X500Name dn = new X500Name("CN=Otis Smith,E=otis@fedoraproject.org" + ",OU=Certificate Server,O=Fedora,C=US"); generalNames = new GeneralNames(); generalNames.addElement(dn); idp.setFullName(generalNames); idpExt.set(IssuingDistributionPointExtension.ISSUING_DISTRIBUTION_POINT, idp); // DN + reason BitArray ba = new BitArray(5, new byte[] { (byte) 0x28 }); idp = new IssuingDistributionPoint(); idp.setFullName(generalNames); idp.setOnlySomeReasons(ba); idpExt.set(IssuingDistributionPointExtension.ISSUING_DISTRIBUTION_POINT, idp); // relative DN + reason + crlIssuer idp = new IssuingDistributionPoint(); RDN rdn = new RDN("OU=foobar dept"); idp.setRelativeName(rdn); idp.setOnlySomeReasons(ba); idp.setOnlyContainsCACerts(true); idp.setOnlyContainsUserCerts(true); idp.setIndirectCRL(true); idpExt.set(IssuingDistributionPointExtension.ISSUING_DISTRIBUTION_POINT, idp); idpExt.setCritical(false); idpExt.encode(bos); } catch (Exception e) { e.printStackTrace(); } finally { if (bos != null) { try { bos.close(); } catch (IOException e) { e.printStackTrace(); } } } } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 2557 Content-Disposition: inline; filename="KeyIdentifier.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "643e86a31fe947e33bfd0671122fb7402bec51b6" // --- 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.x509; import java.io.IOException; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; /** * Represent the Key Identifier ASN.1 object. * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.4 */ public class KeyIdentifier implements java.io.Serializable { /** * */ private static final long serialVersionUID = 2412286879441154979L; private byte[] octetString; /** * Create a KeyIdentifier with the passed bit settings. * * @param octetString the octet string identifying the key identifier. */ public KeyIdentifier(byte[] octetString) { this.octetString = octetString; } /** * Create a KeyIdentifier from the DER encoded value. * * @param val the DerValue */ public KeyIdentifier(DerValue val) throws IOException { octetString = val.getOctetString(); } /** * Return the value of the KeyIdentifier as byte array. */ public byte[] getIdentifier() { return octetString.clone(); } /** * Returns a printable representation of the KeyUsage. */ public String toString() { netscape.security.util.PrettyPrintFormat pp = new netscape.security.util.PrettyPrintFormat(" ", 20); String octetbits = pp.toHexString(octetString); String s = "KeyIdentifier [\n"; s += octetbits; s += "]\n"; return (s); } /** * Write the KeyIdentifier to the DerOutputStream. * * @param out the DerOutputStream to write the object to. * @exception IOException */ void encode(DerOutputStream out) throws IOException { out.putOctetString(octetString); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 14438 Content-Disposition: inline; filename="KeyUsageExtension.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "a21aa8fa32ce646e96ace7078958930f5bca2532" // --- 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.x509; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Array; import java.util.Enumeration; import java.util.Vector; import netscape.security.util.BitArray; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; /** * Represent the Key Usage Extension. * *

* This extension, if present, defines the purpose (e.g., encipherment, signature, certificate signing) of the key * contained in the certificate. The usage restriction might be employed when a multipurpose key is to be restricted * (e.g., when an RSA key should be used only for signing or only for key encipherment). * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.9 * @see Extension * @see CertAttrSet */ public class KeyUsageExtension extends Extension implements CertAttrSet { /** * */ private static final long serialVersionUID = 2899719374157256708L; /** * Identifier for this attribute, to be used with the * get, set, delete methods of Certificate, x509 type. */ public static final String IDENT = "x509.info.extensions.KeyUsage"; /** * Attribute names. */ public static final String NAME = "KeyUsage"; public static final String DIGITAL_SIGNATURE = "digital_signature"; public static final String NON_REPUDIATION = "non_repudiation"; public static final String KEY_ENCIPHERMENT = "key_encipherment"; public static final String DATA_ENCIPHERMENT = "data_encipherment"; public static final String KEY_AGREEMENT = "key_agreement"; public static final String KEY_CERTSIGN = "key_certsign"; public static final String CRL_SIGN = "crl_sign"; public static final String ENCIPHER_ONLY = "encipher_only"; public static final String DECIPHER_ONLY = "decipher_only"; public static final int DIGITAL_SIGNATURE_BIT = 0; public static final int NON_REPUDIATION_BIT = 1; public static final int KEY_ENCIPHERMENT_BIT = 2; public static final int DATA_ENCIPHERMENT_BIT = 3; public static final int KEY_AGREEMENT_BIT = 4; public static final int KEY_CERTSIGN_BIT = 5; public static final int CRL_SIGN_BIT = 6; public static final int ENCIPHER_ONLY_BIT = 7; public static final int DECIPHER_ONLY_BIT = 8; public static final int NBITS = 9; public static String[] names = new String[NBITS]; static { names[DIGITAL_SIGNATURE_BIT] = DIGITAL_SIGNATURE; names[NON_REPUDIATION_BIT] = NON_REPUDIATION; names[KEY_ENCIPHERMENT_BIT] = KEY_ENCIPHERMENT; names[DATA_ENCIPHERMENT_BIT] = DATA_ENCIPHERMENT; names[KEY_AGREEMENT_BIT] = KEY_AGREEMENT; names[KEY_CERTSIGN_BIT] = KEY_CERTSIGN; names[CRL_SIGN_BIT] = CRL_SIGN; names[ENCIPHER_ONLY_BIT] = ENCIPHER_ONLY; names[DECIPHER_ONLY_BIT] = DECIPHER_ONLY; } // Private data members private boolean[] bitString; // Encode this extension value private void encodeThis() throws IOException { try (DerOutputStream os = new DerOutputStream()) { os.putUnalignedBitString(this.bitString); this.extensionValue = os.toByteArray(); } } /** * Check if bit is set. * * @param position the position in the bit string to check. */ private boolean isSet(int position) { if (bitString.length <= position) return false; return bitString[position]; } /** * Set the bit at the specified position. */ private void set(int position, boolean val) { // enlarge bitString if necessary if (position >= bitString.length) { boolean[] tmp = new boolean[position + 1]; System.arraycopy(bitString, 0, tmp, 0, bitString.length); bitString = tmp; } bitString[position] = val; } /** * Create a KeyUsageExtension with the passed bit settings. The criticality * is set to true. * * @param bitString the bits to be set for the extension. */ public KeyUsageExtension(boolean critical, byte[] bitString) throws IOException { this.bitString = new BitArray(bitString.length * 8, bitString).toBooleanArray(); this.extensionId = PKIXExtensions.KeyUsage_Id; this.critical = critical; encodeThis(); } public KeyUsageExtension(byte[] bitString) throws IOException { this.bitString = new BitArray(bitString.length * 8, bitString).toBooleanArray(); this.extensionId = PKIXExtensions.KeyUsage_Id; this.critical = true; encodeThis(); } /** * Create a KeyUsageExtension with the passed bit settings. The criticality * is set to true. * * @param bitString the bits to be set for the extension. */ public KeyUsageExtension(boolean critical, boolean[] bitString) throws IOException { this.bitString = bitString; this.extensionId = PKIXExtensions.KeyUsage_Id; this.critical = critical; encodeThis(); } public KeyUsageExtension(boolean[] bitString) throws IOException { this.bitString = bitString; this.extensionId = PKIXExtensions.KeyUsage_Id; this.critical = true; encodeThis(); } /** * Create a KeyUsageExtension with the passed bit settings. The criticality * is set to true. * * @param bitString the bits to be set for the extension. */ public KeyUsageExtension(BitArray bitString) throws IOException { this.bitString = bitString.toBooleanArray(); this.extensionId = PKIXExtensions.KeyUsage_Id; this.critical = true; encodeThis(); } /** * Create the extension from the passed DER encoded value of the same. * * @param critical true if the extension is to be treated as critical. * @param value Array of DER encoded bytes of the actual value. * @exception IOException on error. */ public KeyUsageExtension(Boolean critical, Object value) throws IOException { this.extensionId = PKIXExtensions.KeyUsage_Id; this.critical = critical.booleanValue(); /* * The following check should be activated again after * the PKIX profiling work becomes standard and the check * is not a barrier to interoperability ! * if (!this.critical) { * throw new IOException("KeyUsageExtension not marked critical," * + " invalid profile."); * } */ int len = Array.getLength(value); byte[] extValue = new byte[len]; for (int i = 0; i < len; i++) { extValue[i] = Array.getByte(value, i); } this.extensionValue = extValue; DerValue val = new DerValue(extValue); BitArray bitArray = val.getUnalignedBitString(); if (bitArray == null) { throw new IOException("Invalid bit string"); } this.bitString = bitArray.toBooleanArray(); } /** * Create a default key usage. */ public KeyUsageExtension() { extensionId = PKIXExtensions.KeyUsage_Id; critical = true; bitString = new boolean[0]; } /** * Set the attribute value. */ public void set(String name, Object obj) throws IOException { clearValue(); if (!(obj instanceof Boolean)) { throw new IOException("Attribute must be of type Boolean."); } boolean val = ((Boolean) obj).booleanValue(); if (name.equalsIgnoreCase(DIGITAL_SIGNATURE)) { set(0, val); } else if (name.equalsIgnoreCase(NON_REPUDIATION)) { set(1, val); } else if (name.equalsIgnoreCase(KEY_ENCIPHERMENT)) { set(2, val); } else if (name.equalsIgnoreCase(DATA_ENCIPHERMENT)) { set(3, val); } else if (name.equalsIgnoreCase(KEY_AGREEMENT)) { set(4, val); } else if (name.equalsIgnoreCase(KEY_CERTSIGN)) { set(5, val); } else if (name.equalsIgnoreCase(CRL_SIGN)) { set(6, val); } else if (name.equalsIgnoreCase(ENCIPHER_ONLY)) { set(7, val); } else if (name.equalsIgnoreCase(DECIPHER_ONLY)) { set(8, val); } else { throw new IOException("Attribute name not recognized by" + " CertAttrSet:KeyUsage."); } encodeThis(); } /** * Get the attribute value. */ public Object get(String name) throws IOException { if (name.equalsIgnoreCase(DIGITAL_SIGNATURE)) { return Boolean.valueOf(isSet(0)); } else if (name.equalsIgnoreCase(NON_REPUDIATION)) { return Boolean.valueOf(isSet(1)); } else if (name.equalsIgnoreCase(KEY_ENCIPHERMENT)) { return Boolean.valueOf(isSet(2)); } else if (name.equalsIgnoreCase(DATA_ENCIPHERMENT)) { return Boolean.valueOf(isSet(3)); } else if (name.equalsIgnoreCase(KEY_AGREEMENT)) { return Boolean.valueOf(isSet(4)); } else if (name.equalsIgnoreCase(KEY_CERTSIGN)) { return Boolean.valueOf(isSet(5)); } else if (name.equalsIgnoreCase(CRL_SIGN)) { return Boolean.valueOf(isSet(6)); } else if (name.equalsIgnoreCase(ENCIPHER_ONLY)) { return Boolean.valueOf(isSet(7)); } else if (name.equalsIgnoreCase(DECIPHER_ONLY)) { return Boolean.valueOf(isSet(8)); } else { throw new IOException("Attribute name not recognized by" + " CertAttrSet:KeyUsage."); } } /** * Delete the attribute value. */ public void delete(String name) throws IOException { if (name.equalsIgnoreCase(DIGITAL_SIGNATURE)) { set(0, false); } else if (name.equalsIgnoreCase(NON_REPUDIATION)) { set(1, false); } else if (name.equalsIgnoreCase(KEY_ENCIPHERMENT)) { set(2, false); } else if (name.equalsIgnoreCase(DATA_ENCIPHERMENT)) { set(3, false); } else if (name.equalsIgnoreCase(KEY_AGREEMENT)) { set(4, false); } else if (name.equalsIgnoreCase(KEY_CERTSIGN)) { set(5, false); } else if (name.equalsIgnoreCase(CRL_SIGN)) { set(6, false); } else if (name.equalsIgnoreCase(ENCIPHER_ONLY)) { set(7, false); } else if (name.equalsIgnoreCase(DECIPHER_ONLY)) { set(8, false); } else { throw new IOException("Attribute name not recognized by" + " CertAttrSet:KeyUsage."); } } /** * Returns a printable representation of the KeyUsage. */ public String toString() { String s = super.toString() + "KeyUsage [\n"; try { if (isSet(0)) { s += " DigitalSignature\n"; } if (isSet(1)) { s += " Non_repudiation\n"; } if (isSet(2)) { s += " Key_Encipherment\n"; } if (isSet(3)) { s += " Data_Encipherment\n"; } if (isSet(4)) { s += " Key_Agreement\n"; } if (isSet(5)) { s += " Key_CertSign\n"; } if (isSet(6)) { s += " Crl_Sign\n"; } if (isSet(7)) { s += " Encipher_Only\n"; } if (isSet(8)) { s += " Decipher_Only\n"; } } catch (ArrayIndexOutOfBoundsException ex) { } s += "]\n"; return (s); } /** * Decode the extension from the InputStream. * * @param in the InputStream to unmarshal the contents from. * @exception IOException on decoding or validity errors. */ public void decode(InputStream in) throws IOException { throw new IOException("Method not to be called directly."); } /** * Write the extension to the DerOutputStream. * * @param out the DerOutputStream to write the extension to. * @exception IOException on encoding errors. */ public void encode(OutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); if (this.extensionValue == null) { this.extensionId = PKIXExtensions.KeyUsage_Id; this.critical = true; encodeThis(); } super.encode(tmp); out.write(tmp.toByteArray()); } /** * Return an enumeration of names of attributes existing within this * attribute. */ public Enumeration getAttributeNames() { Vector elements = new Vector(); elements.addElement(DIGITAL_SIGNATURE); elements.addElement(NON_REPUDIATION); elements.addElement(KEY_ENCIPHERMENT); elements.addElement(DATA_ENCIPHERMENT); elements.addElement(KEY_AGREEMENT); elements.addElement(KEY_CERTSIGN); elements.addElement(CRL_SIGN); elements.addElement(ENCIPHER_ONLY); elements.addElement(DECIPHER_ONLY); return (elements.elements()); } public boolean[] getBits() { return bitString.clone(); } /** * Return the name of this attribute. */ public String getName() { return (NAME); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 4160 Content-Disposition: inline; filename="LdapDNStrConverter.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "b42ed61831ec4bc7a156b0a4d581503d26da6c59" // --- 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.x509; import java.io.IOException; /** * Abstract class that converts a Ldap DN String to an X500Name, RDN or AVA * and vice versa, except the string is a java string in unicode. * * @author Lily Hsiao, Slava Galperin at Netscape Communications, Inc. */ public abstract class LdapDNStrConverter { // // public parsing methods. // /** * Converts a Ldap DN string to a X500Name object. * * @param dn a Ldap DN String. * * @return an X500Name object for the Ldap DN String. */ public abstract X500Name parseDN(String dn) throws IOException; /** * Like parseDN with a specified DER encoding order for Directory Strings. */ public abstract X500Name parseDN(String dn, byte[] tags) throws IOException; /** * Converts a Ldap DN string to a RDN object. * * @param rdn a Ldap DN String * * @return an RDN object. */ public abstract RDN parseRDN(String rdn) throws IOException; /** * Like parseRDN with a specified DER encoding order for Directory Strings. */ public abstract RDN parseRDN(String rdn, byte[] tags) throws IOException; /** * Converts a Ldap DN string to a AVA object. * * @param ava a Ldap DN string. * @return an AVA object. */ public abstract AVA parseAVA(String ava) throws IOException; /** * Like parseAVA with a specified DER encoding order for Directory Strings. */ public abstract AVA parseAVA(String rdn, byte[] tags) throws IOException; // // public encoding methods. // /** * Converts a X500Name object to a Ldap dn string. * * @param dn an X500Name object. * @return a Ldap DN String. */ public abstract String encodeDN(X500Name dn) throws IOException; /** * Converts an RDN object to a Ldap dn string. * * @param rdn an RDN object. * @return a Ldap dn string. */ public abstract String encodeRDN(RDN rdn) throws IOException; /** * Converts an AVA object to a Ldap dn string. * * @param ava An AVA object. * @return A Ldap dn string. */ public abstract String encodeAVA(AVA ava) throws IOException; // // public static methods // /** * Gets a global default Ldap DN String converter. * Currently it is LdapV3DNStrConverter object using the default * X500NameAttrMap and accepts unknown OIDs. * * @see netscape.security.x509.LdapV3DNStrConverter * * @return The global default LdapDNStrConverter instance. */ public static LdapDNStrConverter getDefault() { return defaultConverter; } /** * Set the global default LdapDNStrConverter object. * * @param defConverter A LdapDNStrConverter object to become * the global default. */ public static void setDefault(LdapDNStrConverter defConverter) { if (defConverter == null) throw new IllegalArgumentException( "The default Ldap DN String converter cannot be set to null."); defaultConverter = defConverter; } // // private static variables // private static LdapDNStrConverter defaultConverter = new LdapV3DNStrConverter(); } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 27855 Content-Disposition: inline; filename="LdapV3DNStrConverter.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "68bbeb2ad4556f2bb2d525545fe0f4bc57695dd0" // --- 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.x509; import java.io.ByteArrayOutputStream; import java.io.CharArrayWriter; import java.io.IOException; import java.io.PushbackReader; import java.io.StringReader; import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.CharacterCodingException; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; import java.nio.charset.UnsupportedCharsetException; import java.util.Arrays; import java.util.Vector; import netscape.security.util.DerValue; import netscape.security.util.ObjectIdentifier; /** * A converter that converts Ldap v3 DN strings as specified in * draft-ietf-asid-ldapv3-dn-03.txt to a X500Name, RDN or AVA and * vice versa. * * @see LdapDNStrConverter * @see X500Name * @see RDN * @see AVA * @see X500NameAttrMap * * @author Lily Hsiao, Slava Galperin at Netscape Communications, Inc. */ public class LdapV3DNStrConverter extends LdapDNStrConverter { // // Constructors // /** * Constructs a LdapV3DNStrConverter using the global default * X500NameAttrMap and accept OIDs not in the default X500NameAttrMap. * * @see X500NameAttrMap */ public LdapV3DNStrConverter() { attrMap = X500NameAttrMap.getDefault(); acceptUnknownOids = true; } /** * Constructs a LdapV3DNStrConverter using the specified X500NameAttrMap * and a boolean indicating whether to accept OIDs not listed in the * X500NameAttrMap. * * @param attributeMap a X500NameAttrMap * @param doAcceptUnknownOids whether to convert unregistered OIDs * (oids not in the X500NameAttrMap) * @see X500NameAttrMap */ public LdapV3DNStrConverter(X500NameAttrMap attributeMap, boolean doAcceptUnknownOids) { attrMap = attributeMap; acceptUnknownOids = doAcceptUnknownOids; } // // public parsing methods // From LdapDNStrConverter interface // /** * Parse a Ldap v3 DN string to a X500Name. * * @param dn a LDAP v3 DN String * @return a X500Name * @exception IOException if an error occurs during the conversion. */ public X500Name parseDN(String dn) throws IOException { return parseDN(dn, null); } /** * Like parseDN(String) with a DER encoding order given as argument for * Directory Strings. */ public X500Name parseDN(String dn, byte[] encodingOrder) throws IOException { StringReader dn_reader = new StringReader(dn); PushbackReader in = new PushbackReader(dn_reader, 5); return parseDN(in, encodingOrder); } /** * Parse a Ldap v3 DN string with a RDN component to a RDN * * @param rdn a LDAP v3 DN String * @return a RDN * @exception IOException if an error occurs during the conversion. */ public RDN parseRDN(String rdn) throws IOException { return parseRDN(rdn, null); } /** * Like parseRDN(String) with a DER encoding order given as argument for * Directory Strings. */ public RDN parseRDN(String rdn, byte[] encodingOrder) throws IOException { StringReader rdn_reader = new StringReader(rdn); PushbackReader in = new PushbackReader(rdn_reader, 5); return parseRDN(in, null); } /** * Parse a Ldap v3 DN string with a AVA component to a AVA. * * @param ava a LDAP v3 DN string * @return a AVA */ public AVA parseAVA(String ava) throws IOException { return parseAVA(ava, null); } /** * Like parseDN(String) with a DER encoding order given as argument for * Directory Strings. */ public AVA parseAVA(String ava, byte[] encodingOrder) throws IOException { StringReader ava_reader = new StringReader(ava); PushbackReader in = new PushbackReader(ava_reader, 5); return parseAVA(in, encodingOrder); } // // public parsing methods called by other methods. // /** * Parses a Ldap DN string in a string reader to a X500Name. * * @param in Pushback string reader for a Ldap DN string. * The pushback reader must have a pushback buffer size > 2. * * @return a X500Name * * @exception IOException if any reading or parsing error occurs. */ public X500Name parseDN(PushbackReader in) throws IOException { return parseDN(in, null); } /** * Like parseDN(PushbackReader in) with a DER encoding order given as * argument for Directory Strings. */ public X500Name parseDN(PushbackReader in, byte[] encodingOrder) throws IOException { RDN rdn; int lastChar; Vector rdnVector = new Vector(); RDN names[]; int i, j; do { rdn = parseRDN(in, encodingOrder); rdnVector.addElement(rdn); lastChar = in.read(); } while (lastChar == ',' || lastChar == ';'); names = new RDN[rdnVector.size()]; for (i = 0, j = rdnVector.size() - 1; i < rdnVector.size(); i++, j--) names[j] = rdnVector.elementAt(i); return new X500Name(names); } /** * Parses Ldap DN string with a rdn component * from a string reader to a RDN. The string reader will point * to the separator after the rdn component or -1 if at end of string. * * @param in Pushback string reader containing a Ldap DN string with * at least one rdn component. * The pushback reader must have a pushback buffer size > 2. * * @return RDN object of the first rdn component in the Ldap DN string. * * @exception IOException if any read or parse error occurs. */ public RDN parseRDN(PushbackReader in) throws IOException { return parseRDN(in, null); } /** * Like parseRDN(PushbackReader) with a DER encoding order given as * argument for Directory Strings. */ public RDN parseRDN(PushbackReader in, byte[] encodingOrder) throws IOException { Vector avaVector = new Vector(); AVA ava; int lastChar; AVA assertion[]; do { ava = parseAVA(in, encodingOrder); avaVector.addElement(ava); lastChar = in.read(); } while (lastChar == '+'); if (lastChar != -1) in.unread(lastChar); assertion = new AVA[avaVector.size()]; for (int i = 0; i < avaVector.size(); i++) assertion[i] = avaVector.elementAt(i); return new RDN(assertion); } /** * Parses a Ldap DN string with a AVA component * from a string reader to an AVA. The string reader will point * to the AVA separator after the ava string or -1 if end of string. * * @param in a Pushback reader containg a Ldap string with * at least one AVA component. * The Pushback reader must have a pushback buffer size > 2. * * @return AVA object of the first AVA component in the Ldap DN string. */ public AVA parseAVA(PushbackReader in) throws IOException { return parseAVA(in, null); } /** * Like parseAVA(PushbackReader) with a DER encoding order given as * argument for Directory Strings. */ public AVA parseAVA(PushbackReader in, byte[] encodingOrder) throws IOException { int c; ObjectIdentifier oid; DerValue value; StringBuffer keywordBuf; StringBuffer valueBuf; ByteArrayOutputStream berStream; char hexChar1, hexChar2; CharArrayWriter hexCharsBuf; String endChars; /* First get the keyword indicating the attribute's type, * and map it to the appropriate OID. */ keywordBuf = new StringBuffer(); for (;;) { c = in.read(); if (c == '=') break; if (c == -1) { throw new IOException("Bad AVA format: Missing '='"); } keywordBuf.append((char) c); } oid = parseAVAKeyword(keywordBuf.toString()); /* Now parse the value. "#hex", a quoted string, or a string * terminated by "+", ",", ";", ">". Whitespace before or after * the value is stripped. */ for (c = in.read(); c == ' '; c = in.read()) continue; if (c == -1) throw new IOException("Bad AVA format: Missing attribute value"); if (c == '#') { /* * NOTE per LDAPv3 dn string ietf standard the value represented * by this form is a BER value. But we only support DER value here * which is only a form of BER. */ berStream = new ByteArrayOutputStream(); int b; for (;;) { hexChar1 = (char) (c = in.read()); if (c == -1 || octoEndChars.indexOf(c) > 0) // end of value break; hexChar2 = (char) (c = in.read()); if (hexDigits.indexOf(hexChar1) == -1 || hexDigits.indexOf(hexChar2) == -1) throw new IOException("Bad AVA value: bad hex value."); b = (Character.digit(hexChar1, 16) << 4) + Character.digit(hexChar2, 16); berStream.write(b); } if (berStream.size() == 0) throw new IOException("bad AVA format: invalid hex value"); value = parseAVAValue(berStream.toByteArray(), oid); while (c == ' ' && c != -1) c = in.read(); } else { valueBuf = new StringBuffer(); boolean quoted = false; if (c == '"') { quoted = true; endChars = quotedEndChars; if ((c = in.read()) == -1) throw new IOException("Bad AVA format: Missing attrValue"); } else { endChars = valueEndChars; } // QUOTATION * ( quotechar / pair ) QUOTATION // quotechar = any character except '\' or QUOTATION // pair = '\' ( special | '\' | QUOTATION | hexpair ) while (c != -1 && endChars.indexOf(c) == -1) { if (c == '\\') { if ((c = in.read()) == -1) throw new IOException("Bad AVA format: expecting " + "escaped char."); // expect escaping of special chars, space and CR. if (specialChars.indexOf((char) c) != -1 || c == '\n' || c == '\\' || c == '"' || c == ' ') { valueBuf.append((char) c); } else if (hexDigits.indexOf(c) != -1) { hexCharsBuf = new CharArrayWriter(); // handle sequence of '\' hexpair do { hexChar1 = (char) c; hexChar2 = (char) (c = in.read()); if (hexDigits.indexOf((char) c) == -1) throw new IOException("Bad AVA format: " + "invalid escaped hex pair"); hexCharsBuf.write(hexChar1); hexCharsBuf.write(hexChar2); // read ahead to next '\' hex-char if any. if ((c = in.read()) == -1) break; if (c != '\\') { in.unread(c); break; } if ((c = in.read()) == -1) throw new IOException("Bad AVA format: " + "expecting escaped char."); if (hexDigits.indexOf((char) c) == -1) { in.unread(c); in.unread('\\'); break; } } while (true); valueBuf.append( getStringFromHexpairs(hexCharsBuf.toCharArray())); } else { throw new IOException("Bad AVA format: " + "invalid escaping"); } } else valueBuf.append((char) c); c = in.read(); } value = parseAVAValue( valueBuf.toString().trim(), oid, encodingOrder); if (quoted) { // move to next non-white space do { c = in.read(); } while (c == ' '); if (c != -1 && valueEndChars.indexOf(c) == -1) throw new IOException( "Bad AVA format: separator expected at end of ava."); } } if (c != -1) in.unread(c); return new AVA(oid, value); } /** * Converts a AVA keyword from a Ldap DN string to an ObjectIdentifier * from the attribute map or, if this keyword is an OID not * in the attribute map, create a new ObjectIdentifier for the keyword * if acceptUnknownOids is true. * * @param avaKeyword AVA keyword from a Ldap DN string. * * @return a ObjectIdentifier object * @exception IOException if the keyword is an OID not in the attribute * map and acceptUnknownOids is false, or * if an error occurs during conversion. */ public ObjectIdentifier parseAVAKeyword(String avaKeyword) throws IOException { String keyword = avaKeyword.toUpperCase().trim(); String oid_str = null; ObjectIdentifier oid, new_oid; if (Character.digit(keyword.charAt(0), 10) != -1) { // value is an oid string of 1.2.3.4 oid_str = keyword; } else if (keyword.startsWith("oid.") || keyword.startsWith("OID.")) { // value is an oid string of oid.1.2.3.4 or OID.1.2... oid_str = keyword.substring(4); } if (oid_str != null) { // value is an oid string of 1.2.3.4 or oid.1.2.3.4 or OID.1.2... new_oid = new ObjectIdentifier(oid_str); oid = attrMap.getOid(new_oid); if (oid == null) { if (!acceptUnknownOids) throw new IOException("Unknown AVA OID."); oid = new_oid; } } else { oid = attrMap.getOid(keyword); if (oid == null) throw new IOException("Unknown AVA keyword '" + keyword + "'."); } return oid; } /** * Converts a AVA value from a Ldap dn string to a * DerValue according the attribute type. For example, a value for * CN, OU or O is expected to be a Directory String and will be converted * to a DerValue of ASN.1 type PrintableString, T61String or * UniversalString. A Directory String is a ASN.1 CHOICE of Printable, * T.61 or Universal string. * * @param avaValueString a attribute value from a Ldap DN string. * @param oid OID of the attribute. * * @return DerValue for the value. * * @exception IOException if an error occurs during conversion. * @see AVAValueConverter */ public DerValue parseAVAValue(String avaValueString, ObjectIdentifier oid) throws IOException { return parseAVAValue(avaValueString, oid, null); } /** * Like parseAVAValue(String) with a DER encoding order given as argument * for Directory Strings. */ public DerValue parseAVAValue( String avaValueString, ObjectIdentifier oid, byte[] encodingOrder) throws IOException { AVAValueConverter valueConverter = attrMap.getValueConverter(oid); if (valueConverter == null) { if (!acceptUnknownOids) { throw new IllegalArgumentException( "Unrecognized OID for AVA value conversion"); } else { valueConverter = new GenericValueConverter(); } } return valueConverter.getValue(avaValueString, encodingOrder); } /** * Converts a value in BER encoding, for example given in octothorpe form * in a Ldap v3 dn string, to a DerValue. Checks if the BER encoded value * is a legal value for the attribute. *

* NOTE: only DER encoded values are supported for the BER encoded value. * * @param berValue a value in BER encoding * @param oid ObjectIdentifier of the attribute. * * @return DerValue for the BER encoded value * @exception IOException if an error occurs during conversion. */ public DerValue parseAVAValue(byte[] berValue, ObjectIdentifier oid) throws IOException { AVAValueConverter valueConverter = attrMap.getValueConverter(oid); if (valueConverter == null && !acceptUnknownOids) { throw new IllegalArgumentException( "Unrecognized OID for AVA value conversion"); } else { valueConverter = new GenericValueConverter(); } return valueConverter.getValue(berValue); } // // public encoding methods. // /** * Converts a X500Name object to a Ldap v3 DN string (except in unicode). * * @param x500name a X500Name * * @return a Ldap v3 DN String (except in unicode). * * @exception IOException if an error is encountered during conversion. */ public String encodeDN(X500Name x500name) throws IOException { RDN[] rdns = x500name.getNames(); // String fullname = null; StringBuffer fullname = new StringBuffer(); String s; int i; if (rdns.length == 0) return ""; i = rdns.length - 1; fullname.append(encodeRDN(rdns[i--])); while (i >= 0) { s = encodeRDN(rdns[i--]); fullname.append(","); fullname.append(s); } ; return fullname.toString(); } /** * Converts a RDN to a Ldap v3 DN string (except in unicode). * * @param rdn a RDN * * @return a LDAP v3 DN string (except in unicode). * * @exception IOException if an error is encountered during conversion. */ public String encodeRDN(RDN rdn) throws IOException { AVA[] avas = rdn.getAssertion(); // String relname = null; StringBuffer relname = new StringBuffer(); String s; int i = 0; relname.append(encodeAVA(avas[i++])); while (i < avas.length) { s = encodeAVA(avas[i++]); relname.append("+"); relname.append(s); } ; return relname.toString(); } /** * Converts a AVA to a Ldap v3 DN String (except in unicode). * * @param ava an AVA * * @return a Ldap v3 DN string (except in unicode). * * @exception IOException If an error is encountered during exception. */ public String encodeAVA(AVA ava) throws IOException { if (ava == null) { return ""; } ObjectIdentifier oid = ava.getOid(); DerValue value = ava.getValue(); String keyword, valueStr; // get attribute name keyword = encodeOID(oid); valueStr = encodeValue(value, oid); return keyword + "=" + valueStr; } /** * Converts an OID to a attribute keyword in a Ldap v3 DN string * - either a keyword if known or a string of "1.2.3.4" syntax. * * @param oid a ObjectIdentifier * * @return a keyword to use in a Ldap V3 DN string. * * @exception IOException if an error is encountered during conversion. */ public String encodeOID(ObjectIdentifier oid) throws IOException { String keyword = attrMap.getName(oid); if (keyword == null) { if (acceptUnknownOids) keyword = oid.toString(); else throw new IOException("Unknown OID"); } return keyword; } /** * Converts a value as a DerValue to a string in a Ldap V3 DN String. * If the value cannot be converted to a string it will be encoded in * octothorpe form. * * @param attrValue a value as a DerValue. * @param oid OID for the attribute. * @return a string for the value in a LDAP v3 DN String * @exception IOException if an error occurs during conversion. */ public String encodeValue(DerValue attrValue, ObjectIdentifier oid) throws IOException { /* * Construct the value with as little copying and garbage * production as practical. */ StringBuffer retval = new StringBuffer(30); int i; String temp = null; AVAValueConverter valueConverter; X500NameAttrMap lAttrMap = attrMap; if (attrValue.tag == DerValue.tag_UTF8String) { lAttrMap = X500NameAttrMap.getDirDefault(); } valueConverter = lAttrMap.getValueConverter(oid); if (valueConverter == null) { if (acceptUnknownOids) valueConverter = new GenericValueConverter(); else throw new IOException( "Unknown AVA type for encoding AVA value"); } try { temp = valueConverter.getAsString(attrValue); if (temp == null) { // convert to octothorpe form. byte data[] = attrValue.toByteArray(); retval.append('#'); for (i = 0; i < data.length; i++) { retval.append(hexDigits.charAt((data[i] >> 4) & 0x0f)); retval.append(hexDigits.charAt(data[i] & 0x0f)); } } else { retval.append(encodeString(temp)); } } catch (IOException e) { throw new IllegalArgumentException("malformed AVA DER Value"); } return retval.toString(); } /** * converts a raw value string to a string in Ldap V3 DN string format. * * @param valueStr a 'raw' value string. * @return a attribute value string in Ldap V3 DN string format. */ public String encodeString(String valueStr) { int i, j; int len; StringBuffer retval = new StringBuffer(); /* * generate string according to ldapv3 DN. escaping is used. * Strings generated this way are acceptable by rfc1779 * implementations. */ len = valueStr.length(); // get index of first space at the end of the string. for (j = len - 1; j >= 0 && valueStr.charAt(j) == ' '; j--) continue; // escape spaces at the beginning of the string. for (i = 0; i <= j && valueStr.charAt(i) == ' '; i++) { retval.append('\\'); retval.append(valueStr.charAt(i)); } // escape special characters in the middle of the string. for (; i <= j; i++) { if (valueStr.charAt(i) == '\\') { retval.append('\\'); retval.append(valueStr.charAt(i)); } else if (specialChars.indexOf(valueStr.charAt(i)) != -1) { retval.append('\\'); retval.append(valueStr.charAt(i)); } else if (valueStr.charAt(i) == '"') { retval.append('\\'); retval.append(valueStr.charAt(i)); } else retval.append(valueStr.charAt(i)); } // esacape spaces at the end. for (; i < valueStr.length(); i++) { retval.append('\\'); retval.append(' '); } return retval.toString(); } // // public get/set methods // /** * gets the X500NameAttrMap used by the converter. * * @return X500NameAttrMap used by this converter. */ public X500NameAttrMap getAttrMap() { return attrMap; } /** * returns true if the converter accepts unregistered attributes i.e. * OIDS not in the X500NameAttrMap. * * @return true if converter converts attributes not in the * X500NameAttrMap. */ public boolean getAcceptUnknownOids() { return acceptUnknownOids; } // // private and protected variables // protected X500NameAttrMap attrMap; protected boolean acceptUnknownOids; // // private and protected static variables & methods. // protected static final String specialChars = ",+=<>#;"; protected static final String valueEndChars = "+,;>"; protected static final String quotedEndChars = "\""; protected static final String octoEndChars = " " + valueEndChars; /* * Values that aren't printable strings are emitted as BER-encoded * hex data. */ protected static final String hexDigits = "0123456789ABCDEFabcdef"; /** * Parse a sequence of hex pairs, each pair a UTF8 byte to a java string. * For example, "4C75C48D" is "Luc", the last c with caron. */ protected static char[] getStringFromHexpairs(char[] hexPairs) throws UnsupportedEncodingException { try { byte[] buffer = new byte[hexPairs.length / 2]; for (int i = 0; i < buffer.length; i++) { buffer[i] = (byte) ((Character.digit(hexPairs[i * 2], 16) << 4) + Character.digit(hexPairs[i * 2 + 1], 16)); } Charset charset = Charset.forName("UTF-8"); CharsetDecoder decoder = charset.newDecoder(); CharBuffer charBuffer = decoder.decode(ByteBuffer.wrap(buffer)); return Arrays.copyOfRange(charBuffer.array(), charBuffer.arrayOffset(), charBuffer.arrayOffset() + charBuffer.limit()); } catch (UnsupportedCharsetException e) { throw new UnsupportedEncodingException( "No UTF8 byte to char converter to use for " + "parsing LDAP DN String"); } catch (CharacterCodingException e) { throw new IllegalArgumentException( "Invalid hex pair in LDAP DN String."); } } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 7128 Content-Disposition: inline; filename="NSCCommentExtension.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "285fe611488e89a0a2bb7661e99a1971f3e96225" // --- 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.x509; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Array; import java.util.Enumeration; import java.util.Vector; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; import netscape.security.util.ObjectIdentifier; import netscape.security.util.PrettyPrintFormat; /** * This class defines the NSCCommentExtension * * @author asondhi * @see Extension * @see CertAttrSet */ public class NSCCommentExtension extends Extension implements CertAttrSet { /** * */ private static final long serialVersionUID = 4066287070285105375L; /** * Identifier for this attribute, to be used with the * get, set, delete methods of Certificate, x509 type. */ public static final String IDENT = "x509.info.extensions.CommentExtension"; /** * Attribute names. */ public static final String NAME = "NSCCommentExtension"; public static final String INFOS = "infos"; public static final ObjectIdentifier OID = new ObjectIdentifier("2.16.840.1.113730.1.13"); public String mComment = null; // Private data members private Vector mInfos; private transient PrettyPrintFormat pp = new PrettyPrintFormat(":"); // Encode this extension value private void encodeThis() throws IOException { try (DerOutputStream os = new DerOutputStream()) { os.putIA5String(mComment); // DerOutputStream tmp = new DerOutputStream(); // os.write(DerValue.tag_Sequence,tmp); extensionValue = os.toByteArray(); } } /** * Create a NSCCommentExtension with the Vector of CertificatePolicyInfo. * * @param infos the Vector of CertificatePolicyInfo. */ public NSCCommentExtension(boolean critical, String comment) throws IOException { this.mComment = comment; this.extensionId = new ObjectIdentifier("2.16.840.1.113730.1.13"); this.critical = critical; encodeThis(); } /** * Create a default NSCCommentExtension. */ public NSCCommentExtension(boolean critical) { this.extensionId = new ObjectIdentifier("2.16.840.1.113730.1.13"); this.critical = critical; mInfos = new Vector(1, 1); } /** * Create the extension from the passed DER encoded value. * * @param critical true if the extension is to be treated as critical. * @param value Array of DER encoded bytes of the actual value. * @exception IOException on error. */ public NSCCommentExtension(Boolean critical, Object value) throws IOException { this.extensionId = new ObjectIdentifier("2.16.840.1.113730.1.13"); this.critical = critical.booleanValue(); int len = Array.getLength(value); byte[] extValue = new byte[len]; for (int i = 0; i < len; i++) { extValue[i] = Array.getByte(value, i); } this.extensionValue = extValue; DerValue val = new DerValue(extValue); mComment = val.getIA5String(); } /** * Returns a printable representation of the policy extension. */ public String toString() { if (mInfos == null) return ""; String s = super.toString() + "Netscape Comment [\n" + mInfos.toString() + "]\n"; return (s); } public String toPrint(int indent) { String s; s = "Comment :\n" + pp.indent(indent + 4) + ((mComment == null) ? "" : mComment.trim()) + "\n"; return (s); } /** * Write the extension to the OutputStream. * * @param out the OutputStream to write the extension to. * @exception IOException on encoding errors. */ public void encode(OutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); if (extensionValue == null) { extensionId = new ObjectIdentifier("2.16.840.1.113730.1.13"); critical = false; encodeThis(); } super.encode(tmp); out.write(tmp.toByteArray()); } /** * Decode the extension from the InputStream. * * @param in the InputStream to unmarshal the contents from. * @exception IOException on decoding or validity errors. */ public void decode(InputStream in) throws IOException { throw new IOException("Method not to be called directly."); } public String getComment() { return mComment; } /** * Set the attribute value. */ @SuppressWarnings("unchecked") public void set(String name, Object obj) throws IOException { clearValue(); if (name.equalsIgnoreCase(INFOS)) { if (!(obj instanceof Vector)) { throw new IOException("Attribute value should be of" + " type Vector."); } mInfos = (Vector) obj; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:NSCCommentExtension."); } } /** * Get the attribute value. */ public Object get(String name) throws IOException { if (name.equalsIgnoreCase(INFOS)) { return (mInfos); } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:NSCCommentExtension."); } } /** * Delete the attribute value. */ public void delete(String name) throws IOException { if (name.equalsIgnoreCase(INFOS)) { mInfos = null; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:NSCCommentExtension."); } } /** * Return an enumeration of names of attributes existing within this * attribute. */ public Enumeration getAttributeNames() { Vector elements = new Vector(); elements.addElement(INFOS); return (elements.elements()); } /** * Return the name of this attribute. */ public String getName() { return (NAME); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 11653 Content-Disposition: inline; filename="NameConstraintsExtension.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "29cd94f4021addfb54d5a144b55bb67aaa85d263" // --- 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.x509; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Array; import java.util.Enumeration; import java.util.Vector; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; import netscape.security.util.PrettyPrintFormat; /** * This class defines the Name Constraints Extension. *

* The name constraints extension provides permitted and excluded subtrees that place restrictions on names that may be * included within a certificate issued by a given CA. Restrictions may apply to the subject distinguished name or * subject alternative names. Any name matching a restriction in the excluded subtrees field is invalid regardless of * information appearing in the permitted subtrees. *

* The ASN.1 syntax for this is: * *

 * NameConstraints ::= SEQUENCE {
 *    permittedSubtrees [0]  GeneralSubtrees OPTIONAL,
 *    excludedSubtrees  [1]  GeneralSubtrees OPTIONAL
 * }
 * GeneralSubtrees ::= SEQUENCE SIZE (1..MAX) OF GeneralSubtree
 * GeneralSubtree ::== SEQUENCE {
 *    base                   GeneralName,
 *    minimum           [0]  BaseDistance DEFAULT 0,
 *    maximum           [1]  BaseDistance OPTIONAL }
 * BaseDistance ::== INTEGER (0..MAX)
 * 
* * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.10 * @see Extension * @see CertAttrSet */ public class NameConstraintsExtension extends Extension implements CertAttrSet { /** * */ private static final long serialVersionUID = -3506940192931244539L; /** * Identifier for this attribute, to be used with the * get, set, delete methods of Certificate, x509 type. */ public static final String IDENT = "x509.info.extensions.NameConstraints"; /** * Attribute names. */ public static final String NAME = "NameConstraints"; public static final String PERMITTED_SUBTREES = "permitted_subtrees"; public static final String EXCLUDED_SUBTREES = "excluded_subtrees"; // Private data members private static final byte TAG_PERMITTED = 0; private static final byte TAG_EXCLUDED = 1; private GeneralSubtrees permitted; private GeneralSubtrees excluded; private transient PrettyPrintFormat pp = new PrettyPrintFormat(":"); // Encode this extension value. private void encodeThis() throws IOException { try (DerOutputStream seq = new DerOutputStream()) { DerOutputStream tagged = new DerOutputStream(); if ((permitted != null) && (permitted.getSubtrees().size() > 0)) { DerOutputStream tmp = new DerOutputStream(); permitted.encode(tmp); tagged.writeImplicit(DerValue.createTag(DerValue.TAG_CONTEXT, true, TAG_PERMITTED), tmp); } if ((excluded != null) && (excluded.getSubtrees().size() > 0)) { DerOutputStream tmp = new DerOutputStream(); excluded.encode(tmp); tagged.writeImplicit(DerValue.createTag(DerValue.TAG_CONTEXT, true, TAG_EXCLUDED), tmp); } if (permitted == null && excluded == null) { extensionValue = null; // no need to encode this extension } else { seq.write(DerValue.tag_Sequence, tagged); this.extensionValue = seq.toByteArray(); } } } /** * The default constructor for this class. Either parameter * can be set to null to indicate it is omitted but both * cannot be null. * * @param permitted the permitted GeneralSubtrees (null for optional). * @param excluded the excluded GeneralSubtrees (null for optional). */ public NameConstraintsExtension(GeneralSubtrees permitted, GeneralSubtrees excluded) throws IOException { init(false, permitted, excluded); } public NameConstraintsExtension(boolean critical, GeneralSubtrees permitted, GeneralSubtrees excluded) throws IOException { init(critical, permitted, excluded); } private void init(boolean critical, GeneralSubtrees permitted, GeneralSubtrees excluded) throws IOException { if (permitted == null && excluded == null) { throw new IOException("NameConstraints: Invalid arguments"); } this.permitted = permitted; this.excluded = excluded; this.extensionId = PKIXExtensions.NameConstraints_Id; this.critical = critical; encodeThis(); } /** * Create the extension from the passed DER encoded value. * * @param critical true if the extension is to be treated as critical. * @param value Array of DER encoded bytes of the actual value. * @exception IOException on error. */ public NameConstraintsExtension(Boolean critical, Object value) throws IOException { this.extensionId = PKIXExtensions.NameConstraints_Id; this.critical = critical.booleanValue(); if (!(value instanceof byte[])) throw new IOException("Illegal argument type"); int len = Array.getLength(value); byte[] extValue = new byte[len]; System.arraycopy(value, 0, extValue, 0, len); this.extensionValue = extValue; DerValue val = new DerValue(extValue); if (val.tag != DerValue.tag_Sequence) { throw new IOException("Invalid encoding for" + " NameConstraintsExtension."); } // NB. this is always encoded with the IMPLICIT tag // The checks only make sense if we assume implicit tagging, // with explicit tagging the form is always constructed. while (val.data.available() != 0) { DerValue opt = val.data.getDerValue(); if (opt.isContextSpecific(TAG_PERMITTED) && opt.isConstructed()) { if (permitted != null) { throw new IOException("Duplicate permitted " + "GeneralSubtrees in NameConstraintsExtension."); } opt.resetTag(DerValue.tag_Sequence); permitted = new GeneralSubtrees(opt); } else if (opt.isContextSpecific(TAG_EXCLUDED) && opt.isConstructed()) { if (excluded != null) { throw new IOException("Duplicate excluded " + "GeneralSubtrees in NameConstraintsExtension."); } opt.resetTag(DerValue.tag_Sequence); excluded = new GeneralSubtrees(opt); } else throw new IOException("Invalid encoding of " + "NameConstraintsExtension."); } } /** * Return the printable string. */ public String toString() { return (super.toString() + "NameConstraints: [" + ((permitted == null) ? "" : ("\n Permitted:" + permitted.toString())) + ((excluded == null) ? "" : ("\n Excluded:" + excluded.toString())) + " ]\n"); } public String toPrint(int indent) { return ("GeneralSubtrees: " + ((permitted == null) ? "" : ("\n" + pp.indent(indent + 2) + "Permitted:" + permitted.toPrint(indent + 4))) + ((excluded == null) ? "" : ("\n" + pp.indent(indent + 2) + "Excluded:" + excluded.toPrint(indent + 4))) + "\n"); } /** * Decode the extension from the InputStream. * * @param in the InputStream to unmarshal the contents from. * @exception IOException on decoding or validity errors. */ public void decode(InputStream in) throws IOException { throw new IOException("Method not to be called directly."); } /** * Write the extension to the OutputStream. * * @param out the OutputStream to write the extension to. * @exception IOException on encoding errors. */ public void encode(OutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); if (this.extensionValue == null) { this.extensionId = PKIXExtensions.NameConstraints_Id; encodeThis(); } super.encode(tmp); out.write(tmp.toByteArray()); } /** * Set the attribute value. */ public void set(String name, Object obj) throws IOException { clearValue(); if (name.equalsIgnoreCase(PERMITTED_SUBTREES)) { if (!(obj instanceof GeneralSubtrees)) { throw new IOException("Attribute value should be" + " of type GeneralSubtrees."); } permitted = (GeneralSubtrees) obj; } else if (name.equalsIgnoreCase(EXCLUDED_SUBTREES)) { if (!(obj instanceof GeneralSubtrees)) { throw new IOException("Attribute value should be " + "of type GeneralSubtrees."); } excluded = (GeneralSubtrees) obj; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:NameConstraintsExtension."); } } /** * Get the attribute value. */ public Object get(String name) throws IOException { if (name.equalsIgnoreCase(PERMITTED_SUBTREES)) { return (permitted); } else if (name.equalsIgnoreCase(EXCLUDED_SUBTREES)) { return (excluded); } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:NameConstraintsExtension."); } } /** * Delete the attribute value. */ public void delete(String name) throws IOException { if (name.equalsIgnoreCase(PERMITTED_SUBTREES)) { permitted = null; } else if (name.equalsIgnoreCase(EXCLUDED_SUBTREES)) { excluded = null; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:NameConstraintsExtension."); } } /** * Return an enumeration of names of attributes existing within this * attribute. */ public Enumeration getAttributeNames() { Vector elements = new Vector(); elements.addElement(PERMITTED_SUBTREES); elements.addElement(EXCLUDED_SUBTREES); return (elements.elements()); } /** * Return the name of this attribute. */ public String getName() { return (NAME); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 3151 Content-Disposition: inline; filename="NoticeReference.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "66701518b555f420032bf14f24324e97f5ec9aad" // --- 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.x509; import java.io.IOException; import java.io.Serializable; import java.util.Vector; import netscape.security.util.BigInt; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; /** * Represent the NoticeReference. * * NoticeReference ::= SEQUENCE { * organization DisplayText, * noticeNumbers SEQUENCE OF INTEGER * } * * @author Thomas Kwan */ public class NoticeReference implements Serializable { private static final long serialVersionUID = 1986080941078808200L; private DisplayText mOrg = null; private int mNumbers[] = null; public NoticeReference(DisplayText org, int numbers[]) { mOrg = org; mNumbers = numbers; } public NoticeReference(DerValue val) throws IOException { if (val.tag != DerValue.tag_Sequence) { throw new IOException("Invalid encoding for NoticeReference"); } mOrg = new DisplayText(val.data.getDerValue()); DerValue integers = val.data.getDerValue(); if (integers.tag != DerValue.tag_Sequence) { throw new IOException("Invalid encoding for NoticeReference (integers)"); } Vector num = new Vector(); while (integers.data.available() != 0) { DerValue i = integers.data.getDerValue(); BigInt bigI = i.getInteger(); num.addElement(bigI); } if (num.size() <= 0) return; mNumbers = new int[num.size()]; for (int i = 0; i < num.size(); i++) { mNumbers[i] = num.elementAt(i).toInt(); } } public DisplayText getOrganization() { return mOrg; } public int[] getNumbers() { return mNumbers; } /** * Write the NoticeReference to the DerOutputStream. * * @param out the DerOutputStream to write the object to. * @exception IOException on errors. */ public void encode(DerOutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); mOrg.encode(tmp); DerOutputStream iseq = new DerOutputStream(); for (int i = 0; i < mNumbers.length; i++) { iseq.putInteger(new BigInt(mNumbers[i])); } tmp.write(DerValue.tag_Sequence, iseq); out.write(DerValue.tag_Sequence, tmp); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 13454 Content-Disposition: inline; filename="OIDMap.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "20765c934df16ee4fba2bad99c1d7abdfb910280" // --- 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.x509; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.security.cert.CertificateException; import java.util.Hashtable; import java.util.Iterator; import java.util.Properties; import netscape.security.util.ObjectIdentifier; /** * This class defines the mapping from OID & name to classes and vice * versa. Used by CertificateExtensions & PKCS10 to get the java * classes associated with a particular OID/name. * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.12 */ public class OIDMap { /** * Location for where the OID/Classes maps are stored on * the local system. */ public static final String EXTENSIONS_HOME = (System.getProperty("java.home") + File.separator + "lib" + File.separator + "security" + File.separator + "cert" + File.separator); /** * File names for where OIDs and Classes are registered * for V3 extensions. */ public static final String EXTENSIONS_OIDS = "x509extensions.oid"; public static final String EXTENSIONS_CLASSES = "x509extensions.classes"; // Make default names easier private static final String ROOT = X509CertImpl.NAME + "." + X509CertInfo.NAME + "." + X509CertInfo.EXTENSIONS; private static final String AUTH_KEY_IDENTIFIER = ROOT + "." + AuthorityKeyIdentifierExtension.NAME; private static final String SUB_KEY_IDENTIFIER = ROOT + "." + SubjectKeyIdentifierExtension.NAME; private static final String KEY_USAGE = ROOT + "." + KeyUsageExtension.NAME; private static final String PRIVATE_KEY_USAGE = ROOT + "." + PrivateKeyUsageExtension.NAME; private static final String POLICY_MAPPINGS = ROOT + "." + PolicyMappingsExtension.NAME; private static final String SUB_ALT_NAME = ROOT + "." + SubjectAlternativeNameExtension.NAME; private static final String ISSUER_ALT_NAME = ROOT + "." + IssuerAlternativeNameExtension.NAME; private static final String BASIC_CONSTRAINTS = ROOT + "." + BasicConstraintsExtension.NAME; private static final String NAME_CONSTRAINTS = ROOT + "." + NameConstraintsExtension.NAME; private static final String POLICY_CONSTRAINTS = ROOT + "." + PolicyConstraintsExtension.NAME; private static final String CERT_POLICIES = //ROOT + "." + CertificatePoliciesExtension.NAME; private static final String SUBJ_DIR_ATTR = //ROOT + "." + SubjectDirAttributesExtension.NAME; public static final String EXT_KEY_USAGE_NAME = "ExtendedKeyUsageExtension"; public static final String EXT_INHIBIT_ANY_POLICY_NAME = "InhibitAnyPolicyExtension"; private static final String EXT_KEY_USAGE = //ROOT + "." + EXT_KEY_USAGE_NAME; private static final String CRL_NUMBER = ROOT + "." + CRLNumberExtension.NAME; private static final String CRL_REASON = ROOT + "." + CRLReasonExtension.NAME; private static final Hashtable oid2Name = new Hashtable(); private static final Hashtable name2OID = new Hashtable(); private static final Hashtable name2Class = new Hashtable(); // Initialize recognized extensions from EXTENSIONS_{OIDS/CLASSES} files static { loadNames(); loadClasses(); addClass(CRLDistributionPointsExtension.class); } // Load the default name to oid map (EXTENSIONS_OIDS) private static void loadNamesDefault(Properties props) { props.put(SUB_KEY_IDENTIFIER, "2.5.29.14"); props.put(KEY_USAGE, "2.5.29.15"); props.put(PRIVATE_KEY_USAGE, "2.5.29.16"); props.put(SUB_ALT_NAME, "2.5.29.17"); props.put(ISSUER_ALT_NAME, "2.5.29.18"); props.put(BASIC_CONSTRAINTS, "2.5.29.19"); props.put(CRL_NUMBER, "2.5.29.20"); props.put(CRL_REASON, "2.5.29.21"); props.put(NAME_CONSTRAINTS, "2.5.29.30"); props.put(POLICY_MAPPINGS, "2.5.29.33"); props.put(POLICY_CONSTRAINTS, "2.5.29.36"); props.put(CERT_POLICIES, "2.5.29.32"); props.put(AUTH_KEY_IDENTIFIER, "2.5.29.35"); props.put(SUBJ_DIR_ATTR, "2.5.29.9"); props.put(EXT_KEY_USAGE, "2.5.29.37"); } // Load the default name to class map (EXTENSIONS_CLASSES) private static void loadClassDefault(Properties props) { props.put(AUTH_KEY_IDENTIFIER, "netscape.security.x509.AuthorityKeyIdentifierExtension"); props.put(SUB_KEY_IDENTIFIER, "netscape.security.x509.SubjectKeyIdentifierExtension"); props.put(KEY_USAGE, "netscape.security.x509.KeyUsageExtension"); props.put(PRIVATE_KEY_USAGE, "netscape.security.x509.PrivateKeyUsageExtension"); props.put(POLICY_MAPPINGS, "netscape.security.x509.PolicyMappingsExtension"); props.put(SUB_ALT_NAME, "netscape.security.x509.SubjectAlternativeNameExtension"); props.put(ISSUER_ALT_NAME, "netscape.security.x509.IssuerAlternativeNameExtension"); props.put(BASIC_CONSTRAINTS, "netscape.security.x509.BasicConstraintsExtension"); props.put(NAME_CONSTRAINTS, "netscape.security.x509.NameConstraintsExtension"); props.put(POLICY_CONSTRAINTS, "netscape.security.x509.PolicyConstraintsExtension"); props.put(CERT_POLICIES, "netscape.security.x509.CertificatePoliciesExtension"); props.put(SUBJ_DIR_ATTR, "netscape.security.x509.SubjectDirAttributesExtension"); props.put(EXT_KEY_USAGE, "netscape.security.extensions.ExtendedKeyUsageExtension"); props.put(CRL_NUMBER, "netscape.security.x509.CRLNumberExtension"); props.put(CRL_REASON, "netscape.security.x509.CRLReasonExtension"); } // Return the file along with location private static File certificatePropFile(String fileName) { return (new File(EXTENSIONS_HOME + fileName)); } // Load the names to oid map private static void loadNames() { Properties props = new Properties(); File namesMap = certificatePropFile(EXTENSIONS_OIDS); if (!namesMap.exists()) { loadNamesDefault(props); } else { FileInputStream fis = null; try { fis = new FileInputStream(namesMap); props.load(fis); } catch (IOException e) { loadNamesDefault(props); } finally { if (fis != null) { try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } } Iterator names = props.stringPropertyNames().iterator(); while (names.hasNext()) { String name = names.next(); String oidName = props.getProperty(name); ObjectIdentifier oid = new ObjectIdentifier(oidName); name2OID.put(name, oid); oid2Name.put(oid, name); } } // Load the names to classes map private static void loadClasses() { Properties props = new Properties(); File classMap = certificatePropFile(EXTENSIONS_CLASSES); if (!classMap.exists()) { loadClassDefault(props); } else { FileInputStream fis = null; try { fis = new FileInputStream(classMap); props.load(fis); } catch (IOException e) { loadClassDefault(props); } finally { if (fis != null) { try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } } Iterator names = props.stringPropertyNames().iterator(); while (names.hasNext()) { String name = names.next(); String className = props.getProperty(name); name2Class.put(name, className); } } /** * Add an extension to the OIDMap. * * Assumes existence of static OID and NAME fields with unique values. */ public static void addClass(Class clazz) { try { addAttribute(clazz.getName(), (String) clazz.getField("OID").get(null), (String) clazz.getField("NAME").get(null)); } catch (Throwable e) { System.out.println( "Error adding class " + clazz.getName() + " to OIDMap: " + e); } } /** * Add a name to lookup table. * * @param className the name of the fully qualified class implementing * the asn object. * @param oid the string representation of the object identifier for * the class. * @param name the name of the attribute. * @exception CertificateException on errors. */ public static void addAttribute(String className, String oid, String name) throws CertificateException { ObjectIdentifier objId = new ObjectIdentifier(oid); if (oid2Name.get(objId) != null) { throw new CertificateException("Object identifier already exists."); } if (name2OID.get(name) != null) { throw new CertificateException("Name already exists."); } if (name2Class.get(className) != null) { throw new CertificateException("Class already exists."); } oid2Name.put(objId, name); name2OID.put(name, objId); name2Class.put(name, className); } /** * Return user friendly name associated with the OID. * * @param oid the name of the object identifier to be returned. * @return the user friendly name or null if no name * is registered for this oid. */ public static String getName(ObjectIdentifier oid) { return oid2Name.get(oid); } /** * Return Object identifier for user friendly name. * * @param name the user friendly name. * @return the Object Identifier or null if no oid * is registered for this name. */ public static ObjectIdentifier getOID(String name) { return name2OID.get(name); } /** * Return the java class object associated with the user friendly name. * * @param name the user friendly name. * @exception CertificateException if class cannot be instantiated. */ public static Class getClass(String name) throws CertificateException { String className = name2Class.get(name); if (className == null) return null; try { Class extClass = Class.forName(className); return (extClass); } catch (Exception e) { throw new CertificateException("Error instantiating class for " + name + " " + e.toString()); } } /** * Return the java class object associated with the object identifier.. * * @param oid the name of the object identifier to be returned. * @exception CertificateException if class cannot be instatiated. */ public static Class getClass(ObjectIdentifier oid) throws CertificateException { String name = getName(oid); if (name == null) return null; String className = name2Class.get(name); if (className == null) return null; try { Class extClass = Class.forName(className); return (extClass); } catch (Exception e) { throw new CertificateException("Error instantiating class for " + name + " " + e.toString()); } } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 2532 Content-Disposition: inline; filename="OIDName.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "38ebff87dab88e7721faf2a8cdc32129bd716f75" // --- 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.x509; import java.io.IOException; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; import netscape.security.util.ObjectIdentifier; /** * This class implements the OIDName as required by the GeneralNames * ASN.1 object. * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.3 * @see GeneralName * @see GeneralNames * @see GeneralNameInterface */ public class OIDName implements GeneralNameInterface { /** * */ private static final long serialVersionUID = 9198510631835117121L; private ObjectIdentifier oid; /** * Create the OIDName object from the passed encoded Der value. * * @param derValue the encoded DER OIDName. * @exception IOException on error. */ public OIDName(DerValue derValue) throws IOException { oid = derValue.getOID(); } /** * Create the OIDName object with the specified name. * * @param name the OIDName. */ public OIDName(ObjectIdentifier oid) { this.oid = oid; } public OIDName(String oid) { this.oid = new ObjectIdentifier(oid); } /** * Return the type of the GeneralName. */ public int getType() { return (GeneralNameInterface.NAME_OID); } /** * Encode the OID name into the DerOutputStream. * * @param out the DER stream to encode the OIDName to. * @exception IOException on encoding errors. */ public void encode(DerOutputStream out) throws IOException { out.putOID(oid); } /** * Convert the name into user readable string. */ public String toString() { return ("OIDName: " + oid.toString()); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 6607 Content-Disposition: inline; filename="OtherName.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "a78c4fa7ad05bd3836f060a0ea8152330905df1f" // --- 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.x509; import java.io.IOException; import java.io.InputStream; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; import netscape.security.util.ObjectIdentifier; /** * This class implements the OtherName as required by the GeneralNames * ASN.1 object. * * OtherName ::= SEQUENCE { * type-id OBJECT IDENTIFIER, * value [0] EXPLICIT ANY DEFINED BY type-id * } * * @see GeneralName * @see GeneralNameInterface * @see GeneralNames * * @version 1.2 * * @author Amit Kapoor * @author Hemma Prafullchandra */ public class OtherName implements GeneralNameInterface { /** * */ private static final long serialVersionUID = -3533614377346132611L; private ObjectIdentifier mOID = null; private byte[] mData = null; /** * Create the IPAddressName object from the passed encoded Der value. * * @param derValue the encoded DER IPAddressName. * @exception IOException on error. */ public OtherName(DerValue derValue) throws IOException { decodeThis(derValue); } public OtherName(ObjectIdentifier oid, byte data[]) throws IOException { mOID = oid; DerOutputStream dos = new DerOutputStream(); try { dos.putDerValue(new DerValue(data)); } catch (IOException e) { } finally { dos.close(); } mData = dos.toByteArray(); } /** * Constructs a string-based other name. */ public OtherName(ObjectIdentifier oid, byte tag, String value) throws IOException { mOID = oid; DerOutputStream dos = new DerOutputStream(); try { if (tag == DerValue.tag_PrintableString) { dos.putPrintableString(value); } else if (tag == DerValue.tag_IA5String) { dos.putIA5String(value); } else if (tag == DerValue.tag_BMPString) { dos.putBMPString(value); } else if (tag == DerValue.tag_UTF8String) { dos.putUTF8String(value); } } catch (IOException e) { } finally { dos.close(); } mData = dos.toByteArray(); } public OtherName(ObjectIdentifier oid, String value) throws IOException { mOID = oid; DerOutputStream dos = new DerOutputStream(); try { dos.putPrintableString(value); } catch (IOException e) { } finally { dos.close(); } mData = dos.toByteArray(); } /** * Create the IPAddressName object with the specified name. * * @param name the IPAddressName. */ public OtherName(byte[] data) { try { decodeThis(new DerValue(data)); } catch (IOException e) { } } public ObjectIdentifier getOID() { return mOID; } /** * Return the type of the GeneralName. */ public int getType() { return (GeneralNameInterface.NAME_ANY); } /** * Encode the IPAddress name into the DerOutputStream. * * @param out the DER stream to encode the IPAddressName to. * @exception IOException on encoding errors. */ public void encode(DerOutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); //encoding the attributes tmp.putOID(mOID); DerOutputStream tmp1 = new DerOutputStream(); tmp1.write(mData); tmp.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0x80), tmp1); out.write(DerValue.tag_SequenceOf, tmp); } public void decode(InputStream in) throws IOException { DerValue val = new DerValue(in); decodeThis(val); } // Decode this extension value private void decodeThis(DerValue derVal) throws IOException { // if (derVal.tag != DerValue.tag_Sequence) { // throw new IOException("Invalid encoding for other name"); // } // Decode all the Attributes mOID = derVal.data.getOID(); // skip tag DerValue tag = derVal.data.getDerValue(); // read data DerValue data = tag.data.getDerValue(); mData = data.toByteArray(); } public byte[] getValue() { return mData; } /** * Return a printable string of IPaddress */ public String toString() { if (mData != null) { try { DerValue data = new DerValue(mData); if (data.tag == DerValue.tag_PrintableString) { return "OtherName: (PrintableString)" + mOID + "," + data.getPrintableString(); } else if (data.tag == DerValue.tag_IA5String) { return "OtherName: (IA5String)" + mOID + "," + data.getIA5String(); } else if (data.tag == DerValue.tag_BMPString) { return "OtherName: (BMPString)" + mOID + "," + data.getIA5String(); } else if (data.tag == DerValue.tag_UTF8String) { return "OtherName: (UTF8String)" + mOID + "," + data.getUTF8String(); } else { return "OtherName: (Any)" + mOID + "," + toStr(data.toByteArray()); } } catch (IOException e) { return "OtherName: (Any)" + mOID + "," + toStr(mData); } } else { return "OtherName: "; } } public String toStr(byte data[]) { StringBuffer b = new StringBuffer(); for (int i = 0; i < data.length; i++) { if ((data[i] & 0xff) < 16) { b.append("0"); } b.append(Integer.toString((data[i] & 0xff), 0x10)); } return b.toString(); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 7872 Content-Disposition: inline; filename="PKIXExtensions.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "2e35544bf15400716b3433ef7755528e7e5d81f9" // --- 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.x509; import netscape.security.util.ObjectIdentifier; /** * Lists all the object identifiers of the X509 extensions of the PKIX profile. * *

* Extensions are addiitonal attributes which can be inserted in a X509 v3 certificate. For example a * "Driving License Certificate" could have the driving license number as a extension. * *

* Extensions are represented as a sequence of the extension identifier (Object Identifier), a boolean flag stating * whether the extension is to be treated as being critical and the extension value itself (this is again a DER encoding * of the extension value). * * @see Extension * * @version 1.4 * * @author Amit Kapoor * @author Hemma Prafullchandra */ public class PKIXExtensions { // The object identifiers private static final int AuthorityKey_data[] = { 2, 5, 29, 35 }; private static final int SubjectKey_data[] = { 2, 5, 29, 14 }; private static final int KeyUsage_data[] = { 2, 5, 29, 15 }; private static final int PrivateKeyUsage_data[] = { 2, 5, 29, 16 }; private static final int CertificatePolicies_data[] = { 2, 5, 29, 32 }; private static final int PolicyMappings_data[] = { 2, 5, 29, 33 }; private static final int SubjectAlternativeName_data[] = { 2, 5, 29, 17 }; private static final int IssuerAlternativeName_data[] = { 2, 5, 29, 18 }; private static final int SubjectDirectoryAttributes_data[] = { 2, 5, 29, 9 }; private static final int BasicConstraints_data[] = { 2, 5, 29, 19 }; private static final int NameConstraints_data[] = { 2, 5, 29, 30 }; private static final int PolicyConstraints_data[] = { 2, 5, 29, 36 }; private static final int CRLDistributionPoints_data[] = { 2, 5, 29, 31 }; private static final int CRLNumber_data[] = { 2, 5, 29, 20 }; private static final int IssuingDistributionPoint_data[] = { 2, 5, 29, 28 }; private static final int DeltaCRLIndicator_data[] = { 2, 5, 29, 27 }; private static final int ReasonCode_data[] = { 2, 5, 29, 21 }; private static final int HoldInstructionCode_data[] = { 2, 5, 29, 23 }; private static final int InvalidityDate_data[] = { 2, 5, 29, 24 }; private static final int CertificateIssuer_data[] = { 2, 5, 29, 29 }; private static final int FreshestCRL_data[] = { 2, 5, 29, 46 }; /** * Identifies the particular public key used to sign the certificate. */ public static final ObjectIdentifier AuthorityKey_Id = new ObjectIdentifier(AuthorityKey_data); /** * Identifies the particular public key used in an application. */ public static final ObjectIdentifier SubjectKey_Id = new ObjectIdentifier(SubjectKey_data); /** * Defines the purpose of the key contained in the certificate. */ public static final ObjectIdentifier KeyUsage_Id = new ObjectIdentifier(KeyUsage_data); /** * Allows the certificate issuer to specify a different validity period * for the private key than the certificate. */ public static final ObjectIdentifier PrivateKeyUsage_Id = new ObjectIdentifier(PrivateKeyUsage_data); /** * Contains the sequence of policy information terms. */ public static final ObjectIdentifier CertificatePolicies_Id = new ObjectIdentifier(CertificatePolicies_data); /** * Lists pairs of objectidentifiers of policies considered equivalent by the * issuing CA to the subject CA. */ public static final ObjectIdentifier PolicyMappings_Id = new ObjectIdentifier(PolicyMappings_data); /** * Allows additional identities to be bound to the subject of the certificate. */ public static final ObjectIdentifier SubjectAlternativeName_Id = new ObjectIdentifier(SubjectAlternativeName_data); /** * Allows additional identities to be associated with the certificate issuer. */ public static final ObjectIdentifier IssuerAlternativeName_Id = new ObjectIdentifier(IssuerAlternativeName_data); /** * Identifies additional directory attributes. * This extension is always non-critical. */ public static final ObjectIdentifier SubjectDirectoryAttributes_Id = new ObjectIdentifier( SubjectDirectoryAttributes_data); /** * Identifies whether the subject of the certificate is a CA and how deep * a certification path may exist through that CA. */ public static final ObjectIdentifier BasicConstraints_Id = new ObjectIdentifier(BasicConstraints_data); /** * Provides for permitted and excluded subtrees that place restrictions * on names that may be included within a certificate issued by a given CA. */ public static final ObjectIdentifier NameConstraints_Id = new ObjectIdentifier(NameConstraints_data); /** * Used to either prohibit policy mapping or limit the set of policies * that can be in subsequent certificates. */ public static final ObjectIdentifier PolicyConstraints_Id = new ObjectIdentifier(PolicyConstraints_data); /** * Identifies how CRL information is obtained. */ public static final ObjectIdentifier CRLDistributionPoints_Id = new ObjectIdentifier(CRLDistributionPoints_data); /** * Conveys a monotonically increasing sequence number for each CRL * issued by a given CA. */ public static final ObjectIdentifier CRLNumber_Id = new ObjectIdentifier(CRLNumber_data); /** * Identifies the CRL distribution point for a particular CRL. */ public static final ObjectIdentifier IssuingDistributionPoint_Id = new ObjectIdentifier( IssuingDistributionPoint_data); /** * Identifies the delta CRL. */ public static final ObjectIdentifier DeltaCRLIndicator_Id = new ObjectIdentifier(DeltaCRLIndicator_data); /** * Identifies the reason for the certificate revocation. */ public static final ObjectIdentifier ReasonCode_Id = new ObjectIdentifier(ReasonCode_data); /** * This extension provides a registered instruction identifier indicating * the action to be taken, after encountering a certificate that has been * placed on hold. */ public static final ObjectIdentifier HoldInstructionCode_Id = new ObjectIdentifier(HoldInstructionCode_data); /** * Identifies the date on which it is known or suspected that the private * key was compromised or that the certificate otherwise became invalid. */ public static final ObjectIdentifier InvalidityDate_Id = new ObjectIdentifier(InvalidityDate_data); /** * Identifies the date on which it is known or suspected that the private * key was compromised or that the certificate otherwise became invalid. */ public static final ObjectIdentifier CertificateIssuer_Id = new ObjectIdentifier(CertificateIssuer_data); /** * Identifies how delta CRL information is obtained. */ public static final ObjectIdentifier FreshestCRL_Id = new ObjectIdentifier(FreshestCRL_data); } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 4783 Content-Disposition: inline; filename="PolicyConstraint.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "6ceecc6655d84be796d4b23b9befca778514ab78" // --- 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.x509; import java.io.IOException; import netscape.security.util.BigInt; import netscape.security.util.DerInputStream; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; /** * This class defines the PolicyConstraint ASN.1 object. * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.4 */ public class PolicyConstraint { private static final byte TAG_SET = 0; private static final byte TAG_REQUIRE = 1; private static final byte TAG_INHIBIT = 2; private CertificatePolicySet set = null; private int require = -1; private int inhibit = -1; /** * The default constructor for this object * * @param set the CertificatePolicySet (null for optional). * @param require require explicit policy (-1 for optional). * @param inhibit inhibit policy mapping (-1 for optional). */ public PolicyConstraint(CertificatePolicySet set, int require, int inhibit) { this.set = set; this.require = require; this.inhibit = inhibit; } /** * Create the PolicyConstraint from the DerValue. * * @param val the DerValue of the PolicyConstraint. * @exception IOException on decoding errors. */ public PolicyConstraint(DerValue val) throws IOException { if (val.tag != DerValue.tag_Sequence) { throw new IOException("Sequence tag missing for PolicyConstraint."); } DerInputStream in = val.data; while (in != null && in.available() != 0) { DerValue next = in.getDerValue(); switch (next.tag & 0x1f) { case TAG_SET: this.set = new CertificatePolicySet(next.data); break; case TAG_REQUIRE: next = next.data.getDerValue(); this.require = (next.getInteger()).toInt(); break; case TAG_INHIBIT: next = next.data.getDerValue(); this.inhibit = (next.getInteger()).toInt(); break; default: throw new IOException("Invalid tag option for PolicyConstraint."); } } } /** * Return user readable form of the object. */ public String toString() { String s = ((set != null) ? "PolicyConstraint: [\n" + " PolicySet:[" + set.toString() + "]\n" + " Require:" + require + "\n" + " Inhibit:" + inhibit + "\n" + "]\n" : "PolicyConstraint: [\n" + " PolicySet:[null]\n" + " Require:" + require + "\n" + " Inhibit:" + inhibit + "\n" + "]\n"); return (s); } /** * Encode the object to the output stream. * * @param out the DerOutputStream to encode the object to. */ public void encode(DerOutputStream out) throws IOException { DerOutputStream tagged = new DerOutputStream(); if (set != null) { DerOutputStream tmp = new DerOutputStream(); set.encode(tmp); tagged.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, TAG_SET), tmp); } if (require != -1) { DerOutputStream tmp = new DerOutputStream(); tmp.putInteger(new BigInt(require)); tagged.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, TAG_REQUIRE), tmp); } if (inhibit != -1) { DerOutputStream tmp = new DerOutputStream(); tmp.putInteger(new BigInt(inhibit)); tagged.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, TAG_INHIBIT), tmp); } out.write(DerValue.tag_Sequence, tagged); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 10457 Content-Disposition: inline; filename="PolicyConstraintsExtension.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "1aec75e435520e0bfb66856d5755ddd6d01552cb" // --- 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.x509; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Array; import java.util.Enumeration; import java.util.Vector; import netscape.security.util.BigInt; import netscape.security.util.DerInputStream; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; /** * This class defines the certificate extension which specifies the * Policy constraints. *

* The policy constraints extension can be used in certificates issued to CAs. The policy constraints extension * constrains path validation in two ways. It can be used to prohibit policy mapping or require that each certificate in * a path contain an acceptable policy identifier. *

* The ASN.1 syntax for this is (IMPLICIT tagging is defined in the module definition): * *

 * PolicyConstraints ::= SEQUENCE {
 *     requireExplicitPolicy [0] SkipCerts OPTIONAL,
 *     inhibitPolicyMapping  [1] SkipCerts OPTIONAL
 * }
 * SkipCerts ::= INTEGER (0..MAX)
 * 
* * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.9 * @see Extension * @see CertAttrSet */ public class PolicyConstraintsExtension extends Extension implements CertAttrSet { /** * */ private static final long serialVersionUID = -3723759691127622370L; /** * Identifier for this attribute, to be used with the * get, set, delete methods of Certificate, x509 type. */ public static final String IDENT = "x509.info.extensions.PolicyConstraints"; /** * Attribute names. */ public static final String NAME = "PolicyConstraints"; public static final String REQUIRE = "require"; public static final String INHIBIT = "inhibit"; private static final byte TAG_REQUIRE = 0; private static final byte TAG_INHIBIT = 1; private int require = -1; private int inhibit = -1; // Encode this extension value. private void encodeThis() throws IOException { try (DerOutputStream seq = new DerOutputStream()) { DerOutputStream tagged = new DerOutputStream(); if (require != -1) { DerOutputStream tmp = new DerOutputStream(); tmp.putInteger(new BigInt(require)); tagged.writeImplicit(DerValue.createTag(DerValue.TAG_CONTEXT, false, TAG_REQUIRE), tmp); } if (inhibit != -1) { DerOutputStream tmp = new DerOutputStream(); tmp.putInteger(new BigInt(inhibit)); tagged.writeImplicit(DerValue.createTag(DerValue.TAG_CONTEXT, false, TAG_INHIBIT), tmp); } seq.write(DerValue.tag_Sequence, tagged); extensionValue = seq.toByteArray(); } } /** * Create a PolicyConstraintsExtension object with criticality and * both require explicit policy and inhibit policy mapping. * * @param critical whether this extension should be critical * @param require require explicit policy (-1 for optional). * @param inhibit inhibit policy mapping (-1 for optional). */ public PolicyConstraintsExtension(boolean crit, int require, int inhibit) throws IOException { init(crit, require, inhibit); } /** * Create a PolicyConstraintsExtension object with both * require explicit policy and inhibit policy mapping. * * @param require require explicit policy (-1 for optional). * @param inhibit inhibit policy mapping (-1 for optional). */ public PolicyConstraintsExtension(int require, int inhibit) throws IOException { init(false, require, inhibit); } private void init(boolean crit, int require, int inhibit) throws IOException { this.require = require; this.inhibit = inhibit; this.extensionId = PKIXExtensions.PolicyConstraints_Id; this.critical = crit; encodeThis(); } /** * Create the extension from its DER encoded value and criticality. * * @param critical true if the extension is to be treated as critical. * @param value Array of DER encoded bytes of the actual value. * @exception IOException on error. */ public PolicyConstraintsExtension(Boolean critical, Object value) throws IOException { this.extensionId = PKIXExtensions.PolicyConstraints_Id; this.critical = critical.booleanValue(); if (!(value instanceof byte[])) throw new IOException("Illegal argument type"); int len = Array.getLength(value); byte[] extValue = new byte[len]; System.arraycopy(value, 0, extValue, 0, len); this.extensionValue = extValue; DerValue val = new DerValue(extValue); if (val.tag != DerValue.tag_Sequence) { throw new IOException("Sequence tag missing for PolicyConstraint."); } DerInputStream in = val.data; while (in != null && in.available() != 0) { DerValue next = in.getDerValue(); if (next.isContextSpecific(TAG_REQUIRE) && !next.isConstructed()) { if (this.require != -1) throw new IOException("Duplicate requireExplicitPolicy" + "found in the PolicyConstraintsExtension"); next.resetTag(DerValue.tag_Integer); this.require = (next.getInteger()).toInt(); } else if (next.isContextSpecific(TAG_INHIBIT) && !next.isConstructed()) { if (this.inhibit != -1) throw new IOException("Duplicate inhibitPolicyMapping" + "found in the PolicyConstraintsExtension"); next.resetTag(DerValue.tag_Integer); this.inhibit = (next.getInteger()).toInt(); } else throw new IOException("Invalid encoding of PolicyConstraint"); } } /** * Return the extension as user readable string. */ public String toString() { String s; s = super.toString() + "PolicyConstraints: [" + " Require: "; if (require == -1) s += "unspecified;"; else s += require + ";"; s += "\tInhibit: "; if (inhibit == -1) s += "unspecified"; else s += inhibit; s += " ]\n"; return s; } /** * Decode the extension from the InputStream. * * @param in the InputStream to unmarshal the contents from. * @exception IOException on decoding or validity errors. */ public void decode(InputStream in) throws IOException { throw new IOException("Method not to be called directly."); } /** * Write the extension to the DerOutputStream. * * @param out the DerOutputStream to write the extension to. * @exception IOException on encoding errors. */ public void encode(OutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); if (extensionValue == null) { extensionId = PKIXExtensions.PolicyConstraints_Id; encodeThis(); } super.encode(tmp); out.write(tmp.toByteArray()); } /** * Set the attribute value. */ public void set(String name, Object obj) throws IOException { clearValue(); if (!(obj instanceof Integer)) { throw new IOException("Attribute value should be of type Integer."); } if (name.equalsIgnoreCase(REQUIRE)) { require = ((Integer) obj).intValue(); } else if (name.equalsIgnoreCase(INHIBIT)) { inhibit = ((Integer) obj).intValue(); } else { throw new IOException("Attribute name " + "[" + name + "]" + " not recognized by " + "CertAttrSet:PolicyConstraints."); } } /** * Get the attribute value. */ public Object get(String name) throws IOException { if (name.equalsIgnoreCase(REQUIRE)) { return Integer.valueOf(require); } else if (name.equalsIgnoreCase(INHIBIT)) { return Integer.valueOf(inhibit); } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:PolicyConstraints."); } } /** * Delete the attribute value. */ public void delete(String name) throws IOException { if (name.equalsIgnoreCase(REQUIRE)) { require = -1; } else if (name.equalsIgnoreCase(INHIBIT)) { inhibit = -1; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:PolicyConstraints."); } } /** * Return an enumeration of names of attributes existing within this * attribute. */ public Enumeration getAttributeNames() { Vector elements = new Vector(); elements.addElement(REQUIRE); elements.addElement(INHIBIT); return (elements.elements()); } /** * Return the name of this attribute. */ public String getName() { return (NAME); } /** * returns the requireExplicitMapping parameter. */ public int getRequireExplicitMapping() { return require; } /** * returns the inhibitPolicyMapping parameter. */ public int getInhibitPolicyMapping() { return inhibit; } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 8334 Content-Disposition: inline; filename="PolicyMappingsExtension.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "f5205e31e075622c5d0ab7c0baad2e0b4f595d5b" // --- 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.x509; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Array; import java.util.Enumeration; import java.util.Vector; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; /** * Represent the Policy Mappings Extension. * * This extension, if present, identifies the certificate policies considered * identical between the issuing and the subject CA. *

* Extensions are addiitonal attributes which can be inserted in a X509 v3 certificate. For example a * "Driving License Certificate" could have the driving license number as a extension. * *

* Extensions are represented as a sequence of the extension identifier (Object Identifier), a boolean flag stating * whether the extension is to be treated as being critical and the extension value itself (this is again a DER encoding * of the extension value). * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.7 * @see Extension * @see CertAttrSet */ public class PolicyMappingsExtension extends Extension implements CertAttrSet { /** * */ private static final long serialVersionUID = -4023336164621135851L; /** * Identifier for this attribute, to be used with the * get, set, delete methods of Certificate, x509 type. */ public static final String IDENT = "x509.info.extensions.PolicyMappings"; /** * Attribute names. */ public static final String NAME = "PolicyMappings"; public static final String MAP = "map"; // Private data members private Vector maps = null; // Encode this extension value private void encodeThis() throws IOException { try (DerOutputStream os = new DerOutputStream()) { DerOutputStream tmp = new DerOutputStream(); for (int i = 0; i < maps.size(); i++) { maps.elementAt(i).encode(tmp); } os.write(DerValue.tag_Sequence, tmp); extensionValue = os.toByteArray(); } } /** * Create a PolicyMappings with the Vector of CertificatePolicyMap. * * @param maps the Vector of CertificatePolicyMap. */ public PolicyMappingsExtension(Vector map) throws IOException { init(false, map); } /** * Create a PolicyMappings with the Vector of CertificatePolicyMap. * * @param maps the Vector of CertificatePolicyMap. */ public PolicyMappingsExtension(boolean critical, Vector map) throws IOException { init(critical, map); } /** * init policy with criticality and map. */ private void init(boolean critical, Vector map) throws IOException { this.maps = map; this.extensionId = PKIXExtensions.PolicyMappings_Id; this.critical = critical; encodeThis(); } /** * Create a default PolicyMappingsExtension. */ public PolicyMappingsExtension() { extensionId = PKIXExtensions.PolicyMappings_Id; critical = false; maps = new Vector(1, 1); } /** * Create the extension from the passed DER encoded value. * * @param critical true if the extension is to be treated as critical. * @param value Array of DER encoded bytes of the actual value. * @exception IOException on error. */ public PolicyMappingsExtension(Boolean critical, Object value) throws IOException { this.extensionId = PKIXExtensions.PolicyMappings_Id; this.critical = critical.booleanValue(); int len = Array.getLength(value); byte[] extValue = new byte[len]; for (int i = 0; i < len; i++) { extValue[i] = Array.getByte(value, i); } this.extensionValue = extValue; DerValue val = new DerValue(extValue); if (val.tag != DerValue.tag_Sequence) { throw new IOException("Invalid encoding for " + "PolicyMappingsExtension."); } maps = new Vector(1, 1); while (val.data.available() != 0) { DerValue seq = val.data.getDerValue(); CertificatePolicyMap map = new CertificatePolicyMap(seq); maps.addElement(map); } } /** * Returns a printable representation of the policy map. */ public String toString() { if (maps == null) return ""; String s = super.toString() + "PolicyMappings [\n" + maps.toString() + "]\n"; return (s); } /** * Write the extension to the OutputStream. * * @param out the OutputStream to write the extension to. * @exception IOException on encoding errors. */ public void encode(OutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); if (extensionValue == null) { extensionId = PKIXExtensions.PolicyMappings_Id; critical = false; encodeThis(); } super.encode(tmp); out.write(tmp.toByteArray()); } /** * Decode the extension from the InputStream. * * @param in the InputStream to unmarshal the contents from. * @exception IOException on decoding or validity errors. */ public void decode(InputStream in) throws IOException { throw new IOException("Method not to be called directly."); } /** * Set the attribute value. */ @SuppressWarnings("unchecked") public void set(String name, Object obj) throws IOException { clearValue(); if (name.equalsIgnoreCase(MAP)) { if (!(obj instanceof Vector)) { throw new IOException("Attribute value should be of" + " type Vector."); } maps = (Vector) obj; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:PolicyMappingsExtension."); } } /** * Get the attribute value. */ public Object get(String name) throws IOException { if (name.equalsIgnoreCase(MAP)) { return (maps); } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:PolicyMappingsExtension."); } } /** * Delete the attribute value. */ public void delete(String name) throws IOException { if (name.equalsIgnoreCase(MAP)) { maps = null; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:PolicyMappingsExtension."); } } /** * Return an enumeration of names of attributes existing within this * attribute. */ public Enumeration getAttributeNames() { Vector elements = new Vector(); elements.addElement(MAP); return (elements.elements()); } /** * Return the name of this attribute. */ public String getName() { return (NAME); } /** * Returns an enumeration of the mappings in the extension. */ public Enumeration getMappings() { if (maps == null) return null; return maps.elements(); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 3627 Content-Disposition: inline; filename="PolicyQualifierInfo.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "a676e8f62b7f49249fe85c6f01f5bcda8177fac1" // --- 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.x509; import java.io.IOException; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; import netscape.security.util.ObjectIdentifier; /** * Represent the PolicyQualifierInfo. * * policyQualifierInfo ::= SEQUENCE { * policyQualifierId PolicyQualifierId * qualifier ANY DEFINED BY policyQualifierId * } * * @author Thomas Kwan */ public class PolicyQualifierInfo implements java.io.Serializable { /** * */ private static final long serialVersionUID = -2930016944517192379L; public static final int OID_CPS[] = { 1, 3, 6, 1, 5, 5, 7, 2, 1 }; public static final ObjectIdentifier QT_CPS = new ObjectIdentifier(OID_CPS); public static final int OID_UNOTICE[] = { 1, 3, 6, 1, 5, 5, 7, 2, 2 }; public static final ObjectIdentifier QT_UNOTICE = new ObjectIdentifier(OID_UNOTICE); private ObjectIdentifier mId = null; private Qualifier mQualifier = null; /** * Create a PolicyQualifierInfo * * @param id the ObjectIdentifier for the policy id. */ public PolicyQualifierInfo(ObjectIdentifier id, Qualifier qualifier) { mId = id; mQualifier = qualifier; } /** * Create the object from its Der encoded value. * * @param val the DER encoded value for the same. */ public PolicyQualifierInfo(DerValue val) throws IOException { if (val.tag != DerValue.tag_Sequence) { throw new IOException("Invalid encoding for PolicyQualifierInfo."); } DerValue did = val.data.getDerValue(); mId = did.getOID(); if (val.data.available() != 0) { DerValue qualifier = val.data.getDerValue(); if (qualifier.tag == DerValue.tag_IA5String) { mQualifier = new CPSuri(qualifier); } else { mQualifier = new UserNotice(qualifier); } } } public ObjectIdentifier getId() { return mId; } /** * Returns object of type CPSuri or UserNotice. */ public Qualifier getQualifier() { return mQualifier; } /** * Returns a printable representation of the CertificatePolicyId. */ public String toString() { String s = "PolicyQualifierInfo: ["; s = s + getId() + " " + getQualifier(); s = s + "]\n"; return (s); } /** * Write the PolicyQualifier to the DerOutputStream. * * @param out the DerOutputStream to write the object to. * @exception IOException on errors. */ public void encode(DerOutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); tmp.putOID(mId); mQualifier.encode(tmp); out.write(DerValue.tag_Sequence, tmp); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 3199 Content-Disposition: inline; filename="PolicyQualifiers.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "de946a6d50ec878e5595fee9a17a93fddc5e309f" // --- 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.x509; import java.io.IOException; import java.util.Vector; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; /** * Represent the PolicyQualifiers. * * policyQualifiers ::= SEQUENCE SIZE (1..MAX) OF PolicyQualifierInfo * * @author Thomas Kwan */ public class PolicyQualifiers implements java.io.Serializable { /** * */ private static final long serialVersionUID = 6932694408774694516L; private Vector mInfo = new Vector(); /** * Create a PolicyQualifiers with the ObjectIdentifier. * * @param id the ObjectIdentifier for the policy id. */ public PolicyQualifiers() { } /** * Create the object from its Der encoded value. * * @param val the DER encoded value for the same. */ public PolicyQualifiers(DerValue val) throws IOException { if (val.tag != DerValue.tag_Sequence) { throw new IOException("Invalid encoding for " + "PolicyQualifiers."); } while (val.data.available() != 0) { DerValue pq = val.data.getDerValue(); PolicyQualifierInfo info = new PolicyQualifierInfo(pq); add(info); } } public void add(PolicyQualifierInfo info) { mInfo.addElement(info); } public int size() { return mInfo.size(); } public PolicyQualifierInfo getInfoAt(int i) { return mInfo.elementAt(i); } /** * Returns a printable representation of the CertificatePolicyId. */ public String toString() { StringBuffer s = new StringBuffer("PolicyQualifiers: ["); for (int i = 0; i < mInfo.size(); i++) { PolicyQualifierInfo pq = mInfo.elementAt(i); s.append(pq.toString()); } s.append("]\n"); return s.toString(); } /** * Write the PolicyQualifiers to the DerOutputStream. * * @param out the DerOutputStream to write the object to. * @exception IOException on errors. */ public void encode(DerOutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); for (int i = 0; i < mInfo.size(); i++) { PolicyQualifierInfo pq = mInfo.elementAt(i); pq.encode(tmp); } out.write(DerValue.tag_Sequence, tmp); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 4025 Content-Disposition: inline; filename="PrintableConverter.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "27e6ad4d2a9b454f4d5b49838ae2d4ba83e59553" // --- 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.x509; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.CharacterCodingException; import java.nio.charset.CharsetEncoder; import netscape.security.util.ASN1CharStrConvMap; import netscape.security.util.DerValue; /** * A AVAValueConverter that converts a Printable String attribute to a DerValue * and vice versa. An example an attribute that is a printable string is "C". * * @see ASN1CharStrConvMap * @see AVAValueConverter * * @author Lily Hsiao, Slava Galperin at Netscape Communications, Inc. */ public class PrintableConverter implements AVAValueConverter { // public constructors. public PrintableConverter() { } /** * Converts a string with ASN.1 Printable characters to a DerValue. * * @param valueString a string with Printable characters. * * @return a DerValue. * * @exception IOException if a Printable encoder is not * available for the conversion. */ public DerValue getValue(String valueString) throws IOException { return getValue(valueString, null); } public DerValue getValue(String valueString, byte[] tags) throws IOException { try { CharsetEncoder encoder = ASN1CharStrConvMap.getDefault().getEncoder(DerValue.tag_PrintableString); if (encoder == null) throw new IOException("No encoder for printable"); CharBuffer charBuffer = CharBuffer.wrap(valueString.toCharArray()); ByteBuffer byteBuffer = encoder.encode(charBuffer); return new DerValue(DerValue.tag_PrintableString, byteBuffer.array(), byteBuffer.arrayOffset(), byteBuffer.limit()); } catch (CharacterCodingException e) { throw new IllegalArgumentException("Invalid Printable String AVA Value", e); } } /** * Converts a BER encoded value of PrintableString to a DER encoded value. * Checks if the BER encoded value is a PrintableString. * NOTE only DER encoded values are currently accepted on input. * * @param berStream A byte array of the BER encoded value. * * @return A DerValue. * * @exception IOException if the BER value cannot be converted to a * PrintableString DER value. */ public DerValue getValue(byte[] berStream) throws IOException { DerValue value = new DerValue(berStream); if (value.tag != DerValue.tag_PrintableString) throw new IOException("Invalid Printable String AVA Value"); return value; } /** * Converts a DerValue of PrintableString to a java string with * PrintableString characters. * * @param avaValue a DerValue. * * @return a string with PrintableString characters. * * @exception IOException if the DerValue is not a PrintableString i.e. * The DerValue cannot be converted to a string * with PrintableString characters. */ public String getAsString(DerValue avaValue) throws IOException { return avaValue.getPrintableString(); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 12103 Content-Disposition: inline; filename="PrivateKeyUsageExtension.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "9b100bfe21ebf368beeb69d43bb28dfd7013cb43" // --- 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.x509; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Array; import java.security.cert.CertificateException; import java.security.cert.CertificateExpiredException; import java.security.cert.CertificateNotYetValidException; import java.security.cert.CertificateParsingException; import java.util.Date; import java.util.Enumeration; import java.util.Vector; import netscape.security.util.DerInputStream; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; /** * This class defines the Private Key Usage Extension. * *

* The Private Key Usage Period extension allows the certificate issuer to specify a different validity period for the * private key than the certificate. This extension is intended for use with digital signature keys. This extension * consists of two optional components notBefore and notAfter. The private key associated with the certificate should * not be used to sign objects before or after the times specified by the two components, respectively. * *

 * PrivateKeyUsagePeriod ::= SEQUENCE {
 *     notBefore  [0]  GeneralizedTime OPTIONAL,
 *     notAfter   [1]  GeneralizedTime OPTIONAL }
 * 
* * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.12 * @see Extension * @see CertAttrSet */ public class PrivateKeyUsageExtension extends Extension implements CertAttrSet { /** * */ private static final long serialVersionUID = -7623695233957629936L; /** * Identifier for this attribute, to be used with the * get, set, delete methods of Certificate, x509 type. */ public static final String IDENT = "x509.info.extensions.PrivateKeyUsage"; /** * Sub attributes name for this CertAttrSet. */ public static final String NAME = "PrivateKeyUsage"; public static final String NOT_BEFORE = "not_before"; public static final String NOT_AFTER = "not_after"; // Private data members private static final byte TAG_BEFORE = 0; private static final byte TAG_AFTER = 1; private Date notBefore; private Date notAfter; // Encode this extension value. private void encodeThis() throws IOException { try (DerOutputStream seq = new DerOutputStream()) { DerOutputStream tagged = new DerOutputStream(); if (notBefore != null) { DerOutputStream tmp = new DerOutputStream(); tmp.putGeneralizedTime(notBefore); tagged.writeImplicit(DerValue.createTag(DerValue.TAG_CONTEXT, false, TAG_BEFORE), tmp); } if (notAfter != null) { DerOutputStream tmp = new DerOutputStream(); tmp.putGeneralizedTime(notAfter); tagged.writeImplicit(DerValue.createTag(DerValue.TAG_CONTEXT, false, TAG_AFTER), tmp); } seq.write(DerValue.tag_Sequence, tagged); extensionValue = seq.toByteArray(); } } /** * The default constructor for PrivateKeyUsageExtension. * * @param notBefore the date/time before which the private key * should not be used. * @param notAfter the date/time after which the private key * should not be used. */ public PrivateKeyUsageExtension(Date notBefore, Date notAfter) throws IOException { this.notBefore = notBefore; this.notAfter = notAfter; this.extensionId = PKIXExtensions.PrivateKeyUsage_Id; this.critical = false; encodeThis(); } /** * Create the extension from the passed DER encoded value. * * @param critical true if the extension is to be treated as critical. * @param value Array of DER encoded bytes of the actual value. * * @exception CertificateException on certificate parsing errors. * @exception IOException on error. */ public PrivateKeyUsageExtension(Boolean critical, Object value) throws CertificateException, IOException { this.extensionId = PKIXExtensions.PrivateKeyUsage_Id; this.critical = critical.booleanValue(); if (!(value instanceof byte[])) throw new CertificateException("Illegal argument type"); int len = Array.getLength(value); byte[] extValue = new byte[len]; System.arraycopy(value, 0, extValue, 0, len); this.extensionValue = extValue; DerInputStream str = new DerInputStream(extValue); DerValue[] seq = str.getSequence(2); // NB. this is always encoded with the IMPLICIT tag // The checks only make sense if we assume implicit tagging, // with explicit tagging the form is always constructed. for (int i = 0; i < seq.length; i++) { DerValue opt = seq[i]; if (opt.isContextSpecific(TAG_BEFORE) && !opt.isConstructed()) { if (notBefore != null) { throw new CertificateParsingException( "Duplicate notBefore in PrivateKeyUsage."); } opt.resetTag(DerValue.tag_GeneralizedTime); str = new DerInputStream(opt.toByteArray()); notBefore = str.getGeneralizedTime(); } else if (opt.isContextSpecific(TAG_AFTER) && !opt.isConstructed()) { if (notAfter != null) { throw new CertificateParsingException( "Duplicate notAfter in PrivateKeyUsage."); } opt.resetTag(DerValue.tag_GeneralizedTime); str = new DerInputStream(opt.toByteArray()); notAfter = str.getGeneralizedTime(); } else throw new IOException("Invalid encoding of " + "PrivateKeyUsageExtension"); } } /** * Return the printable string. */ public String toString() { return (super.toString() + "PrivateKeyUsage: [From: " + ((notBefore == null) ? "" : notBefore.toString()) + ", To: " + ((notAfter == null) ? "" : notAfter.toString()) + "]\n"); } /** * Return notBefore date */ public Date getNotBefore() { return (notBefore); } /** * Return notAfter date */ public Date getNotAfter() { return (notAfter); } /** * Verify that that the current time is within the validity period. * * @exception CertificateExpiredException if the certificate has expired. * @exception CertificateNotYetValidException if the certificate is not * yet valid. */ public void valid() throws CertificateNotYetValidException, CertificateExpiredException { Date now = new Date(); valid(now); } /** * Verify that that the passed time is within the validity period. * * @exception CertificateExpiredException if the certificate has expired * with respect to the Date supplied. * @exception CertificateNotYetValidException if the certificate is not * yet valid with respect to the Date supplied. * */ public void valid(Date now) throws CertificateNotYetValidException, CertificateExpiredException { /* * we use the internal Dates rather than the passed in Date * because someone could override the Date methods after() * and before() to do something entirely different. */ if (notBefore.after(now)) { throw new CertificateNotYetValidException("NotBefore: " + notBefore.toString()); } if (notAfter.before(now)) { throw new CertificateExpiredException("NotAfter: " + notAfter.toString()); } } /** * Write the extension to the OutputStream. * * @param out the OutputStream to write the extension to. * @exception IOException on encoding errors. */ public void encode(OutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); if (extensionValue == null) { extensionId = PKIXExtensions.PrivateKeyUsage_Id; critical = false; encodeThis(); } super.encode(tmp); out.write(tmp.toByteArray()); } /** * Decode the extension from the InputStream. * * @param in the InputStream to unmarshal the contents from. * @exception CertificateException on decoding errors. */ public void decode(InputStream in) throws CertificateException { throw new CertificateException("Method not to be called directly."); } /** * Set the attribute value. * * @exception CertificateException on attribute handling errors. */ public void set(String name, Object obj) throws CertificateException { clearValue(); if (!(obj instanceof Date)) { throw new CertificateException("Attribute must be of type Date."); } if (name.equalsIgnoreCase(NOT_BEFORE)) { notBefore = (Date) obj; } else if (name.equalsIgnoreCase(NOT_AFTER)) { notAfter = (Date) obj; } else { throw new CertificateException("Attribute name not recognized by" + " CertAttrSet:PrivateKeyUsage."); } } /** * Get the attribute value. * * @exception CertificateException on attribute handling errors. */ public Object get(String name) throws CertificateException { if (name.equalsIgnoreCase(NOT_BEFORE)) { return (new Date(notBefore.getTime())); } else if (name.equalsIgnoreCase(NOT_AFTER)) { return (new Date(notAfter.getTime())); } else { throw new CertificateException("Attribute name not recognized by" + " CertAttrSet:PrivateKeyUsage."); } } /** * Delete the attribute value. * * @exception CertificateException on attribute handling errors. */ public void delete(String name) throws CertificateException { if (name.equalsIgnoreCase(NOT_BEFORE)) { notBefore = null; } else if (name.equalsIgnoreCase(NOT_AFTER)) { notAfter = null; } else { throw new CertificateException("Attribute name not recognized by" + " CertAttrSet:PrivateKeyUsage."); } } /** * Return an enumeration of names of attributes existing within this * attribute. */ public Enumeration getAttributeNames() { Vector elements = new Vector(); elements.addElement(NOT_BEFORE); elements.addElement(NOT_AFTER); return (elements.elements()); } /** * Return the name of this attribute. */ public String getName() { return (NAME); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 1762 Content-Disposition: inline; filename="Qualifier.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "86e0e370807547ae0ebfbfacd4b9c2dc07e08777" // --- 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.x509; import java.io.IOException; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; /** * Represent the Qualifier. * * Qualifier ::= CHOICE { * cPRuri CPSuri, * userNotice UserNotice * } * * @author Thomas Kwan */ public class Qualifier implements java.io.Serializable { /** * */ private static final long serialVersionUID = 2214531407387992974L; /** * Create a PolicyQualifierInfo * * @param id the ObjectIdentifier for the policy id. */ public Qualifier() { } public Qualifier(DerValue val) throws IOException { // needs to override this } /** * Write the PolicyQualifier to the DerOutputStream. * * @param out the DerOutputStream to write the object to. * @exception IOException on errors. */ public void encode(DerOutputStream out) throws IOException { // needs to override this } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 8702 Content-Disposition: inline; filename="RDN.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "bf8212305e8ed9865ab0a9d2d628f72faa321858" // --- 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.x509; import java.io.IOException; import java.util.Arrays; import java.util.Enumeration; import java.util.Vector; import netscape.security.util.DerInputStream; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; import netscape.security.util.ObjectIdentifier; /** * RDNs are a set of {attribute = value} assertions. Some of those * attributes are "distinguished" (unique w/in context). Order is * never relevant. * * Some X.500 names include only a single distinguished attribute * per RDN. This style is currently common. * * Note that DER-encoded RDNs sort AVAs by assertion OID ... so that * when we parse this data we don't have to worry about canonicalizing * it, but we'll need to sort them when we expose the RDN class more. * * @see X500Name * @see AVA * @see LdapDNStrConverter */ public class RDN { // public constructors /** * Constructs a RDN from a Ldap DN String with one RDN component * using the global default LdapDNStrConverter. * * @see LdapDNStrConverter * @param rdnString a Ldap DN string with one RDN component, e.g. as * defined in RFC1779. * @exception IOException if error occurs while parsing the string. */ public RDN(String rdnString) throws IOException { RDN rdn = LdapDNStrConverter.getDefault().parseRDN(rdnString); assertion = rdn.getAssertion(); } /** * Like RDN(String) with a DER encoding order given as argument for * Directory Strings. */ public RDN(String rdnString, byte[] tags) throws IOException { RDN rdn = LdapDNStrConverter.getDefault().parseRDN(rdnString, tags); assertion = rdn.getAssertion(); } /** * Constructs a RDN from a Ldap DN string with one RDN component * using the specified Ldap DN Str converter. * For example, RFC1779StrConverter can be passed to parse a Ldap * DN string in RFC1779 format. * * @see LdapDNStrConverter * @param rdnString Ldap DN string. * @param ldapDNStrConverter a LdapDNStrConverter. */ public RDN(String rdnString, LdapDNStrConverter ldapDNStrConverter) throws IOException { RDN rdn = ldapDNStrConverter.parseRDN(rdnString); assertion = rdn.getAssertion(); } /** * Constructs a RDN from a DerValue. * * @param set Der value of a set of AVAs. */ public RDN(DerValue set) throws IOException { if (set.tag != DerValue.tag_Set) throw new CertParseError("X500 RDN"); int j_max = 50; // XXX j_max = f(data)!! int j; int i; AVA[] avas = new AVA[j_max]; // create a temporary array big enough for a huge set of AVA's for (j = 0; j < j_max; j++) { avas[j] = new AVA(set.data); if (set.data.available() == 0) break; } // copy the elements into it if (j >= j_max - 1) { assertion = new AVA[j + 1]; } else { assertion = new AVA[j + 1]; for (i = 0; i < (j + 1); i++) { assertion[i] = avas[i]; } } /* if (set.data.available () != 0) // throw new CertParseError ("X500 RDN 2"); System.out.println (" ... RDN parse, ignored bytes = " + set.data.available ()); */ } /** * Constructs a RDN from a Der Input Stream. * * @param in a Der Input Stream. */ public RDN(DerInputStream in) throws IOException { /* an RDN is a SET of avas */ DerValue avaset[] = in.getSet(1); int i; assertion = new AVA[avaset.length]; for (i = 0; i < assertion.length; i++) assertion[i] = new AVA(avaset[i].data); } /** * Constructs a RDN from an array of AVA. * * @param avas a AVA Array. */ public RDN(AVA avas[]) { assertion = avas.clone(); } /** * convenience method. */ public RDN(Vector avaVector) { int size = avaVector.size(); assertion = new AVA[size]; for (int i = 0; i < size; i++) { assertion[i] = avaVector.elementAt(i); } } /** * returns an array of AVA in the RDN. * * @return array of AVA in this RDN. */ public AVA[] getAssertion() { return assertion.clone(); } /** * returns the number of AVAs in the RDN. * * @return number of AVAs in this RDN. */ public int getAssertionLength() { return assertion.length; } private AVA assertion[]; private class AVAEnumerator implements Enumeration { private int index; public AVAEnumerator() { index = 0; } public boolean hasMoreElements() { return (index < assertion.length); } public AVA nextElement() { if (index >= assertion.length) return null; return assertion[index++]; } } // other public methods. @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + Arrays.hashCode(assertion); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; RDN other = (RDN) obj; if (!Arrays.equals(assertion, other.assertion)) return false; return true; } DerValue findAttribute(ObjectIdentifier oid) { int i; for (i = 0; i < assertion.length; i++) if (assertion[i].oid.equals(oid)) return assertion[i].value; return null; } /** * Encodes this RDN to a Der output stream. * * @param out the Der Output Stream. */ public void encode(DerOutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); int i; for (i = 0; i < assertion.length; i++) assertion[i].encode(tmp); out.write(DerValue.tag_Set, tmp); } /** * returns an enumeration of AVAs that make up this RDN. * * @return an enumeration of AVAs that make up this RDN. */ public Enumeration getAVAs() { return new AVAEnumerator(); } /** * Returns a Ldap DN string with one RDN component using the * global default LdapDNStrConverter. * * @see LdapDNStrConverter * @return the Ldap DN String of this RDN. * @exception IOException if an error occurs during the conversion. */ public String toLdapDNString() throws IOException { return LdapDNStrConverter.getDefault().encodeRDN(this); } /** * Returns a Ldap DN String with this RDN component using the specified * LdapDNStrConverter. * * @see LdapDNStrConverter * @param ldapDNStrConverter a LdapDNStrConverter. * @return a Ldap DN String. * @exception IOException if an error occurs in the conversion. */ public String toLdapDNString(LdapDNStrConverter ldapDNStrConverter) throws IOException { return ldapDNStrConverter.encodeRDN(this); } /** * Returns a Ldap DN string with this RDN component using the global * default LdapDNStrConverter. * * @see LdapDNStrConverter * @return the Ldap DN String with this RDN component, null if an error * occurs in the conversion. */ public String toString() { String s; try { s = toLdapDNString(); } catch (IOException e) { return null; } return s; } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 3350 Content-Disposition: inline; filename="RFC1779StrConverter.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "e7411801c3613c49509fcf05628ff6b873cfe9a8" // --- 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.x509; import java.io.IOException; import netscape.security.util.DerValue; import netscape.security.util.ObjectIdentifier; /** * Converts a RFC 1779 string to a X500Name, RDN or AVA object and vice versa. * * @see LdapDNStrConverter * @see LdapV3DNStrConverter * * @author Lily Hsiao, Slava Galperin at Netscape Communications, Inc. */ public class RFC1779StrConverter extends LdapV3DNStrConverter { // // Constructors. // /** * Constructs a RFC1779StrConverter using the global default * X500NameAttrMap and accepts OIDs not listed in the attribute map. */ public RFC1779StrConverter() { super(); } /** * Constructs a RFC1779StrConverter using the specified X500NameAttrMap * and boolean for whether to accept OIDs not in the X500NameAttrMap. * * @param attributeMap A X500NameAttrMap to use for this converter. * @param doAcceptUnknownOids Accept unregistered attributes, i.e. OIDs * not in the map). */ public RFC1779StrConverter(X500NameAttrMap attributeMap, boolean doAcceptUnknownOids) { super(attributeMap, doAcceptUnknownOids); } // // overriding methods. // /** * Converts a OID to a attribute keyword in a Ldap DN string or * to a "OID.1.2.3.4" string syntax as defined in RFC1779. * * @param oid an ObjectIdentifier. * * @return a attribute keyword or "OID.1.2.3.4" string. * * @exception IOException if an error occurs during the conversion. */ public String encodeOID(ObjectIdentifier oid) throws IOException { String keyword = attrMap.getName(oid); if (keyword == null) if (!acceptUnknownOids) throw new IllegalArgumentException("Unrecognized OID"); else keyword = "OID" + "." + oid.toString(); return keyword; } /** * Converts a attribute value as a DerValue to a string in a * RFC1779 Ldap DN string. * * @param attrValue an attribute value. * @param oid ObjectIdentifier for the attribute. * @return a string in RFC1779 syntax. * @exception IOException if an error occurs during the conversion. */ public String encodeValue(DerValue attrValue, ObjectIdentifier oid) throws IOException { String s = super.encodeValue(attrValue, oid); if (s.indexOf('\n') != -1) return "\"" + s + "\""; else return s; } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 2423 Content-Disposition: inline; filename="RFC822Name.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "8509b3766b9515551a7386d87a86416f72ad6b19" // --- 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.x509; import java.io.IOException; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; /** * This class implements the RFC822Name as required by the GeneralNames * ASN.1 object. * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.3 * @see GeneralName * @see GeneralNames * @see GeneralNameInterface */ public class RFC822Name implements GeneralNameInterface { /** * */ private static final long serialVersionUID = -1453025303548809007L; private String name; /** * Create the RFC822Name object from the passed encoded Der value. * * @param derValue the encoded DER RFC822Name. * @exception IOException on error. */ public RFC822Name(DerValue derValue) throws IOException { name = derValue.getIA5String(); } /** * Create the RFC822Name object with the specified name. * * @param name the RFC822Name. */ public RFC822Name(String name) { this.name = name; } /** * Return the type of the GeneralName. */ public int getType() { return (GeneralNameInterface.NAME_RFC822); } /** * Encode the RFC822 name into the DerOutputStream. * * @param out the DER stream to encode the RFC822Name to. * @exception IOException on encoding errors. */ public void encode(DerOutputStream out) throws IOException { out.putIA5String(name); } /** * Convert the name into user readable string. */ public String toString() { return ("RFC822Name: " + name); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 9509 Content-Disposition: inline; filename="ReasonFlags.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "f0eacb8163475075d640314c2eae8fe112ebd1ef" // --- 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.x509; import java.io.IOException; import java.util.Enumeration; import java.util.Vector; import netscape.security.util.BitArray; import netscape.security.util.DerInputStream; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; /** * Represent the CRL Reason Flags. * *

* This extension, if present, defines the identifies the reason for the certificate revocation. * * @author Hemma Prafullchandra * @version 1.3 * @see Extension * @see CertAttrSet */ public class ReasonFlags { /** * Reasons */ public static final String UNUSED = "unused"; public static final String KEY_COMPROMISE = "key_compromise"; public static final String CA_COMPROMISE = "ca_compromise"; public static final String AFFLIATION_CHANGED = "affliation_changed"; public static final String SUPERSEDED = "superseded"; public static final String CESSATION_OF_OPERATION = "cessation_of_operation"; public static final String CERTIFICATION_HOLD = "certification_hold"; public static final String PRIVILEGE_WITHDRAWN = "privilege_withdrawn"; public static final String AA_COMPROMISE = "aa_compromise"; // Private data members private boolean[] bitString; /** * Check if bit is set. * * @param position the position in the bit string to check. */ private boolean isSet(int position) { return bitString[position]; } /** * Set the bit at the specified position. */ private void set(int position, boolean val) { // enlarge bitString if necessary if (position >= bitString.length) { boolean[] tmp = new boolean[position + 1]; System.arraycopy(bitString, 0, tmp, 0, bitString.length); bitString = tmp; } bitString[position] = val; } /** * Create a ReasonFlags with the passed bit settings. * * @param reasons the bits to be set for the ReasonFlags. */ public ReasonFlags(byte[] reasons) { bitString = new BitArray(reasons.length * 8, reasons).toBooleanArray(); } /** * Create a ReasonFlags with the passed bit settings. * * @param reasons the bits to be set for the ReasonFlags. */ public ReasonFlags(boolean[] reasons) { this.bitString = reasons; } /** * Create a ReasonFlags with the passed bit settings. * * @param reasons the bits to be set for the ReasonFlags. */ public ReasonFlags(BitArray reasons) { this.bitString = reasons.toBooleanArray(); } /** * Create the object from the passed DER encoded value. * * @param in the DerInputStream to read the ReasonFlags from. * @exception IOException on decoding errors. */ public ReasonFlags(DerInputStream in) throws IOException { DerValue derVal = in.getDerValue(); this.bitString = derVal.getUnalignedBitString(true).toBooleanArray(); } /** * Create the object from the passed DER encoded value. * * @param derVal the DerValue decoded from the stream. * @exception IOException on decoding errors. */ public ReasonFlags(DerValue derVal) throws IOException { this.bitString = derVal.getUnalignedBitString(true).toBooleanArray(); } /** * Set the attribute value. */ public void set(String name, Object obj) throws IOException { if (!(obj instanceof Boolean)) { throw new IOException("Attribute must be of type Boolean."); } boolean val = ((Boolean) obj).booleanValue(); if (name.equalsIgnoreCase(UNUSED)) { set(0, val); } else if (name.equalsIgnoreCase(KEY_COMPROMISE)) { set(1, val); } else if (name.equalsIgnoreCase(CA_COMPROMISE)) { set(2, val); } else if (name.equalsIgnoreCase(AFFLIATION_CHANGED)) { set(3, val); } else if (name.equalsIgnoreCase(SUPERSEDED)) { set(4, val); } else if (name.equalsIgnoreCase(CESSATION_OF_OPERATION)) { set(5, val); } else if (name.equalsIgnoreCase(CERTIFICATION_HOLD)) { set(6, val); } else if (name.equalsIgnoreCase(PRIVILEGE_WITHDRAWN)) { set(7, val); } else if (name.equalsIgnoreCase(AA_COMPROMISE)) { set(8, val); } else { throw new IOException("Name not recognized by ReasonFlags"); } } /** * Get the attribute value. */ public Object get(String name) throws IOException { if (name.equalsIgnoreCase(UNUSED)) { return Boolean.valueOf(isSet(0)); } else if (name.equalsIgnoreCase(KEY_COMPROMISE)) { return Boolean.valueOf(isSet(1)); } else if (name.equalsIgnoreCase(CA_COMPROMISE)) { return Boolean.valueOf(isSet(2)); } else if (name.equalsIgnoreCase(AFFLIATION_CHANGED)) { return Boolean.valueOf(isSet(3)); } else if (name.equalsIgnoreCase(SUPERSEDED)) { return Boolean.valueOf(isSet(4)); } else if (name.equalsIgnoreCase(CESSATION_OF_OPERATION)) { return Boolean.valueOf(isSet(5)); } else if (name.equalsIgnoreCase(CERTIFICATION_HOLD)) { return Boolean.valueOf(isSet(6)); } else if (name.equalsIgnoreCase(PRIVILEGE_WITHDRAWN)) { return Boolean.valueOf(isSet(7)); } else if (name.equalsIgnoreCase(AA_COMPROMISE)) { return Boolean.valueOf(isSet(8)); } else { throw new IOException("Name not recognized by ReasonFlags"); } } /** * Delete the attribute value. */ public void delete(String name) throws IOException { if (name.equalsIgnoreCase(UNUSED)) { set(0, false); } else if (name.equalsIgnoreCase(KEY_COMPROMISE)) { set(1, false); } else if (name.equalsIgnoreCase(CA_COMPROMISE)) { set(2, false); } else if (name.equalsIgnoreCase(AFFLIATION_CHANGED)) { set(3, false); } else if (name.equalsIgnoreCase(SUPERSEDED)) { set(4, false); } else if (name.equalsIgnoreCase(CESSATION_OF_OPERATION)) { set(5, false); } else if (name.equalsIgnoreCase(CERTIFICATION_HOLD)) { set(6, false); } else if (name.equalsIgnoreCase(PRIVILEGE_WITHDRAWN)) { set(7, false); } else if (name.equalsIgnoreCase(AA_COMPROMISE)) { set(8, false); } else { throw new IOException("Name not recognized by ReasonFlags"); } } /** * Returns a printable representation of the ReasonFlags. */ public String toString() { String s = super.toString() + "Reason Flags [\n"; try { if (isSet(0)) { s += " Unused\n"; } if (isSet(1)) { s += " Key Compromise\n"; } if (isSet(2)) { s += " CA_Compromise\n"; } if (isSet(3)) { s += " Affiliation_Changed\n"; } if (isSet(4)) { s += " Superseded\n"; } if (isSet(5)) { s += " Cessation Of Operation\n"; } if (isSet(6)) { s += " Certificate Hold\n"; } if (isSet(7)) { s += " Privilege Withdrawn\n"; } if (isSet(8)) { s += " AA Compromise\n"; } } catch (ArrayIndexOutOfBoundsException ex) { } s += "]\n"; return (s); } /** * Write the extension to the DerOutputStream. * * @param out the DerOutputStream to write the extension to. * @exception IOException on encoding errors. */ public void encode(DerOutputStream out) throws IOException { out.putUnalignedBitString(new BitArray(this.bitString)); } /** * Return an enumeration of names of attributes existing within this * attribute. */ public Enumeration getElements() { Vector elements = new Vector(); elements.addElement(UNUSED); elements.addElement(KEY_COMPROMISE); elements.addElement(CA_COMPROMISE); elements.addElement(AFFLIATION_CHANGED); elements.addElement(SUPERSEDED); elements.addElement(CESSATION_OF_OPERATION); elements.addElement(CERTIFICATION_HOLD); elements.addElement(PRIVILEGE_WITHDRAWN); elements.addElement(AA_COMPROMISE); return (elements.elements()); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 4483 Content-Disposition: inline; filename="RevocationReason.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "183d9eecd20ce4cb4b03ae65df0717de16164642" // --- 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.x509; import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; import java.util.LinkedHashMap; import java.util.Map; /** * Represent the enumerated type used in CRLReason Extension of CRL entry. * * * @author galperin * @version $Revision$, $Date$ */ public final class RevocationReason implements Serializable { private static final long serialVersionUID = -2582403666913588806L; public static final Collection INSTANCES = new ArrayList(); public static final Map CODES = new LinkedHashMap(); public static final Map LABELS = new LinkedHashMap(); /** * Reasons */ public static final RevocationReason UNSPECIFIED = new RevocationReason(0, "Unspecified"); public static final RevocationReason KEY_COMPROMISE = new RevocationReason(1, "Key_Compromise"); public static final RevocationReason CA_COMPROMISE = new RevocationReason(2, "CA_Compromise"); public static final RevocationReason AFFILIATION_CHANGED = new RevocationReason(3, "Affiliation_Changed"); public static final RevocationReason SUPERSEDED = new RevocationReason(4, "Superseded"); public static final RevocationReason CESSATION_OF_OPERATION = new RevocationReason(5, "Cessation_of_Operation"); public static final RevocationReason CERTIFICATE_HOLD = new RevocationReason(6, "Certificate_Hold"); public static final RevocationReason REMOVE_FROM_CRL = new RevocationReason(8, "Remove_from_CRL"); public static final RevocationReason PRIVILEGE_WITHDRAWN = new RevocationReason(9, "Privilege_Withdrawn"); public static final RevocationReason AA_COMPROMISE = new RevocationReason(10, "AA_Compromise"); // Private data members private int code; private String label; /** * Create a RevocationReason with the passed integer value and string label. * * @param reason integer value of the enumeration alternative. * @param label string value of the enumeration alternative. */ private RevocationReason(int reason, String label) { this.code = reason; this.label = label; INSTANCES.add(this); CODES.put(reason, this); LABELS.put(label.toLowerCase(), this); } public int getCode() { return code; } public String getLabel() { return label; } public static RevocationReason fromInt(int reason) { return valueOf(reason); } public static RevocationReason valueOf(int reason) { return CODES.get(reason); } public static RevocationReason valueOf(String string) { return LABELS.get(string.toLowerCase()); } public int toInt() { return code; } public String toString() { return label; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; RevocationReason other = (RevocationReason) obj; if (code != other.code) return false; if (label == null) { if (other.label != null) return false; } else if (!label.equals(other.label)) return false; return true; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + code; result = prime * result + ((label == null) ? 0 : label.hashCode()); return result; } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 1420 Content-Disposition: inline; filename="RevocationReasonAdapter.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "e9445bb4338c21e18d5d360f8f9aaf37d4b9b1a1" // --- 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) 2012 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package netscape.security.x509; import javax.xml.bind.annotation.adapters.XmlAdapter; import org.apache.commons.lang.StringUtils; /** * The RevocationReasonAdapter class provides custom marshaling for RevocationReason. * * @author Endi S. Dewata */ public class RevocationReasonAdapter extends XmlAdapter { public RevocationReason unmarshal(String value) throws Exception { return StringUtils.isEmpty(value) ? null : RevocationReason.valueOf(value); } public String marshal(RevocationReason value) throws Exception { return value == null ? null : value.toString(); } }X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 14909 Content-Disposition: inline; filename="RevokedCertImpl.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "a54c4471ab8bebd0ecf6d6da583f6b1b4695b6b6" // --- 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.x509; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.math.BigInteger; import java.security.cert.CRLException; import java.util.Date; import java.util.Enumeration; import java.util.LinkedHashSet; import java.util.Set; import netscape.security.util.DerInputStream; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; import netscape.security.util.ObjectIdentifier; /** *

* Abstract class for a revoked certificate in a CRL. This class is for each entry in the * revokedCertificates, so it deals with the inner SEQUENCE. The ASN.1 definition for this is: * *

 * revokedCertificates    SEQUENCE OF SEQUENCE  {
 *     userCertificate    CertificateSerialNumber,
 *     revocationDate     ChoiceOfTime,
 *     crlEntryExtensions Extensions OPTIONAL
 *                        -- if present, must be v2
 * }  OPTIONAL
 *
 * CertificateSerialNumber  ::=  INTEGER
 *
 * Extensions  ::=  SEQUENCE SIZE (1..MAX) OF Extension
 *
 * Extension  ::=  SEQUENCE  {
 *     extnId        OBJECT IDENTIFIER,
 *     critical      BOOLEAN DEFAULT FALSE,
 *     extnValue     OCTET STRING
 *                   -- contains a DER encoding of a value
 *                   -- of the type registered for use with
 *                   -- the extnId object identifier value
 * }
 * 
* * @author Hemma Prafullchandra * @version 1.6 97/12/10 */ public class RevokedCertImpl extends RevokedCertificate implements Serializable { /** * */ private static final long serialVersionUID = -3449642360223397701L; private SerialNumber serialNumber; private Date revocationDate; private CRLExtensions extensions = null; private byte[] revokedCert; private final static boolean isExplicit = false; /** * Default constructor. */ public RevokedCertImpl() { } /** * Constructs a revoked certificate entry using the serial number and * revocation date. * * @param num * the serial number of the revoked certificate. * @param date * the Date on which revocation took place. */ public RevokedCertImpl(BigInteger num, Date date) { this.serialNumber = new SerialNumber(num); this.revocationDate = date; } /** * Constructs a revoked certificate entry using the serial number, * revocation date and the entry extensions. * * @param num * the serial number of the revoked certificate. * @param date * the Date on which revocation took place. * @param crlEntryExts * the extensions for this entry. */ public RevokedCertImpl(BigInteger num, Date date, CRLExtensions crlEntryExts) { this.serialNumber = new SerialNumber(num); this.revocationDate = date; this.extensions = crlEntryExts; } public byte[] getEncoded() throws CRLException { // XXX NOT IMPLEMENTED if (revokedCert == null) { DerOutputStream os = new DerOutputStream(); try { encode(os); } catch (Exception e) { // revokedCert = null; } revokedCert = os.toByteArray(); } return revokedCert; } public boolean hasUnsupportedCriticalExtension() { // XXX NOT IMPLEMENTED return true; } /** * Sets extensions for this impl. * * @param crlEntryExts * CRLExtensions */ public void setExtensions(CRLExtensions crlEntryExts) { this.extensions = crlEntryExts; } /** * Unmarshals a revoked certificate from its encoded form. * * @param revokedCert * the encoded bytes. * @exception CRLException * on parsing errors. * @exception X509ExtensionException * on extension handling errors. */ public RevokedCertImpl(byte[] revokedCert) throws CRLException, X509ExtensionException { try { DerValue derValue = new DerValue(revokedCert); parse(derValue); } catch (IOException e) { throw new CRLException("Parsing error: " + e.toString()); } } /** * Unmarshals a revoked certificate from its encoded form. * * @param derValue * the DER value containing the revoked certificate. * @exception CRLException * on parsing errors. * @exception X509ExtensionException * on extension handling errors. */ public RevokedCertImpl(DerValue derValue) throws CRLException, X509ExtensionException { parse(derValue); } /** * Returns true if this revoked certificate entry has extensions, otherwise * false. * * @return true if this CRL entry has extensions, otherwise false. */ public boolean hasExtensions() { if (extensions == null) return false; else return true; } /** * Decode a revoked certificate from an input stream. * * @param inStrm * an input stream holding at least one revoked certificate * @exception CRLException * on parsing errors. * @exception X509ExtensionException * on extension handling errors. */ public void decode(InputStream inStrm) throws CRLException, X509ExtensionException { try { DerValue derValue = new DerValue(inStrm); parse(derValue); } catch (IOException e) { throw new CRLException("Parsing error: " + e.toString()); } } /** * Encodes the revoked certificate to an output stream. * * @param outStrm * an output stream to which the encoded revoked certificate is * written. * @exception CRLException * on encoding errors. * @exception X509ExtensionException * on extension handling errors. */ public void encode(DerOutputStream outStrm) throws CRLException, X509ExtensionException { try (DerOutputStream seq = new DerOutputStream()) { if (revokedCert == null) { DerOutputStream tmp = new DerOutputStream(); // sequence { serialNumber, revocationDate, extensions } serialNumber.encode(tmp); // from 2050 should encode GeneralizedTime tmp.putUTCTime(revocationDate); if (extensions != null) extensions.encode(tmp, isExplicit); seq.write(DerValue.tag_Sequence, tmp); revokedCert = seq.toByteArray(); } outStrm.write(revokedCert); } catch (IOException e) { throw new CRLException("Encoding error: " + e.toString()); } } /** * Gets the serial number for this RevokedCertificate, the userCertificate. * * @return the serial number. */ public BigInteger getSerialNumber() { return serialNumber.getNumber().toBigInteger(); } /** * Gets the revocation date for this RevokedCertificate, the revocationDate. * * @return the revocation date. */ public Date getRevocationDate() { return (new Date(revocationDate.getTime())); } /** * Returns extensions for this impl. * * @return the CRLExtensions */ public CRLExtensions getExtensions() { return extensions; } /** * Returns a printable string of this revoked certificate. * * @return value of this revoked certificate in a printable form. */ public String toString() { StringBuffer sb = new StringBuffer(serialNumber.toString() + " On: " + revocationDate.toString()); if (extensions != null) { sb.append("\n"); for (int i = 0; i < extensions.size(); i++) sb.append("Entry Extension[" + i + "]: " + (extensions.elementAt(i)).toString()); } sb.append("\n"); return (sb.toString()); } /** * Gets a Set of the extension(s) marked CRITICAL in the * RevokedCertificate by OID strings. * * @return a set of the extension oid strings in the * Object that are marked critical. */ public Set getCriticalExtensionOIDs() { if (extensions == null) return null; Set extSet = new LinkedHashSet(); Extension ex; for (Enumeration e = extensions.getElements(); e.hasMoreElements();) { ex = e.nextElement(); if (ex.isCritical()) extSet.add(ex.getExtensionId().toString()); } return extSet; } /** * Gets a Set of the extension(s) marked NON-CRITICAL in the * RevokedCertificate by OID strings. * * @return a set of the extension oid strings in the * Object that are marked critical. */ public Set getNonCriticalExtensionOIDs() { if (extensions == null) return null; Set extSet = new LinkedHashSet(); Extension ex; for (Enumeration e = extensions.getElements(); e.hasMoreElements();) { ex = e.nextElement(); if (!ex.isCritical()) extSet.add(ex.getExtensionId().toString()); } return extSet; } /** * Gets the DER encoded OCTET string for the extension value * (extnValue) identified by the passed in oid String. * The oid string is * represented by a set of positive whole number separated * by ".", that means,
* <positive whole number>.<positive whole number>.<positive * whole number>.<...> * * @param oid the Object Identifier value for the extension. * @return the DER encoded octet string of the extension value. */ public byte[] getExtensionValue(String oid) { if (extensions == null) return null; try (DerOutputStream out = new DerOutputStream()) { String extAlias = OIDMap.getName(new ObjectIdentifier(oid)); Extension crlExt = null; if (extAlias == null) { // may be unknown ObjectIdentifier findOID = new ObjectIdentifier(oid); Extension ex = null; ObjectIdentifier inCertOID; for (Enumeration e = extensions.getElements(); e.hasMoreElements();) { ex = e.nextElement(); inCertOID = ex.getExtensionId(); if (inCertOID.equals(findOID)) { crlExt = ex; break; } } } else crlExt = extensions.get(extAlias); if (crlExt == null) return null; byte[] extData = crlExt.getExtensionValue(); if (extData == null) return null; out.putOctetString(extData); return out.toByteArray(); } catch (Exception e) { return null; } } private void parse(DerValue derVal) throws CRLException, X509ExtensionException { if (derVal.tag != DerValue.tag_Sequence) { throw new CRLException("Invalid encoded RevokedCertificate, " + "starting sequence tag missing."); } if (derVal.data.available() == 0) throw new CRLException("No data encoded for RevokedCertificates"); // serial number try { DerInputStream in = derVal.toDerInputStream(); DerValue val = in.getDerValue(); this.serialNumber = new SerialNumber(val); } catch (IOException e) { throw new CRLException("Parsing Serial Number error: " + e.toString()); } // revocationDate try { int nextByte = derVal.data.peekByte(); if ((byte) nextByte == DerValue.tag_UtcTime) { this.revocationDate = derVal.data.getUTCTime(); } else if ((byte) nextByte == DerValue.tag_GeneralizedTime) { this.revocationDate = derVal.data.getGeneralizedTime(); } else { throw new CRLException("Invalid encoding for RevokedCertificates"); } } catch (IOException e) { throw new CRLException("Parsing Revocation Date error: " + e.toString()); } if (derVal.data.available() == 0) return; // no extensions // crlEntryExtensions try { this.extensions = new CRLExtensions(derVal.toDerInputStream()); } catch (IOException e) { throw new CRLException("Parsing CRL Entry Extensions error: " + e.toString()); } } /** * Serialization write ... X.509 certificates serialize as themselves, and * they're parsed when they get read back. (Actually they serialize as some * type data from the serialization subsystem, then the cert data.) */ private void writeObject(ObjectOutputStream stream) throws CRLException, X509ExtensionException, IOException { DerOutputStream dos = new DerOutputStream(); encode(dos); dos.derEncode(stream); } /** * Serialization read ... X.509 certificates serialize as themselves, and * they're parsed when they get read back. */ private void readObject(ObjectInputStream stream) throws CRLException, X509ExtensionException, IOException { decode(stream); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 2906 Content-Disposition: inline; filename="RevokedCertificate.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "a4f6e9cab4fa3e32c2365f1ff9ae0288c6181479" // --- 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.x509; import java.math.BigInteger; import java.security.cert.X509CRL; import java.security.cert.X509CRLEntry; import java.util.Date; /** *

* Abstract class for a revoked certificate in a CRL (Certificate Revocation List). * * The ASN.1 definition for revokedCertificates is: * *

 *  revokedCertificates    SEQUENCE OF SEQUENCE  {
 *      userCertificate    CertificateSerialNumber,
 *      revocationDate     ChoiceOfTime,
 *      crlEntryExtensions Extensions OPTIONAL
 *                         -- if present, must be v2
 *  }  OPTIONAL
 * 

* CertificateSerialNumber ::= INTEGER *

* Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension *

* Extension ::= SEQUENCE { * extnId OBJECT IDENTIFIER, * critical BOOLEAN DEFAULT FALSE, * extnValue OCTET STRING * -- contains a DER encoding of a value * -- of the type registered for use with * -- the extnId object identifier value * } *

* * @see X509CRL * * @author Hemma Prafullchandra * @version 1.4 97/12/10 */ public abstract class RevokedCertificate extends X509CRLEntry { /* implements X509Extension { */ /** * Gets the serial number for this RevokedCertificate, * the userCertificate. * * @return the serial number. */ public abstract BigInteger getSerialNumber(); /** * Gets the revocation date for this RevokedCertificate, * the revocationDate. * * @return the revocation date. */ public abstract Date getRevocationDate(); /** * Returns true if this revoked certificate entry has * extensions. * * @return true if this entry has extensions, false otherwise. */ public abstract boolean hasExtensions(); /** * Returns a string representation of this revoked certificate. * * @return a string representation of this revoked certificate. */ public abstract String toString(); public abstract CRLExtensions getExtensions(); } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 3820 Content-Disposition: inline; filename="SerialNumber.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "857547a757ad466ee9787cec37c4c6bd5c752b4b" // --- 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.x509; import java.io.IOException; import java.io.InputStream; import java.io.Serializable; import java.math.BigInteger; import netscape.security.util.BigInt; import netscape.security.util.DerInputStream; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; /** * This class defines the SerialNumber class used by certificates. * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.5 */ public class SerialNumber implements Serializable { private static final long serialVersionUID = 1600956411497203535L; private BigInt serialNum; // Construct the class from the DerValue private void construct(DerValue derVal) throws IOException { serialNum = derVal.getInteger(); if (derVal.data.available() != 0) { throw new IOException("Excess SerialNumber data"); } } /** * The default constructor for this class using BigInteger. * * @param num the BigInteger number used to create the serial number. */ public SerialNumber(BigInteger num) { serialNum = new BigInt(num); } public SerialNumber(BigInt num) { serialNum = num; } /** * The default constructor for this class using int. * * @param num the BigInteger number used to create the serial number. */ public SerialNumber(int num) { serialNum = new BigInt(num); } /** * Create the object, decoding the values from the passed DER stream. * * @param in the DerInputStream to read the SerialNumber from. * @exception IOException on decoding errors. */ public SerialNumber(DerInputStream in) throws IOException { DerValue derVal = in.getDerValue(); construct(derVal); } /** * Create the object, decoding the values from the passed DerValue. * * @param val the DerValue to read the SerialNumber from. * @exception IOException on decoding errors. */ public SerialNumber(DerValue val) throws IOException { construct(val); } /** * Create the object, decoding the values from the passed stream. * * @param in the InputStream to read the SerialNumber from. * @exception IOException on decoding errors. */ public SerialNumber(InputStream in) throws IOException { DerValue derVal = new DerValue(in); construct(derVal); } /** * Return the SerialNumber as user readable string. */ public String toString() { return ("SerialNumber: [" + serialNum.toString() + "]"); } /** * Encode the SerialNumber in DER form to the stream. * * @param out the DerOutputStream to marshal the contents to. * @exception IOException on errors. */ public void encode(DerOutputStream out) throws IOException { out.putInteger(serialNum); } /** * Return the serial number. */ public BigInt getNumber() { return (serialNum); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 8044 Content-Disposition: inline; filename="SubjectAlternativeNameExtension.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "82f87e1ef647496353f598a33290d6dcfb5e8f04" // --- 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.x509; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Array; import java.util.Enumeration; import java.util.Vector; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; /** * This represents the Subject Alternative Name Extension. * * This extension, if present, allows the subject to specify multiple * alternative names. * *

* Extensions are represented as a sequence of the extension identifier (Object Identifier), a boolean flag stating * whether the extension is to be treated as being critical and the extension value itself (this is again a DER encoding * of the extension value). *

* The ASN.1 syntax for this is: * *

 * SubjectAltName ::= GeneralNames
 * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
 * 
* * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.9 * @see Extension * @see CertAttrSet */ public class SubjectAlternativeNameExtension extends Extension implements CertAttrSet { /** * */ private static final long serialVersionUID = -4022446008355607196L; /** * Identifier for this attribute, to be used with the * get, set, delete methods of Certificate, x509 type. */ public static final String IDENT = "x509.info.extensions.SubjectAlternativeName"; /** * Attribute names. */ public static final String NAME = "SubjectAlternativeName"; public static final String SUBJECT_NAME = "subject_name"; // private data members GeneralNames names; // Encode this extension private void encodeThis() throws IOException { DerOutputStream os = new DerOutputStream(); try { names.encode(os); } catch (GeneralNamesException e) { throw new IOException("SubjectAlternativeName: " + e); } extensionValue = os.toByteArray(); } /** * Create a SubjectAlternativeNameExtension with the passed GeneralNames. * * @param names the GeneralNames for the subject. * @exception IOException on error. */ public SubjectAlternativeNameExtension(boolean critical, GeneralNames names) throws IOException { this.names = names; this.extensionId = PKIXExtensions.SubjectAlternativeName_Id; this.critical = critical; encodeThis(); } public SubjectAlternativeNameExtension(GeneralNames names) throws IOException { this.names = names; this.extensionId = PKIXExtensions.SubjectAlternativeName_Id; this.critical = false; encodeThis(); } /** * Create a default SubjectAlternativeNameExtension. */ public SubjectAlternativeNameExtension() { extensionId = PKIXExtensions.SubjectAlternativeName_Id; critical = false; names = new GeneralNames(); } /** * Create the extension from the passed DER encoded value. * * @param critical true if the extension is to be treated as critical. * @param value Array of DER encoded bytes of the actual value. * @exception IOException on error. */ public SubjectAlternativeNameExtension(Boolean critical, Object value) throws IOException { this.extensionId = PKIXExtensions.SubjectAlternativeName_Id; this.critical = critical.booleanValue(); if (!(value instanceof byte[])) throw new IOException("SubjectAlternativeName: " + "Illegal argument type"); int len = Array.getLength(value); byte[] extValue = new byte[len]; System.arraycopy(value, 0, extValue, 0, len); this.extensionValue = extValue; DerValue val = new DerValue(extValue); try { names = new GeneralNames(val); } catch (GeneralNamesException e) { throw new IOException("SubjectAlternativeName: " + e, e); } } /** * Returns a printable representation of the SubjectAlternativeName. */ public String toString() { if (names == null) return ""; String s = super.toString() + "SubjectAlternativeName [\n" + names.toString() + "]\n"; return (s); } /** * Decode the extension from the InputStream. * * @param in the InputStream to unmarshal the contents from. * @exception IOException on decoding or validity errors. */ public void decode(InputStream in) throws IOException { throw new IOException("Method not to be called directly."); } /** * Write the extension to the OutputStream. * * @param out the OutputStream to write the extension to. * @exception IOException on encoding errors. */ public void encode(OutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); if (extensionValue == null) { extensionId = PKIXExtensions.SubjectAlternativeName_Id; //critical = false; encodeThis(); } super.encode(tmp); out.write(tmp.toByteArray()); } /** * Set the attribute value. */ public void set(String name, Object obj) throws IOException { clearValue(); if (name.equalsIgnoreCase(SUBJECT_NAME)) { if (!(obj instanceof GeneralNames)) { throw new IOException("Attribute value should be of " + "type GeneralNames."); } names = (GeneralNames) obj; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:SubjectAlternativeName."); } } /** * Set the GeneralNames of this extension. */ public void setGeneralNames(GeneralNames names) { clearValue(); this.names = names; } /** * Get the GeneralNames of this extension. */ public GeneralNames getGeneralNames() { return names; } /** * Get the attribute value. */ public Object get(String name) throws IOException { if (name.equalsIgnoreCase(SUBJECT_NAME)) { return (names); } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:SubjectAlternativeName."); } } /** * Delete the attribute value. */ public void delete(String name) throws IOException { if (name.equalsIgnoreCase(SUBJECT_NAME)) { names = null; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:SubjectAlternativeName."); } } /** * Return an enumeration of names of attributes existing within this * attribute. */ public Enumeration getAttributeNames() { Vector elements = new Vector(); elements.addElement(SUBJECT_NAME); return (elements.elements()); } /** * Return the name of this attribute. */ public String getName() { return (NAME); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 8794 Content-Disposition: inline; filename="SubjectDirAttributesExtension.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "11b199671f3be2ef334b78f8c57ccdf5fa6b97b6" // --- 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.x509; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Array; import java.util.Enumeration; import java.util.Vector; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; /** * This class represents the Subject Directory Attributes Extension. * *

* The subject directory attributes extension is not recommended as an essential part of this profile, but it may be * used in local environments. This extension MUST be non-critical. * *

 * The ASN.1 syntax for this extension is:
 *
 *    SubjectDirectoryAttributes ::= SEQUENCE (1..MAX) OF Attribute
 *
 *    Attribute	::= SEQUENCE {
 * type		AttributeType,
 * 	value		SET OF AttributeValue
 *              	-- at least one value is required --}
 *
 *    AttributeType	::= OBJECT IDENTIFIER
 *
 *    AttributeValue	::= ANY
 *
 * 
* * @author Christine Ho * @version 1.7 * * @see CertAttrSet * @see Extension */ public class SubjectDirAttributesExtension extends Extension implements CertAttrSet { /** * */ private static final long serialVersionUID = -1215458115428197688L; /** * Identifier for this attribute, to be used with the * get, set, delete methods of Certificate, x509 type. */ //public static final String IDENT = "x509.info.extensions.SubjectDirectoryAttributes"; public static final String IDENT = "Subject Directory Attributes"; /** * Attribute names. */ public static final String NAME = "SubjectDirectoryAttributes"; // Private data members private Vector attrList = new Vector(); // Encode this extension value private void encodeThis() throws IOException { try (DerOutputStream out = new DerOutputStream()) { DerOutputStream tmp = new DerOutputStream(); //encoding the attributes Enumeration attrs = attrList.elements(); while (attrs.hasMoreElements()) { Attribute attr = attrs.nextElement(); attr.encode(tmp); } out.write(DerValue.tag_SequenceOf, tmp); this.extensionValue = out.toByteArray(); } } // Decode this extension value private void decodeThis(DerValue derVal) throws IOException { if (derVal.tag != DerValue.tag_Sequence) { throw new IOException("Invalid encoding for " + "Subject Directory Attribute extension."); } if (derVal.data.available() == 0) { throw new IOException(NAME + " No data available in " + "passed DER encoded value."); } // Decode all the Attributes while (derVal.data.available() != 0) { DerValue encAttr = derVal.data.getDerValue(); Attribute attr = new Attribute(encAttr); attrList.addElement(attr); } } /** * Default constructor for this object. * * @param derVal Der encoded value of this extension */ public SubjectDirAttributesExtension(DerValue derVal) throws IOException { this.extensionId = PKIXExtensions.SubjectDirectoryAttributes_Id; this.critical = false; decodeThis(derVal); } /** * Default constructor for this object. * * @param list Attribute object list */ public SubjectDirAttributesExtension(Attribute[] list) throws IOException { this.extensionId = PKIXExtensions.SubjectDirectoryAttributes_Id; this.critical = false; if ((list == null) || (list.length == 0)) { throw new IOException("No data available in " + "passed Attribute List."); } // add the Attributes for (int i = 0; i < list.length; i++) { attrList.addElement(list[i]); } } /** * Constructor from parsing extension * * @param list Attribute object list */ public SubjectDirAttributesExtension(Boolean crit, Object value) throws IOException { this.extensionId = PKIXExtensions.SubjectDirectoryAttributes_Id; this.critical = crit.booleanValue(); if (!(value instanceof byte[])) throw new IOException(NAME + "Illegal argument type"); int len = Array.getLength(value); byte[] extValue = new byte[len]; System.arraycopy(value, 0, extValue, 0, len); this.extensionValue = extValue; decodeThis(new DerValue(extValue)); } /** * Constructor for this object. * * @param list Attribute object list * @param critical The criticality */ public SubjectDirAttributesExtension(Attribute[] list, boolean critical) throws IOException { this.extensionId = PKIXExtensions.SubjectDirectoryAttributes_Id; this.critical = critical; if ((list == null) || (list.length == 0)) { throw new IOException("No data available in " + "passed Attribute List."); } // add the Attributes for (int i = 0; i < list.length; i++) { attrList.addElement(list[i]); } } /** * Return user readable form of extension. */ public String toString() { String s = super.toString() + "SubjectDirectoryAttributes:[\n"; Enumeration attrs = attrList.elements(); StringBuffer tempBuffer = new StringBuffer(); while (attrs.hasMoreElements()) { Attribute attr = attrs.nextElement(); tempBuffer.append(attr.toString()); } s += tempBuffer.toString(); return (s + "]\n"); } /** * Decode the extension from the InputStream. * * @param in the InputStream to unmarshal the contents from. * @exception IOException on decoding or validity errors. */ public void decode(InputStream in) throws IOException { DerValue val = new DerValue(in); decodeThis(val); } /** * Encode this extension value to the output stream. * * @param out the DerOutputStream to encode the extension to. */ public void encode(OutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); if (extensionValue == null) { this.extensionId = PKIXExtensions.SubjectDirectoryAttributes_Id; this.critical = false; encodeThis(); } super.encode(tmp); out.write(tmp.toByteArray()); } /** * Set the attribute value. */ public void set(String name, Object obj) throws IOException { throw new IOException("Attribute name not recognized by " + "CertAttrSet:SubjectDirectoryAttributes."); } /** * Get the attribute value. */ public Object get(String name) throws IOException { throw new IOException("Attribute name not recognized by " + "CertAttrSet:SubjectDirectoryAttributes."); } /** * Delete the attribute value. */ public void delete(String name) throws IOException { throw new IOException("Attribute name not recognized by " + "CertAttrSet:SubjectDirectoryAttributes."); } /** * Return an enumeration of names of attributes existing within this * attribute. */ public Enumeration getAttributeNames() { Vector elements = new Vector(); return (elements.elements()); } /** * Return the name of this attribute. */ public String getName() { return (NAME); } /** * Returns an enumeration of attributes in the extension. */ public Enumeration getAttributesList() { if (attrList == null) return null; return attrList.elements(); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 7138 Content-Disposition: inline; filename="SubjectKeyIdentifierExtension.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "68ff9555fd1b0b4050c133a69c15b62033b27282" // --- 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.x509; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Array; import java.util.Enumeration; import java.util.Vector; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; /** * Represent the Subject Key Identifier Extension. * * This extension, if present, provides a means of identifying the particular * public key used in an application. This extension by default is marked * non-critical. * *

* Extensions are addiitonal attributes which can be inserted in a X509 v3 certificate. For example a * "Driving License Certificate" could have the driving license number as a extension. * *

* Extensions are represented as a sequence of the extension identifier (Object Identifier), a boolean flag stating * whether the extension is to be treated as being critical and the extension value itself (this is again a DER encoding * of the extension value). * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.7 * @see Extension * @see CertAttrSet */ public class SubjectKeyIdentifierExtension extends Extension implements CertAttrSet { /** * */ private static final long serialVersionUID = 2457721262590880939L; /** * Identifier for this attribute, to be used with the * get, set, delete methods of Certificate, x509 type. */ public static final String IDENT = "x509.info.extensions.SubjectKeyIdentifier"; /** * Attribute names. */ public static final String NAME = "SubjectKeyIdentifier"; public static final String KEY_ID = "key_id"; // Private data member private KeyIdentifier id; // Encode this extension value private void encodeThis() throws IOException { DerOutputStream os = new DerOutputStream(); id.encode(os); extensionValue = os.toByteArray(); } /** * Create a SubjectKeyIdentifierExtension with the passed octet string. * The criticality is set to False. * * @param octetString the octet string identifying the key identifier. */ public SubjectKeyIdentifierExtension(boolean critical, byte[] octetString) throws IOException { id = new KeyIdentifier(octetString); this.extensionId = PKIXExtensions.SubjectKey_Id; this.critical = critical; encodeThis(); } public SubjectKeyIdentifierExtension(byte[] octetString) throws IOException { id = new KeyIdentifier(octetString); this.extensionId = PKIXExtensions.SubjectKey_Id; this.critical = false; encodeThis(); } /** * Create the extension from the passed DER encoded value. * * @param critical true if the extension is to be treated as critical. * @param value Array of DER encoded bytes of the actual value. * @exception IOException on error. */ public SubjectKeyIdentifierExtension(Boolean critical, Object value) throws IOException { this.extensionId = PKIXExtensions.SubjectKey_Id; this.critical = critical.booleanValue(); int len = Array.getLength(value); byte[] extValue = new byte[len]; for (int i = 0; i < len; i++) { extValue[i] = Array.getByte(value, i); } this.extensionValue = extValue; DerValue val = new DerValue(extValue); this.id = new KeyIdentifier(val); } /** * Returns a printable representation. */ public String toString() { if (id == null) return ""; String s = super.toString() + "SubjectKeyIdentifier [\n" + id.toString() + "]\n"; return (s); } /** * Write the extension to the OutputStream. * * @param out the OutputStream to write the extension to. * @exception IOException on encoding errors. */ public void encode(OutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); if (extensionValue == null) { extensionId = PKIXExtensions.SubjectKey_Id; critical = false; encodeThis(); } super.encode(tmp); out.write(tmp.toByteArray()); } /** * Decode the extension from the InputStream. * * @param in the InputStream to unmarshal the contents from. * @exception IOException on decoding or validity errors. */ public void decode(InputStream in) throws IOException { throw new IOException("Method not to be called directly."); } /** * Set the attribute value. */ public void set(String name, Object obj) throws IOException { clearValue(); if (name.equalsIgnoreCase(KEY_ID)) { if (!(obj instanceof KeyIdentifier)) { throw new IOException("Attribute value should be of" + " type KeyIdentifier."); } id = (KeyIdentifier) obj; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:SubjectKeyIdentifierExtension."); } } /** * Get the attribute value. */ public Object get(String name) throws IOException { if (name.equalsIgnoreCase(KEY_ID)) { return (id); } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:SubjectKeyIdentifierExtension."); } } /** * Delete the attribute value. */ public void delete(String name) throws IOException { if (name.equalsIgnoreCase(KEY_ID)) { id = null; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:SubjectKeyIdentifierExtension."); } } /** * Return an enumeration of names of attributes existing within this * attribute. */ public Enumeration getAttributeNames() { Vector elements = new Vector(); elements.addElement(KEY_ID); return (elements.elements()); } /** * Return the name of this attribute. */ public String getName() { return (NAME); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 2386 Content-Disposition: inline; filename="URIName.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "539ad249c982f84d08243e5dd3ba74547d98999b" // --- 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.x509; import java.io.IOException; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; /** * This class implements the URIName as required by the GeneralNames * ASN.1 object. * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.3 * @see GeneralName * @see GeneralNames * @see GeneralNameInterface */ public class URIName implements GeneralNameInterface { /** * */ private static final long serialVersionUID = 8340049830612859508L; private String name; /** * Create the URIName object from the passed encoded Der value. * * @param derValue the encoded DER URIName. * @exception IOException on error. */ public URIName(DerValue derValue) throws IOException { name = derValue.getIA5String(); } /** * Create the URIName object with the specified name. * * @param name the URIName. */ public URIName(String name) { this.name = name; } /** * Return the type of the GeneralName. */ public int getType() { return (GeneralNameInterface.NAME_URI); } /** * Encode the URI name into the DerOutputStream. * * @param out the DER stream to encode the URIName to. * @exception IOException on encoding errors. */ public void encode(DerOutputStream out) throws IOException { out.putIA5String(name); } /** * Convert the name into user readable string. */ public String toString() { return ("URIName: " + name); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 3344 Content-Disposition: inline; filename="UniqueIdentity.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "c5a0e1d0033c90b06293d732bf0f51e398ce7305" // --- 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.x509; import java.io.IOException; import netscape.security.util.BitArray; import netscape.security.util.DerInputStream; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; /** * This class defines the UniqueIdentity class used by certificates. * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.6 */ public class UniqueIdentity { // Private data members private BitArray id; /** * The default constructor for this class. * * @param id the byte array containing the unique identifier. */ public UniqueIdentity(BitArray id) { this.id = id; } /** * The default constructor for this class. * * @param id the byte array containing the unique identifier. */ public UniqueIdentity(byte[] id) { this.id = new BitArray(id.length * 8, id); } /** * Create the object, decoding the values from the passed DER stream. * * @param in the DerInputStream to read the UniqueIdentity from. * @exception IOException on decoding errors. */ public UniqueIdentity(DerInputStream in) throws IOException { DerValue derVal = in.getDerValue(); id = derVal.getUnalignedBitString(true); } /** * Create the object, decoding the values from the passed DER stream. * * @param derVal the DerValue decoded from the stream. * @param tag the tag the value is encoded under. * @exception IOException on decoding errors. */ public UniqueIdentity(DerValue derVal) throws IOException { id = derVal.getUnalignedBitString(true); } /** * Return the UniqueIdentity as a printable string. */ public String toString() { return ("UniqueIdentity:" + id.toString() + "\n"); } /** * Encode the UniqueIdentity in DER form to the stream. * * @param out the DerOutputStream to marshal the contents to. * @param tag enocode it under the following tag. * @exception IOException on errors. */ public void encode(DerOutputStream out, byte tag) throws IOException { byte[] bytes = id.toByteArray(); int excessBits = bytes.length * 8 - id.length(); out.write(tag); out.putLength(bytes.length + 1); out.write(excessBits); out.write(bytes); } /** * Return the unique id. */ public boolean[] getId() { if (id == null) return null; return id.toBooleanArray(); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 2925 Content-Disposition: inline; filename="UserNotice.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "9be215b941a06b32d0d06221df9d953b74952d11" // --- 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.x509; import java.io.IOException; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; /** * Represent the UserNotice Qualifier. * * UserNotice ::= SEQUENCE { * noticeRef NoticeReference OPTIONAL, * explicitText DisplayText OPTIONAL * } * * @author Thomas Kwan */ public class UserNotice extends Qualifier { /** * */ private static final long serialVersionUID = 5770869942793748051L; private NoticeReference mNoticeReference = null; private DisplayText mDisplayText = null; public UserNotice(NoticeReference ref, DisplayText text) { mNoticeReference = ref; mDisplayText = text; } public UserNotice(DerValue val) throws IOException { if (val.tag != DerValue.tag_Sequence) { throw new IOException("Invalid encoding for UserNotice"); } // case 0: no element if (val.data.available() == 0) return; // case 1: 1 element DerValue inSeq = val.data.getDerValue(); if (inSeq.tag == DerValue.tag_Sequence) { mNoticeReference = new NoticeReference(inSeq); } else { mDisplayText = new DisplayText(inSeq); } if (val.data.available() == 0) return; // case 2: 2 elements mDisplayText = new DisplayText(val.data.getDerValue()); } public NoticeReference getNoticeReference() { return mNoticeReference; } public DisplayText getDisplayText() { return mDisplayText; } /** * Write the UserNotice to the DerOutputStream. * * @param out the DerOutputStream to write the object to. * @exception IOException on errors. */ public void encode(DerOutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); // OPTIONAL if (mNoticeReference != null) { mNoticeReference.encode(tmp); } // OPTIONAL if (mDisplayText != null) { mDisplayText.encode(tmp); } out.write(DerValue.tag_Sequence, tmp); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 22186 Content-Disposition: inline; filename="X500Name.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "c8627a93c5f36f39d0484867e2a4b8c68fea0fc9" // --- 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.x509; import java.io.IOException; import java.security.Principal; import java.util.ArrayList; import java.util.Arrays; import java.util.Enumeration; import java.util.List; import java.util.Vector; import netscape.security.util.DerInputStream; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; import netscape.security.util.ObjectIdentifier; /** * X.500 names are used to identify entities, such as those which are * identified by X.509 certificates. They are world-wide, hierarchical, * and descriptive. Entities can be identified by attributes, and in * some systems can be searched for according to those attributes. * *

* This class exposes only partial X.500 name functionality. Most * notably, it works best if Relative Distinguished Names only have one * (unique) attribute each, and if only the most common attributes need * to be visible to applications. This limitation, and others, will * be lifted over time. * * @author David Brownell * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.35 * @see GeneralName * @see GeneralNames * @see GeneralNameInterface * @see RDN * @see AVA * @see LdapDNStrConverter */ public class X500Name implements Principal, GeneralNameInterface { /** * */ private static final long serialVersionUID = -730790062013191108L; /** * Constructs a name from a Ldap DN string, such * as &lb;CN=Dave, OU=JavaSoft, O=Sun Microsystems, C=US&rb;. The * older "/C=US/O=Sun Microsystems, Inc/OU=JavaSoft/CN=Dave" syntax * is not currently supported. (The former is RFC 1779 style.) * * @param ldapDNString a Ldap DN String e.g. as defined in RFC1779 */ public X500Name(String ldapDNString) throws IOException { X500Name x500name; if (ldapDNString == null || ldapDNString.equals("")) { clear(); return; } x500name = LdapDNStrConverter.getDefault().parseDN(ldapDNString); names = x500name.getNames(); } /** * Constructs a X500Name from a Ldap DN String using the specified * LdapDNStrConverter. Also use the input tags. * * @see LdapDNStrConverter * * @param ldapDNString a Ldap DN String e.g. as defined in RFC1779. * @param ldapDNStrConverter A LdapDNStrConverter */ public X500Name(String ldapDNString, LdapDNStrConverter ldapDNStrConverter, byte[] tags) throws IOException { if (ldapDNString == null || ldapDNString.equals("")) { clear(); return; } X500Name x500name; x500name = ldapDNStrConverter.parseDN(ldapDNString, tags); names = x500name.getNames(); } public X500Name(String ldapDNString, byte[] tags) throws IOException { if (ldapDNString == null || ldapDNString.equals("")) { clear(); return; } X500Name x500name; x500name = LdapDNStrConverter.getDefault().parseDN(ldapDNString, tags); names = x500name.getNames(); } /** * Constructs a X500Name from a Ldap DN String using the specified * LdapDNStrConverter. * * @see LdapDNStrConverter * * @param ldapDNString a Ldap DN String e.g. as defined in RFC1779. * @param ldapDNStrConverter A LdapDNStrConverter */ public X500Name(String ldapDNString, LdapDNStrConverter ldapDNStrConverter) throws IOException { if (ldapDNString == null || ldapDNString.equals("")) { clear(); return; } X500Name x500name; x500name = ldapDNStrConverter.parseDN(ldapDNString); names = x500name.getNames(); } /** * Constructs a X500Name from fields common in enterprise application * environments. * * @param commonName common name of a person, e.g. "Vivette Davis" * @param organizationUnit small organization name, e.g. "Purchasing" * @param organizationName large organization name, e.g. "Onizuka, Inc." * @param country two letter country code, e.g. "CH" */ public X500Name( String commonName, String organizationUnit, String organizationName, String country) throws IOException { DirStrConverter dirStrConverter = new DirStrConverter(); PrintableConverter printableConverter = new PrintableConverter(); AVA[] assertion = new AVA[1]; // array is cloned in constructors. int i = 4; names = new RDN[i]; /* * NOTE: it's only on output that little-endian * ordering is used. */ assertion[0] = new AVA(commonName_oid, dirStrConverter.getValue(commonName)); names[--i] = new RDN(assertion); assertion[0] = new AVA(orgUnitName_oid, dirStrConverter.getValue(organizationUnit)); names[--i] = new RDN(assertion); assertion[0] = new AVA(orgName_oid, dirStrConverter.getValue(organizationName)); names[--i] = new RDN(assertion); assertion[0] = new AVA(countryName_oid, printableConverter.getValue(country)); names[--i] = new RDN(assertion); } /** * Constructs a X500Name from fields common in Internet application * environments. * * @param commonName common name of a person, e.g. "Vivette Davis" * @param organizationUnit small organization name, e.g. "Purchasing" * @param organizationName large organization name, e.g. "Onizuka, Inc." * @param localityName locality (city) name, e.g. "Palo Alto" * @param stateName state name, e.g. "California" * @param country two letter country code, e.g. "CH" */ public X500Name( String commonName, String organizationUnit, String organizationName, String localityName, String stateName, String country) throws IOException { DirStrConverter dirStrConverter = new DirStrConverter(); PrintableConverter printableConverter = new PrintableConverter(); AVA[] assertion = new AVA[1]; // array is cloned in constructors. int i = 6; names = new RDN[i]; /* * NOTE: it's only on output that little-endian * ordering is used. */ assertion[0] = new AVA(commonName_oid, dirStrConverter.getValue(commonName)); names[--i] = new RDN(assertion); assertion[0] = new AVA(orgUnitName_oid, dirStrConverter.getValue(organizationUnit)); names[--i] = new RDN(assertion); assertion[0] = new AVA(orgName_oid, dirStrConverter.getValue(organizationName)); names[--i] = new RDN(assertion); assertion[0] = new AVA(localityName_oid, dirStrConverter.getValue(localityName)); names[--i] = new RDN(assertion); assertion[0] = new AVA(stateName_oid, dirStrConverter.getValue(stateName)); names[--i] = new RDN(assertion); assertion[0] = new AVA(countryName_oid, printableConverter.getValue(country)); names[--i] = new RDN(assertion); } /** * Constructs a name from an ASN.1 encoded value. The encoding * of the name in the stream uses DER (a BER/1 subset). * * @param value a DER-encoded value holding an X.500 name. */ public X500Name(DerValue value) throws IOException { this(value.toDerInputStream()); } /** * Constructs a name from an ASN.1 encoded input stream. The encoding * of the name in the stream uses DER (a BER/1 subset). * * @param in DER-encoded data holding an X.500 name. */ public X500Name(DerInputStream in) throws IOException { parseDER(in); } /** * Constructs a name from an ASN.1 encoded byte array. * * @param name DER-encoded byte array holding an X.500 name. */ public X500Name(byte[] name) throws IOException { DerInputStream in = new DerInputStream(name); parseDER(in); } /** * Constructs a X500Name from array of RDN. The RDNs are expected to * be in big endian order i.e. most significant first. * * @param rdns an array of RDN. */ public X500Name(RDN[] rdns) throws IOException { names = rdns.clone(); } /** * convenience method. * * @param rdns a vector of rdns. */ public X500Name(Vector rdnVector) throws IOException { int size = rdnVector.size(); names = new RDN[size]; for (int i = 0; i < size; i++) { names[i] = rdnVector.elementAt(i); } } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + Arrays.hashCode(names); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; X500Name other = (X500Name) obj; if (!Arrays.equals(names, other.names)) return false; return true; } /** * Sets private data to a null state */ private void clear() { dn = ""; names = null; } /** * Returns the name component as a Java string, regardless of its * encoding restrictions. */ private String getString(DerValue attribute) throws IOException { String value = attribute.getAsString(); if (value == null) throw new IOException("not a DER string encoding, " + attribute.tag); else return value; } /** * Return type of GeneralName. */ public int getType() { return (GeneralNameInterface.NAME_DIRECTORY); } /** * Returns a "Country" name component. If more than one * such attribute exists, the topmost one is returned. * * @return "C=" component of the name, if any. */ public String getCountry() throws IOException { DerValue attr = findAttribute(countryName_oid); return getString(attr); } /** * Returns an "Organization" name component. If more than * one such attribute exists, the topmost one is returned. * * @return "O=" component of the name, if any. */ public String getOrganization() throws IOException { DerValue attr = findAttribute(orgName_oid); return getString(attr); } /** * Returns an "Organizational Unit" name component. If more * than one such attribute exists, the topmost one is returned. * * @return "OU=" component of the name, if any. */ public String getOrganizationalUnit() throws IOException { DerValue attr = findAttribute(orgUnitName_oid); return getString(attr); } /** * Returns a "Common Name" component. If more than one such * attribute exists, the topmost one is returned. * * @return "CN=" component of the name, if any. */ public String getCommonName() throws IOException { DerValue attr = findAttribute(commonName_oid); return getString(attr); } /** * Returns a "UID" component. If more than one such * attribute exists, the topmost one is returned. * * @return "UID=" component of the name, if any. */ public String getUserID() throws IOException { DerValue attr = findAttribute(uidName_oid); return getString(attr); } /** * Returns a "Locality" name component. If more than one * such component exists, the topmost one is returned. * * @return "L=" component of the name, if any. */ public String getLocality() throws IOException { DerValue attr = findAttribute(localityName_oid); return getString(attr); } /** * Returns a "State" name component. If more than one * such component exists, the topmost one is returned. * * @return "S=" component of the name, if any. */ public String getState() throws IOException { DerValue attr = findAttribute(stateName_oid); return getString(attr); } /** * Returns a "Email" name component. If more than one * such component exists, the topmost one is returned. * * @return "E=" component of the name, if any. */ public String getEmail() throws IOException { DerValue attr = findAttribute(email_oid); if (attr == null) return null; return getString(attr); } /** * Returns a Ldap DN String from the X500Name using the global default * LdapDNStrConverter * * @see LdapDNStrConverter * @return Ldap DN string of this X500Name using the default converter. */ public String toLdapDNString() throws IOException { if (dn == null) generateDN(LdapDNStrConverter.getDefault()); return dn; } /** * Return a list of attributes of the given type. * * The "most specific" value comes last. * * If there are no name attributes of the given type, an empty * list is returned. */ public List getAttributesForOid(ObjectIdentifier oid) throws IOException { List xs = new ArrayList<>(); for (int i = 0; i < names.length; i++) { DerValue v = names[i].findAttribute(oid); if (v != null) xs.add(getString(v)); } return xs; } /** * Returns a Ldap DN String from the X500Name * using the specified LdapDNStrconverter. * For example, RFC1779String converter can be passed to convert the * DN to RFC1779 string syntax. * * @see LdapDNStrConverter * @param ldapDNStrConverter a LdapDNStrConverter * @return Ldap DN string of the X500Name */ public String toLdapDNString(LdapDNStrConverter ldapDNStrConverter) throws IOException { if (dn == null) generateDN(ldapDNStrConverter); return dn; } /** * Returns a Ldap DN string, using the global default LdapDNStrConverter * or null if an error occurs in the conversion. */ public String toString() { String s; if (names == null) { s = ""; return s; } try { s = toLdapDNString(); } catch (IOException e) { return null; } return s; } /** * Returns the value of toString(). This call is needed to * implement the java.security.Principal interface. */ public String getName() { return toString(); } private String dn; // RFC 1779 style DN, or null private RDN names[]; // RDNs /** * Find the first instance of this attribute in a "top down" * search of all the attributes in the name. */ private DerValue findAttribute(ObjectIdentifier attribute) { int i; DerValue retval = null; for (i = 0; i < names.length; i++) { retval = names[i].findAttribute(attribute); if (retval != null) break; } return retval; } /** * Returns an enumerator of RDNs in the X500Name. * * @return enumeration of rdns in this X500Name. */ public Enumeration getRDNs() { return new RDNEnumerator(); } /** * Returns an array of RDN in the X500Name. * * @return array of RDN in this X500name. */ public RDN[] getNames() { return names.clone(); } /** * Returns the number of RDNs in the X500Name. * * @return number of RDNs in this X500Name. */ public int getNamesLength() { return names.length; } /****************************************************************/ private void parseDER(DerInputStream in) throws IOException { // // X.500 names are a "SEQUENCE OF" RDNs, which means one or // more and order matters. We scan them in order, which // conventionally is big-endian. // DerValue nameseq[] = in.getSequence(5); int i; if (nameseq.length != 0) { names = new RDN[nameseq.length]; } else { clear(); } for (i = 0; i < nameseq.length; i++) names[i] = new RDN(nameseq[i]); } /** * Encodes the name in DER-encoded form. * * @param out where to put the DER-encoded X.500 name */ public void encode(DerOutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); int i; int len = 0; if (names == null) { len = 0; } else { len = names.length; } for (i = 0; i < len; i++) names[i].encode(tmp); out.write(DerValue.tag_Sequence, tmp); } /** * Gets the name in DER-encoded form. * * @return the DER encoded byte array of this name, * null if no names are present. */ public byte[] getEncoded() throws IOException { try (DerOutputStream out = new DerOutputStream()) { DerOutputStream tmp = new DerOutputStream(); int len = 0; if (names == null) { len = 0; } else { len = names.length; } for (int i = 0; i < len; i++) names[i].encode(tmp); out.write(DerValue.tag_Sequence, tmp); return out.toByteArray(); } } /* * Dump the printable form of a distinguished name. Each relative * name is separated from the next by a ",", and assertions in the * relative names have "label=value" syntax. * * Uses RFC 1779 syntax (i.e. little-endian, comma separators) * */ private void generateDN(LdapDNStrConverter ldapDNStrConverter) throws IOException { if (names == null) return; dn = ldapDNStrConverter.encodeDN(this); } private class RDNEnumerator implements Enumeration { private int index; public RDNEnumerator() { index = 0; } public boolean hasMoreElements() { return (index < names.length); } public RDN nextElement() { if (index >= names.length) return null; return names[index++]; } } /****************************************************************/ /* * Maybe return a preallocated OID, to reduce storage costs * and speed recognition of common X.500 attributes. */ static ObjectIdentifier intern(ObjectIdentifier oid) throws IOException { return X500NameAttrMap.getDefault().getOid(oid); } /* * Selected OIDs from X.520 */ /** OID for the "CN=" attribute, denoting a person's common name. */ public static final ObjectIdentifier commonName_oid = X500NameAttrMap.getDefault().getOid("CN"); /** OID for the "UID=" attribute, denoting a person's ID. */ public static final ObjectIdentifier uidName_oid = X500NameAttrMap.getDefault().getOid("UID"); /** OID for the "C=" attribute, denoting a country. */ public static final ObjectIdentifier countryName_oid = X500NameAttrMap.getDefault().getOid("C"); /** OID for the "L=" attribute, denoting a locality (such as a city) */ public static final ObjectIdentifier localityName_oid = X500NameAttrMap.getDefault().getOid("L"); /** OID for the "O=" attribute, denoting an organization name */ public static final ObjectIdentifier orgName_oid = X500NameAttrMap.getDefault().getOid("O"); /** OID for the "OU=" attribute, denoting an organizational unit name */ public static final ObjectIdentifier orgUnitName_oid = X500NameAttrMap.getDefault().getOid("OU"); /** OID for the "S=" attribute, denoting a state (such as Delaware) */ public static final ObjectIdentifier stateName_oid = X500NameAttrMap.getDefault().getOid("ST"); /** OID for the "STREET=" attribute, denoting a street address. */ public static final ObjectIdentifier streetAddress_oid = X500NameAttrMap.getDefault().getOid("STREET"); /** OID for the "T=" attribute, denoting a person's title. */ public static final ObjectIdentifier title_oid = X500NameAttrMap.getDefault().getOid("TITLE"); /** OID for the "E=" attribute, denoting a person's email address. */ public static final ObjectIdentifier email_oid = X500NameAttrMap.getDefault().getOid("E"); /* * OIDs from other sources which show up in X.500 names we * expect to deal with often */ private static final int ipAddress_data[] = // SKIP { 1, 3, 6, 1, 4, 1, 42, 2, 11, 2, 1 }; /** OID for "IP=" IP address attributes, used with SKIP. */ public static final ObjectIdentifier ipAddress_oid = new ObjectIdentifier(ipAddress_data); } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 12988 Content-Disposition: inline; filename="X500NameAttrMap.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "3947f099020827a22d8c248dc0ba7cf9b07e160f" // --- 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.x509; import java.util.Enumeration; import java.util.Hashtable; import netscape.security.util.ObjectIdentifier; /** * Maps an attribute name in an X500 AVA to its OID and a * converter for the attribute type. The converter converts from a string to * its DER encoded attribute value. * For example, "CN" maps to its OID of * 2.5.4.3 and the Directory String Converter. The Directory String * Converter converts from a string to a DerValue with tag Printable, T.61 or * UniversalString. * * @author Lily Hsiao, Slava Galperin at Netscape Communications, Inc. * */ public class X500NameAttrMap { // // public constructors. // /** * Construct a X500NameAttrMap. */ public X500NameAttrMap() { } // // public get methods. // /** * Get the attribute name (keyword) of the specified OID. * * @param oid An ObjectIdentifier * * @return An attribute name (keyword string) for the OID. */ public String getName(ObjectIdentifier oid) { // XXX assert oid != null return oid2Name.get(oid); } /** * Get the ObjectIdentifier of the attribute name. * * @param name An attribute name (string of ascii characters) * * @return An ObjectIdentifier for the attribute. */ public ObjectIdentifier getOid(String name) { // XXX assert name != null return name2OID.get(name.toUpperCase()); } /** * Get the Attribute Value Converter for the specified attribute name. * * @param name An attribute name * * @return An attribute value converter for the attribute name */ public AVAValueConverter getValueConverter(String name) { ObjectIdentifier oid = name2OID.get(name.toUpperCase()); if (oid == null) return null; return oid2ValueConverter.get(oid); } /** * Get the Attribute Value Converter for the specified ObjectIdentifier. * * @param oid An ObjectIdentifier * * @return An AVAValueConverter for the OID. */ public AVAValueConverter getValueConverter(ObjectIdentifier oid) { return oid2ValueConverter.get(oid); } /** * Get an Enumeration of all attribute names in this map. * * @return An Enumeration of all attribute names. */ public Enumeration getAllNames() { return name2OID.keys(); } /** * Get an Enumeration of all ObjectIdentifiers in this map. * * @return An Enumeration of all OIDs in this map. */ public Enumeration getAllOIDs() { return oid2Name.keys(); } /** * Get the ObjectIdentifier object in the map for the specified OID. * * @param oid An ObjectIdentifier. * @return The ObjectIdentifier object in this map for the OID. */ public ObjectIdentifier getOid(ObjectIdentifier oid) { String name = oid2Name.get(oid); if (name == null) return null; return name2OID.get(name); } // // public add methods. // /** * Adds a attribute name, ObjectIdentifier, AVAValueConverter entry * to the map. * * @param name An attribute name (string of ascii chars) * @param oid The ObjectIdentifier for the attribute. * @param valueConverter An AVAValueConverter object for converting * an value for this attribute from a string to * a DerValue and vice versa. */ public void addNameOID(String name, ObjectIdentifier oid, AVAValueConverter valueConverter) { // normalize name for case insensitive compare. ObjectIdentifier theOid; Class expValueConverter; theOid = name2OID.get(name); if (theOid != null) { expValueConverter = oid2ValueConverter.get(theOid).getClass(); if (!theOid.equals(oid) || expValueConverter != valueConverter.getClass()) { throw new IllegalArgumentException( "Another keyword-oid-valueConverter triple already " + "exists in the X500NameAttrMap "); } return; } name2OID.put(name.toUpperCase(), oid); oid2Name.put(oid, name.toUpperCase()); oid2ValueConverter.put(oid, valueConverter); } // // public static methods. // /** * Get the global default X500NameAttrMap. * * @return The global default X500NameAttrMap. */ public static X500NameAttrMap getDefault() { return defMap; } /** * Get the global default X500NamAttrMap using the DirStrConverter. * * @return The global default X500NameAttrMap using the DirStrConverter. */ public static X500NameAttrMap getDirDefault() { return defDirMap; } /** * Set the global default X500NameAttrMap. * * @param newDefault The new default X500NameAttrMap. */ public static void setDefault(X500NameAttrMap newDefault) { // XXX assert newDef != null defMap = newDefault; } // // private variables // Hashtable name2OID = new Hashtable(); Hashtable oid2Name = new Hashtable(); Hashtable oid2ValueConverter = new Hashtable(); // // global defaults. // private static X500NameAttrMap defMap; private static X500NameAttrMap defDirMap; /* * Create the default maps on initialization. */ static { defMap = new X500NameAttrMap(); AVAValueConverter directoryStr = new DirStrConverter(), ia5Str = new IA5StringConverter(); defMap.addNameOID("CN", new ObjectIdentifier("2.5.4.3"), directoryStr); defMap.addNameOID("OU", new ObjectIdentifier("2.5.4.11"), directoryStr); defMap.addNameOID("O", new ObjectIdentifier("2.5.4.10"), directoryStr); // serialNumber added for CEP support defMap.addNameOID("SERIALNUMBER", new ObjectIdentifier("2.5.4.5"), new PrintableConverter()); defMap.addNameOID("C", new ObjectIdentifier("2.5.4.6"), new PrintableConverter()); defMap.addNameOID("L", new ObjectIdentifier("2.5.4.7"), directoryStr); defMap.addNameOID("ST", new ObjectIdentifier("2.5.4.8"), directoryStr); defMap.addNameOID("STREET", new ObjectIdentifier("2.5.4.9"), directoryStr); defMap.addNameOID("TITLE", new ObjectIdentifier("2.5.4.12"), directoryStr); // RFC 1274 UserId, rfc822MailBox defMap.addNameOID("UID", new ObjectIdentifier("0.9.2342.19200300.100.1.1"), directoryStr); defMap.addNameOID("MAIL", new ObjectIdentifier("0.9.2342.19200300.100.1.3"), ia5Str); // PKCS9 e-mail address defMap.addNameOID("E", new ObjectIdentifier("1.2.840.113549.1.9.1"), ia5Str); // DC definition from draft-ietf-asid-ldap-domains-02.txt defMap.addNameOID("DC", new ObjectIdentifier("0.9.2342.19200300.100.1.25"), ia5Str); // more defined in RFC2459 used in Subject Directory Attr extension defMap.addNameOID("SN", // surname new ObjectIdentifier("2.5.4.4"), directoryStr); defMap.addNameOID("GIVENNAME", new ObjectIdentifier("2.5.4.42"), directoryStr); defMap.addNameOID("INITIALS", new ObjectIdentifier("2.5.4.43"), directoryStr); defMap.addNameOID("GENERATIONQUALIFIER", new ObjectIdentifier("2.5.4.44"), directoryStr); defMap.addNameOID("DNQUALIFIER", new ObjectIdentifier("2.5.4.46"), directoryStr); // these two added mainly for CEP support // PKCS9 unstructured name defMap.addNameOID("UNSTRUCTUREDNAME", new ObjectIdentifier("1.2.840.113549.1.9.2"), ia5Str); // PKCS9 unstructured address defMap.addNameOID("UNSTRUCTUREDADDRESS", new ObjectIdentifier("1.2.840.113549.1.9.8"), new PrintableConverter()); }; static { defDirMap = new X500NameAttrMap(); AVAValueConverter directoryStr = new DirStrConverter(); defDirMap.addNameOID("CN", new ObjectIdentifier("2.5.4.3"), directoryStr); defDirMap.addNameOID("OU", new ObjectIdentifier("2.5.4.11"), directoryStr); defDirMap.addNameOID("O", new ObjectIdentifier("2.5.4.10"), directoryStr); // serialNumber added for CEP support defDirMap.addNameOID("SERIALNUMBER", new ObjectIdentifier("2.5.4.5"), directoryStr); defDirMap.addNameOID("C", new ObjectIdentifier("2.5.4.6"), directoryStr); defDirMap.addNameOID("L", new ObjectIdentifier("2.5.4.7"), directoryStr); defDirMap.addNameOID("ST", new ObjectIdentifier("2.5.4.8"), directoryStr); defDirMap.addNameOID("STREET", new ObjectIdentifier("2.5.4.9"), directoryStr); defDirMap.addNameOID("TITLE", new ObjectIdentifier("2.5.4.12"), directoryStr); // RFC 1274 UserId, rfc822MailBox defDirMap.addNameOID("UID", new ObjectIdentifier("0.9.2342.19200300.100.1.1"), directoryStr); defDirMap.addNameOID("MAIL", new ObjectIdentifier("0.9.2342.19200300.100.1.3"), directoryStr); // PKCS9 e-mail address defDirMap.addNameOID("E", new ObjectIdentifier("1.2.840.113549.1.9.1"), directoryStr); // DC definition from draft-ietf-asid-ldap-domains-02.txt defDirMap.addNameOID("DC", new ObjectIdentifier("0.9.2342.19200300.100.1.25"), directoryStr); // more defined in RFC2459 used in Subject Directory Attr extension defDirMap.addNameOID("SN", // surname new ObjectIdentifier("2.5.4.4"), directoryStr); defDirMap.addNameOID("GIVENNAME", new ObjectIdentifier("2.5.4.42"), directoryStr); defDirMap.addNameOID("INITIALS", new ObjectIdentifier("2.5.4.43"), directoryStr); defDirMap.addNameOID("GENERATIONQUALIFIER", new ObjectIdentifier("2.5.4.44"), directoryStr); defDirMap.addNameOID("DNQUALIFIER", new ObjectIdentifier("2.5.4.46"), directoryStr); // these two added mainly for CEP support // PKCS9 unstructured name defDirMap.addNameOID("UNSTRUCTUREDNAME", new ObjectIdentifier("1.2.840.113549.1.9.2"), directoryStr); // PKCS9 unstructured address defDirMap.addNameOID("UNSTRUCTUREDADDRESS", new ObjectIdentifier("1.2.840.113549.1.9.8"), directoryStr); }; } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 3495 Content-Disposition: inline; filename="X500Signer.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "7d429cd9551a0e68b040de70d1d22d5a68888d3e" // --- 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.x509; import java.security.NoSuchAlgorithmException; import java.security.Signature; import java.security.SignatureException; /** * This class provides a binding between a Signature object and an * authenticated X.500 name (from an X.509 certificate chain), which * is needed in many public key signing applications. * *

* The name of the signer is important, both because knowing it is the whole point of the signature, and because the * associated X.509 certificate is always used to verify the signature. * *

* The X.509 certificate chain is temporarily not associated with * the signer, but this omission will be resolved. * * @version 1.18 * * @author David Brownell * @author Amit Kapoor * @author Hemma Prafullchandra */ public final class X500Signer { private Signature sig; private X500Name agent; // XXX should be X509CertChain private AlgorithmId algid; /** * Called for each chunk of the data being signed. That * is, you can present the data in many chunks, so that * it doesn't need to be in a single sequential buffer. * * @param buf buffer holding the next chunk of the data to be signed * @param offset starting point of to-be-signed data * @param len how many bytes of data are to be signed * @exception SignatureException on errors. */ public void update(byte buf[], int offset, int len) throws SignatureException { sig.update(buf, offset, len); } /** * Produces the signature for the data processed by update(). * * @exception SignatureException on errors. */ public byte[] sign() throws SignatureException { return sig.sign(); } /** * Returns the algorithm used to sign. */ public AlgorithmId getAlgorithmId() { return algid; } /** * Returns the name of the signing agent. */ public X500Name getSigner() { return agent; } /* * Constructs a binding between a signature and an X500 name * from an X.509 certificate. */ // package private ----hmmmmm ????? public X500Signer(Signature sig, X500Name agent) { if (sig == null || agent == null) throw new IllegalArgumentException("null parameter"); this.sig = sig; this.agent = agent; try { String alg = sig.getAlgorithm(); if (alg.equals("DSA")) { alg = "SHA1withDSA"; } this.algid = AlgorithmId.get(alg); } catch (NoSuchAlgorithmException e) { throw new RuntimeException("internal error! " + e.getMessage()); } } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 1826 Content-Disposition: inline; filename="X509AttributeName.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "2616ddb8edc3778895eb12c0f92a6c37c6d9646c" // --- 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.x509; /** * This class is used to parse attribute names like "x509.info.extensions". * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.4 */ public class X509AttributeName { // Public members private static final char SEPARATOR = '.'; // Private data members private String prefix = null; private String suffix = null; /** * Default constructor for the class. Name is of the form * "x509.info.extensions". * * @param name the attribute name. */ public X509AttributeName(String name) { int i = name.indexOf(SEPARATOR); if (i == (-1)) { prefix = name; } else { prefix = name.substring(0, i); suffix = name.substring(i + 1); } } /** * Return the prefix of the name. */ public String getPrefix() { return (prefix); } /** * Return the suffix of the name. */ public String getSuffix() { return (suffix); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 38573 Content-Disposition: inline; filename="X509CRLImpl.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "e8e039034576f552006f91be049d4879f18f450a" // --- 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.x509; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.math.BigInteger; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.Principal; import java.security.PrivateKey; import java.security.PublicKey; import java.security.Signature; import java.security.SignatureException; import java.security.cert.CRLException; import java.security.cert.Certificate; import java.security.cert.X509CRL; import java.security.cert.X509CRLEntry; import java.security.cert.X509Certificate; import java.util.Date; import java.util.Enumeration; import java.util.Hashtable; import java.util.LinkedHashSet; import java.util.Set; import netscape.security.util.BigInt; import netscape.security.util.DerInputStream; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; import netscape.security.util.ObjectIdentifier; /** *

* An implmentation for X509 CRL (Certificate Revocation List). *

* The X.509 v2 CRL format is described below in ASN.1: * *

 * 
*

* CertificateList ::= SEQUENCE { tbsCertList TBSCertList, signatureAlgorithm AlgorithmIdentifier, signature BIT STRING * } *

* A good description and profiling is provided in the IETF PKIX WG draft, Part I: X.509 Certificate and CRL Profile, * <draft-ietf-pkix-ipki-part1-06.txt>. *

* The ASN.1 definition of tbsCertList is: * *

 * TBSCertList  ::=  SEQUENCE  {
 *     version                 Version OPTIONAL,
 *                             -- if present, must be v2
 *     signature               AlgorithmIdentifier,
 *     issuer                  Name,
 *     thisUpdate              ChoiceOfTime,
 *     nextUpdate              ChoiceOfTime OPTIONAL,
 *     revokedCertificates     SEQUENCE OF SEQUENCE  {
 *         userCertificate         CertificateSerialNumber,
 *         revocationDate          ChoiceOfTime,
 *         crlEntryExtensions      Extensions OPTIONAL
 *                                 -- if present, must be v2
 *         }  OPTIONAL,
 *     crlExtensions           [0]  EXPLICIT Extensions OPTIONAL
 *                                  -- if present, must be v2
 *     }
 * 
* * @author Hemma Prafullchandra * @version 1.8 * @see X509CRL */ public class X509CRLImpl extends X509CRL { // CRL data, and its envelope private byte[] signedCRL = null; // DER encoded crl private byte[] signature = null; // raw signature bits private byte[] tbsCertList = null; // DER encoded "to-be-signed" CRL private AlgorithmId sigAlgId; // sig alg in CRL // crl information private int version; private AlgorithmId infoSigAlgId; // sig alg in "to-be-signed" crl private X500Name issuer; private Date thisUpdate = null; private Date nextUpdate = null; // private static final Hashtable revokedCerts = new Hashtable(); private Hashtable revokedCerts = new Hashtable(); // private static CRLExtensions extensions = null; private CRLExtensions extensions = null; private boolean entriesIncluded = true; private final static boolean isExplicit = true; private boolean readOnly = false; /** * Unmarshals an X.509 CRL from its encoded form, parsing the encoded * bytes. This form of constructor is used by agents which * need to examine and use CRL contents. Note that the buffer * must include only one CRL, and no "garbage" may be left at * the end. * * @param crlData the encoded bytes, with no trailing padding. * @exception CRLException on parsing errors. * @exception X509ExtensionException on extension handling errors. */ public X509CRLImpl(byte[] crlData) throws CRLException, X509ExtensionException { try { DerValue in = new DerValue(crlData); parse(in); signedCRL = crlData; } catch (IOException e) { throw new CRLException("Parsing error: " + e.getMessage()); } } public X509CRLImpl(byte[] crlData, boolean includeEntries) throws CRLException, X509ExtensionException { try { entriesIncluded = includeEntries; DerValue in = new DerValue(crlData); parse(in, includeEntries); signedCRL = crlData; } catch (IOException e) { throw new CRLException("Parsing error: " + e.getMessage()); } } /** * Unmarshals an X.509 CRL from an input stream. Only one CRL * is expected at the end of the input stream. * * @param inStrm an input stream holding at least one CRL * @exception CRLException on parsing errors. * @exception X509ExtensionException on extension handling errors. */ public X509CRLImpl(InputStream inStrm) throws CRLException, X509ExtensionException { try { DerValue val = new DerValue(inStrm); parse(val); signedCRL = val.toByteArray(); } catch (IOException e) { throw new CRLException("Parsing error: " + e.getMessage()); } } /** * Initial CRL constructor, no revoked certs, and no extensions. * * @param issuer the name of the CA issuing this CRL. * @param thisUpdate the Date of this issue. * @param nextUpdate the Date of the next CRL. */ public X509CRLImpl(X500Name issuer, Date thisDate, Date nextDate) { this.issuer = issuer; this.thisUpdate = thisDate; this.nextUpdate = nextDate; } /** * CRL constructor, revoked certs, no extensions. * * @param issuer the name of the CA issuing this CRL. * @param thisUpdate the Date of this issue. * @param nextUpdate the Date of the next CRL. * @param badCerts the array of revoked certificates. * * @exception CRLException on parsing/construction errors. * @exception X509ExtensionException on extension handling errors. */ public X509CRLImpl(X500Name issuer, Date thisDate, Date nextDate, RevokedCertificate[] badCerts) throws CRLException, X509ExtensionException { this.issuer = issuer; this.thisUpdate = thisDate; this.nextUpdate = nextDate; if (badCerts != null) { for (int i = 0; i < badCerts.length; i++) this.revokedCerts.put(badCerts[i].getSerialNumber(), badCerts[i]); } } /** * CRL constructor, revoked certs and extensions. * * @param issuer the name of the CA issuing this CRL. * @param thisUpdate the Date of this issue. * @param nextUpdate the Date of the next CRL. * @param badCerts the array of revoked certificates. * @param crlExts the CRL extensions. * * @exception CRLException on parsing/construction errors. * @exception X509ExtensionException on extension handling errors. */ public X509CRLImpl(X500Name issuer, Date thisDate, Date nextDate, RevokedCertificate[] badCerts, CRLExtensions crlExts) throws CRLException, X509ExtensionException { this.issuer = issuer; this.thisUpdate = thisDate; this.nextUpdate = nextDate; if (badCerts != null) { for (int i = 0; i < badCerts.length; i++) { if (badCerts[i] != null) { this.revokedCerts.put(badCerts[i].getSerialNumber(), badCerts[i]); if (badCerts[i].hasExtensions()) this.version = 1; } } } if (crlExts != null) { this.extensions = crlExts; this.version = 1; } } /** * CRL constructor, revoked certs and extensions. * This will be used by code that constructs CRL and uses * encodeInfo() in order to sign it using external means * (other than sign() method) * * @param issuer the name of the CA issuing this CRL. * @param sigAlg signing algorithm id * @param thisUpdate the Date of this issue. * @param nextUpdate the Date of the next CRL. * @param badCerts the array of revoked certificates. * @param crlExts the CRL extensions. */ public X509CRLImpl(X500Name issuer, AlgorithmId algId, Date thisDate, Date nextDate, RevokedCertificate[] badCerts, CRLExtensions crlExts) throws CRLException, X509ExtensionException { this(issuer, thisDate, nextDate, badCerts, crlExts); infoSigAlgId = algId; } /** * CRL constructor, revoked certs and extensions. * * @param issuer the name of the CA issuing this CRL. * @param sigAlg signing algorithm id * @param thisUpdate the Date of this issue. * @param nextUpdate the Date of the next CRL. * @param badCerts the hashtable of revoked certificates. * @param crlExts the CRL extensions. * * @exception CRLException on parsing/construction errors. * @exception X509ExtensionException on extension handling errors. */ public X509CRLImpl(X500Name issuer, AlgorithmId algId, Date thisDate, Date nextDate, Hashtable badCerts, CRLExtensions crlExts) throws CRLException, X509ExtensionException { this.issuer = issuer; this.thisUpdate = thisDate; this.nextUpdate = nextDate; this.revokedCerts = badCerts; if (crlExts != null) { this.extensions = crlExts; this.version = 1; } infoSigAlgId = algId; } /** * Returns the ASN.1 DER encoded form of this CRL. * * @exception CRLException if an encoding error occurs. */ public byte[] getEncoded() throws CRLException { if (signedCRL == null) throw new CRLException("Null CRL to encode"); byte[] dup = new byte[signedCRL.length]; System.arraycopy(signedCRL, 0, dup, 0, dup.length); return dup; } /** * Returns true if signedCRL was set. * * @param byte array of containing signed CRL. */ public boolean setSignedCRL(byte[] crl) { boolean done = false; if (tbsCertList != null && signedCRL == null) { signedCRL = new byte[crl.length]; System.arraycopy(crl, 0, signedCRL, 0, signedCRL.length); done = true; } return done; } public boolean hasUnsupportedCriticalExtension() { // XXX NOT IMPLEMENTED return true; } /** * Encodes the "to-be-signed" CRL to the OutputStream. * * @param out the OutputStream to write to. * @exception CRLException on encoding errors. * @exception X509ExtensionException on extension encoding errors. */ public void encodeInfo(OutputStream out) throws CRLException, X509ExtensionException { try (DerOutputStream seq = new DerOutputStream()) { DerOutputStream tmp = new DerOutputStream(); DerOutputStream rCerts = new DerOutputStream(); if (version != 0) // v2 crl encode version tmp.putInteger(new BigInt(version)); infoSigAlgId.encode(tmp); issuer.encode(tmp); // from 2050 should encode GeneralizedTime tmp.putUTCTime(thisUpdate); if (nextUpdate != null) tmp.putUTCTime(nextUpdate); if (!revokedCerts.isEmpty()) { for (Enumeration e = revokedCerts.elements(); e.hasMoreElements();) ((RevokedCertImpl) e.nextElement()).encode(rCerts); tmp.write(DerValue.tag_Sequence, rCerts); } if (extensions != null) extensions.encode(tmp, isExplicit); seq.write(DerValue.tag_Sequence, tmp); tbsCertList = seq.toByteArray(); out.write(tbsCertList); } catch (IOException e) { throw new CRLException("Encoding error: " + e.getMessage()); } } /** * Verifies that this CRL was signed using the * private key that corresponds to the specified public key. * * @param key the PublicKey used to carry out the verification. * * @exception NoSuchAlgorithmException on unsupported signature * algorithms. * @exception InvalidKeyException on incorrect key. * @exception NoSuchProviderException if there's no default provider. * @exception SignatureException on signature errors. * @exception CRLException on encoding errors. */ public void verify(PublicKey key) throws CRLException, NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException, SignatureException { String sigProvider = null; verify(key, sigProvider); } /** * Verifies that this CRL was signed using the * private key that corresponds to the specified public key, * and that the signature verification was computed by * the given provider. * * @param key the PublicKey used to carry out the verification. * @param sigProvider the name of the signature provider. * * @exception NoSuchAlgorithmException on unsupported signature * algorithms. * @exception InvalidKeyException on incorrect key. * @exception NoSuchProviderException on incorrect provider. * @exception SignatureException on signature errors. * @exception CRLException on encoding errors. */ public void verify(PublicKey key, String sigProvider) throws CRLException, NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException, SignatureException { if (signedCRL == null) { throw new CRLException("Uninitialized CRL"); } Signature sigVerf = null; String sigAlg = sigAlgId.getName(); if (sigProvider != null && sigProvider.equals("Mozilla-JSS")) { if (sigAlg.equals("MD5withRSA")) { sigAlg = "MD5/RSA"; } else if (sigAlg.equals("MD2withRSA")) { sigAlg = "MD2/RSA"; } else if (sigAlg.equals("SHA1withRSA")) { sigAlg = "SHA1/RSA"; } else if (sigAlg.equals("SHA1withDSA")) { sigAlg = "SHA1/DSA"; } else if (sigAlg.equals("SHA1withEC")) { sigAlg = "SHA1/EC"; } else if (sigAlg.equals("SHA256withRSA")) { sigAlg = "SHA256/RSA"; } else if (sigAlg.equals("SHA384withRSA")) { sigAlg = "SHA384/RSA"; } else if (sigAlg.equals("SHA512withRSA")) { sigAlg = "SHA512/RSA"; } else if (sigAlg.equals("SHA256withEC")) { sigAlg = "SHA256/EC"; } else if (sigAlg.equals("SHA384withEC")) { sigAlg = "SHA384/EC"; } else if (sigAlg.equals("SHA512withEC")) { sigAlg = "SHA512/EC"; } } sigVerf = Signature.getInstance(sigAlg, sigProvider); sigVerf.initVerify(key); if (tbsCertList == null) throw new CRLException("Uninitialized CRL"); sigVerf.update(tbsCertList, 0, tbsCertList.length); if (!sigVerf.verify(signature)) { throw new CRLException("Signature does not match."); } } /** * Encodes an X.509 CRL, and signs it using the key * passed. * * @param key the private key used for signing. * @param algorithm the name of the signature algorithm used. * * @exception NoSuchAlgorithmException on unsupported signature * algorithms. * @exception InvalidKeyException on incorrect key. * @exception NoSuchProviderException on incorrect provider. * @exception SignatureException on signature errors. * @exception CRLException if any mandatory data was omitted. * @exception X509ExtensionException on any extension errors. */ public void sign(PrivateKey key, String algorithm) throws CRLException, NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException, SignatureException, X509ExtensionException { sign(key, algorithm, null); } /** * Encodes an X.509 CRL, and signs it using the key * passed. * * @param key the private key used for signing. * @param algorithm the name of the signature algorithm used. * @param provider the name of the provider. * * @exception NoSuchAlgorithmException on unsupported signature * algorithms. * @exception InvalidKeyException on incorrect key. * @exception NoSuchProviderException on incorrect provider. * @exception SignatureException on signature errors. * @exception CRLException if any mandatory data was omitted. * @exception X509ExtensionException on any extension errors. */ public void sign(PrivateKey key, String algorithm, String provider) throws CRLException, NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException, SignatureException, X509ExtensionException { try (DerOutputStream out = new DerOutputStream()){ if (readOnly) throw new CRLException("cannot over-write existing CRL"); Signature sigEngine = null; if (provider == null) sigEngine = Signature.getInstance(algorithm); else sigEngine = Signature.getInstance(algorithm, provider); sigEngine.initSign(key); // in case the name is reset sigAlgId = AlgorithmId.get(sigEngine.getAlgorithm()); infoSigAlgId = sigAlgId; DerOutputStream tmp = new DerOutputStream(); // encode crl info encodeInfo(tmp); // encode algorithm identifier sigAlgId.encode(tmp); // Create and encode the signature itself. sigEngine.update(tbsCertList, 0, tbsCertList.length); signature = sigEngine.sign(); tmp.putBitString(signature); // Wrap the signed data in a SEQUENCE { data, algorithm, sig } out.write(DerValue.tag_Sequence, tmp); signedCRL = out.toByteArray(); readOnly = true; } catch (IOException e) { throw new CRLException("Error while encoding data: " + e.getMessage()); } } /** * Returns a printable string of this CRL. * * @return value of this CRL in a printable form. */ public String toString() { StringBuffer sb = new StringBuffer("X.509 CRL v" + (version + 1) + "\n" + "Signature Algorithm: " + sigAlgId + ", OID=" + sigAlgId.getOID() + "\n" + "Issuer: " + issuer + "\n" + "\nThis Update: " + thisUpdate + "\n"); if (nextUpdate != null) sb.append("Next Update: " + nextUpdate + "\n"); if (revokedCerts.isEmpty()) sb.append("\nNO certificates have been revoked\n"); else { sb.append("\nRevoked Certificates:\n"); for (Enumeration e = revokedCerts.elements(); e.hasMoreElements();) sb.append(e.nextElement()); } if (extensions != null) { for (int i = 0; i < extensions.size(); i++) { sb.append("\nCRL Extension[" + i + "]: " + extensions.elementAt(i)); } } netscape.security.util.PrettyPrintFormat pp = new netscape.security.util.PrettyPrintFormat(" ", 20); String signaturebits = pp.toHexString(signature); sb.append("\nSignature:\n" + signaturebits); return sb.toString(); } /** * Checks whether the given serial number is on this CRL. * * @param serialNumber the number to check for. * @return true if the given serial number is on this CRL, * false otherwise. */ public boolean isRevoked(BigInteger serialNumber) { if (revokedCerts == null || revokedCerts.isEmpty()) return false; return revokedCerts.containsKey(serialNumber); } public boolean isRevoked(Certificate cert) { if (cert == null) return false; if (cert instanceof X509Certificate) { return isRevoked(((X509Certificate) cert).getSerialNumber()); } else { return false; } } /** * Gets the version number from the CRL. * The ASN.1 definition for this is: * *
     * Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
     *             -- v3 does not apply to CRLs but appears for consistency
     *             -- with definition of Version for certs
     * 
* * @return the version number. */ public int getVersion() { return version; } /** * Gets the issuer distinguished name from this CRL. * The issuer name identifies the entity who has signed (and * issued the CRL). The issuer name field contains an * X.500 distinguished name (DN). * The ASN.1 definition for this is: * *
     * issuer    Name
     *
     * Name ::= CHOICE { RDNSequence }
     * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
     * RelativeDistinguishedName ::=
     *     SET OF AttributeValueAssertion
     *
     * AttributeValueAssertion ::= SEQUENCE {
     *                               AttributeType,
     *                               AttributeValue }
     * AttributeType ::= OBJECT IDENTIFIER
     * AttributeValue ::= ANY
     * 
* * The Name describes a hierarchical name composed of attributes, * such as country name, and corresponding values, such as US. * The type of the component AttributeValue is determined by the * AttributeType; in general it will be a directoryString. * A directoryString is usually one of PrintableString, * TeletexString or UniversalString. * * @return the issuer name. */ public Principal getIssuerDN() { return issuer; } /** * Gets the thisUpdate date from the CRL. * The ASN.1 definition for this is: * * @return the thisUpdate date from the CRL. */ public Date getThisUpdate() { return (new Date(thisUpdate.getTime())); } /** * Gets the nextUpdate date from the CRL. * * @return the nextUpdate date from the CRL, or null if * not present. */ public Date getNextUpdate() { if (nextUpdate == null) return null; return (new Date(nextUpdate.getTime())); } /** * Get the revoked certificate from the CRL by the serial * number provided. * * @return the revoked certificate or null if there is * no entry in the CRL marked with the provided serial number. * @see RevokedCertificate */ public X509CRLEntry getRevokedCertificate(BigInteger serialNumber) { if (revokedCerts == null || revokedCerts.isEmpty()) return null; return revokedCerts.get(serialNumber); } /** * Gets all the revoked certificates from the CRL. * A Set of RevokedCertificate. * * @return all the revoked certificates or null if there are * none. * @see RevokedCertificate */ public Set getRevokedCertificates() { if (revokedCerts == null || revokedCerts.isEmpty()) return null; else { Set certSet = new LinkedHashSet(revokedCerts.values()); return certSet; } } @SuppressWarnings("unchecked") public Hashtable getListOfRevokedCertificates() { if (revokedCerts == null) { return null; } else { return (Hashtable) revokedCerts.clone(); } } public int getNumberOfRevokedCertificates() { if (revokedCerts == null) return -1; else return revokedCerts.size(); } /** * Gets the DER encoded CRL information, the tbsCertList from this CRL. * This can be used to verify the signature independently. * * @return the DER encoded CRL information. * @exception CRLException on parsing errors. * @exception X509ExtensionException on extension parsing errors. */ public byte[] getTBSCertList() throws CRLException { if (tbsCertList == null) throw new CRLException("Uninitialized CRL"); byte[] dup = new byte[tbsCertList.length]; System.arraycopy(tbsCertList, 0, dup, 0, dup.length); return dup; } /** * Gets the raw Signature bits from the CRL. * * @return the signature. */ public byte[] getSignature() { if (signature == null) return null; byte[] dup = new byte[signature.length]; System.arraycopy(signature, 0, dup, 0, dup.length); return dup; } /** * Returns true if signature was set. * * @param byte array of containing CRL signature. */ public boolean setSignature(byte[] crlSignature) { boolean done = false; if (tbsCertList != null && signature == null) { signature = new byte[crlSignature.length]; System.arraycopy(crlSignature, 0, signature, 0, signature.length); done = true; } return done; } /** * Gets the signature algorithm name for the CRL * signature algorithm. For example, the string "SHA1withDSA". * The ASN.1 definition for this is: * *
     * AlgorithmIdentifier  ::=  SEQUENCE  {
     *     algorithm               OBJECT IDENTIFIER,
     *     parameters              ANY DEFINED BY algorithm OPTIONAL  }
     *                             -- contains a value of the type
     *                             -- registered for use with the
     *                             -- algorithm object identifier value
     * 
* * @return the signature algorithm name. */ public String getSigAlgName() { if (sigAlgId == null) return null; return sigAlgId.getName(); } /** * Gets the signature algorithm OID string from the CRL. * An OID is represented by a set of positive whole number separated * by ".", that means,
* <positive whole number>.<positive whole number>.<...> * For example, the string "1.2.840.10040.4.3" identifies the SHA-1 * with DSA signature algorithm, as per the PKIX part I. * * @return the signature algorithm oid string. */ public String getSigAlgOID() { if (sigAlgId == null) return null; ObjectIdentifier oid = sigAlgId.getOID(); return oid.toString(); } /** * Gets the DER encoded signature algorithm parameters from this * CRL's signature algorithm. In most cases, the signature * algorithm parameters are null, the parameters are usually * supplied with the Public Key. * * @return the DER encoded signature algorithm parameters, or * null if no parameters are present. */ public byte[] getSigAlgParams() { if (sigAlgId == null) return null; try { return sigAlgId.getEncodedParams(); } catch (IOException e) { return null; } } /** * Gets a Set of the extension(s) marked CRITICAL in the * CRL by OID strings. * * @return a set of the extension oid strings in the * CRL that are marked critical. */ public Set getCriticalExtensionOIDs() { if (extensions == null) return null; Set extSet = new LinkedHashSet(); Extension ex; for (Enumeration e = extensions.getElements(); e.hasMoreElements();) { ex = e.nextElement(); if (ex.isCritical()) { extSet.add(ex.getExtensionId().toString()); } } return extSet; } /** * Gets a Set of the extension(s) marked NON-CRITICAL in the * CRL by OID strings. * * @return a set of the extension oid strings in the * CRL that are NOT marked critical. */ public Set getNonCriticalExtensionOIDs() { if (extensions == null) return null; Set extSet = new LinkedHashSet(); Extension ex; for (Enumeration e = extensions.getElements(); e.hasMoreElements();) { ex = e.nextElement(); if (!ex.isCritical()) extSet.add(ex.getExtensionId().toString()); } return extSet; } /** * Gets the DER encoded OCTET string for the extension value * (extnValue) identified by the passed in oid String. * The oid string is * represented by a set of positive whole number separated * by ".", that means,
* <positive whole number>.<positive whole number>.<...> * * @param oid the Object Identifier value for the extension. * @return the der encoded octet string of the extension value. */ public byte[] getExtensionValue(String oid) { if (extensions == null) return null; try (DerOutputStream out = new DerOutputStream()) { String extAlias = OIDMap.getName(new ObjectIdentifier(oid)); Extension crlExt = null; if (extAlias == null) { // may be unknown ObjectIdentifier findOID = new ObjectIdentifier(oid); Extension ex = null; ObjectIdentifier inCertOID; for (Enumeration e = extensions.getElements(); e.hasMoreElements();) { ex = e.nextElement(); inCertOID = ex.getExtensionId(); if (inCertOID.equals(findOID)) { crlExt = ex; break; } } } else crlExt = extensions.get(extAlias); if (crlExt == null) return null; byte[] extData = crlExt.getExtensionValue(); if (extData == null) return null; out.putOctetString(extData); return out.toByteArray(); } catch (Exception e) { return null; } } public BigInteger getCRLNumber() { try { CRLExtensions exts = getExtensions(); if (exts == null) return null; Enumeration e = exts.getElements(); while (e.hasMoreElements()) { Extension ext = e.nextElement(); if (ext instanceof CRLNumberExtension) { CRLNumberExtension numExt = (CRLNumberExtension) ext; return (BigInteger) numExt.get(CRLNumberExtension.NUMBER); } } } catch (Exception e) { } return null; } public BigInteger getDeltaBaseCRLNumber() { try { CRLExtensions exts = getExtensions(); if (exts == null) return null; Enumeration e = exts.getElements(); while (e.hasMoreElements()) { Extension ext = e.nextElement(); if (ext instanceof DeltaCRLIndicatorExtension) { DeltaCRLIndicatorExtension numExt = (DeltaCRLIndicatorExtension) ext; return (BigInteger) numExt.get(DeltaCRLIndicatorExtension.NUMBER); } } } catch (Exception e) { } return null; } public boolean isDeltaCRL() { try { CRLExtensions exts = getExtensions(); if (exts == null) return false; Enumeration e = exts.getElements(); while (e.hasMoreElements()) { Extension ext = e.nextElement(); if (ext instanceof DeltaCRLIndicatorExtension) { return true; } } } catch (Exception e) { } return false; } /** * Returns extensions for this impl. * * @param extn CRLExtensions */ public CRLExtensions getExtensions() { return extensions; } public boolean areEntriesIncluded() { return entriesIncluded; } /*********************************************************************/ /* * Parses an X.509 CRL, should be used only by constructors. */ private void parse(DerValue val) throws CRLException, IOException, X509ExtensionException { parse(val, true); } private void parse(DerValue val, boolean includeEntries) throws CRLException, IOException, X509ExtensionException { // check if can over write the certificate if (readOnly) throw new CRLException("cannot over-write existing CRL"); readOnly = true; DerValue seq[] = new DerValue[3]; seq[0] = val.data.getDerValue(); seq[1] = val.data.getDerValue(); seq[2] = val.data.getDerValue(); if (val.data.available() != 0) throw new CRLException("signed overrun, bytes = " + val.data.available()); if (seq[0].tag != DerValue.tag_Sequence) throw new CRLException("signed CRL fields invalid"); sigAlgId = AlgorithmId.parse(seq[1]); signature = seq[2].getBitString(); if (seq[1].data.available() != 0) throw new CRLException("AlgorithmId field overrun"); if (seq[2].data.available() != 0) throw new CRLException("Signature field overrun"); // the tbsCertsList tbsCertList = seq[0].toByteArray(); // parse the information DerInputStream derStrm = seq[0].data; DerValue tmp; byte nextByte; // version (optional if v1) version = 0; // by default, version = v1 == 0 nextByte = (byte) derStrm.peekByte(); if (nextByte == DerValue.tag_Integer) { version = derStrm.getInteger().toInt(); if (version != 1) // i.e. v2 throw new CRLException("Invalid version"); } tmp = derStrm.getDerValue(); // signature { AlgorithmId tmpId = AlgorithmId.parse(tmp); if (!tmpId.equals(sigAlgId)) throw new CRLException("Signature algorithm mismatch"); infoSigAlgId = tmpId; } // issuer issuer = new X500Name(derStrm); // thisUpdate // check if UTCTime encoded or GeneralizedTime nextByte = (byte) derStrm.peekByte(); if (nextByte == DerValue.tag_UtcTime) { thisUpdate = derStrm.getUTCTime(); } else if (nextByte == DerValue.tag_GeneralizedTime) { thisUpdate = derStrm.getGeneralizedTime(); } else { throw new CRLException("Invalid encoding for thisUpdate" + " (tag=" + nextByte + ")"); } if (derStrm.available() == 0) return; // done parsing no more optional fields present // nextUpdate (optional) nextByte = (byte) derStrm.peekByte(); if (nextByte == DerValue.tag_UtcTime) { nextUpdate = derStrm.getUTCTime(); } else if (nextByte == DerValue.tag_GeneralizedTime) { nextUpdate = derStrm.getGeneralizedTime(); } // else it is not present if (derStrm.available() == 0) return; // done parsing no more optional fields present // revokedCertificates (optional) nextByte = (byte) derStrm.peekByte(); if ((nextByte == DerValue.tag_SequenceOf) && (!((nextByte & 0x0c0) == 0x080))) { if (includeEntries) { DerValue[] badCerts = derStrm.getSequence(4); for (int i = 0; i < badCerts.length; i++) { RevokedCertImpl entry = new RevokedCertImpl(badCerts[i]); if (entry.hasExtensions() && (version == 0)) throw new CRLException("Invalid encoding, extensions" + " not supported in CRL v1 entries."); revokedCerts.put(entry.getSerialNumber(), entry); } } else { derStrm.skipSequence(4); } } if (derStrm.available() == 0) return; // done parsing no extensions // crlExtensions (optional) tmp = derStrm.getDerValue(); if (tmp.isConstructed() && tmp.isContextSpecific((byte) 0)) { if (version == 0) throw new CRLException("Invalid encoding, extensions not" + " supported in CRL v1."); extensions = new CRLExtensions(tmp.data); } } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 28828 Content-Disposition: inline; filename="X509Cert.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "51aff172c1c730c36e7cd9ad1943a9caf8e79c1c" // --- 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.x509; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.OutputStream; import java.io.Serializable; import java.security.Certificate; import java.security.InvalidKeyException; import java.security.Key; import java.security.NoSuchAlgorithmException; import java.security.Principal; import java.security.PrivateKey; import java.security.PublicKey; import java.security.Signature; import java.security.SignatureException; import java.util.Date; import netscape.security.util.BigInt; import netscape.security.util.DerInputStream; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; /** * @author David Brownell * @version 1.5 * * @see CertAndKeyGen * @deprecated Use the new X509Certificate class. * This class is only restored for backwards compatibility. */ public class X509Cert implements Certificate, Serializable { /** * */ private static final long serialVersionUID = -6968141532738786900L; /* The algorithm id */ protected AlgorithmId algid; /** * Construct a uninitialized X509 Cert on which * decode must later be called (or which may be deserialized). */ // XXX deprecated, delete this public X509Cert() { } /** * Unmarshals a certificate from its encoded form, parsing the * encoded bytes. This form of constructor is used by agents which * need to examine and use certificate contents. That is, this is * one of the more commonly used constructors. Note that the buffer * must include only a certificate, and no "garbage" may be left at * the end. If you need to ignore data at the end of a certificate, * use another constructor. * * @param cert the encoded bytes, with no terminatu (CONSUMED) * @exception IOException when the certificate is improperly encoded. */ public X509Cert( byte cert[]) throws IOException { DerValue in = new DerValue(cert); parse(in); if (in.data.available() != 0) throw new CertParseError("garbage at end"); signedCert = cert; } /** * Unmarshals a certificate from its encoded form, parsing the * encoded bytes. This form of constructor is used by agents which * need to examine and use certificate contents. That is, this is * one of the most commonly used constructors. * * @param buf the buffer holding the encoded bytes * @param offset the offset in the buffer where the bytes begin * @param len how many bytes of certificate exist * * @exception IOException when the certificate is improperly encoded. */ public X509Cert( byte buf[], int offset, int len) throws IOException { DerValue in = new DerValue(buf, offset, len); parse(in); if (in.data.available() != 0) throw new CertParseError("garbage at end"); signedCert = new byte[len]; System.arraycopy(buf, offset, signedCert, 0, len); } /** * Unmarshal a certificate from its encoded form, parsing a DER value. * This form of constructor is used by agents which need to examine * and use certificate contents. * * @param derVal the der value containing the encoded cert. * @exception IOException when the certificate is improperly encoded. */ public X509Cert(DerValue derVal) throws IOException { parse(derVal); if (derVal.data.available() != 0) throw new CertParseError("garbage at end"); signedCert = derVal.toByteArray(); } /** * Partially constructs a certificate from descriptive parameters. * This constructor may be used by Certificate Authority (CA) code, * which later signs and encodes the * certificate. Also, self-signed certificates serve as CA certificates, * and are sometimes used as certificate requests. * *

* Until the certificate has been signed and encoded, some of the mandatory fields in the certificate will not be * available via accessor functions: the serial number, issuer name and signing algorithm, and of course the signed * certificate. The fields passed to this constructor are available, and must be non-null. * *

* Note that the public key being signed is generally independent of the signature algorithm being used. So for * example Diffie-Hellman keys (which do not support signatures) can be placed in X.509 certificates when some other * signature algorithm (e.g. DSS/DSA, or one of the RSA based algorithms) is used. * * @see CertAndKeyGen * * @param subjectName the X.500 distinguished name being certified * @param subjectPublicKey the public key being certified. This * must be an "X509Key" implementing the "PublicKey" interface. * @param notBefore the first time the certificate is valid * @param notAfter the last time the certificate is valid * * @exception CertException if the public key is inappropriate */ public X509Cert( X500Name subjectName, X509Key subjectPublicKey, Date notBefore, Date notAfter) throws CertException { subject = subjectName; if (subjectPublicKey == null) throw new CertException(CertException.err_INVALID_PUBLIC_KEY, "Public Key is NULL"); /* * The X509 cert API requires X509 keys, else things break. */ pubkey = subjectPublicKey; notbefore = notBefore; notafter = notAfter; version = 0; } /** * Decode an X.509 certificate from an input stream. * * @param in an input stream holding at least one certificate * @exception IOException when the certificate is improperly encoded. */ public void decode(InputStream in) throws IOException { DerValue val = new DerValue(in); parse(val); if (val.data.available() != 0) throw new CertParseError("garbage at end"); signedCert = val.toByteArray(); } /** * Appends the certificate to an output stream. * * @param out an input stream to which the certificate is appended. * @exception IOException when appending fails. */ public void encode(OutputStream out) throws IOException { out.write(getSignedCert()); } /** * Compares two certificates. This is false if the * certificates are not both X.509 certs, otherwise it * compares them as binary data. * * @param other the object being compared with this one * @return true iff the certificates are equivalent */ public boolean equals(Object other) { if (other instanceof X509Cert) return equals((X509Cert) other); else return false; } /** * Compares two certificates, returning false if any data * differs between the two. * * @param other the object being compared with this one * @return true iff the certificates are equivalent */ public boolean equals(X509Cert src) { if (this == src) return true; if (signedCert == null || src.signedCert == null) return false; if (signedCert.length != src.signedCert.length) return false; for (int i = 0; i < signedCert.length; i++) if (signedCert[i] != src.signedCert[i]) return false; return true; } /** Returns the "X.509" format identifier. */ public String getFormat() // for Certificate { return "X.509"; } /** Returns getIssuerName */ public Principal getGuarantor() // for Certificate { return getIssuerName(); } /** Returns getSubjectName */ public Principal getPrincipal() { return getSubjectName(); } /** * Throws an exception if the certificate is invalid because it is * now outside of the certificate's validity period, or because it * was not signed using the verification key provided. Successfully * verifying a certificate does not indicate that one should * trust the entity which it represents. * *

* Note that since this class represents only a single X.509 * certificate, it cannot know anything about the certificate chain * which is used to provide the verification key and to establish trust. * Other code must manage and use those cert chains. * *

For now, you must walk the cert chain being used to verify any * given cert. Start at the root, which is a self-signed certificate; * verify it using the key inside the certificate. Then use that to * verify the next certificate in the chain, issued by that CA. In * this manner, verify each certificate until you reach the particular * certificate you wish to verify. You should not use a certificate * if any of the verification operations for its certificate chain * were unsuccessful. * * * @param issuerPublicKey the public key of the issuing CA * @exception CertException when the certificate is not valid. */ public void verify(PublicKey issuerPublicKey) throws CertException { Date now = new Date(); if (now.before(notbefore)) throw new CertException(CertException.verf_INVALID_NOTBEFORE); if (now.after(notafter)) throw new CertException(CertException.verf_INVALID_EXPIRED); if (signedCert == null) throw new CertException(CertException.verf_INVALID_SIG, "?? certificate is not signed yet ??"); // // Verify the signature ... // String algName = null; try { Signature sigVerf = null; algName = issuerSigAlg.getName(); sigVerf = Signature.getInstance(algName); sigVerf.initVerify(issuerPublicKey); sigVerf.update(rawCert, 0, rawCert.length); if (!sigVerf.verify(signature)) { throw new CertException(CertException.verf_INVALID_SIG, "Signature ... by <" + issuer + "> for <" + subject + ">"); } // Gag -- too many catch clauses, let most through. } catch (NoSuchAlgorithmException e) { throw new CertException(CertException.verf_INVALID_SIG, "Unsupported signature algorithm (" + algName + ")"); } catch (InvalidKeyException e) { // e.printStackTrace(); throw new CertException(CertException.err_INVALID_PUBLIC_KEY, "Algorithm (" + algName + ") rejected public key"); } catch (SignatureException e) { throw new CertException(CertException.verf_INVALID_SIG, "Signature by <" + issuer + "> for <" + subject + ">"); } } /** * Creates an X.509 certificate, and signs it using the issuer * passed (associating a signature algorithm and an X.500 name). * This operation is used to implement the certificate generation * functionality of a certificate authority. * * @see #getSignedCert * @see #getSigner * @see CertAndKeyGen * * @param serial the serial number of the certificate (non-null) * @param issuer the certificate issuer (CA) (non-null) * @return the signed certificate, as returned by getSignedCert * * @exception IOException if any of the data could not be encoded, * or when any mandatory data was omitted * @exception SignatureException on signing failures */ public byte[] encodeAndSign( BigInt serial, X500Signer issuer ) throws IOException, SignatureException { rawCert = null; /* * Get the remaining cert parameters, and make sure we have enough. * * We deduce version based on what attribute data are available * For now, we have no attributes, so we always deduce X.509v1 ! */ version = 0; serialnum = serial; this.issuer = issuer.getSigner(); issuerSigAlg = issuer.getAlgorithmId(); if (subject == null || pubkey == null || notbefore == null || notafter == null) throw new IOException("not enough cert parameters"); /* * Encode the raw cert, create its signature and put it * into the envelope. */ rawCert = DERencode(); signedCert = sign(issuer, rawCert); return signedCert; } /** * Returns an X500Signer that may be used to create signatures. Those * signature may in turn be verified using this certificate (or a * copy of it). * *

* NOTE: If the private key is by itself capable of * creating signatures, this fact may not be recognized at this time. * Specifically, the case of DSS/DSA keys which get their algorithm * parameters from higher in the certificate chain is not supportable * without using an X509CertChain API, and there is no current support * for other sources of algorithm parameters. * * @param algorithm the signature algorithm to be used. Note that a * given public/private key pair may support several such algorithms. * @param privateKey the private key used to create the signature, * which must correspond to the public key in this certificate * @return the Signer object * * @exception NoSuchAlgorithmException if the signature * algorithm is not supported * @exception InvalidKeyException if either the key in the certificate, * or the private key parameter, does not support the requested * signature algorithm */ public X500Signer getSigner(AlgorithmId algorithmId, PrivateKey privateKey) throws NoSuchAlgorithmException, InvalidKeyException { String algorithm; Signature sig; if (privateKey != null) { Key key = privateKey; algorithm = key.getAlgorithm(); } else { throw new InvalidKeyException("Private Key is NULL"); } sig = Signature.getInstance(algorithmId.getName()); if (!pubkey.getAlgorithm().equals(algorithm)) { throw new InvalidKeyException("Private key algorithm " + algorithm + " incompatible with certificate " + pubkey.getAlgorithm()); } sig.initSign(privateKey); return new X500Signer(sig, subject); } /** * Returns a signature object that may be used to verify signatures * created using a specified signature algorithm and the public key * contained in this certificate. * *

* NOTE: If the public key in this certificate is not by * itself capable of verifying signatures, this may not be recognized * at this time. Specifically, the case of DSS/DSA keys which get * their algorithm parameters from higher in the certificate chain * is not supportable without using an X509CertChain API, and there * is no current support for other sources of algorithm parameters. * * @param algorithm the algorithm of the signature to be verified * @return the Signature object * @exception NoSuchAlgorithmException if the signature * algorithm is not supported * @exception InvalidKeyException if the key in the certificate * does not support the requested signature algorithm */ public Signature getVerifier(String algorithm) throws NoSuchAlgorithmException, InvalidKeyException { Signature sig; sig = Signature.getInstance(algorithm); sig.initVerify(pubkey); return sig; } /** * Return the signed X.509 certificate as a byte array. * The bytes are in standard DER marshaled form. * Null is returned in the case of a partially constructed cert. */ public byte[] getSignedCert() { return signedCert; } /** * Returns the certificate's serial number. * Null is returned in the case of a partially constructed cert. */ public BigInt getSerialNumber() { return serialnum; } /** * Returns the subject's X.500 distinguished name. */ public X500Name getSubjectName() { return subject; } /** * Returns the certificate issuer's X.500 distinguished name. * Null is returned in the case of a partially constructed cert. */ public X500Name getIssuerName() { return issuer; } /** * Returns the algorithm used by the issuer to sign the certificate. * Null is returned in the case of a partially constructed cert. */ public AlgorithmId getIssuerAlgorithmId() { return issuerSigAlg; } /** * Returns the first time the certificate is valid. */ public Date getNotBefore() { return notbefore; } /** * Returns the last time the certificate is valid. */ public Date getNotAfter() { return notafter; } /** * Returns the subject's public key. Note that some public key * algorithms support an optional certificate generation policy * where the keys in the certificates are not in themselves sufficient * to perform a public key operation. Those keys need to be augmented * by algorithm parameters, which the certificate generation policy * chose not to place in the certificate. * *

* Two such public key algorithms are: DSS/DSA, where algorithm parameters could be acquired from a CA certificate * in the chain of issuers; and Diffie-Hellman, with a similar solution although the CA then needs both a * Diffie-Hellman certificate and a signature capable certificate. */ public PublicKey getPublicKey() { return pubkey; } /** * Returns the X.509 version number of this certificate, zero based. * That is, "2" indicates an X.509 version 3 (1993) certificate, * and "0" indicates X.509v1 (1988). * Zero is returned in the case of a partially constructed cert. */ public int getVersion() { return version; } /** * Calculates a hash code value for the object. Objects * which are equal will also have the same hashcode. */ public int hashCode() { int retval = 0; for (int i = 0; i < signedCert.length; i++) retval += signedCert[i] * i; return retval; } /** * Returns a printable representation of the certificate. This does not * contain all the information available to distinguish this from any * other certificate. The certificate must be fully constructed * before this function may be called; in particular, if you are * creating certificates you must call encodeAndSign() before calling * this function. */ public String toString() { String s; if (subject == null || pubkey == null || notbefore == null || notafter == null || issuer == null || issuerSigAlg == null || serialnum == null) throw new NullPointerException("X.509 cert is incomplete"); s = " X.509v" + (version + 1) + " certificate,\n"; s += " Subject is " + subject + "\n"; s += " Key: " + pubkey; s += " Validity <" + notbefore + "> until <" + notafter + ">\n"; s += " Issuer is " + issuer + "\n"; s += " Issuer signature used " + issuerSigAlg.toString() + "\n"; s += " Serial number = " + serialnum + "\n"; // optional v2, v3 extras return "[\n" + s + "]"; } /** * Returns a printable representation of the certificate. * * @param detailed true iff lots of detail is requested */ public String toString(boolean detailed) { return toString(); } /* * Certificate data, and its envelope */ private byte rawCert[]; private byte signature[]; private byte signedCert[]; /* * X509.v1 data (parsed) */ private X500Name subject; // from subject private X509Key pubkey; private Date notafter; // from CA (constructor) private Date notbefore; private int version; // from CA (signAndEncode) private BigInt serialnum; private X500Name issuer; private AlgorithmId issuerSigAlg; /* * X509.v2 extensions */ /* * X509.v3 extensions */ /* * Other extensions ... Netscape, Verisign, SET, etc */ /************************************************************/ /* * Cert is a SIGNED ASN.1 macro, a three elment sequence: * * - Data to be signed (ToBeSigned) -- the "raw" cert * - Signature algorithm (SigAlgId) * - The signature bits * * This routine unmarshals the certificate, saving the signature * parts away for later verification. */ private void parse(DerValue val) throws IOException { DerValue seq[] = new DerValue[3]; seq[0] = val.data.getDerValue(); seq[1] = val.data.getDerValue(); seq[2] = val.data.getDerValue(); if (val.data.available() != 0) throw new CertParseError("signed overrun, bytes = " + val.data.available()); if (seq[0].tag != DerValue.tag_Sequence) throw new CertParseError("signed fields invalid"); rawCert = seq[0].toByteArray(); // XXX slow; fixme! issuerSigAlg = AlgorithmId.parse(seq[1]); signature = seq[2].getBitString(); if (seq[1].data.available() != 0) { // XXX why was this error check commented out? // It was originally part of the next check. throw new CertParseError("algid field overrun"); } if (seq[2].data.available() != 0) throw new CertParseError("signed fields overrun"); /* * Let's have fun parsing the cert itself. */ DerInputStream in; DerValue tmp; in = seq[0].data; /* * Version -- this is optional (default zero). If it's there it's * the first field and is specially tagged. * * Both branches leave "tmp" holding a value for the serial * number that comes next. */ version = 0; tmp = in.getDerValue(); if (tmp.isConstructed() && tmp.isContextSpecific()) { version = tmp.data.getInteger().toInt(); if (tmp.data.available() != 0) throw new IOException("X.509 version, bad format"); tmp = in.getDerValue(); } /* * serial number ... an integer */ serialnum = tmp.getInteger(); /* * algorithm type for CA's signature ... needs to match the * one on the envelope, and that's about it! different IDs * may represent a signature attack. In general we want to * inherit parameters. */ tmp = in.getDerValue(); { AlgorithmId algid; algid = AlgorithmId.parse(tmp); if (!algid.equals(issuerSigAlg)) throw new CertParseError("CA Algorithm mismatch!"); this.algid = algid; } /* * issuer name */ issuer = new X500Name(in); /* * validity: SEQUENCE { start date, end date } */ tmp = in.getDerValue(); if (tmp.tag != DerValue.tag_Sequence) throw new CertParseError("corrupt validity field"); notbefore = tmp.data.getUTCTime(); notafter = tmp.data.getUTCTime(); if (tmp.data.available() != 0) throw new CertParseError("excess validity data"); /* * subject name and public key */ subject = new X500Name(in); tmp = in.getDerValue(); pubkey = X509Key.parse(tmp); /* * XXX for v2 and later, a bunch of tagged options follow */ if (in.available() != 0) { /* * Until we parse V2/V3 data ... ignore it. * // throw new CertParseError ("excess cert data"); System.out.println ( "@end'o'cert, optional V2/V3 data unparsed: " + in.available () + " bytes" ); */ } } /* * Encode only the parts that will later be signed. */ private byte[] DERencode() throws IOException { DerOutputStream raw = new DerOutputStream(); encode(raw); return raw.toByteArray(); } /* * Marshal the contents of a "raw" certificate into a DER sequence. */ private void encode(DerOutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); /* * encode serial number, issuer signing algorithm, * and issuer name into the data we'll return */ tmp.putInteger(serialnum); issuerSigAlg.encode(tmp); issuer.encode(tmp); /* * Validity is a two element sequence ... encode the * elements, then wrap them into the data we'll return */ { DerOutputStream seq = new DerOutputStream(); seq.putUTCTime(notbefore); seq.putUTCTime(notafter); tmp.write(DerValue.tag_Sequence, seq); } /* * Encode subject (principal) and associated key */ subject.encode(tmp); pubkey.encode(tmp); /* * Wrap the data; encoding of the "raw" cert is now complete. */ out.write(DerValue.tag_Sequence, tmp); } /* * Calculate the signature of the "raw" certificate, * and marshal the cert with the signature and a * description of the signing algorithm. */ private byte[] sign(X500Signer issuer, byte data[]) throws IOException, SignatureException { /* * Encode the to-be-signed data, then the algorithm used * to create the signature. */ try (DerOutputStream out = new DerOutputStream()) { DerOutputStream tmp = new DerOutputStream(); tmp.write(data); issuer.getAlgorithmId().encode(tmp); /* * Create and encode the signature itself. */ issuer.update(data, 0, data.length); signature = issuer.sign(); tmp.putBitString(signature); /* * Wrap the signed data in a SEQUENCE { data, algorithm, sig } */ out.write(DerValue.tag_Sequence, tmp); return out.toByteArray(); } } /** * Serialization write ... X.509 certificates serialize as * themselves, and they're parsed when they get read back. * (Actually they serialize as some type data from the * serialization subsystem, then the cert data.) */ private void writeObject(java.io.ObjectOutputStream stream) throws IOException { encode(stream); } /** * Serialization read ... X.509 certificates serialize as * themselves, and they're parsed when they get read back. */ private void readObject(ObjectInputStream stream) throws IOException { decode(stream); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 43929 Content-Disposition: inline; filename="X509CertImpl.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "0ad7724ee0e2be2591e009b0b567da4ca2e0632c" // --- 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.x509; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.OutputStream; import java.io.Serializable; import java.math.BigInteger; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.Principal; import java.security.PrivateKey; import java.security.PublicKey; import java.security.Signature; import java.security.SignatureException; import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateException; import java.security.cert.CertificateExpiredException; import java.security.cert.CertificateFactory; import java.security.cert.CertificateNotYetValidException; import java.security.cert.CertificateParsingException; import java.security.cert.X509Certificate; import java.util.Date; import java.util.Enumeration; import java.util.LinkedHashSet; import java.util.Set; import java.util.Vector; import netscape.security.util.DerEncoder; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; import netscape.security.util.ObjectIdentifier; /** * The X509CertImpl class represents an X.509 certificate. These certificates * are widely used to support authentication and other functionality in * Internet security systems. Common applications include Privacy Enhanced * Mail (PEM), Transport Layer Security (SSL), code signing for trusted * software distribution, and Secure Electronic Transactions (SET). There * is a commercial infrastructure ready to manage large scale deployments * of X.509 identity certificates. * *

* These certificates are managed and vouched for by Certificate * Authorities (CAs). CAs are services which create certificates by placing data in the X.509 standard format and * then digitally signing that data. Such signatures are quite difficult to forge. CAs act as trusted third parties, * making introductions between agents who have no direct knowledge of each other. CA certificates are either signed by * themselves, or by some other CA such as a "root" CA. * *

* RFC 1422 is very informative, though it does not describe much of the recent work being done with X.509 certificates. * That includes a 1996 version (X.509v3) and a variety of enhancements being made to facilitate an explosion of * personal certificates used as "Internet Drivers' Licences", or with SET for credit card transactions. * *

* More recent work includes the IETF PKIX Working Group efforts, especially part 1. * * @author Dave Brownell * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.94 97/12/10 * @see X509CertInfo */ public class X509CertImpl extends X509Certificate implements Serializable, DerEncoder { // Serialization compatibility with the X509CertImpl in x509v1.jar // supporting the subset of X509Certificate on JDK1.1.x platforms. static final long serialVersionUID = -2048442350420423405L; private static final String DOT = "."; /** * Public attribute names. */ public static final String NAME = "x509"; public static final String INFO = X509CertInfo.NAME; public static final String ALG_ID = "algorithm"; public static final String SIGNATURE = "signature"; public static final String SIGNED_CERT = "signed_cert"; /** * The following are defined for ease-of-use. These * are the most frequently retrieved attributes. */ // x509.info.subject.dname public static final String SUBJECT_DN = NAME + DOT + INFO + DOT + X509CertInfo.SUBJECT + DOT + CertificateSubjectName.DN_NAME; // x509.info.issuer.dname public static final String ISSUER_DN = NAME + DOT + INFO + DOT + X509CertInfo.ISSUER + DOT + CertificateIssuerName.DN_NAME; // x509.info.serialNumber.number public static final String SERIAL_ID = NAME + DOT + INFO + DOT + X509CertInfo.SERIAL_NUMBER + DOT + CertificateSerialNumber.NUMBER; // x509.info.key.value public static final String PUBLIC_KEY = NAME + DOT + INFO + DOT + X509CertInfo.KEY + DOT + CertificateX509Key.KEY; // x509.algorithm public static final String SIG_ALG = NAME + DOT + ALG_ID; // x509.signature public static final String SIG = NAME + DOT + SIGNATURE; // when we sign and decode we set this to true // this is our means to make certificates immutable private boolean readOnly = false; // Certificate data, and its envelope private byte[] signedCert; protected X509CertInfo info = null; protected AlgorithmId algId; protected byte[] signature; // recognized extension OIDS private static final String KEY_USAGE_OID = "2.5.29.15"; private static final String BASIC_CONSTRAINT_OID = "2.5.29.19"; /** * Default constructor. */ public X509CertImpl() { } /** * Unmarshals a certificate from its encoded form, parsing the * encoded bytes. This form of constructor is used by agents which * need to examine and use certificate contents. That is, this is * one of the more commonly used constructors. Note that the buffer * must include only a certificate, and no "garbage" may be left at * the end. If you need to ignore data at the end of a certificate, * use another constructor. * * @param certData the encoded bytes, with no trailing padding. * @exception CertificateException on parsing and initialization errors. */ public X509CertImpl(byte[] certData) throws CertificateException { this(certData, null); } /** * As a special optimization, this constructor acts as X509CertImpl(byte[]) * except that it takes an X509CertInfo which it uses as a 'hint' for * how to construct one field. * * @param certData the encode bytes, with no traiing padding * @param certInfo the certInfo which has already been constructed * from the certData */ public X509CertImpl(byte[] certData, X509CertInfo certInfo) throws CertificateException { // setting info here causes it to skip decoding in the parse() // method info = certInfo; try { DerValue in = new DerValue(certData); parse(in); signedCert = certData; } catch (IOException e) { throw new CertificateException("Unable to initialize, " + e); } } /** * unmarshals an X.509 certificate from an input stream. * * @param in an input stream holding at least one certificate * @exception CertificateException on parsing and initialization errors. */ public X509CertImpl(InputStream in) throws CertificateException { try { DerValue val = new DerValue(in); parse(val); signedCert = val.toByteArray(); } catch (IOException e) { throw new CertificateException("Unable to initialize, " + e); } } /** * Construct an initialized X509 Certificate. The certificate is stored * in raw form and has to be signed to be useful. * * @param certInfo the X509CertificateInfo which the Certificate is to be * created from. */ public X509CertImpl(X509CertInfo certInfo) { this.info = certInfo; } /** * Unmarshal a certificate from its encoded form, parsing a DER value. * This form of constructor is used by agents which need to examine * and use certificate contents. * * @param derVal the der value containing the encoded cert. * @exception CertificateException on parsing and initialization errors. */ public X509CertImpl(DerValue derVal) throws CertificateException { try { parse(derVal); signedCert = derVal.toByteArray(); } catch (IOException e) { throw new CertificateException("Unable to initialize, " + e); } } public boolean hasUnsupportedCriticalExtension() { // XXX NOT IMPLEMENTED return true; } /** * Decode an X.509 certificate from an input stream. * * @param in an input stream holding at least one certificate * @exception CertificateException on parsing errors. * @exception IOException on other errors. */ public void decode(InputStream in) throws CertificateException, IOException { DerValue val = new DerValue(in); parse(val); signedCert = val.toByteArray(); } /** * Appends the certificate to an output stream. * * @param out an input stream to which the certificate is appended. * @exception CertificateEncodingException on encoding errors. */ public void encode(OutputStream out) throws CertificateEncodingException { if (signedCert == null) throw new CertificateEncodingException( "Null certificate to encode"); try { out.write(signedCert); } catch (IOException e) { throw new CertificateEncodingException(e.toString()); } } /** * DER encode this object onto an output stream. * Implements the DerEncoder interface. * * @param out * the output stream on which to write the DER encoding. * * @exception IOException on encoding error. */ public void derEncode(OutputStream out) throws IOException { if (signedCert == null) throw new IOException("Null certificate to encode"); out.write(signedCert); } /** * Returns the encoded form of this certificate. It is * assumed that each certificate type would have only a single * form of encoding; for example, X.509 certificates would * be encoded as ASN.1 DER. * * @exception CertificateEncodingException if an encoding error occurs. */ public byte[] getEncoded() throws CertificateEncodingException { if (signedCert == null) throw new CertificateEncodingException( "Null certificate to encode"); byte[] dup = new byte[signedCert.length]; System.arraycopy(signedCert, 0, dup, 0, dup.length); return dup; } /** * Throws an exception if the certificate was not signed using the * verification key provided. Successfully verifying a certificate * does not indicate that one should trust the entity which * it represents. * * @param key the public key used for verification. * * @exception InvalidKeyException on incorrect key. * @exception NoSuchAlgorithmException on unsupported signature * algorithms. * @exception NoSuchProviderException if there's no default provider. * @exception SignatureException on signature errors. * @exception CertificateException on encoding errors. */ public void verify(PublicKey key) throws CertificateException, NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException, SignatureException { String sigProvider = null; verify(key, sigProvider); } /** * Throws an exception if the certificate was not signed using the * verification key provided. Successfully verifying a certificate * does not indicate that one should trust the entity which * it represents. * * @param key the public key used for verification. * @param sigProvider the name of the provider. * * @exception NoSuchAlgorithmException on unsupported signature * algorithms. * @exception InvalidKeyException on incorrect key. * @exception NoSuchProviderException on incorrect provider. * @exception SignatureException on signature errors. * @exception CertificateException on encoding errors. */ public void verify(PublicKey key, String sigProvider) throws CertificateException, NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException, SignatureException { if (signedCert == null) { throw new CertificateEncodingException("Uninitialized certificate"); } // Verify the signature ... Signature sigVerf = null; sigVerf = Signature.getInstance(algId.getName(), sigProvider); sigVerf.initVerify(key); byte[] rawCert = info.getEncodedInfo(); sigVerf.update(rawCert, 0, rawCert.length); if (!sigVerf.verify(signature)) { throw new SignatureException("Signature does not match."); } } /** * Creates an X.509 certificate, and signs it using the key * passed (associating a signature algorithm and an X.500 name). * This operation is used to implement the certificate generation * functionality of a certificate authority. * * @param key the private key used for signing. * @param algorithm the name of the signature algorithm used. * * @exception InvalidKeyException on incorrect key. * @exception NoSuchAlgorithmException on unsupported signature * algorithms. * @exception NoSuchProviderException if there's no default provider. * @exception SignatureException on signature errors. * @exception CertificateException on encoding errors. */ public void sign(PrivateKey key, String algorithm) throws CertificateException, NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException, SignatureException { sign(key, algorithm, null); } /** * Creates an X.509 certificate, and signs it using the key * passed (associating a signature algorithm and an X.500 name). * This operation is used to implement the certificate generation * functionality of a certificate authority. * * @param key the private key used for signing. * @param algorithm the name of the signature algorithm used. * @param provider the name of the provider. * * @exception NoSuchAlgorithmException on unsupported signature * algorithms. * @exception InvalidKeyException on incorrect key. * @exception NoSuchProviderException on incorrect provider. * @exception SignatureException on signature errors. * @exception CertificateException on encoding errors. */ public void sign(PrivateKey key, String algorithm, String provider) throws CertificateException, NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException, SignatureException { try (DerOutputStream out = new DerOutputStream()){ if (readOnly) throw new CertificateEncodingException( "cannot over-write existing certificate"); Signature sigEngine = null; if (provider == null) sigEngine = Signature.getInstance(algorithm); else sigEngine = Signature.getInstance(algorithm, provider); sigEngine.initSign(key); // in case the name is reset algId = AlgorithmId.get(sigEngine.getAlgorithm()); DerOutputStream tmp = new DerOutputStream(); // encode certificate info info.encode(tmp); byte[] rawCert = tmp.toByteArray(); // encode algorithm identifier algId.encode(tmp); // Create and encode the signature itself. sigEngine.update(rawCert, 0, rawCert.length); signature = sigEngine.sign(); tmp.putBitString(signature); // Wrap the signed data in a SEQUENCE { data, algorithm, sig } out.write(DerValue.tag_Sequence, tmp); signedCert = out.toByteArray(); readOnly = true; } catch (IOException e) { throw new CertificateEncodingException(e.toString()); } } /** * Checks that the certificate is currently valid, i.e. the current * time is within the specified validity period. * * @exception CertificateExpiredException if the certificate has expired. * @exception CertificateNotYetValidException if the certificate is not * yet valid. */ public void checkValidity() throws CertificateExpiredException, CertificateNotYetValidException { Date date = new Date(); checkValidity(date); } /** * Checks that the specified date is within the certificate's * validity period, or basically if the certificate would be * valid at the specified date/time. * * @param date the Date to check against to see if this certificate * is valid at that date/time. * * @exception CertificateExpiredException if the certificate has expired * with respect to the date supplied. * @exception CertificateNotYetValidException if the certificate is not * yet valid with respect to the date supplied. */ public void checkValidity(Date date) throws CertificateExpiredException, CertificateNotYetValidException { CertificateValidity interval = null; try { interval = (CertificateValidity) info.get(CertificateValidity.NAME); } catch (Exception e) { throw new CertificateNotYetValidException("Incorrect validity period"); } if (interval == null) throw new CertificateNotYetValidException("Null validity period"); interval.valid(date); } /** * Return the requested attribute from the certificate. * * @param name the name of the attribute. * @exception CertificateParsingException on invalid attribute identifier. */ public Object get(String name) throws CertificateParsingException { X509AttributeName attr = new X509AttributeName(name); String id = attr.getPrefix(); if (!(id.equalsIgnoreCase(NAME))) { throw new CertificateParsingException("Invalid root of " + "attribute name, expected [" + NAME + "], received " + "[" + id + "]"); } attr = new X509AttributeName(attr.getSuffix()); id = attr.getPrefix(); if (id.equalsIgnoreCase(INFO)) { if (attr.getSuffix() != null) { try { return info.get(attr.getSuffix()); } catch (IOException e) { throw new CertificateParsingException(e.toString()); } catch (CertificateException e) { throw new CertificateParsingException(e.toString()); } } else { return (info); } } else if (id.equalsIgnoreCase(ALG_ID)) { return (algId); } else if (id.equalsIgnoreCase(SIGNATURE)) { return (signature); } else if (id.equalsIgnoreCase(SIGNED_CERT)) { return (signedCert); } else { throw new CertificateParsingException("Attribute name not " + "recognized or get() not allowed for the same: " + id); } } /** * Set the requested attribute in the certificate. * * @param name the name of the attribute. * @param obj the value of the attribute. * @exception CertificateException on invalid attribute identifier. * @exception IOException on encoding error of attribute. */ public void set(String name, Object obj) throws CertificateException, IOException { // check if immutable if (readOnly) throw new CertificateException("cannot over-write existing" + " certificate"); X509AttributeName attr = new X509AttributeName(name); String id = attr.getPrefix(); if (!(id.equalsIgnoreCase(NAME))) { throw new CertificateException("Invalid root of attribute name," + " expected [" + NAME + "], received " + id); } attr = new X509AttributeName(attr.getSuffix()); id = attr.getPrefix(); if (id.equalsIgnoreCase(INFO)) { if (attr.getSuffix() == null) { if (!(obj instanceof X509CertInfo)) { throw new CertificateException("Attribute value should" + " be of type X509CertInfo."); } info = (X509CertInfo) obj; signedCert = null; //reset this as certificate data has changed } else { info.set(attr.getSuffix(), obj); signedCert = null; //reset this as certificate data has changed } } else { throw new CertificateException("Attribute name not recognized or " + "set() not allowed for the same: " + id); } } /** * Delete the requested attribute from the certificate. * * @param name the name of the attribute. * @exception CertificateException on invalid attribute identifier. * @exception IOException on other errors. */ public void delete(String name) throws CertificateException, IOException { // check if immutable if (readOnly) throw new CertificateException("cannot over-write existing" + " certificate"); X509AttributeName attr = new X509AttributeName(name); String id = attr.getPrefix(); if (!(id.equalsIgnoreCase(NAME))) { throw new CertificateException("Invalid root of attribute name," + " expected [" + NAME + "], received " + id); } attr = new X509AttributeName(attr.getSuffix()); id = attr.getPrefix(); if (id.equalsIgnoreCase(INFO)) { if (attr.getSuffix() != null) { info = null; } else { info.delete(attr.getSuffix()); } } else if (id.equalsIgnoreCase(ALG_ID)) { algId = null; } else if (id.equalsIgnoreCase(SIGNATURE)) { signature = null; } else if (id.equalsIgnoreCase(SIGNED_CERT)) { signedCert = null; } else { throw new CertificateException("Attribute name not recognized or " + "delete() not allowed for the same: " + id); } } /** * Return an enumeration of names of attributes existing within this * attribute. */ public Enumeration getElements() { Vector elements = new Vector(); elements.addElement(NAME + DOT + INFO); elements.addElement(NAME + DOT + ALG_ID); elements.addElement(NAME + DOT + SIGNATURE); elements.addElement(NAME + DOT + SIGNED_CERT); return (elements.elements()); } /** * Return the name of this attribute. */ public String getName() { return (NAME); } /** * Returns a printable representation of the certificate. This does not * contain all the information available to distinguish this from any * other certificate. The certificate must be fully constructed * before this function may be called. */ public String toString() { if (info == null || algId == null || signature == null) return ""; StringBuffer sb = new StringBuffer("[\n"+info.toString() + "\n" + " Algorithm: [" + algId.toString() + "]\n"); netscape.security.util.PrettyPrintFormat pp = new netscape.security.util.PrettyPrintFormat(" ", 20); String signaturebits = pp.toHexString(signature); sb.append(" Signature:\n" + signaturebits); sb.append("]"); return sb.toString(); } // the strongly typed gets, as per java.security.cert.X509Certificate /** * Gets the publickey from this certificate. * * @return the publickey. */ public PublicKey getPublicKey() { if (info == null) return null; try { PublicKey key = (PublicKey) info.get(CertificateX509Key.NAME + DOT + CertificateX509Key.KEY); return key; } catch (Exception e) { return null; } } /** * Gets the version number from the certificate. * * @return the version number. */ public int getVersion() { if (info == null) return -1; try { int vers = ((Integer) info.get(CertificateVersion.NAME + DOT + CertificateVersion.VERSION)).intValue(); return vers; } catch (Exception e) { return -1; } } /** * Gets the serial number from the certificate. * * @return the serial number. */ public BigInteger getSerialNumber() { if (info == null) return null; try { SerialNumber ser = (SerialNumber) info.get( CertificateSerialNumber.NAME + DOT + CertificateSerialNumber.NUMBER); return ser.getNumber().toBigInteger(); } catch (Exception e) { return null; } } /** * Gets the subject distinguished name from the certificate. * * @return the subject name. */ public Principal getSubjectDN() { if (info == null) return null; try { Principal subject = (Principal) info.get( CertificateSubjectName.NAME + DOT + CertificateSubjectName.DN_NAME); return subject; } catch (Exception e) { return null; } } public CertificateSubjectName getSubjectObj() { return info.getSubjectObj(); } /** * Gets the issuer distinguished name from the certificate. * * @return the issuer name. */ public Principal getIssuerDN() { if (info == null) return null; try { Principal issuer = (Principal) info.get( CertificateIssuerName.NAME + DOT + CertificateIssuerName.DN_NAME); return issuer; } catch (Exception e) { return null; } } public CertificateIssuerName getIssuerObj() { return info.getIssuerObj(); } /** * Gets the notBefore date from the validity period of the certificate. * * @return the start date of the validity period. */ public Date getNotBefore() { if (info == null) return null; try { Date d = (Date) info.get(CertificateValidity.NAME + DOT + CertificateValidity.NOT_BEFORE); return d; } catch (Exception e) { return null; } } /** * Gets the notAfter date from the validity period of the certificate. * * @return the end date of the validity period. */ public Date getNotAfter() { if (info == null) return null; try { Date d = (Date) info.get(CertificateValidity.NAME + DOT + CertificateValidity.NOT_AFTER); return d; } catch (Exception e) { return null; } } /** * Gets the DER encoded certificate informations, the tbsCertificate from this certificate. * This can be used to verify the signature independently. * * @return the DER encoded certificate information. * @exception CertificateEncodingException if an encoding error occurs. */ public byte[] getTBSCertificate() throws CertificateEncodingException { if (info != null) { return info.getEncodedInfo(); } else throw new CertificateEncodingException("Uninitialized certificate"); } /** * Gets the raw Signature bits from the certificate. * * @return the signature. */ public byte[] getSignature() { if (signature == null) return null; byte[] dup = new byte[signature.length]; System.arraycopy(signature, 0, dup, 0, dup.length); return dup; } /** * Gets the signature algorithm name for the certificate * signature algorithm. * For example, the string "SHA-1/DSA" or "DSS". * * @return the signature algorithm name. */ public String getSigAlgName() { if (algId == null) return null; return (algId.getName()); } /** * Gets the signature algorithm OID string from the certificate. * For example, the string "1.2.840.10040.4.3" * * @return the signature algorithm oid string. */ public String getSigAlgOID() { if (algId == null) return null; ObjectIdentifier oid = algId.getOID(); return (oid.toString()); } /** * Gets the DER encoded signature algorithm parameters from this * certificate's signature algorithm. * * @return the DER encoded signature algorithm parameters, or * null if no parameters are present. */ public byte[] getSigAlgParams() { if (algId == null) return null; try { return algId.getEncodedParams(); } catch (IOException e) { return null; } } /** * Gets the Issuer Unique Identity from the certificate. * * @return the Issuer Unique Identity. */ public boolean[] getIssuerUniqueID() { if (info == null) return null; try { UniqueIdentity id = (UniqueIdentity) info.get( CertificateIssuerUniqueIdentity.NAME + DOT + CertificateIssuerUniqueIdentity.ID); if (id == null) return null; else return (id.getId()); } catch (Exception e) { return null; } } /** * Gets the Subject Unique Identity from the certificate. * * @return the Subject Unique Identity. */ public boolean[] getSubjectUniqueID() { if (info == null) return null; try { UniqueIdentity id = (UniqueIdentity) info.get( CertificateSubjectUniqueIdentity.NAME + DOT + CertificateSubjectUniqueIdentity.ID); if (id == null) return null; else return (id.getId()); } catch (Exception e) { return null; } } /** * Gets a Set of the extension(s) marked CRITICAL in the * certificate by OID strings. * * @return a set of the extension oid strings in the * certificate that are marked critical. */ public Set getCriticalExtensionOIDs() { if (info == null) return null; try { CertificateExtensions exts = (CertificateExtensions) info.get( CertificateExtensions.NAME); if (exts == null) return null; Set extSet = new LinkedHashSet(); Extension ex; for (Enumeration e = exts.getAttributes(); e.hasMoreElements();) { ex = e.nextElement(); if (ex.isCritical()) extSet.add(ex.getExtensionId().toString()); } return extSet; } catch (Exception e) { return null; } } /** * Gets a Set of the extension(s) marked NON-CRITICAL in the * certificate by OID strings. * * @return a set of the extension oid strings in the * certificate that are NOT marked critical. */ public Set getNonCriticalExtensionOIDs() { if (info == null) return null; try { CertificateExtensions exts = (CertificateExtensions) info.get( CertificateExtensions.NAME); if (exts == null) return null; Set extSet = new LinkedHashSet(); Extension ex; for (Enumeration e = exts.getAttributes(); e.hasMoreElements();) { ex = e.nextElement(); if (!ex.isCritical()) extSet.add(ex.getExtensionId().toString()); } return extSet; } catch (Exception e) { return null; } } public Extension getExtension(String oid) { try { CertificateExtensions exts = (CertificateExtensions) info.get( CertificateExtensions.NAME); if (exts == null) return null; ObjectIdentifier findOID = new ObjectIdentifier(oid); Extension ex = null; ; ObjectIdentifier inCertOID; for (Enumeration e = exts.getAttributes(); e.hasMoreElements();) { ex = e.nextElement(); inCertOID = ex.getExtensionId(); if (inCertOID.equals(findOID)) { return ex; } } } catch (Exception e) { } return null; } /** * Gets the DER encoded extension identified by the passed * in oid String. * * @param oid the Object Identifier value for the extension. */ public byte[] getExtensionValue(String oid) { DerOutputStream out = null; try { String extAlias = OIDMap.getName(new ObjectIdentifier(oid)); Extension certExt = null; if (extAlias == null) { // may be unknown // get the extensions, search thru' for this oid CertificateExtensions exts = (CertificateExtensions) info.get( CertificateExtensions.NAME); if (exts == null) return null; ObjectIdentifier findOID = new ObjectIdentifier(oid); Extension ex = null; ; ObjectIdentifier inCertOID; for (Enumeration e = exts.getAttributes(); e.hasMoreElements();) { ex = e.nextElement(); inCertOID = ex.getExtensionId(); if (inCertOID.equals(findOID)) { certExt = ex; break; } } } else { // there's sub-class that can handle this extension certExt = (Extension) this.get(extAlias); } if (certExt == null) return null; byte[] extData = certExt.getExtensionValue(); if (extData == null) return null; out = new DerOutputStream(); out.putOctetString(extData); return out.toByteArray(); } catch (Exception e) { return null; } finally { if (out != null) { try { out.close(); } catch (IOException e) { e.printStackTrace(); } } } } /** * Get a boolean array representing the bits of the KeyUsage extension, * (oid = 2.5.29.15). * * @return the bit values of this extension as an array of booleans. */ public boolean[] getKeyUsage() { try { String extAlias = OIDMap.getName(new ObjectIdentifier( KEY_USAGE_OID)); if (extAlias == null) return null; KeyUsageExtension certExt = (KeyUsageExtension) this.get(extAlias); if (certExt == null) return null; return certExt.getBits(); } catch (Exception e) { return null; } } /** * Get the certificate constraints path length from the * the critical BasicConstraints extension, (oid = 2.5.29.19). * * @return the length of the constraint. */ public int getBasicConstraints() { try { String extAlias = OIDMap.getName(new ObjectIdentifier( BASIC_CONSTRAINT_OID)); if (extAlias == null) return -1; BasicConstraintsExtension certExt = (BasicConstraintsExtension) this.get(extAlias); if (certExt == null) return -1; if (((Boolean) certExt.get(BasicConstraintsExtension.IS_CA)).booleanValue() == true) return ((Integer) certExt.get( BasicConstraintsExtension.PATH_LEN)).intValue(); else return -1; } catch (Exception e) { return -1; } } public boolean getBasicConstraintsIsCA() { boolean isCA = false; try { String extAlias = OIDMap.getName(new ObjectIdentifier( BASIC_CONSTRAINT_OID)); if (extAlias == null) return false; BasicConstraintsExtension certExt = (BasicConstraintsExtension) this.get(extAlias); if (certExt == null) return false; isCA = ((Boolean) certExt.get(BasicConstraintsExtension.IS_CA)).booleanValue(); } catch (Exception e) { return false; } return isCA; } /************************************************************/ /* * Cert is a SIGNED ASN.1 macro, a three elment sequence: * * - Data to be signed (ToBeSigned) -- the "raw" cert * - Signature algorithm (SigAlgId) * - The signature bits * * This routine unmarshals the certificate, saving the signature * parts away for later verification. */ private void parse(DerValue val) throws CertificateException, IOException { // check if can over write the certificate if (readOnly) throw new CertificateParsingException( "cannot over-write existing certificate"); readOnly = true; DerValue seq[] = new DerValue[3]; seq[0] = val.data.getDerValue(); seq[1] = val.data.getDerValue(); seq[2] = val.data.getDerValue(); if (val.data.available() != 0) { throw new CertificateParsingException("signed overrun, bytes = " + val.data.available()); } if (seq[0].tag != DerValue.tag_Sequence) { throw new CertificateParsingException("signed fields invalid"); } algId = AlgorithmId.parse(seq[1]); signature = seq[2].getBitString(); if (seq[1].data.available() != 0) { throw new CertificateParsingException("algid field overrun"); } if (seq[2].data.available() != 0) throw new CertificateParsingException("signed fields overrun"); // The CertificateInfo if (info == null) { info = new X509CertInfo(seq[0]); } } /** * Serialization write ... X.509 certificates serialize as * themselves, and they're parsed when they get read back. * (Actually they serialize as some type data from the * serialization subsystem, then the cert data.) */ private void writeObject(ObjectOutputStream stream) throws CertificateException, IOException { encode(stream); } /** * Serialization read ... X.509 certificates serialize as * themselves, and they're parsed when they get read back. */ private void readObject(ObjectInputStream stream) throws CertificateException, IOException { decode(stream); } protected static class CertificateRep1 implements java.io.Serializable { /** * */ private static final long serialVersionUID = -5207881613631592409L; private String type1; private byte[] data1; /** * Construct the alternate Certificate class with the Certificate * type and Certificate encoding bytes. * *

* * @param type the standard name of the Certificate type. *

* * @param data the Certificate data. */ protected CertificateRep1(String type, byte[] data) { this.type1 = type; this.data1 = data; } /** * Resolve the Certificate Object. * *

* * @return the resolved Certificate Object. * * @throws java.io.ObjectStreamException if the Certificate could not * be resolved. */ protected Object readResolve() throws java.io.ObjectStreamException { try { @SuppressWarnings("unused") CertificateFactory cf = CertificateFactory.getInstance(type1); // check for errors return new X509CertImpl(data1); /* return cf.generateCertificate (new java.io.ByteArrayInputStream(data1)); */ } catch (CertificateException e) { throw new java.io.NotSerializableException("java.security.cert.Certificate: " + type1 + ": " + e.getMessage()); } } } protected Object writeReplace() throws java.io.ObjectStreamException { try { return new CertificateRep1("X.509", getEncoded()); } catch (CertificateException e) { throw new java.io.NotSerializableException("java.security.cert.Certificate: " + "X.509" + ": " + e.getMessage()); } } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 33459 Content-Disposition: inline; filename="X509CertInfo.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "e4768294e704f67527b517bb5864ffe5362ce627" // --- 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.x509; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.OutputStream; import java.io.Serializable; import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateException; import java.security.cert.CertificateParsingException; import java.util.Enumeration; import java.util.Hashtable; import java.util.Vector; import netscape.security.util.DerInputStream; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; /** * The X509CertInfo class represents X.509 certificate information. * *

* X.509 certificates have several base data elements, including: *

    * *
  • The Subject Name, an X.500 Distinguished Name for the entity (subject) for which the certificate was * issued. * *
  • The Subject Public Key, the public key of the subject. This is one of the most important parts of the * certificate. * *
  • The Validity Period, a time period (e.g. six months) within which the certificate is valid (unless * revoked). * *
  • The Issuer Name, an X.500 Distinguished Name for the Certificate Authority (CA) which issued the * certificate. * *
  • A Serial Number assigned by the CA, for use in certificate revocation and other applications. * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.16 * @see CertAttrSet * @see Serializable * @see X509CertImpl */ public class X509CertInfo implements CertAttrSet, Serializable { /** * */ private static final long serialVersionUID = -5094073467876311577L; /** * Identifier for this attribute, to be used with the * get, set, delete methods of Certificate, x509 type. */ public static final String IDENT = "x509.info"; // Certificate attribute names public static final String NAME = "info"; public static final String VERSION = CertificateVersion.NAME; public static final String SERIAL_NUMBER = CertificateSerialNumber.NAME; public static final String ALGORITHM_ID = CertificateAlgorithmId.NAME; public static final String ISSUER = CertificateIssuerName.NAME; public static final String VALIDITY = CertificateValidity.NAME; public static final String SUBJECT = CertificateSubjectName.NAME; public static final String KEY = CertificateX509Key.NAME; public static final String ISSUER_ID = CertificateIssuerUniqueIdentity.NAME; public static final String SUBJECT_ID = CertificateSubjectUniqueIdentity.NAME; public static final String EXTENSIONS = CertificateExtensions.NAME; // X509.v1 data protected CertificateVersion version = new CertificateVersion(); protected CertificateSerialNumber serialNum = null; protected CertificateAlgorithmId algId = null; protected CertificateIssuerName issuer = null; protected CertificateValidity interval = null; protected CertificateSubjectName subject = null; protected CertificateX509Key pubKey = null; // X509.v2 & v3 extensions protected CertificateIssuerUniqueIdentity issuerUniqueId = null; protected CertificateSubjectUniqueIdentity subjectUniqueId = null; // X509.v3 extensions protected CertificateExtensions extensions = null; // Attribute numbers for internal manipulation private static final int ATTR_VERSION = 1; private static final int ATTR_SERIAL = 2; private static final int ATTR_ALGORITHM = 3; private static final int ATTR_ISSUER = 4; private static final int ATTR_VALIDITY = 5; private static final int ATTR_SUBJECT = 6; private static final int ATTR_KEY = 7; private static final int ATTR_ISSUER_ID = 8; private static final int ATTR_SUBJECT_ID = 9; private static final int ATTR_EXTENSIONS = 10; // DER encoded CertificateInfo data private byte[] rawCertInfo = null; // The certificate attribute name to integer mapping stored here private static final Hashtable map = new Hashtable(); static { map.put(VERSION, Integer.valueOf(ATTR_VERSION)); map.put(SERIAL_NUMBER, Integer.valueOf(ATTR_SERIAL)); map.put(ALGORITHM_ID, Integer.valueOf(ATTR_ALGORITHM)); map.put(ISSUER, Integer.valueOf(ATTR_ISSUER)); map.put(VALIDITY, Integer.valueOf(ATTR_VALIDITY)); map.put(SUBJECT, Integer.valueOf(ATTR_SUBJECT)); map.put(KEY, Integer.valueOf(ATTR_KEY)); map.put(ISSUER_ID, Integer.valueOf(ATTR_ISSUER_ID)); map.put(SUBJECT_ID, Integer.valueOf(ATTR_SUBJECT_ID)); map.put(EXTENSIONS, Integer.valueOf(ATTR_EXTENSIONS)); } /** * Construct an uninitialized X509CertInfo on which * decode must later be called (or which may be deserialized). */ public X509CertInfo() { } /** * Unmarshals a certificate from its encoded form, parsing the * encoded bytes. This form of constructor is used by agents which * need to examine and use certificate contents. That is, this is * one of the more commonly used constructors. Note that the buffer * must include only a certificate, and no "garbage" may be left at * the end. If you need to ignore data at the end of a certificate, * use another constructor. * * @param cert the encoded bytes, with no trailing data. * @exception CertificateParsingException on parsing errors. */ public X509CertInfo(byte[] cert) throws CertificateParsingException { try { DerValue in = new DerValue(cert); parse(in); } catch (IOException e) { throw new CertificateParsingException(e); } } /** * Unmarshal a certificate from its encoded form, parsing a DER value. * This form of constructor is used by agents which need to examine * and use certificate contents. * * @param derVal the der value containing the encoded cert. * @exception CertificateParsingException on parsing errors. */ public X509CertInfo(DerValue derVal) throws CertificateParsingException { try { parse(derVal); } catch (IOException e) { throw new CertificateParsingException(e); } } /** * Decode an X.509 certificate from an input stream. * * @param in an input stream holding at least one certificate * @exception CertificateParsingException on decoding errors. * @exception IOException on other errors. */ public void decode(InputStream in) throws CertificateParsingException, IOException { DerValue val = new DerValue(in); parse(val); } /** * Appends the certificate to an output stream. * * @param out an output stream to which the certificate is appended. * @exception CertificateException on encoding errors. * @exception IOException on other errors. */ public void encode(OutputStream out) throws CertificateException, IOException { encode(out, false); } /** * Appends the certificate to an output stream. * * @param out An output stream to which the certificate is appended. * @param ignoreCache Whether to ignore the internal cache when encoding. * (the cache can easily become out of date). */ public void encode(OutputStream out, boolean ignoreCache) throws IOException, CertificateException { if (ignoreCache || (rawCertInfo == null)) { DerOutputStream tmp = new DerOutputStream(); emit(tmp); rawCertInfo = tmp.toByteArray(); } out.write(rawCertInfo); } /** * Return an enumeration of names of attributes existing within this * attribute. */ public Enumeration getAttributeNames() { Vector elements = new Vector(); elements.addElement(VERSION); elements.addElement(SERIAL_NUMBER); elements.addElement(ALGORITHM_ID); elements.addElement(ISSUER); elements.addElement(VALIDITY); elements.addElement(SUBJECT); elements.addElement(KEY); elements.addElement(ISSUER_ID); elements.addElement(SUBJECT_ID); elements.addElement(EXTENSIONS); return (elements.elements()); } /** * Return the name of this attribute. */ public String getName() { return (NAME); } /** * Returns the encoded certificate info. * * @exception CertificateEncodingException on encoding information errors. */ public byte[] getEncodedInfo() throws CertificateEncodingException { return getEncodedInfo(false); } public byte[] getEncodedInfo(boolean ignoreCache) throws CertificateEncodingException { try { if (ignoreCache || (rawCertInfo == null)) { DerOutputStream tmp = new DerOutputStream(); emit(tmp); rawCertInfo = tmp.toByteArray(); } byte[] dup = new byte[rawCertInfo.length]; System.arraycopy(rawCertInfo, 0, dup, 0, dup.length); return dup; } catch (IOException e) { throw new CertificateEncodingException(e); } catch (CertificateException e) { throw new CertificateEncodingException(e); } } /** * Compares two X509CertInfo objects. This is false if the * certificates are not both X.509 certs, otherwise it * compares them as binary data. * * @param other the object being compared with this one * @return true iff the certificates are equivalent */ public boolean equals(Object other) { if (other instanceof X509CertInfo) { return equals((X509CertInfo) other); } else { return false; } } /** * Compares two certificates, returning false if any data * differs between the two. * * @param other the object being compared with this one * @return true iff the certificates are equivalent */ public boolean equals(X509CertInfo other) { if (this == other) { return (true); } else if (rawCertInfo == null || other.rawCertInfo == null) { return (false); } else if (rawCertInfo.length != other.rawCertInfo.length) { return (false); } for (int i = 0; i < rawCertInfo.length; i++) { if (rawCertInfo[i] != other.rawCertInfo[i]) { return (false); } } return (true); } /** * Calculates a hash code value for the object. Objects * which are equal will also have the same hashcode. */ public int hashCode() { int retval = 0; for (int i = 1; i < rawCertInfo.length; i++) { retval += rawCertInfo[i] * i; } return (retval); } /** * Returns a printable representation of the certificate. */ public String toString() { if (subject == null || pubKey == null || interval == null || issuer == null || algId == null || serialNum == null) { throw new NullPointerException("X.509 cert is incomplete"); } StringBuffer sb = new StringBuffer("[\n" + " " + version.toString() + "\n" + " Subject: " + subject.toString() + "\n" + " Signature Algorithm: " + algId.toString() + "\n" + " Key: " + pubKey.toString() + "\n"); sb.append(" " + interval.toString() + "\n" + " Issuer: " + issuer.toString() + "\n" + " " + serialNum.toString() + "\n"); // optional v2, v3 extras if (issuerUniqueId != null) { sb.append(" Issuer Id:\n" + issuerUniqueId.toString() + "\n"); } if (subjectUniqueId != null) { sb.append(" Subject Id:\n" + subjectUniqueId.toString() + "\n"); } if (extensions != null) { netscape.security.util.PrettyPrintFormat pp = new netscape.security.util.PrettyPrintFormat(" ", 20); for (int i = 0; i < extensions.size(); i++) { sb.append(" Extension[" + i + "] = "); Extension ext = extensions.elementAt(i); DerOutputStream out = null; try { if (OIDMap.getClass(ext.getExtensionId()) == null) { sb.append(ext.toString()); byte[] extValue = ext.getExtensionValue(); if (extValue != null) { out = new DerOutputStream(); out.putOctetString(extValue); extValue = out.toByteArray(); String extValuebits = pp.toHexString(extValue); sb.append("Extension unknown: " + "DER encoded OCTET string =\n" + extValuebits); } } else sb.append(ext.toString()); //sub-class exists } catch (CertificateException e) { sb.append(", Error parsing this extension"); } catch (IOException e) { sb.append(", Error parsing this extension"); } finally { if (out != null) { try { out.close(); } catch (IOException e) { e.printStackTrace(); } } } } } sb.append("\n]"); return sb.toString(); } /** * Set the certificate attribute. * * @param name the name of the Certificate attribute. * @param val the value of the Certificate attribute. * @exception CertificateException on invalid attributes. * @exception IOException on other errors. */ public void set(String name, Object val) throws CertificateException, IOException { X509AttributeName attrName = new X509AttributeName(name); int attr = attributeMap(attrName.getPrefix()); if (attr == 0) { throw new CertificateException("Attribute name not recognized: " + name); } // set rawCertInfo to null, so that we are forced to re-encode rawCertInfo = null; switch (attr) { case ATTR_VERSION: if (attrName.getSuffix() == null) { setVersion(val); } else { version.set(attrName.getSuffix(), val); } break; case ATTR_SERIAL: if (attrName.getSuffix() == null) { setSerialNumber(val); } else { serialNum.set(attrName.getSuffix(), val); } break; case ATTR_ALGORITHM: if (attrName.getSuffix() == null) { setAlgorithmId(val); } else { algId.set(attrName.getSuffix(), val); } break; case ATTR_ISSUER: if (attrName.getSuffix() == null) { setIssuer(val); } else { issuer.set(attrName.getSuffix(), val); } break; case ATTR_VALIDITY: if (attrName.getSuffix() == null) { setValidity(val); } else { interval.set(attrName.getSuffix(), val); } break; case ATTR_SUBJECT: if (attrName.getSuffix() == null) { setSubject(val); } else { subject.set(attrName.getSuffix(), val); } break; case ATTR_KEY: if (attrName.getSuffix() == null) { setKey(val); } else { pubKey.set(attrName.getSuffix(), val); } break; case ATTR_ISSUER_ID: if (attrName.getSuffix() == null) { setIssuerUniqueId(val); } else { issuerUniqueId.set(attrName.getSuffix(), val); } break; case ATTR_SUBJECT_ID: if (attrName.getSuffix() == null) { setSubjectUniqueId(val); } else { subjectUniqueId.set(attrName.getSuffix(), val); } break; case ATTR_EXTENSIONS: if (attrName.getSuffix() == null) { setExtensions(val); } else { extensions.set(attrName.getSuffix(), val); } break; } } /** * Delete the certificate attribute. * * @param name the name of the Certificate attribute. * @exception CertificateException on invalid attributes. * @exception IOException on other errors. */ public void delete(String name) throws CertificateException, IOException { X509AttributeName attrName = new X509AttributeName(name); int attr = attributeMap(attrName.getPrefix()); if (attr == 0) { throw new CertificateException("Attribute name not recognized: " + name); } // set rawCertInfo to null, so that we are forced to re-encode rawCertInfo = null; switch (attr) { case ATTR_VERSION: if (attrName.getSuffix() == null) { version = null; } else { version.delete(attrName.getSuffix()); } break; case (ATTR_SERIAL): if (attrName.getSuffix() == null) { serialNum = null; } else { serialNum.delete(attrName.getSuffix()); } break; case (ATTR_ALGORITHM): if (attrName.getSuffix() == null) { algId = null; } else { algId.delete(attrName.getSuffix()); } break; case (ATTR_ISSUER): if (attrName.getSuffix() == null) { issuer = null; } else { issuer.delete(attrName.getSuffix()); } break; case (ATTR_VALIDITY): if (attrName.getSuffix() == null) { interval = null; } else { interval.delete(attrName.getSuffix()); } break; case (ATTR_SUBJECT): if (attrName.getSuffix() == null) { subject = null; } else { subject.delete(attrName.getSuffix()); } break; case (ATTR_KEY): if (attrName.getSuffix() == null) { pubKey = null; } else { pubKey.delete(attrName.getSuffix()); } break; case (ATTR_ISSUER_ID): if (attrName.getSuffix() == null) { issuerUniqueId = null; } else { issuerUniqueId.delete(attrName.getSuffix()); } break; case (ATTR_SUBJECT_ID): if (attrName.getSuffix() == null) { subjectUniqueId = null; } else { subjectUniqueId.delete(attrName.getSuffix()); } break; case (ATTR_EXTENSIONS): if (attrName.getSuffix() == null) { extensions = null; } else { extensions.delete(attrName.getSuffix()); } break; } } /** * Get the certificate attribute. * * @param name the name of the Certificate attribute. * * @exception CertificateException on invalid attributes. * @exception IOException on other errors. */ public Object get(String name) throws CertificateException, IOException { X509AttributeName attrName = new X509AttributeName(name); int attr = attributeMap(attrName.getPrefix()); if (attr == 0) { throw new CertificateParsingException( "Attribute name not recognized: " + name); } switch (attr) { case (ATTR_VERSION): if (attrName.getSuffix() == null) { return (version); } else { return (version.get(attrName.getSuffix())); } case (ATTR_SERIAL): if (attrName.getSuffix() == null) { return (serialNum); } else { return (serialNum.get(attrName.getSuffix())); } case (ATTR_ALGORITHM): if (attrName.getSuffix() == null) { return (algId); } else { return (algId.get(attrName.getSuffix())); } case (ATTR_ISSUER): if (attrName.getSuffix() == null) { return (issuer); } else { return (issuer.get(attrName.getSuffix())); } case (ATTR_VALIDITY): if (attrName.getSuffix() == null) { return (interval); } else { return (interval.get(attrName.getSuffix())); } case (ATTR_SUBJECT): if (attrName.getSuffix() == null) { return (subject); } else { return (subject.get(attrName.getSuffix())); } case (ATTR_KEY): if (attrName.getSuffix() == null) { return (pubKey); } else { return (pubKey.get(attrName.getSuffix())); } case (ATTR_ISSUER_ID): if (attrName.getSuffix() == null) { return (issuerUniqueId); } else { if (issuerUniqueId == null) return null; else return (issuerUniqueId.get(attrName.getSuffix())); } case (ATTR_SUBJECT_ID): if (attrName.getSuffix() == null) { return (subjectUniqueId); } else { if (subjectUniqueId == null) return null; else return (subjectUniqueId.get(attrName.getSuffix())); } case (ATTR_EXTENSIONS): if (attrName.getSuffix() == null) { return (extensions); } else { if (extensions == null) return null; else return (extensions.get(attrName.getSuffix())); } } return null; } /* * This routine unmarshals the certificate information. */ private void parse(DerValue val) throws CertificateParsingException, IOException { DerInputStream in; DerValue tmp; if (val.tag != DerValue.tag_Sequence) { throw new CertificateParsingException("signed fields invalid"); } rawCertInfo = val.toByteArray(); in = val.data; // Version tmp = in.getDerValue(); if (tmp.isContextSpecific((byte) 0)) { version = new CertificateVersion(tmp); tmp = in.getDerValue(); } // Serial number ... an integer serialNum = new CertificateSerialNumber(tmp); // Algorithm Identifier algId = new CertificateAlgorithmId(in); // Issuer name issuer = new CertificateIssuerName(in); // validity: SEQUENCE { start date, end date } interval = new CertificateValidity(in); // subject name subject = new CertificateSubjectName(in); // public key pubKey = new CertificateX509Key(in); // If more data available, make sure version is not v1. if (in.available() != 0) { if (version.compare(CertificateVersion.V1) == 0) { throw new CertificateParsingException("excess cert data"); } } else { return; } // Get the issuerUniqueId if present tmp = in.getDerValue(); if (tmp.isContextSpecific((byte) 1)) { issuerUniqueId = new CertificateIssuerUniqueIdentity(tmp); if (in.available() == 0) { return; } tmp = in.getDerValue(); } // Get the subjectUniqueId if present. if (tmp.isContextSpecific((byte) 2)) { subjectUniqueId = new CertificateSubjectUniqueIdentity(tmp); if (in.available() == 0) { return; } tmp = in.getDerValue(); } // Get the extensions. if (version.compare(CertificateVersion.V3) != 0) { throw new CertificateParsingException("excess cert data"); } if (tmp.isConstructed() && tmp.isContextSpecific((byte) 3)) { extensions = new CertificateExtensions(tmp.data); } } /* * Marshal the contents of a "raw" certificate into a DER sequence. */ private void emit(DerOutputStream out) throws CertificateException, IOException { DerOutputStream tmp = new DerOutputStream(); // version number, iff not V1 version.encode(tmp); // Encode serial number, issuer signing algorithm, issuer name // and validity serialNum.encode(tmp); algId.encode(tmp); issuer.encode(tmp); interval.encode(tmp); // Encode subject (principal) and associated key subject.encode(tmp); pubKey.encode(tmp); // Encode issuerUniqueId & subjectUniqueId. if (issuerUniqueId != null) { issuerUniqueId.encode(tmp); } if (subjectUniqueId != null) { subjectUniqueId.encode(tmp); } // Write all the extensions. if (extensions != null) { extensions.encode(tmp); } // Wrap the data; encoding of the "raw" cert is now complete. out.write(DerValue.tag_Sequence, tmp); } /** * Serialization write ... X.509 certificates serialize as * themselves, and they're parsed when they get read back. * (Actually they serialize as some type data from the * serialization subsystem, then the cert data.) */ private void writeObject(ObjectOutputStream stream) throws CertificateException, IOException { encode(stream); } /** * Serialization read ... X.509 certificates serialize as * themselves, and they're parsed when they get read back. */ private void readObject(ObjectInputStream stream) throws CertificateException, IOException { decode(stream); } /** * Returns the integer attribute number for the passed attribute name. */ private int attributeMap(String name) { Integer num = map.get(name); if (num == null) { return (0); } return (num.intValue()); } /** * Set the version number of the certificate. * * @param val the Object class value for the Extensions * @exception CertificateException on invalid data. */ private void setVersion(Object val) throws CertificateException { if (!(val instanceof CertificateVersion)) { throw new CertificateException("Version class type invalid."); } version = (CertificateVersion) val; } /** * Set the serial number of the certificate. * * @param val the Object class value for the CertificateSerialNumber * @exception CertificateException on invalid data. */ private void setSerialNumber(Object val) throws CertificateException { if (!(val instanceof CertificateSerialNumber)) { throw new CertificateException("SerialNumber class type invalid."); } serialNum = (CertificateSerialNumber) val; } /** * Set the algorithm id of the certificate. * * @param val the Object class value for the AlgorithmId * @exception CertificateException on invalid data. */ private void setAlgorithmId(Object val) throws CertificateException { if (!(val instanceof CertificateAlgorithmId)) { throw new CertificateException( "AlgorithmId class type invalid."); } algId = (CertificateAlgorithmId) val; } /** * Set the issuer name of the certificate. * * @param val the Object class value for the issuer * @exception CertificateException on invalid data. */ private void setIssuer(Object val) throws CertificateException { if (!(val instanceof CertificateIssuerName)) { throw new CertificateException( "Issuer class type invalid."); } issuer = (CertificateIssuerName) val; } public CertificateIssuerName getIssuerObj() { return issuer; } /** * Set the validity interval of the certificate. * * @param val the Object class value for the CertificateValidity * @exception CertificateException on invalid data. */ private void setValidity(Object val) throws CertificateException { if (!(val instanceof CertificateValidity)) { throw new CertificateException( "CertificateValidity class type invalid."); } interval = (CertificateValidity) val; } /** * Set the subject name of the certificate. * * @param val the Object class value for the Subject * @exception CertificateException on invalid data. */ private void setSubject(Object val) throws CertificateException { if (!(val instanceof CertificateSubjectName)) { throw new CertificateException( "Subject class type invalid."); } subject = (CertificateSubjectName) val; } public CertificateSubjectName getSubjectObj() { return subject; } /** * Set the public key in the certificate. * * @param val the Object class value for the PublicKey * @exception CertificateException on invalid data. */ private void setKey(Object val) throws CertificateException { if (!(val instanceof CertificateX509Key)) { throw new CertificateException( "Key class type invalid."); } pubKey = (CertificateX509Key) val; } /** * Set the Issuer Unique Identity in the certificate. * * @param val the Object class value for the IssuerUniqueId * @exception CertificateException */ private void setIssuerUniqueId(Object val) throws CertificateException { if (version.compare(CertificateVersion.V2) < 0) { throw new CertificateException("Invalid version"); } if (!(val instanceof CertificateIssuerUniqueIdentity)) { throw new CertificateException( "IssuerUniqueId class type invalid."); } issuerUniqueId = (CertificateIssuerUniqueIdentity) val; } /** * Set the Subject Unique Identity in the certificate. * * @param val the Object class value for the SubjectUniqueId * @exception CertificateException */ private void setSubjectUniqueId(Object val) throws CertificateException { if (version.compare(CertificateVersion.V2) < 0) { throw new CertificateException("Invalid version"); } if (!(val instanceof CertificateSubjectUniqueIdentity)) { throw new CertificateException( "SubjectUniqueId class type invalid."); } subjectUniqueId = (CertificateSubjectUniqueIdentity) val; } /** * Set the extensions in the certificate. * * @param val the Object class value for the Extensions * @exception CertificateException */ private void setExtensions(Object val) throws CertificateException { if (version.compare(CertificateVersion.V3) < 0) { throw new CertificateException("Invalid version"); } if (!(val instanceof CertificateExtensions)) { throw new CertificateException( "Extensions class type invalid."); } extensions = (CertificateExtensions) val; } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 1653 Content-Disposition: inline; filename="X509ExtensionException.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "6e30746e3a68e4a1bd35f6f0540c4ab5ec07a29c" // --- 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.x509; import java.security.GeneralSecurityException; /** * X.509 Extension Exception. * * @author Hemma Prafullchandra * 1.2 */ public class X509ExtensionException extends GeneralSecurityException { /** * */ private static final long serialVersionUID = 8152491877676477910L; /** * Constructs an X509ExtensionException with no detail message. A * detail message is a String that describes this particular * exception. */ public X509ExtensionException() { super(); } /** * Constructs the exception with the specified detail * message. A detail message is a String that describes this * particular exception. * * @param message the detail message. */ public X509ExtensionException(String message) { super(message); } } X-Content-Type-Options: nosniff Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 17073 Content-Disposition: inline; filename="X509Key.java" Last-Modified: Fri, 02 Jan 2026 01:41:26 GMT Expires: Fri, 02 Jan 2026 01:46:26 GMT ETag: "7af1036ea3609172a2fd800248532351d3c56751" // --- 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.x509; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.security.InvalidKeyException; import java.security.Key; import java.security.KeyFactory; import java.security.NoSuchAlgorithmException; import java.security.Provider; import java.security.PublicKey; import java.security.Security; import java.security.spec.InvalidKeySpecException; import java.security.spec.X509EncodedKeySpec; import netscape.security.util.DerOutputStream; import netscape.security.util.DerValue; /** * Holds an X.509 key, for example a public key found in an X.509 * certificate. Includes a description of the algorithm to be used * with the key; these keys normally are used as * "SubjectPublicKeyInfo". * *

    * While this class can represent any kind of X.509 key, it may be desirable to provide subclasses which understand how * to parse keying data. For example, RSA public keys have two members, one for the public modulus and one for the prime * exponent. If such a class is provided, it is used when parsing X.509 keys. If one is not provided, the key still * parses correctly. * * @version 1.74, 97/12/10 * @author David Brownell */ public class X509Key implements PublicKey { /** use serialVersionUID from JDK 1.1. for interoperability */ private static final long serialVersionUID = -5359250853002055002L; /* The algorithm information (name, parameters, etc). */ protected AlgorithmId algid; /* The key bytes, without the algorithm information */ protected byte[] key; /* The encoding for the key. */ protected byte[] encodedKey; /** * Default constructor. The key constructed must have its key * and algorithm initialized before it may be used, for example * by using decode. */ public X509Key() { } /* * Build and initialize as a "default" key. All X.509 key * data is stored and transmitted losslessly, but no knowledge * about this particular algorithm is available. */ public X509Key(AlgorithmId algid, byte[] key) throws InvalidKeyException { this.algid = algid; this.key = key; encode(); } /** * Construct X.509 subject public key from a DER value. If * the runtime environment is configured with a specific class for * this kind of key, a subclass is returned. Otherwise, a generic * X509Key object is returned. * *

    * This mechanism gurantees that keys (and algorithms) may be freely manipulated and transferred, without risk of * losing information. Also, when a key (or algorithm) needs some special handling, that specific need can be * accomodated. * * @param in the DER-encoded SubjectPublicKeyInfo value * @exception IOException on data format errors */ public static X509Key parse(DerValue in) throws IOException { AlgorithmId algorithm; X509Key subjectKey; if (in.tag != DerValue.tag_Sequence) throw new IOException("corrupt subject key"); algorithm = AlgorithmId.parse(in.data.getDerValue()); try { subjectKey = buildX509Key(algorithm, in.data.getBitString()); } catch (InvalidKeyException e) { throw new IOException("subject key, " + e.getMessage()); } if (in.data.available() != 0) throw new IOException("excess subject key"); return subjectKey; } /** * Parse the key bits. This may be redefined by subclasses to take * advantage of structure within the key. For example, RSA public * keys encapsulate two unsigned integers (modulus and exponent) as * DER values within the key bits; Diffie-Hellman and * DSS/DSA keys encapsulate a single unsigned integer. * *

    * This function is called when creating X.509 SubjectPublicKeyInfo values using the X509Key member functions, such * as parse and decode. * * @exception IOException on parsing errors. * @exception InvalidKeyException on invalid key encodings. */ protected void parseKeyBits() throws IOException, InvalidKeyException { encode(); } /* * Factory interface, building the kind of key associated with this * specific algorithm ID or else returning this generic base class. * See the description above. */ static X509Key buildX509Key(AlgorithmId algid, byte[] key) throws IOException, InvalidKeyException { /* * Use the algid and key parameters to produce the ASN.1 encoding * of the key, which will then be used as the input to the * key factory. */ DerOutputStream x509EncodedKeyStream = new DerOutputStream(); encode(x509EncodedKeyStream, algid, key); X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(x509EncodedKeyStream.toByteArray()); try { // Instantiate the key factory of the appropriate algorithm KeyFactory keyFac = null; if (Security.getProvider("Mozilla-JSS") == null) { keyFac = KeyFactory.getInstance(algid.getName()); } else { keyFac = KeyFactory.getInstance(algid.getName(), "Mozilla-JSS"); } // Generate the public key PublicKey pubKey = keyFac.generatePublic(x509KeySpec); if (pubKey instanceof X509Key) { /* * Return specialized X509Key, where the structure within the * key has been parsed */ return (X509Key) pubKey; } } catch (NoSuchAlgorithmException e) { // Return generic X509Key with opaque key data (see below) } catch (InvalidKeySpecException e) { throw new InvalidKeyException(e.toString()); } catch (Exception e) { throw new InvalidKeyException(e.toString()); } /* * Try again using JDK1.1-style for backwards compatibility. */ String classname = ""; try { Provider sunProvider; sunProvider = Security.getProvider("SUN"); if (sunProvider == null) throw new InstantiationException(); classname = sunProvider.getProperty("PublicKey.X.509." + algid.getName()); if (classname == null) { throw new InstantiationException(); } Class keyClass = Class.forName(classname); Object inst; X509Key result; inst = keyClass.newInstance(); if (inst instanceof X509Key) { result = (X509Key) inst; result.algid = algid; result.key = key; result.parseKeyBits(); return result; } } catch (ClassNotFoundException e) { } catch (InstantiationException e) { } catch (IllegalAccessException e) { // this should not happen. throw new IOException(classname + " [internal error]"); } X509Key result = new X509Key(); result.algid = algid; result.key = key; return result; } /** * Returns the algorithm to be used with this key. */ public String getAlgorithm() { return algid.getName(); } /** * Returns the algorithm ID to be used with this key. */ public AlgorithmId getAlgorithmId() { return algid; } /** * Encode SubjectPublicKeyInfo sequence on the DER output stream. * * @exception IOException on encoding errors. */ public final void encode(DerOutputStream out) throws IOException { encode(out, this.algid, this.key); } /** * Returns the DER-encoded form of the key as a byte array. */ public synchronized byte[] getEncoded() { byte[] result = null; try { result = encode(); } catch (InvalidKeyException e) { } return result; } /** * Returns the format for this key: "X.509" */ public String getFormat() { return "X.509"; } /** * Returns the raw key as a byte array */ public byte[] getKey() { return key; } /** * Returns the DER-encoded form of the key as a byte array. * * @exception InvalidKeyException on encoding errors. */ public byte[] encode() throws InvalidKeyException { if (encodedKey == null) { try { DerOutputStream out; out = new DerOutputStream(); encode(out); encodedKey = out.toByteArray(); } catch (IOException e) { throw new InvalidKeyException("IOException : " + e.getMessage()); } } return copyEncodedKey(encodedKey); } /* * Returns a printable representation of the key */ public String toString() { netscape.security.util.PrettyPrintFormat pp = new netscape.security.util.PrettyPrintFormat(" ", 20); String keybits = pp.toHexString(key); return "algorithm = " + algid.toString() + ", unparsed keybits = \n" + keybits; } /** * Initialize an X509Key object from an input stream. The data on that * input stream must be encoded using DER, obeying the X.509 SubjectPublicKeyInfo format. That is, the * data is a * sequence consisting of an algorithm ID and a bit string which holds * the key. (That bit string is often used to encapsulate another DER * encoded sequence.) * *

    * Subclasses should not normally redefine this method; they should instead provide a parseKeyBits * method to parse any fields inside the key member. * *

    * The exception to this rule is that since private keys need not be encoded using the X.509 * SubjectPublicKeyInfo format, private keys may override this method, encode, and of * course getFormat. * * @param in an input stream with a DER-encoded X.509 * SubjectPublicKeyInfo value * @exception InvalidKeyException on parsing errors. */ public void decode(InputStream in) throws InvalidKeyException { DerValue val; try { val = new DerValue(in); if (val.tag != DerValue.tag_Sequence) throw new InvalidKeyException("invalid key format"); algid = AlgorithmId.parse(val.data.getDerValue()); key = val.data.getBitString(); parseKeyBits(); if (val.data.available() != 0) throw new InvalidKeyException("excess key data"); } catch (IOException e) { // e.printStackTrace (); throw new InvalidKeyException("IOException : " + e.getMessage()); } } public void decode(byte[] encodedKey) throws InvalidKeyException { decode(new ByteArrayInputStream(encodedKey)); } /** * Serialization write ... X.509 keys serialize as * themselves, and they're parsed when they get read back. */ private void writeObject(java.io.ObjectOutputStream stream) throws IOException { stream.write(getEncoded()); } /** * Serialization read ... X.509 keys serialize as * themselves, and they're parsed when they get read back. */ private void readObject(ObjectInputStream stream) throws IOException { try { decode(stream); } catch (InvalidKeyException e) { e.printStackTrace(); throw new IOException("deserialized key is invalid: " + e.getMessage()); } } public boolean equals(Object object) { if (this == object) { return true; } if (object instanceof Key) { Key key = (Key) object; byte[] b1; if (encodedKey != null) { b1 = encodedKey; } else { b1 = getEncoded(); } byte[] b2 = key.getEncoded(); return java.security.MessageDigest.isEqual(b1, b2); } return false; } /** * Calculates a hash code value for the object. Objects * which are equal will also have the same hashcode. */ public int hashCode() { int retval = 0; byte[] b1 = getEncoded(); for (int i = 1; i < b1.length; i++) { retval += b1[i] * i; } return (retval); } /* * Make a copy of the encoded key. */ private byte[] copyEncodedKey(byte[] encodedKey) { int len = encodedKey.length; byte[] copy = new byte[len]; System.arraycopy(encodedKey, 0, copy, 0, len); return copy; } /* * Produce SubjectPublicKey encoding from algorithm id and key material. */ static void encode(DerOutputStream out, AlgorithmId algid, byte[] key) throws IOException { DerOutputStream tmp = new DerOutputStream(); algid.encode(tmp); tmp.putBitString(key); out.write(DerValue.tag_Sequence, tmp); } /* * parsePublicKey returns a PublicKey for use with package JSS from within netscape.security.*. * This function provide an interim solution for migrating from using the netscape.security.* package * to using the JSS package. */ public static PublicKey parsePublicKey(DerValue in) throws IOException { AlgorithmId algorithm; PublicKey subjectKey; if (in.tag != DerValue.tag_Sequence) throw new IOException("corrupt subject key"); algorithm = AlgorithmId.parse(in.data.getDerValue()); try { subjectKey = buildPublicKey(algorithm, in.data.getBitString()); } catch (InvalidKeyException e) { throw new IOException("subject key, " + e.getMessage()); } if (in.data.available() != 0) throw new IOException("excess subject key"); return subjectKey; } /* buildPublicKey returns a PublicKey for use with the JSS package from within netscape.security.*. * This function provide an interim solution for migrating from using the netscape.security.* package * to using the JSS package. */ static PublicKey buildPublicKey(AlgorithmId algid, byte[] key) throws IOException, InvalidKeyException { /* * Use the algid and key parameters to produce the ASN.1 encoding * of the key, which will then be used as the input to the * key factory. */ DerOutputStream x509EncodedKeyStream = new DerOutputStream(); encode(x509EncodedKeyStream, algid, key); X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(x509EncodedKeyStream.toByteArray()); try { // Instantiate the key factory of the appropriate algorithm KeyFactory keyFac = null; if (Security.getProvider("Mozilla-JSS") == null) { keyFac = KeyFactory.getInstance(algid.getName()); } else { keyFac = KeyFactory.getInstance(algid.getName(), "Mozilla-JSS"); } // Generate the public key PublicKey pubKey = keyFac.generatePublic(x509KeySpec); /* * Return specialized X509Key, where the structure within the * key has been parsed */ return pubKey; } catch (NoSuchAlgorithmException e) { // Return generic X509Key with opaque key data (see below) throw new InvalidKeyException(e.toString()); } catch (InvalidKeySpecException e) { throw new InvalidKeyException(e.toString()); } catch (Exception e) { throw new InvalidKeyException(e.toString()); } } }