Logo Search packages:      
Sourcecode: bouncycastle version File versions  Download package

TrustAnchor.java

package java.security.cert;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.security.PublicKey;

import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.DERInputStream;
import org.bouncycastle.asn1.DERObject;

/**
 * A trust anchor or most-trusted Certification Authority (CA). <br />
 * <br />
 * This class represents a "most-trusted CA", which is used as a trust anchor
 * for validating X.509 certification paths. A most-trusted CA includes the
 * public key of the CA, the CA's name, and any constraints upon the set of
 * paths which may be validated using this key. These parameters can be
 * specified in the form of a trusted X509Certificate or as individual
 * parameters. <br />
 * <br />
 * <strong>Concurrent Access</strong><br />
 * <br />
 * All TrustAnchor objects must be immutable and thread-safe. That is, multiple
 * threads may concurrently invoke the methods defined in this class on a
 * single TrustAnchor object (or more than one) with no ill effects. Requiring
 * TrustAnchor objects to be immutable and thread-safe allows them to be passed
 * around to various pieces of code without worrying about coordinating access.
 * This stipulation applies to all public fields and methods of this class and
 * any added or overridden by subclasses.<br />
 * <br />
 * <b>TODO: implement better nameConstraints testing.</b>
 **/
00033 public class TrustAnchor
{
    private X509Certificate trustCert = null;
    private PublicKey       trustPublicKey = null;
    private String          trustName = null;
    private byte[]          nameConstraints = null;

    /**
     * Creates an instance of TrustAnchor with the specified
     * X509Certificate and optional name constraints, which are
     * intended to be used as additional constraints when
     * validating an X.509 certification path.<br />
     * <br /> 
     * The name constraints are specified as a byte array. This
     * byte array should contain the DER encoded form of the name
     * constraints, as they would appear in the NameConstraints
     * structure defined in RFC 2459 and X.509. The ASN.1
     * definition of this structure appears below.<br />
     * <br />
     * <pre>
     *  NameConstraints ::= SEQUENCE {
     *       permittedSubtrees       [0]     GeneralSubtrees OPTIONAL,
     *       excludedSubtrees        [1]     GeneralSubtrees OPTIONAL }
     *
     *  GeneralSubtrees ::= SEQUENCE SIZE (1..MAX) OF GeneralSubtree
     *
     *  GeneralSubtree ::= SEQUENCE {
     *       base                    GeneralName,
     *       minimum         [0]     BaseDistance DEFAULT 0,
     *       maximum         [1]     BaseDistance OPTIONAL }
     *
     *  BaseDistance ::= INTEGER (0..MAX)
     *
     *  GeneralName ::= CHOICE {
     *       otherName                       [0]     OtherName,
     *       rfc822Name                      [1]     IA5String,
     *       dNSName                         [2]     IA5String,
     *       x400Address                     [3]     ORAddress,
     *       directoryName                   [4]     Name,
     *       ediPartyName                    [5]     EDIPartyName,
     *       uniformResourceIdentifier       [6]     IA5String,
     *       iPAddress                       [7]     OCTET STRING,
     *       registeredID                    [8]     OBJECT IDENTIFIER}
     * </pre><br />
     * <br />
     * Note that the name constraints byte array supplied is
     * cloned to protect against subsequent modifications.
     *
     * @param trustedCert a trusted X509Certificate
     * @param nameConstraints a byte array containing the ASN.1
     * DER encoding of a NameConstraints extension to be used for
     * checking name constraints. Only the value of the extension
     * is included, not the OID or criticality flag. Specify null
     * to omit the parameter.
     *
     * @exception IllegalArgumentException if the name constraints
     * cannot be decoded
     * @exception NullPointerException if the specified X509Certificate is null
     **/
00092     public TrustAnchor( X509Certificate trustedCert,
            byte[] nameConstraints)
    {
    if ( trustedCert == null )
        throw new NullPointerException( "trustedCert must be non-null" );

    this.trustCert = trustedCert;
    if ( nameConstraints != null )
    {
        this.nameConstraints = (byte[])nameConstraints.clone();
        checkNameConstraints(this.nameConstraints);
    }
    }

    /**
     * Creates an instance of <code>TrustAnchor</code> where the most-trusted
     * CA is specified as a distinguished name and public
     * key. Name constraints are an optional parameter, and are
     * intended to be used as additional constraints when
     * validating an X.509 certification path.
     * 
     * The name constraints are specified as a byte array. This
     * byte array contains the DER encoded form of the name
     * constraints, as they would appear in the NameConstraints
     * structure defined in RFC 2459 and X.509. The ASN.1 notation
     * for this structure is supplied in the documentation for
     * {@link #TrustAnchor(X509Certificate trustedCert, byte[]
     * nameConstraints) TrustAnchor(X509Certificate trustedCert,
     * byte[] nameConstraints) }.
     *
     * Note that the name constraints byte array supplied here is
     * cloned to protect against subsequent modifications.
     *
     * @param caName the X.500 distinguished name of the
     * most-trusted CA in RFC 2253 String format
     * @param pubKey the public key of the most-trusted CA
     * @param nameConstraints a byte array containing the ASN.1
     * DER encoding of a NameConstraints extension to be used for
     * checking name constraints. Only the value of the extension
     * is included, not the OID or criticality flag. Specify null
     * to omit the parameter.
     *
     * @exception IllegalArgumentException if the specified caName
     * parameter is empty (<code>caName.length() == 0</code>) or incorrectly
     * formatted or the name constraints cannot be decoded
     * @exception NullPointerException if the specified caName or pubKey parameter is null
     **/
00139     public TrustAnchor(String caName, PublicKey pubKey,
               byte[] nameConstraints)
    {
    if ( caName == null )
        throw new NullPointerException( "caName must be non-null" );
    if ( pubKey == null )
        throw new NullPointerException( "pubKey must be non-null" );
    if ( caName.length() == 0 )
        throw new IllegalArgumentException( "caName can not be an empty string" );

    this.trustName = caName;
    this.trustPublicKey = pubKey;
    if ( nameConstraints != null )
    {
        this.nameConstraints = (byte[])nameConstraints.clone();
        checkNameConstraints(this.nameConstraints);
    }
    }

    /**
     * Returns the most-trusted CA certificate.
     *
     * @return a trusted <code>X509Certificate</code> or <code>null</code> if the trust
     * anchor was not specified as a trusted certificate
     **/
00164     public final X509Certificate getTrustedCert()
    {
    return trustCert;
    }

    /**
     * Returns the name of the most-trusted CA in RFC 2253 String
     * format.
     *
     * @return the X.500 distinguished name of the most-trusted
     * CA, or <code>null</code> if the trust anchor was not specified as a
     * trusted public key and name pair
     **/
00177     public final String getCAName()
    {
    return trustName;
    }

    /**
     * Returns the public key of the most-trusted CA.
     *
     * @return the public key of the most-trusted CA, or null if
     * the trust anchor was not specified as a trusted public key
     * and name pair
     **/
00189     public final PublicKey getCAPublicKey()
    {
    return trustPublicKey;
    }

    /**
     * Returns the name constraints parameter. The specified name
     * constraints are associated with this trust anchor and are
     * intended to be used as additional constraints when
     * validating an X.509 certification path.<br />
     * <br />
     * The name constraints are returned as a byte array. This
     * byte array contains the DER encoded form of the name
     * constraints, as they would appear in the NameConstraints
     * structure defined in RFC 2459 and X.509. The ASN.1 notation
     * for this structure is supplied in the documentation for
     * <code>TrustAnchor(X509Certificate trustedCert, byte[]
     * nameConstraints)</code>.<br />
     * <br />
     * Note that the byte array returned is cloned to protect against subsequent modifications.
     *
     * @return a byte array containing the ASN.1 DER encoding of a
     * NameConstraints extension used for checking name
     * constraints, or <code>null</code> if not set.
     **/
00214     public final byte[] getNameConstraints()
    {
    return (byte[])nameConstraints.clone();
    }

    /**
     * Returns a formatted string describing the <code>TrustAnchor</code>.
     *
     * @return a formatted string describing the <code>TrustAnchor</code>
     */
00224     public String toString()
    {
    StringBuffer sb = new StringBuffer();
    sb.append("[\n");
    if ( getCAPublicKey() != null) {
        sb.append("  Trusted CA Public Key: " + getCAPublicKey() + "\n");
        sb.append("  Trusted CA Issuer Name: " + getCAName() + "\n");
    } else {
        sb.append("  Trusted CA cert: " + getTrustedCert() + "\n");
    }
    if (nameConstraints != null)
        sb.append("  Name Constraints: " + nameConstraints.toString() + "\n");
    return sb.toString();
    }

    /**
     * Check given DER encoded nameConstraints for correct decoding.
     * Currently only basic DER decoding test.<br />
     * <br />
     * <b>TODO: implement more testing.</b>
     *
     * @param data the DER encoded nameConstrains to be checked or <code>null</code>
     * @exception IllegalArgumentException if the check failed.
     **/
00248     private void checkNameConstraints(byte[] data)
    {
    if ( data != null )
    {
        try {
        ByteArrayInputStream inStream = new ByteArrayInputStream(data);
        DERInputStream derInStream = new DERInputStream( inStream );
        DERObject derObject = derInStream.readObject();
        if ( derObject == null || ! ( derObject instanceof ASN1Sequence ) )
            throw new IllegalArgumentException("nameConstraints parameter decoding error");
        } catch ( IOException ex ) {
        throw new IllegalArgumentException("nameConstraints parameter decoding error: " + ex);
        }
    }
    }
}

Generated by  Doxygen 1.6.0   Back to index