public class X509Extensions
extends java.lang.Object
The X.509v3 certificate format has been introduced by ISO/IEC and ANSI X9
to add the the Extensions field to the X.509v2 certificate format for
including some additional information. Extension support for CRLs has been
introduced by the X.509v2 CRL format (see RFC 3280). An extension may be a defined
standard extension (e.g. certificatePolicies,
keyUsage, ...), or it may be a private extension providing
some community-specific information. If an extension is marked as critical,
but the certificate handling software cannot parse this extension, the appertaining
certifcate has to be rejected. Non-Critical extensions can be ignored, if
they cannot be handled (i.e. of unknown state).
In ASN.1, the Extensions field is defined as a SEQUENCE of Extension:
Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
Extension ::= SEQUENCE {
extnID OBJECT IDENTIFIER,
critical BOOLEAN DEFAULT FALSE,
extnValue OCTET STRING }
where critical specifies whether an extension has to be treated
as being critical or not; the default value is FALSE. An extension can be
identified by its object identifier, given in the extnID field.
The value of the extension is represented as ASN.1 encoded OCTET STRING data
structure in the extnValue field. Only one instance of a particular
extension may be present in a particular certiifcate.
The X509v3 certificate profile presented in RFC 3280
prescribes that confirming CAs must support the AuthorityKeyIdentifier,
SubjectKeyIdentifer, BasicConstraints, KeyUsage
and CertificatePolicies extensions. The SubjectAltName
extensions has to be supported if certificates with empty subject fields are issued.
This class consits of two parts:
Every class which implements a specific extension must first register itself, e.g.:
MyPrivateExtension extens V3Extension {
...
public static final ObjectID oid = ...;
}
X509Extensions.register(MyPrivateExtension.oid, MyPrivateExtension.class);
At this time, per default, implementations of the following extensions are registered:
The dynamic part of this class provides a variety of useful methods for
managing extensions. Most of these methods are, for instance, internally called
within the X509Certificate
class for adding, accessing and removing extensions of a X509 certificate, or for
querying for the properties of included extensions.
This class manages extensions by maintaining two separate hashtables for storing
critical and noncritical extensions. When an extension has to be added to one of
the two hashtables by calling the addExtension
method, the DER encoded value of the extension is put into the corresponding hashtable
using the OID of the extension as key. In the same way, when an already existing
X509Extensions object is parsed for any included extensions, only their DER
encoded values are put into the hashtables. For saving time, the extensions are
not actually parsed for their internal structures at this time. Parsing some
extension is induced when reading it back from one of the hashtables by calling
getExtension(ObjectID). Only at this
time actually the appropriate implementation class is instantiated and initialized
through the DER encoded extension value derived from the corresponding hashtable.
If the initialization process fails for some reason, a X509ExtensionInitException
is thrown. If the extension just initialized is an unknown extension (i.e.
an extension, for which there exists no registered implementation), an UnknownExtension object is created
and returned by the getExtension method
to be parsed for obtaining as much information as possible from the unknown extension.
When using the listExtensions method
for obtaining all the extensions included in the actual X509Extensions
object, an enumeration is returned containing an UnknownExtension for
any included unknown extension, and an ErrorExtension for
any extension which cannot be initialized because it is burdened with some kind of
error. Note the difference: Within the IAIK-JCE environment, an unknown
extension denotes an extension, for which there exists no registered implementation;
whereas an error extension represents an - registered or unknown -
erroneous extension which cannot be parsed properly.
V3Extension,
X509Certificate,
RevokedCertificate,
X509CRL| Modifier and Type | Field and Description |
|---|---|
protected java.util.Hashtable |
critical_extensions
Repository for critical extensions.
|
protected java.util.Hashtable |
noncritical_extensions
Repository for noncritical extensions.
|
protected java.util.ArrayList<ObjectID> |
ordered_extensions
Used to keep track of extension order when encoding order is important
|
| Constructor and Description |
|---|
X509Extensions()
Default Constructor.
|
X509Extensions(ASN1Object extensions)
Creates a new X.509Extensions object from an ASN1Object.
|
| Modifier and Type | Method and Description |
|---|---|
boolean |
addExtension(V3Extension e)
Adds an extension to this
X509Extensions object. |
int |
countExtensions()
Returns the number of extensions included in this
X509Extensions
object. |
static V3Extension |
create(ObjectID oid)
Returns the implementation of the specified extension defined through an
ASN.1 ObjectID.
|
java.util.Set |
getCriticalExtensionOIDs()
Gets a Set of the OID strings for the extension(s) marked CRITICAL in
this X509Extensions object.
|
V3Extension |
getExtension(ObjectID oid)
Returns a particular extension, specified by its object ID.
|
byte[] |
getExtensionValue(java.lang.String oid)
Returns a byte array representing the DER encoding of the
extension value identified by the passed-in OID string.
|
java.util.Set |
getNonCriticalExtensionOIDs()
Gets a Set of the OID strings for the extension(s) marked NON-CRITICAL in this
X509Extensions object.
|
boolean |
hasExtensions()
Checks, if there are any extensions currently maintained by this
X509Extensions object.
|
boolean |
hasUnsupportedCriticalExtension()
Returns true if there are unsupported critical extensions.
|
java.util.Enumeration |
listExtensions()
Returns an enumeration of all extensions currently maintained by this
X509Extensions object. |
protected void |
parseExtensions(ASN1Object extObj)
Initializes the extensions from an ASN1Object.
|
static void |
register(ObjectID oid,
java.lang.Class cl)
Registers a new implementation for a X.509 certificate or CRL extension.
|
void |
removeAllExtensions()
Removes all extensions currently maintained by this X509Extensions object.
|
boolean |
removeExtension(ObjectID oid)
Removes an extension, identified by its object ID.
|
ASN1Object |
toASN1Object()
Returns this X509Extensions object as (SEQUENCE) ASN1Object.
|
ASN1Object |
toASN1Object(boolean ordered)
Returns this X509Extensions object as (SEQUENCE) ASN1Object.
|
java.lang.String |
toString()
Returns a string that represents the contents of the extensions.
|
protected java.util.Hashtable critical_extensions
protected java.util.Hashtable noncritical_extensions
protected java.util.ArrayList<ObjectID> ordered_extensions
public X509Extensions()
X509Extensions object to be supplied
with V3Extensions. Two hashtables - one for critical and the other
for non critical extensions - are created.public X509Extensions(ASN1Object extensions) throws X509ExtensionException
The given ASN1Object has the ASN.1 type "SEQUENCE of Extensions", and may
have been created by calling the toASN1Objetct method.
extensions - the extensions as ASN1ObjectX509ExtensionException - if the extensions cannot be parsedpublic static V3Extension create(ObjectID oid) throws java.lang.InstantiationException
This method belongs to the static part of this class.
oid - the ObjectID of the extension.java.lang.InstantiationException - if the internal factory
couldn't create an instance of requested typepublic static void register(ObjectID oid, java.lang.Class cl)
oid - the object id of the extension to be registeredclass - the class which implements this extensionpublic boolean addExtension(V3Extension e) throws X509ExtensionException
X509Extensions object.
The extension to be added shall be an implemented V3Extension. This class manages extensions by
maintaining two separate hashtables for storing critical and noncritical
extensions. Only the DER encoded value of the given extension is put into
the corresponding hashtable using the OID of the extension as key. If an
extension with the same object ID already exists (either critical or
non-critical), it is replaced. In this case this method returns
true, otherwise - if there exists no extension with the
same object ID - this method returns false. For reading
back some extension from one of the hashtables, use the
getExtension(ObjectID) method. Only at this time
actually the appropriate implementation class is created and initialized
through the DER encoded extension value derived from the corresponding
hashtable.
e - the X509v3 extension to add to the list of extensionstrue, if an extension with the same object id has
been replaced, or false if there has yet not been
included any extension with the same ObjectIDX509ExtensionException - if an error occurs while DER encoding the extensionpublic boolean removeExtension(ObjectID oid)
objectID - the object ID of the extension to removetrue if the extension successfully has been removed,
false otherwisepublic void removeAllExtensions()
public java.util.Enumeration listExtensions()
X509Extensions object.
The enumeration returned by this method will contain an UnknownExtension
for any included unknown extension, and an ErrorExtension for
any extension which cannot be initialized because it is burdened with some kind of
error.
public boolean hasExtensions()
true if there are extensions, false if notpublic int countExtensions()
X509Extensions
object.public V3Extension getExtension(ObjectID oid) throws X509ExtensionInitException
This method creates a new implementation of the class registered for
this ObjectID and initializes it with the extension value derived from the
corresponding hashtable.
If the extension is an unknown extension, an UnknownExtension
is returned. If the extension cannot be initialized properly because
of some error, an X509ExtensionInitException is thrown.
objectID - the object ID of the extensionnull if notX509ExtensionInitException - if the extension can not be initializedpublic java.util.Set getCriticalExtensionOIDs()
nullpublic java.util.Set getNonCriticalExtensionOIDs()
null.public boolean hasUnsupportedCriticalExtension()
public byte[] getExtensionValue(java.lang.String oid)
The OID string is represented by a set of positive whole numbers separated
by periods, e.g. "2.5.29.15" for the KeyUsage extension.
In ASN.1, the Extensions field is defined as a SEQUENCE of Extension:
Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
Extension ::= SEQUENCE {
extnID OBJECT IDENTIFIER,
critical BOOLEAN DEFAULT FALSE,
extnValue OCTET STRING }
where critical specifies whether an extension has to be treated
as being critical or not; the default value is FALSE. An extension can be
identified by its object identifier, given in the extnID field.
The value of the extension is represented as ASN.1 OCTET STRING data
structure in the extnValue field. Only one instance of a particular
extension may be present in a particular certificate.
The byte value returned by this method represents the DER encoding of the extnValue (OCTET_STRING) from above, and the value of this OCTET STRING represents the DER encoding of the specific extension's ASN.1 representation itsself.
Attention: For compatibility reasons to the standard JCA certificate API this method has been changed to return the OCTET STRING value as described above. Prior versions of this class have returned the DER encoding of the specific extension's ASN.1 representation itsself.
oid - the Object Identifier value for the extensionnull if it is not presentprotected void parseExtensions(ASN1Object extObj) throws X509ExtensionException
The ASN1Object must be an ASN.1 datastructure "SEQUENCE of Extensions", as can be found in X509v3 certificates or X509v2 CRLs.
The given ASN1Object is parsed for any included extension. For each
included extension, the DER encoded extension value is computed and
put into one of two hashtables for critical respectively non-critical
extensions. For actually getting an implematation of some included
extension call the getExtension
method. For getting an enumeration of all included extensions, use the
listExtensions() method.
extObj - the ASN.1 datastructure "SEQUENCE of Extensions"X509ExtensionException - if there is an error while parsing the extensionsUnknownExtensionpublic ASN1Object toASN1Object() throws X509ExtensionException
If the value of the System property:
iaik.x509.X509Extensions.keepOrder=true
Then the ordering of the encoded extensions will be maintained. By default
the value of keepOrder is false. When set to false, the ordering of the extensions
is not important and could change on subsequent encodings.X509ExtensionException - if the extensions could not be createdpublic ASN1Object toASN1Object(boolean ordered) throws X509ExtensionException
ordered - set to true if the extension ordering matters, false otherwiseX509ExtensionException - if the extensions could not be createdpublic java.lang.String toString()
toString in class java.lang.Object