diff options
Diffstat (limited to 'Crypto/src/pkix/TrustAnchor.cs')
-rw-r--r-- | Crypto/src/pkix/TrustAnchor.cs | 259 |
1 files changed, 259 insertions, 0 deletions
diff --git a/Crypto/src/pkix/TrustAnchor.cs b/Crypto/src/pkix/TrustAnchor.cs new file mode 100644 index 000000000..22078baf2 --- /dev/null +++ b/Crypto/src/pkix/TrustAnchor.cs @@ -0,0 +1,259 @@ +using System; +using System.IO; +using System.Text; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.X509; + +namespace Org.BouncyCastle.Pkix +{ + /// <summary> + /// A trust anchor or most-trusted Certification Authority (CA). + /// + /// 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. + /// </summary> + public class TrustAnchor + { + private readonly AsymmetricKeyParameter pubKey; + private readonly string caName; + private readonly X509Name caPrincipal; + private readonly X509Certificate trustedCert; + private byte[] ncBytes; + private NameConstraints nc; + + /// <summary> + /// 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. + /// 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. + /// + /// <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> + /// + /// Note that the name constraints byte array supplied is cloned to protect + /// against subsequent modifications. + /// </summary> + /// <param name="trustedCert">a trusted X509Certificate</param> + /// <param name="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.</param> + /// <exception cref="ArgumentNullException">if the specified X509Certificate is null</exception> + public TrustAnchor( + X509Certificate trustedCert, + byte[] nameConstraints) + { + if (trustedCert == null) + throw new ArgumentNullException("trustedCert"); + + this.trustedCert = trustedCert; + this.pubKey = null; + this.caName = null; + this.caPrincipal = null; + setNameConstraints(nameConstraints); + } + + /// <summary> + /// Creates an instance of <c>TrustAnchor</c> where the + /// most-trusted CA is specified as an X500Principal and public key. + /// </summary> + /// <remarks> + /// <p> + /// Name constraints are an optional parameter, and are intended to be used + /// as additional constraints when validating an X.509 certification path. + /// </p><p> + /// 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 the other constructors. + /// </p><p> + /// Note that the name constraints byte array supplied here is cloned to + /// protect against subsequent modifications. + /// </p> + /// </remarks> + /// <param name="caPrincipal">the name of the most-trusted CA as X509Name</param> + /// <param name="pubKey">the public key of the most-trusted CA</param> + /// <param name="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 <c>null</c> to omit the parameter. + /// </param> + /// <exception cref="ArgumentNullException"> + /// if <c>caPrincipal</c> or <c>pubKey</c> is null + /// </exception> + public TrustAnchor( + X509Name caPrincipal, + AsymmetricKeyParameter pubKey, + byte[] nameConstraints) + { + if (caPrincipal == null) + throw new ArgumentNullException("caPrincipal"); + if (pubKey == null) + throw new ArgumentNullException("pubKey"); + + this.trustedCert = null; + this.caPrincipal = caPrincipal; + this.caName = caPrincipal.ToString(); + this.pubKey = pubKey; + setNameConstraints(nameConstraints); + } + + /// <summary> + /// 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. + /// <br/> + /// 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. + /// </summary> + /// <param name="caName">the X.500 distinguished name of the most-trusted CA in RFC + /// 2253 string format</param> + /// <param name="pubKey">the public key of the most-trusted CA</param> + /// <param name="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.</param> + /// throws NullPointerException, IllegalArgumentException + public TrustAnchor( + string caName, + AsymmetricKeyParameter pubKey, + byte[] nameConstraints) + { + if (caName == null) + throw new ArgumentNullException("caName"); + if (pubKey == null) + throw new ArgumentNullException("pubKey"); + if (caName.Length == 0) + throw new ArgumentException("caName can not be an empty string"); + + this.caPrincipal = new X509Name(caName); + this.pubKey = pubKey; + this.caName = caName; + this.trustedCert = null; + setNameConstraints(nameConstraints); + } + + /// <summary> + /// Returns the most-trusted CA certificate. + /// </summary> + public X509Certificate TrustedCert + { + get { return this.trustedCert; } + } + + /// <summary> + /// Returns the name of the most-trusted CA as an X509Name. + /// </summary> + public X509Name CA + { + get { return this.caPrincipal; } + } + + /// <summary> + /// Returns the name of the most-trusted CA in RFC 2253 string format. + /// </summary> + public string CAName + { + get { return this.caName; } + } + + /// <summary> + /// Returns the public key of the most-trusted CA. + /// </summary> + public AsymmetricKeyParameter CAPublicKey + { + get { return this.pubKey; } + } + + /// <summary> + /// Decode the name constraints and clone them if not null. + /// </summary> + private void setNameConstraints( + byte[] bytes) + { + if (bytes == null) + { + ncBytes = null; + nc = null; + } + else + { + ncBytes = (byte[]) bytes.Clone(); + // validate DER encoding + //nc = new NameConstraintsExtension(Boolean.FALSE, bytes); + nc = NameConstraints.GetInstance(Asn1Object.FromByteArray(bytes)); + } + } + + public byte[] GetNameConstraints + { + get { return Arrays.Clone(ncBytes); } + } + + /// <summary> + /// Returns a formatted string describing the <code>TrustAnchor</code>. + /// </summary> + /// <returns>a formatted string describing the <code>TrustAnchor</code></returns> + public override string ToString() + { + // TODO Some of the sub-objects might not implement ToString() properly + string nl = Platform.NewLine; + StringBuilder sb = new StringBuilder(); + sb.Append("["); + sb.Append(nl); + if (this.pubKey != null) + { + sb.Append(" Trusted CA Public Key: ").Append(this.pubKey).Append(nl); + sb.Append(" Trusted CA Issuer Name: ").Append(this.caName).Append(nl); + } + else + { + sb.Append(" Trusted CA cert: ").Append(this.TrustedCert).Append(nl); + } + if (nc != null) + { + sb.Append(" Name Constraints: ").Append(nc).Append(nl); + } + return sb.ToString(); + } + } +} \ No newline at end of file |