// --- 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).
*
*
* @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;
/**
*
*/
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.
*
*
*/
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.
*
*