Initial Commit

This commit is contained in:
2023-06-21 12:46:23 -04:00
commit c70248a520
1352 changed files with 336780 additions and 0 deletions

View File

@@ -0,0 +1,420 @@
using System;
using System.Collections;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Security.Certificates;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.X509.Store;
namespace Org.BouncyCastle.X509
{
/// <remarks>
/// The Holder object.
/// <pre>
/// Holder ::= SEQUENCE {
/// baseCertificateID [0] IssuerSerial OPTIONAL,
/// -- the issuer and serial number of
/// -- the holder's Public Key Certificate
/// entityName [1] GeneralNames OPTIONAL,
/// -- the name of the claimant or role
/// objectDigestInfo [2] ObjectDigestInfo OPTIONAL
/// -- used to directly authenticate the holder,
/// -- for example, an executable
/// }
/// </pre>
/// </remarks>
public class AttributeCertificateHolder
//: CertSelector, Selector
: IX509Selector
{
internal readonly Holder holder;
internal AttributeCertificateHolder(
Asn1Sequence seq)
{
holder = Holder.GetInstance(seq);
}
public AttributeCertificateHolder(
X509Name issuerName,
BigInteger serialNumber)
{
holder = new Holder(
new IssuerSerial(
GenerateGeneralNames(issuerName),
new DerInteger(serialNumber)));
}
public AttributeCertificateHolder(
X509Certificate cert)
{
X509Name name;
try
{
name = PrincipalUtilities.GetIssuerX509Principal(cert);
}
catch (Exception e)
{
throw new CertificateParsingException(e.Message);
}
holder = new Holder(new IssuerSerial(GenerateGeneralNames(name), new DerInteger(cert.SerialNumber)));
}
public AttributeCertificateHolder(
X509Name principal)
{
holder = new Holder(GenerateGeneralNames(principal));
}
/**
* Constructs a holder for v2 attribute certificates with a hash value for
* some type of object.
* <p>
* <code>digestedObjectType</code> can be one of the following:
* <ul>
* <li>0 - publicKey - A hash of the public key of the holder must be
* passed.</li>
* <li>1 - publicKeyCert - A hash of the public key certificate of the
* holder must be passed.</li>
* <li>2 - otherObjectDigest - A hash of some other object type must be
* passed. <code>otherObjectTypeID</code> must not be empty.</li>
* </ul>
* </p>
* <p>This cannot be used if a v1 attribute certificate is used.</p>
*
* @param digestedObjectType The digest object type.
* @param digestAlgorithm The algorithm identifier for the hash.
* @param otherObjectTypeID The object type ID if
* <code>digestedObjectType</code> is
* <code>otherObjectDigest</code>.
* @param objectDigest The hash value.
*/
public AttributeCertificateHolder(
int digestedObjectType,
string digestAlgorithm,
string otherObjectTypeID,
byte[] objectDigest)
{
// TODO Allow 'objectDigest' to be null?
holder = new Holder(new ObjectDigestInfo(digestedObjectType, otherObjectTypeID,
new AlgorithmIdentifier(digestAlgorithm), Arrays.Clone(objectDigest)));
}
/**
* Returns the digest object type if an object digest info is used.
* <p>
* <ul>
* <li>0 - publicKey - A hash of the public key of the holder must be
* passed.</li>
* <li>1 - publicKeyCert - A hash of the public key certificate of the
* holder must be passed.</li>
* <li>2 - otherObjectDigest - A hash of some other object type must be
* passed. <code>otherObjectTypeID</code> must not be empty.</li>
* </ul>
* </p>
*
* @return The digest object type or -1 if no object digest info is set.
*/
public int DigestedObjectType
{
get
{
ObjectDigestInfo odi = holder.ObjectDigestInfo;
return odi == null
? -1
: odi.DigestedObjectType.Value.IntValue;
}
}
/**
* Returns the other object type ID if an object digest info is used.
*
* @return The other object type ID or <code>null</code> if no object
* digest info is set.
*/
public string DigestAlgorithm
{
get
{
ObjectDigestInfo odi = holder.ObjectDigestInfo;
return odi == null
? null
: odi.DigestAlgorithm.ObjectID.Id;
}
}
/**
* Returns the hash if an object digest info is used.
*
* @return The hash or <code>null</code> if no object digest info is set.
*/
public byte[] GetObjectDigest()
{
ObjectDigestInfo odi = holder.ObjectDigestInfo;
return odi == null
? null
: odi.ObjectDigest.GetBytes();
}
/**
* Returns the digest algorithm ID if an object digest info is used.
*
* @return The digest algorithm ID or <code>null</code> if no object
* digest info is set.
*/
public string OtherObjectTypeID
{
get
{
ObjectDigestInfo odi = holder.ObjectDigestInfo;
return odi == null
? null
: odi.OtherObjectTypeID.Id;
}
}
private GeneralNames GenerateGeneralNames(
X509Name principal)
{
// return GeneralNames.GetInstance(new DerSequence(new GeneralName(principal)));
return new GeneralNames(new GeneralName(principal));
}
private bool MatchesDN(
X509Name subject,
GeneralNames targets)
{
GeneralName[] names = targets.GetNames();
for (int i = 0; i != names.Length; i++)
{
GeneralName gn = names[i];
if (gn.TagNo == GeneralName.DirectoryName)
{
try
{
if (X509Name.GetInstance(gn.Name).Equivalent(subject))
{
return true;
}
}
catch (Exception)
{
}
}
}
return false;
}
private object[] GetNames(
GeneralName[] names)
{
ArrayList l = new ArrayList(names.Length);
for (int i = 0; i != names.Length; i++)
{
if (names[i].TagNo == GeneralName.DirectoryName)
{
l.Add(X509Name.GetInstance(names[i].Name));
}
}
return l.ToArray();
}
private X509Name[] GetPrincipals(
GeneralNames names)
{
object[] p = this.GetNames(names.GetNames());
ArrayList l = new ArrayList(p.Length);
for (int i = 0; i != p.Length; i++)
{
if (p[i] is X509Name)
{
l.Add(p[i]);
}
}
return (X509Name[]) l.ToArray(typeof(X509Name));
}
/**
* Return any principal objects inside the attribute certificate holder entity names field.
*
* @return an array of IPrincipal objects (usually X509Name), null if no entity names field is set.
*/
public X509Name[] GetEntityNames()
{
if (holder.EntityName != null)
{
return GetPrincipals(holder.EntityName);
}
return null;
}
/**
* Return the principals associated with the issuer attached to this holder
*
* @return an array of principals, null if no BaseCertificateID is set.
*/
public X509Name[] GetIssuer()
{
if (holder.BaseCertificateID != null)
{
return GetPrincipals(holder.BaseCertificateID.Issuer);
}
return null;
}
/**
* Return the serial number associated with the issuer attached to this holder.
*
* @return the certificate serial number, null if no BaseCertificateID is set.
*/
public BigInteger SerialNumber
{
get
{
if (holder.BaseCertificateID != null)
{
return holder.BaseCertificateID.Serial.Value;
}
return null;
}
}
public object Clone()
{
return new AttributeCertificateHolder((Asn1Sequence)holder.ToAsn1Object());
}
public bool Match(
// Certificate cert)
X509Certificate x509Cert)
{
// if (!(cert is X509Certificate))
// {
// return false;
// }
//
// X509Certificate x509Cert = (X509Certificate)cert;
try
{
if (holder.BaseCertificateID != null)
{
return holder.BaseCertificateID.Serial.Value.Equals(x509Cert.SerialNumber)
&& MatchesDN(PrincipalUtilities.GetIssuerX509Principal(x509Cert), holder.BaseCertificateID.Issuer);
}
if (holder.EntityName != null)
{
if (MatchesDN(PrincipalUtilities.GetSubjectX509Principal(x509Cert), holder.EntityName))
{
return true;
}
}
if (holder.ObjectDigestInfo != null)
{
IDigest md = null;
try
{
md = DigestUtilities.GetDigest(DigestAlgorithm);
}
catch (Exception)
{
return false;
}
switch (DigestedObjectType)
{
case ObjectDigestInfo.PublicKey:
{
// TODO: DSA Dss-parms
//byte[] b = x509Cert.GetPublicKey().getEncoded();
// TODO Is this the right way to encode?
byte[] b = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(
x509Cert.GetPublicKey()).GetEncoded();
md.BlockUpdate(b, 0, b.Length);
break;
}
case ObjectDigestInfo.PublicKeyCert:
{
byte[] b = x509Cert.GetEncoded();
md.BlockUpdate(b, 0, b.Length);
break;
}
// TODO Default handler?
}
// TODO Shouldn't this be the other way around?
if (!Arrays.AreEqual(DigestUtilities.DoFinal(md), GetObjectDigest()))
{
return false;
}
}
}
catch (CertificateEncodingException)
{
return false;
}
return false;
}
public override bool Equals(
object obj)
{
if (obj == this)
{
return true;
}
if (!(obj is AttributeCertificateHolder))
{
return false;
}
AttributeCertificateHolder other = (AttributeCertificateHolder)obj;
return this.holder.Equals(other.holder);
}
public override int GetHashCode()
{
return this.holder.GetHashCode();
}
public bool Match(
object obj)
{
if (!(obj is X509Certificate))
{
return false;
}
// return Match((Certificate)obj);
return Match((X509Certificate)obj);
}
}
}

View File

@@ -0,0 +1,177 @@
using System;
using System.Collections;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.X509.Store;
namespace Org.BouncyCastle.X509
{
/**
* Carrying class for an attribute certificate issuer.
*/
public class AttributeCertificateIssuer
//: CertSelector, Selector
: IX509Selector
{
internal readonly Asn1Encodable form;
/**
* Set the issuer directly with the ASN.1 structure.
*
* @param issuer The issuer
*/
internal AttributeCertificateIssuer(
AttCertIssuer issuer)
{
form = issuer.Issuer;
}
public AttributeCertificateIssuer(
X509Name principal)
{
// form = new V2Form(GeneralNames.GetInstance(new DerSequence(new GeneralName(principal))));
form = new V2Form(new GeneralNames(new GeneralName(principal)));
}
private object[] GetNames()
{
GeneralNames name;
if (form is V2Form)
{
name = ((V2Form)form).IssuerName;
}
else
{
name = (GeneralNames)form;
}
GeneralName[] names = name.GetNames();
ArrayList l = new ArrayList(names.Length);
for (int i = 0; i != names.Length; i++)
{
if (names[i].TagNo == GeneralName.DirectoryName)
{
l.Add(X509Name.GetInstance(names[i].Name));
}
}
return l.ToArray();
}
/// <summary>Return any principal objects inside the attribute certificate issuer object.</summary>
/// <returns>An array of IPrincipal objects (usually X509Principal).</returns>
public X509Name[] GetPrincipals()
{
object[] p = this.GetNames();
ArrayList l = new ArrayList(p.Length);
for (int i = 0; i != p.Length; i++)
{
if (p[i] is X509Name)
{
l.Add(p[i]);
}
}
return (X509Name[]) l.ToArray(typeof(X509Name));
}
private bool MatchesDN(
X509Name subject,
GeneralNames targets)
{
GeneralName[] names = targets.GetNames();
for (int i = 0; i != names.Length; i++)
{
GeneralName gn = names[i];
if (gn.TagNo == GeneralName.DirectoryName)
{
try
{
if (X509Name.GetInstance(gn.Name).Equivalent(subject))
{
return true;
}
}
catch (Exception)
{
}
}
}
return false;
}
public object Clone()
{
return new AttributeCertificateIssuer(AttCertIssuer.GetInstance(form));
}
public bool Match(
// Certificate cert)
X509Certificate x509Cert)
{
// if (!(cert is X509Certificate))
// {
// return false;
// }
//
// X509Certificate x509Cert = (X509Certificate)cert;
if (form is V2Form)
{
V2Form issuer = (V2Form) form;
if (issuer.BaseCertificateID != null)
{
return issuer.BaseCertificateID.Serial.Value.Equals(x509Cert.SerialNumber)
&& MatchesDN(x509Cert.IssuerDN, issuer.BaseCertificateID.Issuer);
}
return MatchesDN(x509Cert.SubjectDN, issuer.IssuerName);
}
return MatchesDN(x509Cert.SubjectDN, (GeneralNames) form);
}
public override bool Equals(
object obj)
{
if (obj == this)
{
return true;
}
if (!(obj is AttributeCertificateIssuer))
{
return false;
}
AttributeCertificateIssuer other = (AttributeCertificateIssuer)obj;
return this.form.Equals(other.form);
}
public override int GetHashCode()
{
return this.form.GetHashCode();
}
public bool Match(
object obj)
{
if (!(obj is X509Certificate))
{
return false;
}
//return Match((Certificate)obj);
return Match((X509Certificate)obj);
}
}
}

View File

@@ -0,0 +1,57 @@
using System;
using System.IO;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Math;
namespace Org.BouncyCastle.X509
{
/// <remarks>Interface for an X.509 Attribute Certificate.</remarks>
public interface IX509AttributeCertificate
: IX509Extension
{
/// <summary>The version number for the certificate.</summary>
int Version { get; }
/// <summary>The serial number for the certificate.</summary>
BigInteger SerialNumber { get; }
/// <summary>The UTC DateTime before which the certificate is not valid.</summary>
DateTime NotBefore { get; }
/// <summary>The UTC DateTime after which the certificate is not valid.</summary>
DateTime NotAfter { get; }
/// <summary>The holder of the certificate.</summary>
AttributeCertificateHolder Holder { get; }
/// <summary>The issuer details for the certificate.</summary>
AttributeCertificateIssuer Issuer { get; }
/// <summary>Return the attributes contained in the attribute block in the certificate.</summary>
/// <returns>An array of attributes.</returns>
X509Attribute[] GetAttributes();
/// <summary>Return the attributes with the same type as the passed in oid.</summary>
/// <param name="oid">The object identifier we wish to match.</param>
/// <returns>An array of matched attributes, null if there is no match.</returns>
X509Attribute[] GetAttributes(string oid);
bool[] GetIssuerUniqueID();
bool IsValidNow { get; }
bool IsValid(DateTime date);
void CheckValidity();
void CheckValidity(DateTime date);
byte[] GetSignature();
void Verify(AsymmetricKeyParameter publicKey);
/// <summary>Return an ASN.1 encoded byte array representing the attribute certificate.</summary>
/// <returns>An ASN.1 encoded byte array.</returns>
/// <exception cref="IOException">If the certificate cannot be encoded.</exception>
byte[] GetEncoded();
}
}

View File

@@ -0,0 +1,27 @@
using System;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Utilities.Collections;
namespace Org.BouncyCastle.X509
{
public interface IX509Extension
{
/// <summary>
/// Get all critical extension values, by oid
/// </summary>
/// <returns>IDictionary with DerObjectIdentifier keys and Asn1OctetString values</returns>
ISet GetCriticalExtensionOids();
/// <summary>
/// Get all non-critical extension values, by oid
/// </summary>
/// <returns>IDictionary with DerObjectIdentifier keys and Asn1OctetString values</returns>
ISet GetNonCriticalExtensionOids();
[Obsolete("Use version taking a DerObjectIdentifier instead")]
Asn1OctetString GetExtensionValue(string oid);
Asn1OctetString GetExtensionValue(DerObjectIdentifier oid);
}
}

View File

@@ -0,0 +1,94 @@
using System;
using System.IO;
using System.Text;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Utilities.Encoders;
namespace Org.BouncyCastle.X509
{
class PemParser
{
private readonly string _header1;
private readonly string _header2;
private readonly string _footer1;
private readonly string _footer2;
internal PemParser(
string type)
{
_header1 = "-----BEGIN " + type + "-----";
_header2 = "-----BEGIN X509 " + type + "-----";
_footer1 = "-----END " + type + "-----";
_footer2 = "-----END X509 " + type + "-----";
}
private string ReadLine(
Stream inStream)
{
int c;
StringBuilder l = new StringBuilder();
do
{
while (((c = inStream.ReadByte()) != '\r') && c != '\n' && (c >= 0))
{
if (c == '\r')
{
continue;
}
l.Append((char)c);
}
}
while (c >= 0 && l.Length == 0);
if (c < 0)
{
return null;
}
return l.ToString();
}
internal Asn1Sequence ReadPemObject(
Stream inStream)
{
string line;
StringBuilder pemBuf = new StringBuilder();
while ((line = ReadLine(inStream)) != null)
{
if (line.Equals(_header1) || line.Equals(_header2))
{
break;
}
}
while ((line = ReadLine(inStream)) != null)
{
if (line.Equals(_footer1) || line.Equals(_footer2))
{
break;
}
pemBuf.Append(line);
}
if (pemBuf.Length != 0)
{
Asn1Object o = Asn1Object.FromByteArray(Base64.Decode(pemBuf.ToString()));
if (!(o is Asn1Sequence))
{
throw new IOException("malformed PEM data encountered");
}
return (Asn1Sequence) o;
}
return null;
}
}
}

View File

@@ -0,0 +1,70 @@
using System;
using System.IO;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Security.Certificates;
namespace Org.BouncyCastle.X509
{
/// <remarks>
/// A utility class that will extract X509Principal objects from X.509 certificates.
/// <p>
/// Use this in preference to trying to recreate a principal from a string, not all
/// DNs are what they should be, so it's best to leave them encoded where they
/// can be.</p>
/// </remarks>
public class PrincipalUtilities
{
/// <summary>Return the issuer of the given cert as an X509Principal.</summary>
public static X509Name GetIssuerX509Principal(
X509Certificate cert)
{
try
{
TbsCertificateStructure tbsCert = TbsCertificateStructure.GetInstance(
Asn1Object.FromByteArray(cert.GetTbsCertificate()));
return tbsCert.Issuer;
}
catch (Exception e)
{
throw new CertificateEncodingException("Could not extract issuer", e);
}
}
/// <summary>Return the subject of the given cert as an X509Principal.</summary>
public static X509Name GetSubjectX509Principal(
X509Certificate cert)
{
try
{
TbsCertificateStructure tbsCert = TbsCertificateStructure.GetInstance(
Asn1Object.FromByteArray(cert.GetTbsCertificate()));
return tbsCert.Subject;
}
catch (Exception e)
{
throw new CertificateEncodingException("Could not extract subject", e);
}
}
/// <summary>Return the issuer of the given CRL as an X509Principal.</summary>
public static X509Name GetIssuerX509Principal(
X509Crl crl)
{
try
{
TbsCertificateList tbsCertList = TbsCertificateList.GetInstance(
Asn1Object.FromByteArray(crl.GetTbsCertList()));
return tbsCertList.Issuer;
}
catch (Exception e)
{
throw new CrlException("Could not extract issuer", e);
}
}
}
}

View File

@@ -0,0 +1,178 @@
using System;
using System.IO;
using System.Collections;
using System.Text;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.CryptoPro;
using Org.BouncyCastle.Asn1.Oiw;
using Org.BouncyCastle.Asn1.Pkcs;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Asn1.X9;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Math.EC;
using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.X509
{
/// <summary>
/// A factory to produce Public Key Info Objects.
/// </summary>
public sealed class SubjectPublicKeyInfoFactory
{
private SubjectPublicKeyInfoFactory()
{
}
/// <summary>
/// Create a Subject Public Key Info object for a given public key.
/// </summary>
/// <param name="key">One of ElGammalPublicKeyParameters, DSAPublicKeyParameter, DHPublicKeyParameters, RsaKeyParameters or ECPublicKeyParameters</param>
/// <returns>A subject public key info object.</returns>
/// <exception cref="Exception">Throw exception if object provided is not one of the above.</exception>
public static SubjectPublicKeyInfo CreateSubjectPublicKeyInfo(
AsymmetricKeyParameter key)
{
if (key == null)
throw new ArgumentNullException("key");
if (key.IsPrivate)
throw new ArgumentException("Private key passed - public key expected.", "key");
if (key is ElGamalPublicKeyParameters)
{
ElGamalPublicKeyParameters _key = (ElGamalPublicKeyParameters)key;
ElGamalParameters kp = _key.Parameters;
SubjectPublicKeyInfo info = new SubjectPublicKeyInfo(
new AlgorithmIdentifier(
OiwObjectIdentifiers.ElGamalAlgorithm,
new ElGamalParameter(kp.P, kp.G).ToAsn1Object()),
new DerInteger(_key.Y));
return info;
}
if (key is DsaPublicKeyParameters)
{
DsaPublicKeyParameters _key = (DsaPublicKeyParameters) key;
DsaParameters kp = _key.Parameters;
Asn1Encodable ae = kp == null
? null
: new DsaParameter(kp.P, kp.Q, kp.G).ToAsn1Object();
return new SubjectPublicKeyInfo(
new AlgorithmIdentifier(X9ObjectIdentifiers.IdDsa, ae),
new DerInteger(_key.Y));
}
if (key is DHPublicKeyParameters)
{
DHPublicKeyParameters _key = (DHPublicKeyParameters) key;
DHParameters kp = _key.Parameters;
SubjectPublicKeyInfo info = new SubjectPublicKeyInfo(
new AlgorithmIdentifier(
X9ObjectIdentifiers.DHPublicNumber,
new DHParameter(kp.P, kp.G, kp.L).ToAsn1Object()),
new DerInteger(_key.Y));
return info;
} // End of DH
if (key is RsaKeyParameters)
{
RsaKeyParameters _key = (RsaKeyParameters) key;
SubjectPublicKeyInfo info = new SubjectPublicKeyInfo(
new AlgorithmIdentifier(PkcsObjectIdentifiers.RsaEncryption, DerNull.Instance),
new RsaPublicKeyStructure(_key.Modulus, _key.Exponent).ToAsn1Object());
return info;
} // End of RSA.
if (key is ECPublicKeyParameters)
{
ECPublicKeyParameters _key = (ECPublicKeyParameters) key;
if (_key.AlgorithmName == "ECGOST3410")
{
if (_key.PublicKeyParamSet == null)
throw Platform.CreateNotImplementedException("Not a CryptoPro parameter set");
ECPoint q = _key.Q;
BigInteger bX = q.X.ToBigInteger();
BigInteger bY = q.Y.ToBigInteger();
byte[] encKey = new byte[64];
ExtractBytes(encKey, 0, bX);
ExtractBytes(encKey, 32, bY);
Gost3410PublicKeyAlgParameters gostParams = new Gost3410PublicKeyAlgParameters(
_key.PublicKeyParamSet, CryptoProObjectIdentifiers.GostR3411x94CryptoProParamSet);
AlgorithmIdentifier algID = new AlgorithmIdentifier(
CryptoProObjectIdentifiers.GostR3410x2001,
gostParams.ToAsn1Object());
return new SubjectPublicKeyInfo(algID, new DerOctetString(encKey));
}
else
{
ECDomainParameters kp = _key.Parameters;
X9ECParameters ecP = new X9ECParameters(kp.Curve, kp.G, kp.N, kp.H, kp.GetSeed());
X962Parameters x962 = new X962Parameters(ecP);
Asn1OctetString p = (Asn1OctetString)(new X9ECPoint(_key.Q).ToAsn1Object());
AlgorithmIdentifier algID = new AlgorithmIdentifier(
X9ObjectIdentifiers.IdECPublicKey, x962.ToAsn1Object());
return new SubjectPublicKeyInfo(algID, p.GetOctets());
}
} // End of EC
if (key is Gost3410PublicKeyParameters)
{
Gost3410PublicKeyParameters _key = (Gost3410PublicKeyParameters) key;
if (_key.PublicKeyParamSet == null)
throw Platform.CreateNotImplementedException("Not a CryptoPro parameter set");
byte[] keyEnc = _key.Y.ToByteArrayUnsigned();
byte[] keyBytes = new byte[keyEnc.Length];
for (int i = 0; i != keyBytes.Length; i++)
{
keyBytes[i] = keyEnc[keyEnc.Length - 1 - i]; // must be little endian
}
Gost3410PublicKeyAlgParameters algParams = new Gost3410PublicKeyAlgParameters(
_key.PublicKeyParamSet, CryptoProObjectIdentifiers.GostR3411x94CryptoProParamSet);
AlgorithmIdentifier algID = new AlgorithmIdentifier(
CryptoProObjectIdentifiers.GostR3410x94,
algParams.ToAsn1Object());
return new SubjectPublicKeyInfo(algID, new DerOctetString(keyBytes));
}
throw new ArgumentException("Class provided no convertible: " + key.GetType().FullName);
}
private static void ExtractBytes(
byte[] encKey,
int offset,
BigInteger bI)
{
byte[] val = bI.ToByteArray();
int n = (bI.BitLength + 7) / 8;
for (int i = 0; i < n; ++i)
{
encKey[offset + i] = val[val.Length - 1 - i];
}
}
}
}

View File

@@ -0,0 +1,172 @@
using System;
using System.Collections;
using System.IO;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.Pkcs;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Security.Certificates;
using Org.BouncyCastle.Utilities.IO;
namespace Org.BouncyCastle.X509
{
public class X509AttrCertParser
{
private static readonly PemParser PemAttrCertParser = new PemParser("ATTRIBUTE CERTIFICATE");
private Asn1Set sData;
private int sDataObjectCount;
private Stream currentStream;
private IX509AttributeCertificate ReadDerCertificate(
Asn1InputStream dIn)
{
Asn1Sequence seq = (Asn1Sequence)dIn.ReadObject();
if (seq.Count > 1 && seq[0] is DerObjectIdentifier)
{
if (seq[0].Equals(PkcsObjectIdentifiers.SignedData))
{
sData = SignedData.GetInstance(
Asn1Sequence.GetInstance((Asn1TaggedObject) seq[1], true)).Certificates;
return GetCertificate();
}
}
// return new X509V2AttributeCertificate(seq.getEncoded());
return new X509V2AttributeCertificate(AttributeCertificate.GetInstance(seq));
}
private IX509AttributeCertificate GetCertificate()
{
if (sData != null)
{
while (sDataObjectCount < sData.Count)
{
object obj = sData[sDataObjectCount++];
if (obj is Asn1TaggedObject && ((Asn1TaggedObject)obj).TagNo == 2)
{
//return new X509V2AttributeCertificate(
// Asn1Sequence.GetInstance((Asn1TaggedObject)obj, false).GetEncoded());
return new X509V2AttributeCertificate(
AttributeCertificate.GetInstance(
Asn1Sequence.GetInstance((Asn1TaggedObject)obj, false)));
}
}
}
return null;
}
private IX509AttributeCertificate ReadPemCertificate(
Stream inStream)
{
Asn1Sequence seq = PemAttrCertParser.ReadPemObject(inStream);
return seq == null
? null
//: new X509V2AttributeCertificate(seq.getEncoded());
: new X509V2AttributeCertificate(AttributeCertificate.GetInstance(seq));
}
/// <summary>
/// Create loading data from byte array.
/// </summary>
/// <param name="input"></param>
public IX509AttributeCertificate ReadAttrCert(
byte[] input)
{
return ReadAttrCert(new MemoryStream(input, false));
}
/// <summary>
/// Create loading data from byte array.
/// </summary>
/// <param name="input"></param>
public ICollection ReadAttrCerts(
byte[] input)
{
return ReadAttrCerts(new MemoryStream(input, false));
}
/**
* Generates a certificate object and initializes it with the data
* read from the input stream inStream.
*/
public IX509AttributeCertificate ReadAttrCert(
Stream inStream)
{
if (inStream == null)
throw new ArgumentNullException("inStream");
if (!inStream.CanRead)
throw new ArgumentException("inStream must be read-able", "inStream");
if (currentStream == null)
{
currentStream = inStream;
sData = null;
sDataObjectCount = 0;
}
else if (currentStream != inStream) // reset if input stream has changed
{
currentStream = inStream;
sData = null;
sDataObjectCount = 0;
}
try
{
if (sData != null)
{
if (sDataObjectCount != sData.Count)
{
return GetCertificate();
}
sData = null;
sDataObjectCount = 0;
return null;
}
PushbackStream pis = new PushbackStream(inStream);
int tag = pis.ReadByte();
if (tag < 0)
return null;
pis.Unread(tag);
if (tag != 0x30) // assume ascii PEM encoded.
{
return ReadPemCertificate(pis);
}
return ReadDerCertificate(new Asn1InputStream(pis));
}
catch (Exception e)
{
throw new CertificateException(e.ToString());
}
}
/**
* Returns a (possibly empty) collection view of the certificates
* read from the given input stream inStream.
*/
public ICollection ReadAttrCerts(
Stream inStream)
{
IX509AttributeCertificate attrCert;
IList attrCerts = new ArrayList();
while ((attrCert = ReadAttrCert(inStream)) != null)
{
attrCerts.Add(attrCert);
}
return attrCerts;
}
}
}

View File

@@ -0,0 +1,76 @@
using System;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.X509;
namespace Org.BouncyCastle.X509
{
/**
* Class for carrying the values in an X.509 Attribute.
*/
public class X509Attribute
: Asn1Encodable
{
private readonly AttributeX509 attr;
/**
* @param at an object representing an attribute.
*/
internal X509Attribute(
Asn1Encodable at)
{
this.attr = AttributeX509.GetInstance(at);
}
/**
* Create an X.509 Attribute with the type given by the passed in oid and
* the value represented by an ASN.1 Set containing value.
*
* @param oid type of the attribute
* @param value value object to go into the atribute's value set.
*/
public X509Attribute(
string oid,
Asn1Encodable value)
{
this.attr = new AttributeX509(new DerObjectIdentifier(oid), new DerSet(value));
}
/**
* Create an X.59 Attribute with the type given by the passed in oid and the
* value represented by an ASN.1 Set containing the objects in value.
*
* @param oid type of the attribute
* @param value vector of values to go in the attribute's value set.
*/
public X509Attribute(
string oid,
Asn1EncodableVector value)
{
this.attr = new AttributeX509(new DerObjectIdentifier(oid), new DerSet(value));
}
public string Oid
{
get { return attr.AttrType.Id; }
}
public Asn1Encodable[] GetValues()
{
Asn1Set s = attr.AttrValues;
Asn1Encodable[] values = new Asn1Encodable[s.Count];
for (int i = 0; i != s.Count; i++)
{
values[i] = (Asn1Encodable)s[i];
}
return values;
}
public override Asn1Object ToAsn1Object()
{
return attr.ToAsn1Object();
}
}
}

View File

@@ -0,0 +1,94 @@
using System;
using System.Collections;
using System.IO;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Security.Certificates;
using Org.BouncyCastle.Utilities.IO;
namespace Org.BouncyCastle.X509
{
public class X509CertPairParser
{
private Stream currentStream;
private X509CertificatePair ReadDerCrossCertificatePair(
Stream inStream)
{
Asn1InputStream dIn = new Asn1InputStream(inStream);//, ProviderUtil.getReadLimit(in));
Asn1Sequence seq = (Asn1Sequence)dIn.ReadObject();
CertificatePair pair = CertificatePair.GetInstance(seq);
return new X509CertificatePair(pair);
}
/// <summary>
/// Create loading data from byte array.
/// </summary>
/// <param name="input"></param>
public X509CertificatePair ReadCertPair(
byte[] input)
{
return ReadCertPair(new MemoryStream(input, false));
}
/// <summary>
/// Create loading data from byte array.
/// </summary>
/// <param name="input"></param>
public ICollection ReadCertPairs(
byte[] input)
{
return ReadCertPairs(new MemoryStream(input, false));
}
public X509CertificatePair ReadCertPair(
Stream inStream)
{
if (inStream == null)
throw new ArgumentNullException("inStream");
if (!inStream.CanRead)
throw new ArgumentException("inStream must be read-able", "inStream");
if (currentStream == null)
{
currentStream = inStream;
}
else if (currentStream != inStream) // reset if input stream has changed
{
currentStream = inStream;
}
try
{
PushbackStream pis = new PushbackStream(inStream);
int tag = pis.ReadByte();
if (tag < 0)
return null;
pis.Unread(tag);
return ReadDerCrossCertificatePair(pis);
}
catch (Exception e)
{
throw new CertificateException(e.ToString());
}
}
public ICollection ReadCertPairs(
Stream inStream)
{
X509CertificatePair certPair;
IList certPairs = new ArrayList();
while ((certPair = ReadCertPair(inStream)) != null)
{
certPairs.Add(certPair);
}
return certPairs;
}
}
}

View File

@@ -0,0 +1,579 @@
using System;
using System.Collections;
using System.IO;
using System.Text;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.Misc;
using Org.BouncyCastle.Asn1.Utilities;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Security.Certificates;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.Encoders;
using Org.BouncyCastle.X509.Extension;
namespace Org.BouncyCastle.X509
{
/// <summary>
/// An Object representing an X509 Certificate.
/// Has static methods for loading Certificates encoded in many forms that return X509Certificate Objects.
/// </summary>
public class X509Certificate
: X509ExtensionBase
// , PKCS12BagAttributeCarrier
{
private readonly X509CertificateStructure c;
// private Hashtable pkcs12Attributes = new Hashtable();
// private ArrayList pkcs12Ordering = new ArrayList();
private readonly BasicConstraints basicConstraints;
private readonly bool[] keyUsage;
private bool hashValueSet;
private int hashValue;
protected X509Certificate()
{
}
public X509Certificate(
X509CertificateStructure c)
{
this.c = c;
try
{
Asn1OctetString str = this.GetExtensionValue(new DerObjectIdentifier("2.5.29.19"));
if (str != null)
{
basicConstraints = BasicConstraints.GetInstance(
X509ExtensionUtilities.FromExtensionValue(str));
}
}
catch (Exception e)
{
throw new CertificateParsingException("cannot construct BasicConstraints: " + e);
}
try
{
Asn1OctetString str = this.GetExtensionValue(new DerObjectIdentifier("2.5.29.15"));
if (str != null)
{
DerBitString bits = DerBitString.GetInstance(
X509ExtensionUtilities.FromExtensionValue(str));
byte[] bytes = bits.GetBytes();
int length = (bytes.Length * 8) - bits.PadBits;
keyUsage = new bool[(length < 9) ? 9 : length];
for (int i = 0; i != length; i++)
{
// keyUsage[i] = (bytes[i / 8] & (0x80 >>> (i % 8))) != 0;
keyUsage[i] = (bytes[i / 8] & (0x80 >> (i % 8))) != 0;
}
}
else
{
keyUsage = null;
}
}
catch (Exception e)
{
throw new CertificateParsingException("cannot construct KeyUsage: " + e);
}
}
// internal X509Certificate(
// Asn1Sequence seq)
// {
// this.c = X509CertificateStructure.GetInstance(seq);
// }
// /// <summary>
// /// Load certificate from byte array.
// /// </summary>
// /// <param name="encoded">Byte array containing encoded X509Certificate.</param>
// public X509Certificate(
// byte[] encoded)
// : this((Asn1Sequence) new Asn1InputStream(encoded).ReadObject())
// {
// }
//
// /// <summary>
// /// Load certificate from Stream.
// /// Must be positioned at start of certificate.
// /// </summary>
// /// <param name="input"></param>
// public X509Certificate(
// Stream input)
// : this((Asn1Sequence) new Asn1InputStream(input).ReadObject())
// {
// }
/// <summary>
/// Return true if the current time is within the start and end times nominated on the certificate.
/// </summary>
/// <returns>true id certificate is valid for the current time.</returns>
public virtual bool IsValidNow
{
get { return IsValid(DateTime.UtcNow); }
}
/// <summary>
/// Return true if the nominated time is within the start and end times nominated on the certificate.
/// </summary>
/// <param name="time">The time to test validity against.</param>
/// <returns>True if certificate is valid for nominated time.</returns>
public virtual bool IsValid(
DateTime time)
{
return time.CompareTo(NotBefore) >= 0 && time.CompareTo(NotAfter) <= 0;
}
/// <summary>
/// Checks if the current date is within certificate's validity period.
/// </summary>
public virtual void CheckValidity()
{
this.CheckValidity(DateTime.UtcNow);
}
/// <summary>
/// Checks if the given date is within certificate's validity period.
/// </summary>
/// <exception cref="CertificateExpiredException">if the certificate is expired by given date</exception>
/// <exception cref="CertificateNotYetValidException">if the certificate is not yet valid on given date</exception>
public virtual void CheckValidity(
DateTime time)
{
if (time.CompareTo(NotAfter) > 0)
throw new CertificateExpiredException("certificate expired on " + c.EndDate.GetTime());
if (time.CompareTo(NotBefore) < 0)
throw new CertificateNotYetValidException("certificate not valid until " + c.StartDate.GetTime());
}
/// <summary>
/// Return the certificate's version.
/// </summary>
/// <returns>An integer whose value Equals the version of the cerficate.</returns>
public virtual int Version
{
get { return c.Version; }
}
/// <summary>
/// Return a <see cref="Org.BouncyCastle.Math.BigInteger">BigInteger</see> containing the serial number.
/// </summary>
/// <returns>The Serial number.</returns>
public virtual BigInteger SerialNumber
{
get { return c.SerialNumber.Value; }
}
/// <summary>
/// Get the Issuer Distinguished Name. (Who signed the certificate.)
/// </summary>
/// <returns>And X509Object containing name and value pairs.</returns>
// public IPrincipal IssuerDN
public virtual X509Name IssuerDN
{
get { return c.Issuer; }
}
/// <summary>
/// Get the subject of this certificate.
/// </summary>
/// <returns>An X509Name object containing name and value pairs.</returns>
// public IPrincipal SubjectDN
public virtual X509Name SubjectDN
{
get { return c.Subject; }
}
/// <summary>
/// The time that this certificate is valid from.
/// </summary>
/// <returns>A DateTime object representing that time in the local time zone.</returns>
public virtual DateTime NotBefore
{
get { return c.StartDate.ToDateTime(); }
}
/// <summary>
/// The time that this certificate is valid up to.
/// </summary>
/// <returns>A DateTime object representing that time in the local time zone.</returns>
public virtual DateTime NotAfter
{
get { return c.EndDate.ToDateTime(); }
}
/// <summary>
/// Return the Der encoded TbsCertificate data.
/// This is the certificate component less the signature.
/// To Get the whole certificate call the GetEncoded() member.
/// </summary>
/// <returns>A byte array containing the Der encoded Certificate component.</returns>
public virtual byte[] GetTbsCertificate()
{
return c.TbsCertificate.GetDerEncoded();
}
/// <summary>
/// The signature.
/// </summary>
/// <returns>A byte array containg the signature of the certificate.</returns>
public virtual byte[] GetSignature()
{
return c.Signature.GetBytes();
}
/// <summary>
/// A meaningful version of the Signature Algorithm. (EG SHA1WITHRSA)
/// </summary>
/// <returns>A sting representing the signature algorithm.</returns>
public virtual string SigAlgName
{
get { return SignerUtilities.GetEncodingName(c.SignatureAlgorithm.ObjectID); }
}
/// <summary>
/// Get the Signature Algorithms Object ID.
/// </summary>
/// <returns>A string containg a '.' separated object id.</returns>
public virtual string SigAlgOid
{
get { return c.SignatureAlgorithm.ObjectID.Id; }
}
/// <summary>
/// Get the signature algorithms parameters. (EG DSA Parameters)
/// </summary>
/// <returns>A byte array containing the Der encoded version of the parameters or null if there are none.</returns>
public virtual byte[] GetSigAlgParams()
{
if (c.SignatureAlgorithm.Parameters != null)
{
return c.SignatureAlgorithm.Parameters.GetDerEncoded();
}
return null;
}
/// <summary>
/// Get the issuers UID.
/// </summary>
/// <returns>A DerBitString.</returns>
public virtual DerBitString IssuerUniqueID
{
get { return c.TbsCertificate.IssuerUniqueID; }
}
/// <summary>
/// Get the subjects UID.
/// </summary>
/// <returns>A DerBitString.</returns>
public virtual DerBitString SubjectUniqueID
{
get { return c.TbsCertificate.SubjectUniqueID; }
}
/// <summary>
/// Get a key usage guidlines.
/// </summary>
public virtual bool[] GetKeyUsage()
{
return keyUsage == null ? null : (bool[]) keyUsage.Clone();
}
// TODO Replace with something that returns a list of DerObjectIdentifier
public virtual IList GetExtendedKeyUsage()
{
Asn1OctetString str = this.GetExtensionValue(new DerObjectIdentifier("2.5.29.37"));
if (str == null)
return null;
try
{
Asn1Sequence seq = Asn1Sequence.GetInstance(
X509ExtensionUtilities.FromExtensionValue(str));
ArrayList list = new ArrayList();
foreach (DerObjectIdentifier oid in seq)
{
list.Add(oid.Id);
}
return list;
}
catch (Exception e)
{
throw new CertificateParsingException("error processing extended key usage extension", e);
}
}
public virtual int GetBasicConstraints()
{
if (basicConstraints != null && basicConstraints.IsCA())
{
if (basicConstraints.PathLenConstraint == null)
{
return int.MaxValue;
}
return basicConstraints.PathLenConstraint.IntValue;
}
return -1;
}
public virtual ICollection GetSubjectAlternativeNames()
{
return GetAlternativeNames("2.5.29.17");
}
public virtual ICollection GetIssuerAlternativeNames()
{
return GetAlternativeNames("2.5.29.18");
}
protected virtual ICollection GetAlternativeNames(
string oid)
{
Asn1OctetString altNames = GetExtensionValue(new DerObjectIdentifier(oid));
if (altNames == null)
return null;
Asn1Object asn1Object = X509ExtensionUtilities.FromExtensionValue(altNames);
GeneralNames gns = GeneralNames.GetInstance(asn1Object);
ArrayList result = new ArrayList();
foreach (GeneralName gn in gns.GetNames())
{
ArrayList entry = new ArrayList();
entry.Add(gn.TagNo);
entry.Add(gn.Name.ToString());
result.Add(entry);
}
return result;
}
protected override X509Extensions GetX509Extensions()
{
return c.Version == 3
? c.TbsCertificate.Extensions
: null;
}
/// <summary>
/// Get the public key of the subject of the certificate.
/// </summary>
/// <returns>The public key parameters.</returns>
public virtual AsymmetricKeyParameter GetPublicKey()
{
return PublicKeyFactory.CreateKey(c.SubjectPublicKeyInfo);
}
/// <summary>
/// Return a Der encoded version of this certificate.
/// </summary>
/// <returns>A byte array.</returns>
public virtual byte[] GetEncoded()
{
return c.GetDerEncoded();
}
public override bool Equals(
object obj)
{
if (obj == this)
return true;
X509Certificate other = obj as X509Certificate;
if (other == null)
return false;
return c.Equals(other.c);
// NB: May prefer this implementation of Equals if more than one certificate implementation in play
// return Arrays.AreEqual(this.GetEncoded(), other.GetEncoded());
}
public override int GetHashCode()
{
lock (this)
{
if (!hashValueSet)
{
hashValue = c.GetHashCode();
hashValueSet = true;
}
}
return hashValue;
}
// public void setBagAttribute(
// DERObjectIdentifier oid,
// DEREncodable attribute)
// {
// pkcs12Attributes.put(oid, attribute);
// pkcs12Ordering.addElement(oid);
// }
//
// public DEREncodable getBagAttribute(
// DERObjectIdentifier oid)
// {
// return (DEREncodable)pkcs12Attributes.get(oid);
// }
//
// public Enumeration getBagAttributeKeys()
// {
// return pkcs12Ordering.elements();
// }
public override string ToString()
{
StringBuilder buf = new StringBuilder();
string nl = Platform.NewLine;
buf.Append(" [0] Version: ").Append(this.Version).Append(nl);
buf.Append(" SerialNumber: ").Append(this.SerialNumber).Append(nl);
buf.Append(" IssuerDN: ").Append(this.IssuerDN).Append(nl);
buf.Append(" Start Date: ").Append(this.NotBefore).Append(nl);
buf.Append(" Final Date: ").Append(this.NotAfter).Append(nl);
buf.Append(" SubjectDN: ").Append(this.SubjectDN).Append(nl);
buf.Append(" Public Key: ").Append(this.GetPublicKey()).Append(nl);
buf.Append(" Signature Algorithm: ").Append(this.SigAlgName).Append(nl);
byte[] sig = this.GetSignature();
byte[] hex = Hex.Encode(sig, 0, 20);
string ascii = Encoding.ASCII.GetString(hex, 0, hex.Length);
buf.Append(" Signature: ").Append(ascii).Append(nl);
for (int i = 20; i < sig.Length; i += 20)
{
int len = System.Math.Min(20, sig.Length - i);
hex = Hex.Encode(sig, i, len);
ascii = Encoding.ASCII.GetString(hex, 0, hex.Length);
buf.Append(" ").Append(ascii).Append(nl);
}
X509Extensions extensions = c.TbsCertificate.Extensions;
if (extensions != null)
{
IEnumerator e = extensions.ExtensionOids.GetEnumerator();
if (e.MoveNext())
{
buf.Append(" Extensions: \n");
}
do
{
DerObjectIdentifier oid = (DerObjectIdentifier)e.Current;
X509Extension ext = extensions.GetExtension(oid);
if (ext.Value != null)
{
byte[] octs = ext.Value.GetOctets();
Asn1Object obj = Asn1Object.FromByteArray(octs);
buf.Append(" critical(").Append(ext.IsCritical).Append(") ");
try
{
if (oid.Equals(X509Extensions.BasicConstraints))
{
buf.Append(BasicConstraints.GetInstance(obj));
}
else if (oid.Equals(X509Extensions.KeyUsage))
{
buf.Append(KeyUsage.GetInstance(obj));
}
else if (oid.Equals(MiscObjectIdentifiers.NetscapeCertType))
{
buf.Append(new NetscapeCertType((DerBitString) obj));
}
else if (oid.Equals(MiscObjectIdentifiers.NetscapeRevocationUrl))
{
buf.Append(new NetscapeRevocationUrl((DerIA5String) obj));
}
else if (oid.Equals(MiscObjectIdentifiers.VerisignCzagExtension))
{
buf.Append(new VerisignCzagExtension((DerIA5String) obj));
}
else
{
buf.Append(oid.Id);
buf.Append(" value = ").Append(Asn1Dump.DumpAsString(obj));
//buf.Append(" value = ").Append("*****").Append(nl);
}
}
catch (Exception)
{
buf.Append(oid.Id);
//buf.Append(" value = ").Append(new string(Hex.encode(ext.getValue().getOctets()))).Append(nl);
buf.Append(" value = ").Append("*****");
}
}
buf.Append(nl);
}
while (e.MoveNext());
}
return buf.ToString();
}
/// <summary>
/// Verify the certificate's signature using the nominated public key.
/// </summary>
/// <param name="key">An appropriate public key parameter object, RsaPublicKeyParameters, DsaPublicKeyParameters or ECDsaPublicKeyParameters</param>
/// <returns>True if the signature is valid.</returns>
/// <exception cref="Exception">If key submitted is not of the above nominated types.</exception>
public virtual void Verify(
AsymmetricKeyParameter key)
{
string sigName = X509SignatureUtilities.GetSignatureName(c.SignatureAlgorithm);
ISigner signature = SignerUtilities.GetSigner(sigName);
CheckSignature(key, signature);
}
protected virtual void CheckSignature(
AsymmetricKeyParameter publicKey,
ISigner signature)
{
if (!c.SignatureAlgorithm.Equals(c.TbsCertificate.Signature))
{
throw new CertificateException("signature algorithm in TBS cert not same as outer cert");
}
Asn1Encodable parameters = c.SignatureAlgorithm.Parameters;
X509SignatureUtilities.SetSignatureParameters(signature, parameters);
signature.Init(false, publicKey);
byte[] b = this.GetTbsCertificate();
signature.BlockUpdate(b, 0, b.Length);
byte[] sig = this.GetSignature();
if (!signature.VerifySignature(sig))
{
throw new InvalidKeyException("Public key presented not for certificate signature");
}
}
}
}

View File

@@ -0,0 +1,117 @@
using System;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Security.Certificates;
using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.X509
{
/// <remarks>
/// This class contains a cross certificate pair. Cross certificates pairs may
/// contain two cross signed certificates from two CAs. A certificate from the
/// other CA to this CA is contained in the forward certificate, the certificate
/// from this CA to the other CA is contained in the reverse certificate.
/// </remarks>
public class X509CertificatePair
{
private readonly X509Certificate forward;
private readonly X509Certificate reverse;
/// <summary>Constructor</summary>
/// <param name="forward">Certificate from the other CA to this CA.</param>
/// <param name="reverse">Certificate from this CA to the other CA.</param>
public X509CertificatePair(
X509Certificate forward,
X509Certificate reverse)
{
this.forward = forward;
this.reverse = reverse;
}
/// <summary>Constructor from a ASN.1 CertificatePair structure.</summary>
/// <param name="pair">The <c>CertificatePair</c> ASN.1 object.</param>
public X509CertificatePair(
CertificatePair pair)
{
if (pair.Forward != null)
{
this.forward = new X509Certificate(pair.Forward);
}
if (pair.Reverse != null)
{
this.reverse = new X509Certificate(pair.Reverse);
}
}
public byte[] GetEncoded()
{
try
{
X509CertificateStructure f = null, r = null;
if (forward != null)
{
f = X509CertificateStructure.GetInstance(
Asn1Object.FromByteArray(forward.GetEncoded()));
}
if (reverse != null)
{
r = X509CertificateStructure.GetInstance(
Asn1Object.FromByteArray(reverse.GetEncoded()));
}
return new CertificatePair(f, r).GetDerEncoded();
}
catch (Exception e)
{
// TODO
// throw new ExtCertificateEncodingException(e.toString(), e);
throw new CertificateEncodingException(e.Message, e);
}
}
/// <summary>Returns the certificate from the other CA to this CA.</summary>
public X509Certificate Forward
{
get { return forward; }
}
/// <summary>Returns the certificate from this CA to the other CA.</summary>
public X509Certificate Reverse
{
get { return reverse; }
}
public override bool Equals(
object obj)
{
if (obj == this)
return true;
X509CertificatePair other = obj as X509CertificatePair;
if (other == null)
return false;
return Platform.Equals(this.forward, other.forward)
&& Platform.Equals(this.reverse, other.reverse);
}
public override int GetHashCode()
{
int hash = -1;
if (forward != null)
{
hash ^= forward.GetHashCode();
}
if (reverse != null)
{
hash *= 17;
hash ^= reverse.GetHashCode();
}
return hash;
}
}
}

View File

@@ -0,0 +1,182 @@
using System;
using System.Collections;
using System.IO;
using System.Text;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.Pkcs;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Security.Certificates;
using Org.BouncyCastle.Utilities.Encoders;
using Org.BouncyCastle.Utilities.IO;
namespace Org.BouncyCastle.X509
{
/**
* class for dealing with X509 certificates.
* <p>
* At the moment this will deal with "-----BEGIN CERTIFICATE-----" to "-----END CERTIFICATE-----"
* base 64 encoded certs, as well as the BER binaries of certificates and some classes of PKCS#7
* objects.</p>
*/
public class X509CertificateParser
{
private static readonly PemParser PemCertParser = new PemParser("CERTIFICATE");
private Asn1Set sData;
private int sDataObjectCount;
private Stream currentStream;
private X509Certificate ReadDerCertificate(
Asn1InputStream dIn)
{
Asn1Sequence seq = (Asn1Sequence)dIn.ReadObject();
if (seq.Count > 1 && seq[0] is DerObjectIdentifier)
{
if (seq[0].Equals(PkcsObjectIdentifiers.SignedData))
{
sData = SignedData.GetInstance(
Asn1Sequence.GetInstance((Asn1TaggedObject) seq[1], true)).Certificates;
return GetCertificate();
}
}
return CreateX509Certificate(X509CertificateStructure.GetInstance(seq));
}
private X509Certificate GetCertificate()
{
if (sData != null)
{
while (sDataObjectCount < sData.Count)
{
object obj = sData[sDataObjectCount++];
if (obj is Asn1Sequence)
{
return CreateX509Certificate(
X509CertificateStructure.GetInstance(obj));
}
}
}
return null;
}
private X509Certificate ReadPemCertificate(
Stream inStream)
{
Asn1Sequence seq = PemCertParser.ReadPemObject(inStream);
return seq == null
? null
: CreateX509Certificate(X509CertificateStructure.GetInstance(seq));
}
protected virtual X509Certificate CreateX509Certificate(
X509CertificateStructure c)
{
return new X509Certificate(c);
}
/// <summary>
/// Create loading data from byte array.
/// </summary>
/// <param name="input"></param>
public X509Certificate ReadCertificate(
byte[] input)
{
return ReadCertificate(new MemoryStream(input, false));
}
/// <summary>
/// Create loading data from byte array.
/// </summary>
/// <param name="input"></param>
public ICollection ReadCertificates(
byte[] input)
{
return ReadCertificates(new MemoryStream(input, false));
}
/**
* Generates a certificate object and initializes it with the data
* read from the input stream inStream.
*/
public X509Certificate ReadCertificate(
Stream inStream)
{
if (inStream == null)
throw new ArgumentNullException("inStream");
if (!inStream.CanRead)
throw new ArgumentException("inStream must be read-able", "inStream");
if (currentStream == null)
{
currentStream = inStream;
sData = null;
sDataObjectCount = 0;
}
else if (currentStream != inStream) // reset if input stream has changed
{
currentStream = inStream;
sData = null;
sDataObjectCount = 0;
}
try
{
if (sData != null)
{
if (sDataObjectCount != sData.Count)
{
return GetCertificate();
}
sData = null;
sDataObjectCount = 0;
return null;
}
PushbackStream pis = new PushbackStream(inStream);
int tag = pis.ReadByte();
if (tag < 0)
return null;
pis.Unread(tag);
if (tag != 0x30) // assume ascii PEM encoded.
{
return ReadPemCertificate(pis);
}
return ReadDerCertificate(new Asn1InputStream(pis));
}
catch (Exception e)
{
throw new CertificateException(e.ToString());
}
}
/**
* Returns a (possibly empty) collection view of the certificates
* read from the given input stream inStream.
*/
public ICollection ReadCertificates(
Stream inStream)
{
X509Certificate cert;
IList certs = new ArrayList();
while ((cert = ReadCertificate(inStream)) != null)
{
certs.Add(cert);
}
return certs;
}
}
}

View File

@@ -0,0 +1,409 @@
using System;
using System.Collections;
using System.Text;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.Utilities;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Security.Certificates;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.Collections;
using Org.BouncyCastle.Utilities.Date;
using Org.BouncyCastle.Utilities.Encoders;
using Org.BouncyCastle.X509.Extension;
namespace Org.BouncyCastle.X509
{
/**
* The following extensions are listed in RFC 2459 as relevant to CRLs
*
* Authority Key Identifier
* Issuer Alternative Name
* CRL Number
* Delta CRL Indicator (critical)
* Issuing Distribution Point (critical)
*/
public class X509Crl
: X509ExtensionBase
// TODO Add interface Crl?
{
private readonly CertificateList c;
private readonly string sigAlgName;
private readonly byte[] sigAlgParams;
private readonly bool isIndirect;
public X509Crl(
CertificateList c)
{
this.c = c;
try
{
this.sigAlgName = X509SignatureUtilities.GetSignatureName(c.SignatureAlgorithm);
if (c.SignatureAlgorithm.Parameters != null)
{
this.sigAlgParams = ((Asn1Encodable)c.SignatureAlgorithm.Parameters).GetDerEncoded();
}
else
{
this.sigAlgParams = null;
}
this.isIndirect = IsIndirectCrl;
}
catch (Exception e)
{
throw new CrlException("CRL contents invalid: " + e);
}
}
protected override X509Extensions GetX509Extensions()
{
return Version == 2
? c.TbsCertList.Extensions
: null;
}
public virtual byte[] GetEncoded()
{
try
{
return c.GetDerEncoded();
}
catch (Exception e)
{
throw new CrlException(e.ToString());
}
}
public virtual void Verify(
AsymmetricKeyParameter publicKey)
{
if (!c.SignatureAlgorithm.Equals(c.TbsCertList.Signature))
{
throw new CrlException("Signature algorithm on CertificateList does not match TbsCertList.");
}
ISigner sig = SignerUtilities.GetSigner(SigAlgName);
sig.Init(false, publicKey);
byte[] encoded = this.GetTbsCertList();
sig.BlockUpdate(encoded, 0, encoded.Length);
if (!sig.VerifySignature(this.GetSignature()))
{
throw new SignatureException("CRL does not verify with supplied public key.");
}
}
public virtual int Version
{
get { return c.Version; }
}
public virtual X509Name IssuerDN
{
get { return c.Issuer; }
}
public virtual DateTime ThisUpdate
{
get { return c.ThisUpdate.ToDateTime(); }
}
public virtual DateTimeObject NextUpdate
{
get
{
return c.NextUpdate == null
? null
: new DateTimeObject(c.NextUpdate.ToDateTime());
}
}
private ISet LoadCrlEntries()
{
ISet entrySet = new HashSet();
IEnumerable certs = c.GetRevokedCertificateEnumeration();
X509Name previousCertificateIssuer = IssuerDN;
foreach (CrlEntry entry in certs)
{
X509CrlEntry crlEntry = new X509CrlEntry(entry, isIndirect, previousCertificateIssuer);
entrySet.Add(crlEntry);
previousCertificateIssuer = crlEntry.GetCertificateIssuer();
}
return entrySet;
}
public virtual X509CrlEntry GetRevokedCertificate(
BigInteger serialNumber)
{
IEnumerable certs = c.GetRevokedCertificateEnumeration();
X509Name previousCertificateIssuer = IssuerDN;
foreach (CrlEntry entry in certs)
{
X509CrlEntry crlEntry = new X509CrlEntry(entry, isIndirect, previousCertificateIssuer);
if (serialNumber.Equals(entry.UserCertificate.Value))
{
return crlEntry;
}
previousCertificateIssuer = crlEntry.GetCertificateIssuer();
}
return null;
}
public virtual ISet GetRevokedCertificates()
{
ISet entrySet = LoadCrlEntries();
if (entrySet.Count > 0)
{
return entrySet; // TODO? Collections.unmodifiableSet(entrySet);
}
return null;
}
public virtual byte[] GetTbsCertList()
{
try
{
return c.TbsCertList.GetDerEncoded();
}
catch (Exception e)
{
throw new CrlException(e.ToString());
}
}
public virtual byte[] GetSignature()
{
return c.Signature.GetBytes();
}
public virtual string SigAlgName
{
get { return sigAlgName; }
}
public virtual string SigAlgOid
{
get { return c.SignatureAlgorithm.ObjectID.Id; }
}
public virtual byte[] GetSigAlgParams()
{
return Arrays.Clone(sigAlgParams);
}
public override bool Equals(
object obj)
{
if (obj == this)
return true;
X509Crl other = obj as X509Crl;
if (other == null)
return false;
return c.Equals(other.c);
// NB: May prefer this implementation of Equals if more than one certificate implementation in play
//return Arrays.AreEqual(this.GetEncoded(), other.GetEncoded());
}
public override int GetHashCode()
{
return c.GetHashCode();
}
/**
* Returns a string representation of this CRL.
*
* @return a string representation of this CRL.
*/
public override string ToString()
{
StringBuilder buf = new StringBuilder();
string nl = Platform.NewLine;
buf.Append(" Version: ").Append(this.Version).Append(nl);
buf.Append(" IssuerDN: ").Append(this.IssuerDN).Append(nl);
buf.Append(" This update: ").Append(this.ThisUpdate).Append(nl);
buf.Append(" Next update: ").Append(this.NextUpdate).Append(nl);
buf.Append(" Signature Algorithm: ").Append(this.SigAlgName).Append(nl);
byte[] sig = this.GetSignature();
buf.Append(" Signature: ").Append(
Encoding.ASCII.GetString(Hex.Encode(sig, 0, 20))).Append(nl);
for (int i = 20; i < sig.Length; i += 20)
{
if (i < sig.Length - 20)
{
buf.Append(" ").Append(
Encoding.ASCII.GetString(Hex.Encode(sig, i, 20))).Append(nl);
}
else
{
buf.Append(" ").Append(
Encoding.ASCII.GetString(Hex.Encode(sig, i, sig.Length - i))).Append(nl);
}
}
X509Extensions extensions = c.TbsCertList.Extensions;
if (extensions != null)
{
IEnumerator e = extensions.ExtensionOids.GetEnumerator();
if (e.MoveNext())
{
buf.Append(" Extensions: ").Append(nl);
}
do
{
DerObjectIdentifier oid = (DerObjectIdentifier) e.Current;
X509Extension ext = extensions.GetExtension(oid);
if (ext.Value != null)
{
Asn1Object asn1Value = X509ExtensionUtilities.FromExtensionValue(ext.Value);
buf.Append(" critical(").Append(ext.IsCritical).Append(") ");
try
{
if (oid.Equals(X509Extensions.CrlNumber))
{
buf.Append(new CrlNumber(DerInteger.GetInstance(asn1Value).PositiveValue)).Append(nl);
}
else if (oid.Equals(X509Extensions.DeltaCrlIndicator))
{
buf.Append(
"Base CRL: "
+ new CrlNumber(DerInteger.GetInstance(
asn1Value).PositiveValue))
.Append(nl);
}
else if (oid.Equals(X509Extensions.IssuingDistributionPoint))
{
buf.Append(IssuingDistributionPoint.GetInstance((Asn1Sequence) asn1Value)).Append(nl);
}
else if (oid.Equals(X509Extensions.CrlDistributionPoints))
{
buf.Append(CrlDistPoint.GetInstance((Asn1Sequence) asn1Value)).Append(nl);
}
else if (oid.Equals(X509Extensions.FreshestCrl))
{
buf.Append(CrlDistPoint.GetInstance((Asn1Sequence) asn1Value)).Append(nl);
}
else
{
buf.Append(oid.Id);
buf.Append(" value = ").Append(
Asn1Dump.DumpAsString(asn1Value))
.Append(nl);
}
}
catch (Exception)
{
buf.Append(oid.Id);
buf.Append(" value = ").Append("*****").Append(nl);
}
}
else
{
buf.Append(nl);
}
}
while (e.MoveNext());
}
ISet certSet = GetRevokedCertificates();
if (certSet != null)
{
foreach (X509CrlEntry entry in certSet)
{
buf.Append(entry);
buf.Append(nl);
}
}
return buf.ToString();
}
/**
* Checks whether the given certificate is on this CRL.
*
* @param cert the certificate to check for.
* @return true if the given certificate is on this CRL,
* false otherwise.
*/
// public bool IsRevoked(
// Certificate cert)
// {
// if (!cert.getType().Equals("X.509"))
// {
// throw new RuntimeException("X.509 CRL used with non X.509 Cert");
// }
public virtual bool IsRevoked(
X509Certificate cert)
{
CrlEntry[] certs = c.GetRevokedCertificates();
if (certs != null)
{
// BigInteger serial = ((X509Certificate)cert).SerialNumber;
BigInteger serial = cert.SerialNumber;
for (int i = 0; i < certs.Length; i++)
{
if (certs[i].UserCertificate.Value.Equals(serial))
{
return true;
}
}
}
return false;
}
protected virtual bool IsIndirectCrl
{
get
{
Asn1OctetString idp = GetExtensionValue(X509Extensions.IssuingDistributionPoint);
bool isIndirect = false;
try
{
if (idp != null)
{
isIndirect = IssuingDistributionPoint.GetInstance(
X509ExtensionUtilities.FromExtensionValue(idp)).IsIndirectCrl;
}
}
catch (Exception e)
{
// TODO
// throw new ExtCrlException("Exception reading IssuingDistributionPoint", e);
throw new CrlException("Exception reading IssuingDistributionPoint" + e);
}
return isIndirect;
}
}
}
}

View File

@@ -0,0 +1,201 @@
using System;
using System.Collections;
using System.IO;
using System.Text;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.Utilities;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security.Certificates;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.X509.Extension;
namespace Org.BouncyCastle.X509
{
/**
* The following extensions are listed in RFC 2459 as relevant to CRL Entries
*
* ReasonCode Hode Instruction Code Invalidity Date Certificate Issuer
* (critical)
*/
public class X509CrlEntry
: X509ExtensionBase
{
private CrlEntry c;
private bool isIndirect;
private X509Name previousCertificateIssuer;
private X509Name certificateIssuer;
public X509CrlEntry(
CrlEntry c)
{
this.c = c;
this.certificateIssuer = loadCertificateIssuer();
}
/**
* Constructor for CRLEntries of indirect CRLs. If <code>isIndirect</code>
* is <code>false</code> {@link #getCertificateIssuer()} will always
* return <code>null</code>, <code>previousCertificateIssuer</code> is
* ignored. If this <code>isIndirect</code> is specified and this CrlEntry
* has no certificate issuer CRL entry extension
* <code>previousCertificateIssuer</code> is returned by
* {@link #getCertificateIssuer()}.
*
* @param c
* TbsCertificateList.CrlEntry object.
* @param isIndirect
* <code>true</code> if the corresponding CRL is a indirect
* CRL.
* @param previousCertificateIssuer
* Certificate issuer of the previous CrlEntry.
*/
public X509CrlEntry(
CrlEntry c,
bool isIndirect,
X509Name previousCertificateIssuer)
{
this.c = c;
this.isIndirect = isIndirect;
this.previousCertificateIssuer = previousCertificateIssuer;
this.certificateIssuer = loadCertificateIssuer();
}
private X509Name loadCertificateIssuer()
{
if (!isIndirect)
{
return null;
}
Asn1OctetString ext = GetExtensionValue(X509Extensions.CertificateIssuer);
if (ext == null)
{
return previousCertificateIssuer;
}
try
{
GeneralName[] names = GeneralNames.GetInstance(
X509ExtensionUtilities.FromExtensionValue(ext)).GetNames();
for (int i = 0; i < names.Length; i++)
{
if (names[i].TagNo == GeneralName.DirectoryName)
{
return X509Name.GetInstance(names[i].Name);
}
}
}
catch (Exception)
{
}
return null;
}
public X509Name GetCertificateIssuer()
{
return certificateIssuer;
}
protected override X509Extensions GetX509Extensions()
{
return c.Extensions;
}
public byte[] GetEncoded()
{
try
{
return c.GetDerEncoded();
}
catch (Exception e)
{
throw new CrlException(e.ToString());
}
}
public BigInteger SerialNumber
{
get { return c.UserCertificate.Value; }
}
public DateTime RevocationDate
{
get { return c.RevocationDate.ToDateTime(); }
}
public bool HasExtensions
{
get { return c.Extensions != null; }
}
public override string ToString()
{
StringBuilder buf = new StringBuilder();
string nl = Platform.NewLine;
buf.Append(" userCertificate: ").Append(this.SerialNumber).Append(nl);
buf.Append(" revocationDate: ").Append(this.RevocationDate).Append(nl);
buf.Append(" certificateIssuer: ").Append(this.GetCertificateIssuer()).Append(nl);
X509Extensions extensions = c.Extensions;
if (extensions != null)
{
IEnumerator e = extensions.ExtensionOids.GetEnumerator();
if (e.MoveNext())
{
buf.Append(" crlEntryExtensions:").Append(nl);
do
{
DerObjectIdentifier oid = (DerObjectIdentifier)e.Current;
X509Extension ext = extensions.GetExtension(oid);
if (ext.Value != null)
{
Asn1Object obj = Asn1Object.FromByteArray(ext.Value.GetOctets());
buf.Append(" critical(")
.Append(ext.IsCritical)
.Append(") ");
try
{
if (oid.Equals(X509Extensions.ReasonCode))
{
buf.Append(new CrlReason(DerEnumerated.GetInstance(obj)));
}
else if (oid.Equals(X509Extensions.CertificateIssuer))
{
buf.Append("Certificate issuer: ").Append(
GeneralNames.GetInstance((Asn1Sequence)obj));
}
else
{
buf.Append(oid.Id);
buf.Append(" value = ").Append(Asn1Dump.DumpAsString(obj));
}
buf.Append(nl);
}
catch (Exception)
{
buf.Append(oid.Id);
buf.Append(" value = ").Append("*****").Append(nl);
}
}
else
{
buf.Append(nl);
}
}
while (e.MoveNext());
}
}
return buf.ToString();
}
}
}

View File

@@ -0,0 +1,194 @@
using System;
using System.Collections;
using System.IO;
using System.Text;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.Pkcs;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Security.Certificates;
using Org.BouncyCastle.Utilities.Encoders;
using Org.BouncyCastle.Utilities.IO;
namespace Org.BouncyCastle.X509
{
public class X509CrlParser
{
private static readonly PemParser PemCrlParser = new PemParser("CRL");
private readonly bool lazyAsn1;
private Asn1Set sCrlData;
private int sCrlDataObjectCount;
private Stream currentCrlStream;
public X509CrlParser()
: this(false)
{
}
public X509CrlParser(
bool lazyAsn1)
{
this.lazyAsn1 = lazyAsn1;
}
private X509Crl ReadPemCrl(
Stream inStream)
{
Asn1Sequence seq = PemCrlParser.ReadPemObject(inStream);
return seq == null
? null
: CreateX509Crl(CertificateList.GetInstance(seq));
}
private X509Crl ReadDerCrl(
Asn1InputStream dIn)
{
Asn1Sequence seq = (Asn1Sequence)dIn.ReadObject();
if (seq.Count > 1 && seq[0] is DerObjectIdentifier)
{
if (seq[0].Equals(PkcsObjectIdentifiers.SignedData))
{
sCrlData = SignedData.GetInstance(
Asn1Sequence.GetInstance((Asn1TaggedObject) seq[1], true)).Crls;
return GetCrl();
}
}
return CreateX509Crl(CertificateList.GetInstance(seq));
}
private X509Crl GetCrl()
{
if (sCrlData == null || sCrlDataObjectCount >= sCrlData.Count)
{
return null;
}
return CreateX509Crl(
CertificateList.GetInstance(
sCrlData[sCrlDataObjectCount++]));
}
protected virtual X509Crl CreateX509Crl(
CertificateList c)
{
return new X509Crl(c);
}
/// <summary>
/// Create loading data from byte array.
/// </summary>
/// <param name="input"></param>
public X509Crl ReadCrl(
byte[] input)
{
return ReadCrl(new MemoryStream(input, false));
}
/// <summary>
/// Create loading data from byte array.
/// </summary>
/// <param name="input"></param>
public ICollection ReadCrls(
byte[] input)
{
return ReadCrls(new MemoryStream(input, false));
}
/**
* Generates a certificate revocation list (CRL) object and initializes
* it with the data read from the input stream inStream.
*/
public X509Crl ReadCrl(
Stream inStream)
{
if (inStream == null)
throw new ArgumentNullException("inStream");
if (!inStream.CanRead)
throw new ArgumentException("inStream must be read-able", "inStream");
if (currentCrlStream == null)
{
currentCrlStream = inStream;
sCrlData = null;
sCrlDataObjectCount = 0;
}
else if (currentCrlStream != inStream) // reset if input stream has changed
{
currentCrlStream = inStream;
sCrlData = null;
sCrlDataObjectCount = 0;
}
try
{
if (sCrlData != null)
{
if (sCrlDataObjectCount != sCrlData.Count)
{
return GetCrl();
}
sCrlData = null;
sCrlDataObjectCount = 0;
return null;
}
PushbackStream pis = new PushbackStream(inStream);
int tag = pis.ReadByte();
if (tag < 0)
return null;
pis.Unread(tag);
if (tag != 0x30) // assume ascii PEM encoded.
{
return ReadPemCrl(pis);
}
Asn1InputStream asn1 = lazyAsn1
? new LazyAsn1InputStream(pis)
: new Asn1InputStream(pis);
return ReadDerCrl(asn1);
}
catch (CrlException e)
{
throw e;
}
catch (Exception e)
{
throw new CrlException(e.ToString());
}
}
/**
* Returns a (possibly empty) collection view of the CRLs read from
* the given input stream inStream.
*
* The inStream may contain a sequence of DER-encoded CRLs, or
* a PKCS#7 CRL set. This is a PKCS#7 SignedData object, with the
* only significant field being crls. In particular the signature
* and the contents are ignored.
*/
public ICollection ReadCrls(
Stream inStream)
{
X509Crl crl;
IList crls = new ArrayList();
while ((crl = ReadCrl(inStream)) != null)
{
crls.Add(crl);
}
return crls;
}
}
}

View File

@@ -0,0 +1,82 @@
using System;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Utilities.Collections;
namespace Org.BouncyCastle.X509
{
public abstract class X509ExtensionBase
: IX509Extension
{
protected abstract X509Extensions GetX509Extensions();
protected virtual ISet GetExtensionOids(
bool critical)
{
X509Extensions extensions = GetX509Extensions();
if (extensions != null)
{
HashSet set = new HashSet();
foreach (DerObjectIdentifier oid in extensions.ExtensionOids)
{
X509Extension ext = extensions.GetExtension(oid);
if (ext.IsCritical == critical)
{
set.Add(oid.Id);
}
}
return set;
}
return null;
}
/// <summary>
/// Get non critical extensions.
/// </summary>
/// <returns>A set of non critical extension oids.</returns>
public virtual ISet GetNonCriticalExtensionOids()
{
return GetExtensionOids(false);
}
/// <summary>
/// Get any critical extensions.
/// </summary>
/// <returns>A sorted list of critical entension.</returns>
public virtual ISet GetCriticalExtensionOids()
{
return GetExtensionOids(true);
}
/// <summary>
/// Get the value of a given extension.
/// </summary>
/// <param name="oid">The object ID of the extension. </param>
/// <returns>An Asn1OctetString object if that extension is found or null if not.</returns>
[Obsolete("Use version taking a DerObjectIdentifier instead")]
public Asn1OctetString GetExtensionValue(
string oid)
{
return GetExtensionValue(new DerObjectIdentifier(oid));
}
public virtual Asn1OctetString GetExtensionValue(
DerObjectIdentifier oid)
{
X509Extensions exts = GetX509Extensions();
if (exts != null)
{
X509Extension ext = exts.GetExtension(oid);
if (ext != null)
{
return ext.Value;
}
}
return null;
}
}
}

View File

@@ -0,0 +1,59 @@
using System;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.X509;
namespace Org.BouncyCastle.X509
{
/**
* A holding class for constructing an X509 Key Usage extension.
*
* <pre>
* id-ce-keyUsage OBJECT IDENTIFIER ::= { id-ce 15 }
*
* KeyUsage ::= BIT STRING {
* digitalSignature (0),
* nonRepudiation (1),
* keyEncipherment (2),
* dataEncipherment (3),
* keyAgreement (4),
* keyCertSign (5),
* cRLSign (6),
* encipherOnly (7),
* decipherOnly (8) }
* </pre>
*/
public class X509KeyUsage
: Asn1Encodable
{
public const int DigitalSignature = 1 << 7;
public const int NonRepudiation = 1 << 6;
public const int KeyEncipherment = 1 << 5;
public const int DataEncipherment = 1 << 4;
public const int KeyAgreement = 1 << 3;
public const int KeyCertSign = 1 << 2;
public const int CrlSign = 1 << 1;
public const int EncipherOnly = 1 << 0;
public const int DecipherOnly = 1 << 15;
private readonly int usage;
/**
* Basic constructor.
*
* @param usage - the bitwise OR of the Key Usage flags giving the
* allowed uses for the key.
* e.g. (X509KeyUsage.keyEncipherment | X509KeyUsage.dataEncipherment)
*/
public X509KeyUsage(
int usage)
{
this.usage = usage;
}
public override Asn1Object ToAsn1Object()
{
return new KeyUsage(usage);
}
}
}

View File

@@ -0,0 +1,128 @@
using System;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.CryptoPro;
using Org.BouncyCastle.Asn1.Nist;
using Org.BouncyCastle.Asn1.Oiw;
using Org.BouncyCastle.Asn1.Pkcs;
using Org.BouncyCastle.Asn1.TeleTrust;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Asn1.X9;
using Org.BouncyCastle.Crypto;
namespace Org.BouncyCastle.X509
{
internal class X509SignatureUtilities
{
private static readonly Asn1Null derNull = DerNull.Instance;
internal static void SetSignatureParameters(
ISigner signature,
Asn1Encodable parameters)
{
if (parameters != null && !derNull.Equals(parameters))
{
// TODO Put back in
// AlgorithmParameters sigParams = AlgorithmParameters.GetInstance(signature.getAlgorithm());
//
// try
// {
// sigParams.Init(parameters.ToAsn1Object().GetDerEncoded());
// }
// catch (IOException e)
// {
// throw new SignatureException("IOException decoding parameters: " + e.Message);
// }
//
// if (signature.getAlgorithm().EndsWith("MGF1"))
// {
// try
// {
// signature.setParameter(sigParams.getParameterSpec(PSSParameterSpec.class));
// }
// catch (GeneralSecurityException e)
// {
// throw new SignatureException("Exception extracting parameters: " + e.Message);
// }
// }
}
}
internal static string GetSignatureName(
AlgorithmIdentifier sigAlgId)
{
Asn1Encodable parameters = sigAlgId.Parameters;
if (parameters != null && !derNull.Equals(parameters))
{
if (sigAlgId.ObjectID.Equals(PkcsObjectIdentifiers.IdRsassaPss))
{
RsassaPssParameters rsaParams = RsassaPssParameters.GetInstance(parameters);
return GetDigestAlgName(rsaParams.HashAlgorithm.ObjectID) + "withRSAandMGF1";
}
if (sigAlgId.ObjectID.Equals(X9ObjectIdentifiers.ECDsaWithSha2))
{
Asn1Sequence ecDsaParams = Asn1Sequence.GetInstance(parameters);
return GetDigestAlgName((DerObjectIdentifier)ecDsaParams[0]) + "withECDSA";
}
}
return sigAlgId.ObjectID.Id;
}
/**
* Return the digest algorithm using one of the standard JCA string
* representations rather than the algorithm identifier (if possible).
*/
private static string GetDigestAlgName(
DerObjectIdentifier digestAlgOID)
{
if (PkcsObjectIdentifiers.MD5.Equals(digestAlgOID))
{
return "MD5";
}
else if (OiwObjectIdentifiers.IdSha1.Equals(digestAlgOID))
{
return "SHA1";
}
else if (NistObjectIdentifiers.IdSha224.Equals(digestAlgOID))
{
return "SHA224";
}
else if (NistObjectIdentifiers.IdSha256.Equals(digestAlgOID))
{
return "SHA256";
}
else if (NistObjectIdentifiers.IdSha384.Equals(digestAlgOID))
{
return "SHA384";
}
else if (NistObjectIdentifiers.IdSha512.Equals(digestAlgOID))
{
return "SHA512";
}
else if (TeleTrusTObjectIdentifiers.RipeMD128.Equals(digestAlgOID))
{
return "RIPEMD128";
}
else if (TeleTrusTObjectIdentifiers.RipeMD160.Equals(digestAlgOID))
{
return "RIPEMD160";
}
else if (TeleTrusTObjectIdentifiers.RipeMD256.Equals(digestAlgOID))
{
return "RIPEMD256";
}
else if (CryptoProObjectIdentifiers.GostR3411.Equals(digestAlgOID))
{
return "GOST3411";
}
else
{
return digestAlgOID.Id;
}
}
}
}

View File

@@ -0,0 +1,183 @@
using System;
using System.Collections;
using System.Globalization;
using System.IO;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.CryptoPro;
using Org.BouncyCastle.Asn1.Nist;
using Org.BouncyCastle.Asn1.Oiw;
using Org.BouncyCastle.Asn1.Pkcs;
using Org.BouncyCastle.Asn1.TeleTrust;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Asn1.X9;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities.Collections;
namespace Org.BouncyCastle.X509
{
internal class X509Utilities
{
private static readonly Hashtable algorithms = new Hashtable();
private static readonly Hashtable exParams = new Hashtable();
private static readonly ISet noParams = new HashSet();
static X509Utilities()
{
algorithms.Add("MD2WITHRSAENCRYPTION", PkcsObjectIdentifiers.MD2WithRsaEncryption);
algorithms.Add("MD2WITHRSA", PkcsObjectIdentifiers.MD2WithRsaEncryption);
algorithms.Add("MD5WITHRSAENCRYPTION", PkcsObjectIdentifiers.MD5WithRsaEncryption);
algorithms.Add("MD5WITHRSA", PkcsObjectIdentifiers.MD5WithRsaEncryption);
algorithms.Add("SHA1WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha1WithRsaEncryption);
algorithms.Add("SHA1WITHRSA", PkcsObjectIdentifiers.Sha1WithRsaEncryption);
algorithms.Add("SHA224WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha224WithRsaEncryption);
algorithms.Add("SHA224WITHRSA", PkcsObjectIdentifiers.Sha224WithRsaEncryption);
algorithms.Add("SHA256WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha256WithRsaEncryption);
algorithms.Add("SHA256WITHRSA", PkcsObjectIdentifiers.Sha256WithRsaEncryption);
algorithms.Add("SHA384WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha384WithRsaEncryption);
algorithms.Add("SHA384WITHRSA", PkcsObjectIdentifiers.Sha384WithRsaEncryption);
algorithms.Add("SHA512WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha512WithRsaEncryption);
algorithms.Add("SHA512WITHRSA", PkcsObjectIdentifiers.Sha512WithRsaEncryption);
algorithms.Add("SHA1WITHRSAANDMGF1", PkcsObjectIdentifiers.IdRsassaPss);
algorithms.Add("SHA224WITHRSAANDMGF1", PkcsObjectIdentifiers.IdRsassaPss);
algorithms.Add("SHA256WITHRSAANDMGF1", PkcsObjectIdentifiers.IdRsassaPss);
algorithms.Add("SHA384WITHRSAANDMGF1", PkcsObjectIdentifiers.IdRsassaPss);
algorithms.Add("SHA512WITHRSAANDMGF1", PkcsObjectIdentifiers.IdRsassaPss);
algorithms.Add("RIPEMD160WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD160);
algorithms.Add("RIPEMD160WITHRSA", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD160);
algorithms.Add("RIPEMD128WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD128);
algorithms.Add("RIPEMD128WITHRSA", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD128);
algorithms.Add("RIPEMD256WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD256);
algorithms.Add("RIPEMD256WITHRSA", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD256);
algorithms.Add("SHA1WITHDSA", X9ObjectIdentifiers.IdDsaWithSha1);
algorithms.Add("DSAWITHSHA1", X9ObjectIdentifiers.IdDsaWithSha1);
algorithms.Add("SHA224WITHDSA", NistObjectIdentifiers.DsaWithSha224);
algorithms.Add("SHA256WITHDSA", NistObjectIdentifiers.DsaWithSha256);
algorithms.Add("SHA1WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha1);
algorithms.Add("ECDSAWITHSHA1", X9ObjectIdentifiers.ECDsaWithSha1);
algorithms.Add("SHA224WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha224);
algorithms.Add("SHA256WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha256);
algorithms.Add("SHA384WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha384);
algorithms.Add("SHA512WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha512);
algorithms.Add("GOST3411WITHGOST3410", CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x94);
algorithms.Add("GOST3411WITHGOST3410-94", CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x94);
algorithms.Add("GOST3411WITHECGOST3410", CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001);
algorithms.Add("GOST3411WITHECGOST3410-2001", CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001);
algorithms.Add("GOST3411WITHGOST3410-2001", CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001);
//
// According to RFC 3279, the ASN.1 encoding SHALL (id-dsa-with-sha1) or MUST (ecdsa-with-SHA*) omit the parameters field.
// The parameters field SHALL be NULL for RSA based signature algorithms.
//
noParams.Add(X9ObjectIdentifiers.ECDsaWithSha1);
noParams.Add(X9ObjectIdentifiers.ECDsaWithSha224);
noParams.Add(X9ObjectIdentifiers.ECDsaWithSha256);
noParams.Add(X9ObjectIdentifiers.ECDsaWithSha384);
noParams.Add(X9ObjectIdentifiers.ECDsaWithSha512);
noParams.Add(X9ObjectIdentifiers.IdDsaWithSha1);
noParams.Add(NistObjectIdentifiers.DsaWithSha224);
noParams.Add(NistObjectIdentifiers.DsaWithSha256);
//
// RFC 4491
//
noParams.Add(CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x94);
noParams.Add(CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001);
//
// explicit params
//
AlgorithmIdentifier sha1AlgId = new AlgorithmIdentifier(OiwObjectIdentifiers.IdSha1, DerNull.Instance);
exParams.Add("SHA1WITHRSAANDMGF1", CreatePssParams(sha1AlgId, 20));
AlgorithmIdentifier sha224AlgId = new AlgorithmIdentifier(NistObjectIdentifiers.IdSha224, DerNull.Instance);
exParams.Add("SHA224WITHRSAANDMGF1", CreatePssParams(sha224AlgId, 28));
AlgorithmIdentifier sha256AlgId = new AlgorithmIdentifier(NistObjectIdentifiers.IdSha256, DerNull.Instance);
exParams.Add("SHA256WITHRSAANDMGF1", CreatePssParams(sha256AlgId, 32));
AlgorithmIdentifier sha384AlgId = new AlgorithmIdentifier(NistObjectIdentifiers.IdSha384, DerNull.Instance);
exParams.Add("SHA384WITHRSAANDMGF1", CreatePssParams(sha384AlgId, 48));
AlgorithmIdentifier sha512AlgId = new AlgorithmIdentifier(NistObjectIdentifiers.IdSha512, DerNull.Instance);
exParams.Add("SHA512WITHRSAANDMGF1", CreatePssParams(sha512AlgId, 64));
}
private static RsassaPssParameters CreatePssParams(
AlgorithmIdentifier hashAlgId,
int saltSize)
{
return new RsassaPssParameters(
hashAlgId,
new AlgorithmIdentifier(PkcsObjectIdentifiers.IdMgf1, hashAlgId),
new DerInteger(saltSize),
new DerInteger(1));
}
internal static DerObjectIdentifier GetAlgorithmOid(
string algorithmName)
{
algorithmName = algorithmName.ToUpper(CultureInfo.InvariantCulture);
if (algorithms.ContainsKey(algorithmName))
{
return (DerObjectIdentifier) algorithms[algorithmName];
}
return new DerObjectIdentifier(algorithmName);
}
internal static AlgorithmIdentifier GetSigAlgID(
DerObjectIdentifier sigOid,
string algorithmName)
{
if (noParams.Contains(sigOid))
{
return new AlgorithmIdentifier(sigOid);
}
algorithmName = algorithmName.ToUpper(CultureInfo.InvariantCulture);
if (exParams.ContainsKey(algorithmName))
{
return new AlgorithmIdentifier(sigOid, (Asn1Encodable) exParams[algorithmName]);
}
return new AlgorithmIdentifier(sigOid, DerNull.Instance);
}
internal static IEnumerable GetAlgNames()
{
return new EnumerableProxy(algorithms.Keys);
}
internal static byte[] GetSignatureForObject(
DerObjectIdentifier sigOid, // TODO Redundant now?
string sigName,
AsymmetricKeyParameter privateKey,
SecureRandom random,
Asn1Encodable ae)
{
if (sigOid == null)
throw new ArgumentNullException("sigOid");
ISigner sig = SignerUtilities.GetSigner(sigName);
if (random != null)
{
sig.Init(true, new ParametersWithRandom(privateKey, random));
}
else
{
sig.Init(true, privateKey);
}
byte[] encoded = ae.GetDerEncoded();
sig.BlockUpdate(encoded, 0, encoded.Length);
return sig.GenerateSignature();
}
}
}

View File

@@ -0,0 +1,205 @@
using System;
using System.Collections;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Security.Certificates;
namespace Org.BouncyCastle.X509
{
/// <summary>
/// Class to Generate X509V1 Certificates.
/// </summary>
public class X509V1CertificateGenerator
{
private V1TbsCertificateGenerator tbsGen;
private DerObjectIdentifier sigOID;
private AlgorithmIdentifier sigAlgId;
private string signatureAlgorithm;
/// <summary>
/// Default Constructor.
/// </summary>
public X509V1CertificateGenerator()
{
tbsGen = new V1TbsCertificateGenerator();
}
/// <summary>
/// Reset the generator.
/// </summary>
public void Reset()
{
tbsGen = new V1TbsCertificateGenerator();
}
/// <summary>
/// Set the certificate's serial number.
/// </summary>
/// <remarks>Make serial numbers long, if you have no serial number policy make sure the number is at least 16 bytes of secure random data.
/// You will be surprised how ugly a serial number collision can get.</remarks>
/// <param name="serialNumber">The serial number.</param>
public void SetSerialNumber(
BigInteger serialNumber)
{
if (serialNumber.SignValue <= 0)
{
throw new ArgumentException("serial number must be a positive integer", "serialNumber");
}
tbsGen.SetSerialNumber(new DerInteger(serialNumber));
}
/// <summary>
/// Set the issuer distinguished name.
/// The issuer is the entity whose private key is used to sign the certificate.
/// </summary>
/// <param name="issuer">The issuers DN.</param>
public void SetIssuerDN(
X509Name issuer)
{
tbsGen.SetIssuer(issuer);
}
/// <summary>
/// Set the date that this certificate is to be valid from.
/// </summary>
/// <param name="date"/>
public void SetNotBefore(
DateTime date)
{
tbsGen.SetStartDate(new Time(date));
}
/// <summary>
/// Set the date after which this certificate will no longer be valid.
/// </summary>
/// <param name="date"/>
public void SetNotAfter(
DateTime date)
{
tbsGen.SetEndDate(new Time(date));
}
/// <summary>
/// Set the subject distinguished name.
/// The subject describes the entity associated with the public key.
/// </summary>
/// <param name="subject"/>
public void SetSubjectDN(
X509Name subject)
{
tbsGen.SetSubject(subject);
}
/// <summary>
/// Set the public key that this certificate identifies.
/// </summary>
/// <param name="publicKey"/>
public void SetPublicKey(
AsymmetricKeyParameter publicKey)
{
try
{
tbsGen.SetSubjectPublicKeyInfo(
SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(publicKey));
}
catch (Exception e)
{
throw new ArgumentException("unable to process key - " + e.ToString());
}
}
/// <summary>
/// Set the signature algorithm that will be used to sign this certificate.
/// This can be either a name or an OID, names are treated as case insensitive.
/// </summary>
/// <param name="signatureAlgorithm">string representation of the algorithm name</param>
public void SetSignatureAlgorithm(
string signatureAlgorithm)
{
this.signatureAlgorithm = signatureAlgorithm;
try
{
sigOID = X509Utilities.GetAlgorithmOid(signatureAlgorithm);
}
catch (Exception)
{
throw new ArgumentException("Unknown signature type requested", "signatureAlgorithm");
}
sigAlgId = X509Utilities.GetSigAlgID(sigOID, signatureAlgorithm);
tbsGen.SetSignature(sigAlgId);
}
/// <summary>
/// Generate a new X509Certificate.
/// </summary>
/// <param name="privateKey">The private key of the issuer used to sign this certificate.</param>
/// <returns>An X509Certificate.</returns>
public X509Certificate Generate(
AsymmetricKeyParameter privateKey)
{
return Generate(privateKey, null);
}
/// <summary>
/// Generate a new X509Certificate specifying a SecureRandom instance that you would like to use.
/// </summary>
/// <param name="privateKey">The private key of the issuer used to sign this certificate.</param>
/// <param name="random">The Secure Random you want to use.</param>
/// <returns>An X509Certificate.</returns>
public X509Certificate Generate(
AsymmetricKeyParameter privateKey,
SecureRandom random)
{
TbsCertificateStructure tbsCert = tbsGen.GenerateTbsCertificate();
byte[] signature;
try
{
signature = X509Utilities.GetSignatureForObject(
sigOID, signatureAlgorithm, privateKey, random, tbsCert);
}
catch (Exception e)
{
// TODO
// throw new ExtCertificateEncodingException("exception encoding TBS cert", e);
throw new CertificateEncodingException("exception encoding TBS cert", e);
}
try
{
return GenerateJcaObject(tbsCert, signature);
}
catch (CertificateParsingException e)
{
// TODO
// throw new ExtCertificateEncodingException("exception producing certificate object", e);
throw new CertificateEncodingException("exception producing certificate object", e);
}
}
private X509Certificate GenerateJcaObject(
TbsCertificateStructure tbsCert,
byte[] signature)
{
return new X509Certificate(
new X509CertificateStructure(tbsCert, sigAlgId, new DerBitString(signature)));
}
/// <summary>
/// Allows enumeration of the signature names supported by the generator.
/// </summary>
public IEnumerable SignatureAlgNames
{
get { return X509Utilities.GetAlgNames(); }
}
}
}

View File

@@ -0,0 +1,239 @@
using System;
using System.Collections;
using System.IO;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Security.Certificates;
namespace Org.BouncyCastle.X509
{
/// <summary>An implementation of a version 2 X.509 Attribute Certificate.</summary>
public class X509V2AttributeCertificate
: X509ExtensionBase, IX509AttributeCertificate
{
private readonly AttributeCertificate cert;
private readonly DateTime notBefore;
private readonly DateTime notAfter;
public X509V2AttributeCertificate(
Stream encIn)
: this(new Asn1InputStream(encIn))
{
}
public X509V2AttributeCertificate(
byte[] encoded)
: this(new Asn1InputStream(encoded))
{
}
internal X509V2AttributeCertificate(
Asn1InputStream ais)
: this(AttributeCertificate.GetInstance(ais.ReadObject()))
{
}
internal X509V2AttributeCertificate(
AttributeCertificate cert)
{
this.cert = cert;
try
{
this.notAfter = cert.ACInfo.AttrCertValidityPeriod.NotAfterTime.ToDateTime();
this.notBefore = cert.ACInfo.AttrCertValidityPeriod.NotBeforeTime.ToDateTime();
}
catch (Exception e)
{
throw new IOException("invalid data structure in certificate!", e);
}
}
public virtual int Version
{
get { return cert.ACInfo.Version.Value.IntValue; }
}
public virtual BigInteger SerialNumber
{
get { return cert.ACInfo.SerialNumber.Value; }
}
public virtual AttributeCertificateHolder Holder
{
get
{
return new AttributeCertificateHolder((Asn1Sequence)cert.ACInfo.Holder.ToAsn1Object());
}
}
public virtual AttributeCertificateIssuer Issuer
{
get
{
return new AttributeCertificateIssuer(cert.ACInfo.Issuer);
}
}
public virtual DateTime NotBefore
{
get { return notBefore; }
}
public virtual DateTime NotAfter
{
get { return notAfter; }
}
public virtual bool[] GetIssuerUniqueID()
{
DerBitString id = cert.ACInfo.IssuerUniqueID;
if (id != null)
{
byte[] bytes = id.GetBytes();
bool[] boolId = new bool[bytes.Length * 8 - id.PadBits];
for (int i = 0; i != boolId.Length; i++)
{
//boolId[i] = (bytes[i / 8] & (0x80 >>> (i % 8))) != 0;
boolId[i] = (bytes[i / 8] & (0x80 >> (i % 8))) != 0;
}
return boolId;
}
return null;
}
public virtual bool IsValidNow
{
get { return IsValid(DateTime.UtcNow); }
}
public virtual bool IsValid(
DateTime date)
{
return date.CompareTo(NotBefore) >= 0 && date.CompareTo(NotAfter) <= 0;
}
public virtual void CheckValidity()
{
this.CheckValidity(DateTime.UtcNow);
}
public virtual void CheckValidity(
DateTime date)
{
if (date.CompareTo(NotAfter) > 0)
throw new CertificateExpiredException("certificate expired on " + NotAfter);
if (date.CompareTo(NotBefore) < 0)
throw new CertificateNotYetValidException("certificate not valid until " + NotBefore);
}
public virtual byte[] GetSignature()
{
return cert.SignatureValue.GetBytes();
}
public virtual void Verify(
AsymmetricKeyParameter publicKey)
{
if (!cert.SignatureAlgorithm.Equals(cert.ACInfo.Signature))
{
throw new CertificateException("Signature algorithm in certificate info not same as outer certificate");
}
ISigner signature = SignerUtilities.GetSigner(cert.SignatureAlgorithm.ObjectID.Id);
signature.Init(false, publicKey);
try
{
byte[] b = cert.ACInfo.GetEncoded();
signature.BlockUpdate(b, 0, b.Length);
}
catch (IOException e)
{
throw new SignatureException("Exception encoding certificate info object", e);
}
if (!signature.VerifySignature(this.GetSignature()))
{
throw new InvalidKeyException("Public key presented not for certificate signature");
}
}
public virtual byte[] GetEncoded()
{
return cert.GetEncoded();
}
protected override X509Extensions GetX509Extensions()
{
return cert.ACInfo.Extensions;
}
public virtual X509Attribute[] GetAttributes()
{
Asn1Sequence seq = cert.ACInfo.Attributes;
X509Attribute[] attrs = new X509Attribute[seq.Count];
for (int i = 0; i != seq.Count; i++)
{
attrs[i] = new X509Attribute((Asn1Encodable)seq[i]);
}
return attrs;
}
public virtual X509Attribute[] GetAttributes(
string oid)
{
Asn1Sequence seq = cert.ACInfo.Attributes;
ArrayList list = new ArrayList();
for (int i = 0; i != seq.Count; i++)
{
X509Attribute attr = new X509Attribute((Asn1Encodable)seq[i]);
if (attr.Oid.Equals(oid))
{
list.Add(attr);
}
}
if (list.Count < 1)
{
return null;
}
return (X509Attribute[]) list.ToArray(typeof(X509Attribute));
}
public override bool Equals(
object obj)
{
if (obj == this)
return true;
X509V2AttributeCertificate other = obj as X509V2AttributeCertificate;
if (other == null)
return false;
return cert.Equals(other.cert);
// NB: May prefer this implementation of Equals if more than one certificate implementation in play
//return Arrays.AreEqual(this.GetEncoded(), other.GetEncoded());
}
public override int GetHashCode()
{
return cert.GetHashCode();
}
}
}

View File

@@ -0,0 +1,180 @@
using System;
using System.Collections;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Security.Certificates;
using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.X509
{
/// <remarks>Class to produce an X.509 Version 2 AttributeCertificate.</remarks>
public class X509V2AttributeCertificateGenerator
{
private readonly X509ExtensionsGenerator extGenerator = new X509ExtensionsGenerator();
private V2AttributeCertificateInfoGenerator acInfoGen;
private DerObjectIdentifier sigOID;
private AlgorithmIdentifier sigAlgId;
private string signatureAlgorithm;
public X509V2AttributeCertificateGenerator()
{
acInfoGen = new V2AttributeCertificateInfoGenerator();
}
/// <summary>Reset the generator</summary>
public void Reset()
{
acInfoGen = new V2AttributeCertificateInfoGenerator();
extGenerator.Reset();
}
/// <summary>Set the Holder of this Attribute Certificate.</summary>
public void SetHolder(
AttributeCertificateHolder holder)
{
acInfoGen.SetHolder(holder.holder);
}
/// <summary>Set the issuer.</summary>
public void SetIssuer(
AttributeCertificateIssuer issuer)
{
acInfoGen.SetIssuer(AttCertIssuer.GetInstance(issuer.form));
}
/// <summary>Set the serial number for the certificate.</summary>
public void SetSerialNumber(
BigInteger serialNumber)
{
acInfoGen.SetSerialNumber(new DerInteger(serialNumber));
}
public void SetNotBefore(
DateTime date)
{
acInfoGen.SetStartDate(new DerGeneralizedTime(date));
}
public void SetNotAfter(
DateTime date)
{
acInfoGen.SetEndDate(new DerGeneralizedTime(date));
}
/// <summary>
/// Set the signature algorithm. This can be either a name or an OID, names
/// are treated as case insensitive.
/// </summary>
/// <param name="signatureAlgorithm">The algorithm name.</param>
public void SetSignatureAlgorithm(
string signatureAlgorithm)
{
this.signatureAlgorithm = signatureAlgorithm;
try
{
sigOID = X509Utilities.GetAlgorithmOid(signatureAlgorithm);
}
catch (Exception)
{
throw new ArgumentException("Unknown signature type requested");
}
sigAlgId = X509Utilities.GetSigAlgID(sigOID, signatureAlgorithm);
acInfoGen.SetSignature(sigAlgId);
}
/// <summary>Add an attribute.</summary>
public void AddAttribute(
X509Attribute attribute)
{
acInfoGen.AddAttribute(AttributeX509.GetInstance(attribute.ToAsn1Object()));
}
public void SetIssuerUniqueId(
bool[] iui)
{
// TODO convert bool array to bit string
//acInfoGen.SetIssuerUniqueID(iui);
throw Platform.CreateNotImplementedException("SetIssuerUniqueId()");
}
/// <summary>Add a given extension field for the standard extensions tag.</summary>
public void AddExtension(
string oid,
bool critical,
Asn1Encodable extensionValue)
{
extGenerator.AddExtension(new DerObjectIdentifier(oid), critical, extensionValue);
}
/// <summary>
/// Add a given extension field for the standard extensions tag.
/// The value parameter becomes the contents of the octet string associated
/// with the extension.
/// </summary>
public void AddExtension(
string oid,
bool critical,
byte[] extensionValue)
{
extGenerator.AddExtension(new DerObjectIdentifier(oid), critical, extensionValue);
}
/// <summary>
/// Generate an X509 certificate, based on the current issuer and subject.
/// </summary>
public IX509AttributeCertificate Generate(
AsymmetricKeyParameter publicKey)
{
return Generate(publicKey, null);
}
/// <summary>
/// Generate an X509 certificate, based on the current issuer and subject,
/// using the supplied source of randomness, if required.
/// </summary>
public IX509AttributeCertificate Generate(
AsymmetricKeyParameter publicKey,
SecureRandom random)
{
if (!extGenerator.IsEmpty)
{
acInfoGen.SetExtensions(extGenerator.Generate());
}
AttributeCertificateInfo acInfo = acInfoGen.GenerateAttributeCertificateInfo();
Asn1EncodableVector v = new Asn1EncodableVector();
v.Add(acInfo, sigAlgId);
try
{
v.Add(new DerBitString(X509Utilities.GetSignatureForObject(sigOID, signatureAlgorithm, publicKey, random, acInfo)));
return new X509V2AttributeCertificate(AttributeCertificate.GetInstance(new DerSequence(v)));
}
catch (Exception e)
{
// TODO
// throw new ExtCertificateEncodingException("constructed invalid certificate", e);
throw new CertificateEncodingException("constructed invalid certificate", e);
}
}
/// <summary>
/// Allows enumeration of the signature names supported by the generator.
/// </summary>
public IEnumerable SignatureAlgNames
{
get { return X509Utilities.GetAlgNames(); }
}
}
}

View File

@@ -0,0 +1,261 @@
using System;
using System.Collections;
using System.IO;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Security.Certificates;
using Org.BouncyCastle.Utilities.Collections;
namespace Org.BouncyCastle.X509
{
/**
* class to produce an X.509 Version 2 CRL.
*/
public class X509V2CrlGenerator
{
private readonly X509ExtensionsGenerator extGenerator = new X509ExtensionsGenerator();
private V2TbsCertListGenerator tbsGen;
private DerObjectIdentifier sigOID;
private AlgorithmIdentifier sigAlgId;
private string signatureAlgorithm;
public X509V2CrlGenerator()
{
tbsGen = new V2TbsCertListGenerator();
}
/**
* reset the generator
*/
public void Reset()
{
tbsGen = new V2TbsCertListGenerator();
extGenerator.Reset();
}
/**
* Set the issuer distinguished name - the issuer is the entity whose private key is used to sign the
* certificate.
*/
public void SetIssuerDN(
X509Name issuer)
{
tbsGen.SetIssuer(issuer);
}
public void SetThisUpdate(
DateTime date)
{
tbsGen.SetThisUpdate(new Time(date));
}
public void SetNextUpdate(
DateTime date)
{
tbsGen.SetNextUpdate(new Time(date));
}
/**
* Reason being as indicated by CrlReason, i.e. CrlReason.KeyCompromise
* or 0 if CrlReason is not to be used
**/
public void AddCrlEntry(
BigInteger userCertificate,
DateTime revocationDate,
int reason)
{
tbsGen.AddCrlEntry(new DerInteger(userCertificate), new Time(revocationDate), reason);
}
/**
* Add a CRL entry with an Invalidity Date extension as well as a CrlReason extension.
* Reason being as indicated by CrlReason, i.e. CrlReason.KeyCompromise
* or 0 if CrlReason is not to be used
**/
public void AddCrlEntry(
BigInteger userCertificate,
DateTime revocationDate,
int reason,
DateTime invalidityDate)
{
tbsGen.AddCrlEntry(new DerInteger(userCertificate), new Time(revocationDate), reason, new DerGeneralizedTime(invalidityDate));
}
/**
* Add a CRL entry with extensions.
**/
public void AddCrlEntry(
BigInteger userCertificate,
DateTime revocationDate,
X509Extensions extensions)
{
tbsGen.AddCrlEntry(new DerInteger(userCertificate), new Time(revocationDate), extensions);
}
/**
* Add the CRLEntry objects contained in a previous CRL.
*
* @param other the X509Crl to source the other entries from.
*/
public void AddCrl(
X509Crl other)
{
if (other == null)
throw new ArgumentNullException("other");
ISet revocations = other.GetRevokedCertificates();
if (revocations != null)
{
foreach (X509CrlEntry entry in revocations)
{
try
{
tbsGen.AddCrlEntry(
Asn1Sequence.GetInstance(
Asn1Object.FromByteArray(entry.GetEncoded())));
}
catch (IOException e)
{
throw new CrlException("exception processing encoding of CRL", e);
}
}
}
}
/**
* Set the signature algorithm. This can be either a name or an oid, names
* are treated as case insensitive.
*
* @param signatureAlgorithm string representation of the algorithm name.
*/
public void SetSignatureAlgorithm(
string signatureAlgorithm)
{
this.signatureAlgorithm = signatureAlgorithm;
try
{
sigOID = X509Utilities.GetAlgorithmOid(signatureAlgorithm);
}
catch (Exception e)
{
throw new ArgumentException("Unknown signature type requested", e);
}
sigAlgId = X509Utilities.GetSigAlgID(sigOID, signatureAlgorithm);
tbsGen.SetSignature(sigAlgId);
}
/**
* add a given extension field for the standard extensions tag (tag 0)
*/
public void AddExtension(
string oid,
bool critical,
Asn1Encodable extensionValue)
{
extGenerator.AddExtension(new DerObjectIdentifier(oid), critical, extensionValue);
}
/**
* add a given extension field for the standard extensions tag (tag 0)
*/
public void AddExtension(
DerObjectIdentifier oid,
bool critical,
Asn1Encodable extensionValue)
{
extGenerator.AddExtension(oid, critical, extensionValue);
}
/**
* add a given extension field for the standard extensions tag (tag 0)
*/
public void AddExtension(
string oid,
bool critical,
byte[] extensionValue)
{
extGenerator.AddExtension(new DerObjectIdentifier(oid), critical, new DerOctetString(extensionValue));
}
/**
* add a given extension field for the standard extensions tag (tag 0)
*/
public void AddExtension(
DerObjectIdentifier oid,
bool critical,
byte[] extensionValue)
{
extGenerator.AddExtension(oid, critical, new DerOctetString(extensionValue));
}
/// <summary>Generate an X509 CRL, based on the current issuer and subject.</summary>
/// <param name="privateKey">The key used for signing.</param>
public X509Crl Generate(
AsymmetricKeyParameter privateKey)
{
return Generate(privateKey, null);
}
/// <summary>Generate an X509 CRL, based on the current issuer and subject.</summary>
/// <param name="privateKey">The key used for signing.</param>
/// <param name="random">A user-defined source of randomness.</param>
public X509Crl Generate(
AsymmetricKeyParameter privateKey,
SecureRandom random)
{
TbsCertificateList tbsCrl = GenerateCertList();
byte[] signature;
try
{
signature = X509Utilities.GetSignatureForObject(
sigOID, signatureAlgorithm, privateKey, random, tbsCrl);
}
catch (IOException e)
{
// TODO
// throw new ExtCrlException("cannot generate CRL encoding", e);
throw new CrlException("cannot generate CRL encoding", e);
}
return GenerateJcaObject(tbsCrl, signature);
}
private TbsCertificateList GenerateCertList()
{
if (!extGenerator.IsEmpty)
{
tbsGen.SetExtensions(extGenerator.Generate());
}
return tbsGen.GenerateTbsCertList();
}
private X509Crl GenerateJcaObject(
TbsCertificateList tbsCrl,
byte[] signature)
{
return new X509Crl(
CertificateList.GetInstance(
new DerSequence(tbsCrl, sigAlgId, new DerBitString(signature))));
}
/// <summary>
/// Allows enumeration of the signature names supported by the generator.
/// </summary>
public IEnumerable SignatureAlgNames
{
get { return X509Utilities.GetAlgNames(); }
}
}
}

View File

@@ -0,0 +1,303 @@
using System;
using System.Collections;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Security.Certificates;
using Org.BouncyCastle.X509.Extension;
namespace Org.BouncyCastle.X509
{
/// <summary>
/// A class to Generate Version 3 X509Certificates.
/// </summary>
public class X509V3CertificateGenerator
{
private readonly X509ExtensionsGenerator extGenerator = new X509ExtensionsGenerator();
private V3TbsCertificateGenerator tbsGen;
private DerObjectIdentifier sigOid;
private AlgorithmIdentifier sigAlgId;
private string signatureAlgorithm;
public X509V3CertificateGenerator()
{
tbsGen = new V3TbsCertificateGenerator();
}
/// <summary>
/// Reset the Generator.
/// </summary>
public void Reset()
{
tbsGen = new V3TbsCertificateGenerator();
extGenerator.Reset();
}
/// <summary>
/// Set the certificate's serial number.
/// </summary>
/// <remarks>Make serial numbers long, if you have no serial number policy make sure the number is at least 16 bytes of secure random data.
/// You will be surprised how ugly a serial number collision can Get.</remarks>
/// <param name="serialNumber">The serial number.</param>
public void SetSerialNumber(
BigInteger serialNumber)
{
if (serialNumber.SignValue <= 0)
{
throw new ArgumentException("serial number must be a positive integer", "serialNumber");
}
tbsGen.SetSerialNumber(new DerInteger(serialNumber));
}
/// <summary>
/// Set the distinguished name of the issuer.
/// The issuer is the entity which is signing the certificate.
/// </summary>
/// <param name="issuer">The issuer's DN.</param>
public void SetIssuerDN(
X509Name issuer)
{
tbsGen.SetIssuer(issuer);
}
/// <summary>
/// Set the date that this certificate is to be valid from.
/// </summary>
/// <param name="date"/>
public void SetNotBefore(
DateTime date)
{
tbsGen.SetStartDate(new Time(date));
}
/// <summary>
/// Set the date after which this certificate will no longer be valid.
/// </summary>
/// <param name="date"/>
public void SetNotAfter(
DateTime date)
{
tbsGen.SetEndDate(new Time(date));
}
/// <summary>
/// Set the DN of the entity that this certificate is about.
/// </summary>
/// <param name="subject"/>
public void SetSubjectDN(
X509Name subject)
{
tbsGen.SetSubject(subject);
}
/// <summary>
/// Set the public key that this certificate identifies.
/// </summary>
/// <param name="publicKey"/>
public void SetPublicKey(
AsymmetricKeyParameter publicKey)
{
tbsGen.SetSubjectPublicKeyInfo(SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(publicKey));
}
/// <summary>
/// Set the signature algorithm that will be used to sign this certificate.
/// </summary>
/// <param name="signatureAlgorithm"/>
public void SetSignatureAlgorithm(
string signatureAlgorithm)
{
this.signatureAlgorithm = signatureAlgorithm;
try
{
sigOid = X509Utilities.GetAlgorithmOid(signatureAlgorithm);
}
catch (Exception)
{
throw new ArgumentException("Unknown signature type requested: " + signatureAlgorithm);
}
sigAlgId = X509Utilities.GetSigAlgID(sigOid, signatureAlgorithm);
tbsGen.SetSignature(sigAlgId);
}
/// <summary>
/// Add a given extension field for the standard extensions tag (tag 3).
/// </summary>
/// <param name="oid">string containing a dotted decimal Object Identifier.</param>
/// <param name="critical">Is it critical.</param>
/// <param name="extensionValue">The value.</param>
public void AddExtension(
string oid,
bool critical,
Asn1Encodable extensionValue)
{
extGenerator.AddExtension(new DerObjectIdentifier(oid), critical, extensionValue);
}
/// <summary>
/// Add an extension to this certificate.
/// </summary>
/// <param name="oid">Its Object Identifier.</param>
/// <param name="critical">Is it critical.</param>
/// <param name="extensionValue">The value.</param>
public void AddExtension(
DerObjectIdentifier oid,
bool critical,
Asn1Encodable extensionValue)
{
extGenerator.AddExtension(oid, critical, extensionValue);
}
/// <summary>
/// Add an extension using a string with a dotted decimal OID.
/// </summary>
/// <param name="oid">string containing a dotted decimal Object Identifier.</param>
/// <param name="critical">Is it critical.</param>
/// <param name="extensionValue">byte[] containing the value of this extension.</param>
public void AddExtension(
string oid,
bool critical,
byte[] extensionValue)
{
extGenerator.AddExtension(new DerObjectIdentifier(oid), critical, new DerOctetString(extensionValue));
}
/// <summary>
/// Add an extension to this certificate.
/// </summary>
/// <param name="oid">Its Object Identifier.</param>
/// <param name="critical">Is it critical.</param>
/// <param name="extensionValue">byte[] containing the value of this extension.</param>
public void AddExtension(
DerObjectIdentifier oid,
bool critical,
byte[] extensionValue)
{
extGenerator.AddExtension(oid, critical, new DerOctetString(extensionValue));
}
/// <summary>
/// Add a given extension field for the standard extensions tag (tag 3),
/// copying the extension value from another certificate.
/// </summary>
public void CopyAndAddExtension(
string oid,
bool critical,
X509Certificate cert)
{
CopyAndAddExtension(new DerObjectIdentifier(oid), critical, cert);
}
/**
* add a given extension field for the standard extensions tag (tag 3)
* copying the extension value from another certificate.
* @throws CertificateParsingException if the extension cannot be extracted.
*/
public void CopyAndAddExtension(
DerObjectIdentifier oid,
bool critical,
X509Certificate cert)
{
Asn1OctetString extValue = cert.GetExtensionValue(oid);
if (extValue == null)
{
throw new CertificateParsingException("extension " + oid + " not present");
}
try
{
Asn1Encodable value = X509ExtensionUtilities.FromExtensionValue(extValue);
this.AddExtension(oid, critical, value);
}
catch (Exception e)
{
throw new CertificateParsingException(e.Message, e);
}
}
/// <summary>
/// Generate an X509Certificate.
/// </summary>
/// <param name="privateKey">The private key of the issuer that is signing this certificate.</param>
/// <returns>An X509Certificate.</returns>
public X509Certificate Generate(
AsymmetricKeyParameter privateKey)
{
return Generate(privateKey, null);
}
/// <summary>
/// Generate an X509Certificate using your own SecureRandom.
/// </summary>
/// <param name="privateKey">The private key of the issuer that is signing this certificate.</param>
/// <param name="random">You Secure Random instance.</param>
/// <returns>An X509Certificate.</returns>
public X509Certificate Generate(
AsymmetricKeyParameter privateKey,
SecureRandom random)
{
TbsCertificateStructure tbsCert = GenerateTbsCert();
byte[] signature;
try
{
signature = X509Utilities.GetSignatureForObject(
sigOid, signatureAlgorithm, privateKey, random, tbsCert);
}
catch (Exception e)
{
// TODO
// throw new ExtCertificateEncodingException("exception encoding TBS cert", e);
throw new CertificateEncodingException("exception encoding TBS cert", e);
}
try
{
return GenerateJcaObject(tbsCert, signature);
}
catch (CertificateParsingException e)
{
// TODO
// throw new ExtCertificateEncodingException("exception producing certificate object", e);
throw new CertificateEncodingException("exception producing certificate object", e);
}
}
private TbsCertificateStructure GenerateTbsCert()
{
if (!extGenerator.IsEmpty)
{
tbsGen.SetExtensions(extGenerator.Generate());
}
return tbsGen.GenerateTbsCertificate();
}
private X509Certificate GenerateJcaObject(
TbsCertificateStructure tbsCert,
byte[] signature)
{
return new X509Certificate(
new X509CertificateStructure(tbsCert, sigAlgId, new DerBitString(signature)));
}
/// <summary>
/// Allows enumeration of the signature names supported by the generator.
/// </summary>
public IEnumerable SignatureAlgNames
{
get { return X509Utilities.GetAlgNames(); }
}
}
}

View File

@@ -0,0 +1,105 @@
using System;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Security.Certificates;
namespace Org.BouncyCastle.X509.Extension
{
/// <remarks>A high level authority key identifier.</remarks>
public class AuthorityKeyIdentifierStructure
: AuthorityKeyIdentifier
{
/**
* Constructor which will take the byte[] returned from getExtensionValue()
*
* @param encodedValue a DER octet encoded string with the extension structure in it.
* @throws IOException on parsing errors.
*/
// TODO Add a functional constructor from byte[]?
public AuthorityKeyIdentifierStructure(
Asn1OctetString encodedValue)
: base((Asn1Sequence) X509ExtensionUtilities.FromExtensionValue(encodedValue))
{
}
private static Asn1Sequence FromCertificate(
X509Certificate certificate)
{
try
{
GeneralName genName = new GeneralName(
PrincipalUtilities.GetIssuerX509Principal(certificate));
if (certificate.Version == 3)
{
Asn1OctetString ext = certificate.GetExtensionValue(X509Extensions.SubjectKeyIdentifier);
if (ext != null)
{
Asn1OctetString str = (Asn1OctetString) X509ExtensionUtilities.FromExtensionValue(ext);
return (Asn1Sequence) new AuthorityKeyIdentifier(
str.GetOctets(), new GeneralNames(genName), certificate.SerialNumber).ToAsn1Object();
}
}
SubjectPublicKeyInfo info = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(
certificate.GetPublicKey());
return (Asn1Sequence) new AuthorityKeyIdentifier(
info, new GeneralNames(genName), certificate.SerialNumber).ToAsn1Object();
}
catch (Exception e)
{
throw new CertificateParsingException("Exception extracting certificate details", e);
}
}
private static Asn1Sequence FromKey(
AsymmetricKeyParameter pubKey)
{
try
{
// SubjectPublicKeyInfo info = new SubjectPublicKeyInfo(
// (Asn1Sequence) Asn1Object.FromByteArray(
// pubKey.GetEncoded()));
SubjectPublicKeyInfo info = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(pubKey);
return (Asn1Sequence) new AuthorityKeyIdentifier(info).ToAsn1Object();
}
catch (Exception e)
{
throw new InvalidKeyException("can't process key: " + e);
}
}
/**
* Create an AuthorityKeyIdentifier using the passed in certificate's public
* key, issuer and serial number.
*
* @param certificate the certificate providing the information.
* @throws CertificateParsingException if there is a problem processing the certificate
*/
public AuthorityKeyIdentifierStructure(
X509Certificate certificate)
: base(FromCertificate(certificate))
{
}
/**
* Create an AuthorityKeyIdentifier using just the hash of the
* public key.
*
* @param pubKey the key to generate the hash from.
* @throws InvalidKeyException if there is a problem using the key.
*/
public AuthorityKeyIdentifierStructure(
AsymmetricKeyParameter pubKey)
: base(FromKey(pubKey))
{
}
}
}

View File

@@ -0,0 +1,51 @@
using System;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Security.Certificates;
namespace Org.BouncyCastle.X509.Extension
{
/**
* A high level subject key identifier.
*/
public class SubjectKeyIdentifierStructure
: SubjectKeyIdentifier
{
// private AuthorityKeyIdentifier authKeyID;
/**
* Constructor which will take the byte[] returned from getExtensionValue()
*
* @param encodedValue a DER octet encoded string with the extension structure in it.
* @throws IOException on parsing errors.
*/
public SubjectKeyIdentifierStructure(
Asn1OctetString encodedValue)
: base((Asn1OctetString) X509ExtensionUtilities.FromExtensionValue(encodedValue))
{
}
private static Asn1OctetString FromPublicKey(
AsymmetricKeyParameter pubKey)
{
try
{
SubjectPublicKeyInfo info = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(pubKey);
return (Asn1OctetString) new SubjectKeyIdentifier(info).ToAsn1Object();
}
catch (Exception e)
{
throw new CertificateParsingException("Exception extracting certificate details: " + e.ToString());
}
}
public SubjectKeyIdentifierStructure(
AsymmetricKeyParameter pubKey)
: base(FromPublicKey(pubKey))
{
}
}
}

View File

@@ -0,0 +1,88 @@
using System;
using System.Collections;
using System.IO;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Security.Certificates;
namespace Org.BouncyCastle.X509.Extension
{
public class X509ExtensionUtilities
{
public static Asn1Object FromExtensionValue(
Asn1OctetString extensionValue)
{
return Asn1Object.FromByteArray(extensionValue.GetOctets());
}
public static ICollection GetIssuerAlternativeNames(
X509Certificate cert)
{
Asn1OctetString extVal = cert.GetExtensionValue(X509Extensions.IssuerAlternativeName);
return GetAlternativeName(extVal);
}
public static ICollection GetSubjectAlternativeNames(
X509Certificate cert)
{
Asn1OctetString extVal = cert.GetExtensionValue(X509Extensions.SubjectAlternativeName);
return GetAlternativeName(extVal);
}
private static ICollection GetAlternativeName(
Asn1OctetString extVal)
{
ArrayList temp = new ArrayList();
if (extVal != null)
{
try
{
Asn1Sequence seq = DerSequence.GetInstance(FromExtensionValue(extVal));
foreach (GeneralName genName in seq)
{
ArrayList list = new ArrayList();
list.Add(genName.TagNo);
switch (genName.TagNo)
{
case GeneralName.EdiPartyName:
case GeneralName.X400Address:
case GeneralName.OtherName:
list.Add(genName.Name.ToAsn1Object());
break;
case GeneralName.DirectoryName:
list.Add(X509Name.GetInstance(genName.Name).ToString());
break;
case GeneralName.DnsName:
case GeneralName.Rfc822Name:
case GeneralName.UniformResourceIdentifier:
list.Add(((IAsn1String)genName.Name).GetString());
break;
case GeneralName.RegisteredID:
list.Add(DerObjectIdentifier.GetInstance(genName.Name).Id);
break;
case GeneralName.IPAddress:
list.Add(DerOctetString.GetInstance(genName.Name).GetOctets());
break;
default:
throw new IOException("Bad tag number: " + genName.TagNo);
}
temp.Add(list);
}
}
catch (Exception e)
{
throw new CertificateParsingException(e.Message);
}
}
return temp;
}
}
}

View File

@@ -0,0 +1,10 @@
using System;
namespace Org.BouncyCastle.X509.Store
{
public interface IX509Selector
: ICloneable
{
bool Match(object obj);
}
}

View File

@@ -0,0 +1,11 @@
using System;
using System.Collections;
namespace Org.BouncyCastle.X509.Store
{
public interface IX509Store
{
// void Init(IX509StoreParameters parameters);
ICollection GetMatches(IX509Selector selector);
}
}

View File

@@ -0,0 +1,8 @@
using System;
namespace Org.BouncyCastle.X509.Store
{
public interface IX509StoreParameters
{
}
}

View File

@@ -0,0 +1,25 @@
using System;
namespace Org.BouncyCastle.X509.Store
{
public class NoSuchStoreException
: X509StoreException
{
public NoSuchStoreException()
{
}
public NoSuchStoreException(
string message)
: base(message)
{
}
public NoSuchStoreException(
string message,
Exception e)
: base(message, e)
{
}
}
}

View File

@@ -0,0 +1,376 @@
using System;
using System.Collections;
using System.IO;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Utilities.Collections;
using Org.BouncyCastle.Utilities.Date;
using Org.BouncyCastle.X509.Extension;
namespace Org.BouncyCastle.X509.Store
{
/**
* This class is an <code>Selector</code> like implementation to select
* attribute certificates from a given set of criteria.
*
* @see org.bouncycastle.x509.X509AttributeCertificate
* @see org.bouncycastle.x509.X509Store
*/
public class X509AttrCertStoreSelector
: IX509Selector
{
// TODO: name constraints???
private IX509AttributeCertificate attributeCert;
private DateTimeObject attributeCertificateValid;
private AttributeCertificateHolder holder;
private AttributeCertificateIssuer issuer;
private BigInteger serialNumber;
private ISet targetNames = new HashSet();
private ISet targetGroups = new HashSet();
public X509AttrCertStoreSelector()
{
}
private X509AttrCertStoreSelector(
X509AttrCertStoreSelector o)
{
this.attributeCert = o.attributeCert;
this.attributeCertificateValid = o.attributeCertificateValid;
this.holder = o.holder;
this.issuer = o.issuer;
this.serialNumber = o.serialNumber;
this.targetGroups = new HashSet(o.targetGroups);
this.targetNames = new HashSet(o.targetNames);
}
/// <summary>
/// Decides if the given attribute certificate should be selected.
/// </summary>
/// <param name="obj">The attribute certificate to be checked.</param>
/// <returns><code>true</code> if the object matches this selector.</returns>
public bool Match(
object obj)
{
if (obj == null)
throw new ArgumentNullException("obj");
IX509AttributeCertificate attrCert = obj as IX509AttributeCertificate;
if (attrCert == null)
return false;
if (this.attributeCert != null && !this.attributeCert.Equals(attrCert))
return false;
if (serialNumber != null && !attrCert.SerialNumber.Equals(serialNumber))
return false;
if (holder != null && !attrCert.Holder.Equals(holder))
return false;
if (issuer != null && !attrCert.Issuer.Equals(issuer))
return false;
if (attributeCertificateValid != null && !attrCert.IsValid(attributeCertificateValid.Value))
return false;
if (targetNames.Count > 0 || targetGroups.Count > 0)
{
Asn1OctetString targetInfoExt = attrCert.GetExtensionValue(
X509Extensions.TargetInformation);
if (targetInfoExt != null)
{
TargetInformation targetinfo;
try
{
targetinfo = TargetInformation.GetInstance(
X509ExtensionUtilities.FromExtensionValue(targetInfoExt));
}
catch (Exception)
{
return false;
}
Targets[] targetss = targetinfo.GetTargetsObjects();
if (targetNames.Count > 0)
{
bool found = false;
for (int i = 0; i < targetss.Length && !found; i++)
{
Target[] targets = targetss[i].GetTargets();
for (int j = 0; j < targets.Length; j++)
{
GeneralName targetName = targets[j].TargetName;
if (targetName != null && targetNames.Contains(targetName))
{
found = true;
break;
}
}
}
if (!found)
{
return false;
}
}
if (targetGroups.Count > 0)
{
bool found = false;
for (int i = 0; i < targetss.Length && !found; i++)
{
Target[] targets = targetss[i].GetTargets();
for (int j = 0; j < targets.Length; j++)
{
GeneralName targetGroup = targets[j].TargetGroup;
if (targetGroup != null && targetGroups.Contains(targetGroup))
{
found = true;
break;
}
}
}
if (!found)
{
return false;
}
}
}
}
return true;
}
public object Clone()
{
return new X509AttrCertStoreSelector(this);
}
/// <summary>The attribute certificate which must be matched.</summary>
/// <remarks>If <c>null</c> is given, any will do.</remarks>
public IX509AttributeCertificate AttributeCert
{
get { return attributeCert; }
set { this.attributeCert = value; }
}
[Obsolete("Use AttributeCertificateValid instead")]
public DateTimeObject AttribueCertificateValid
{
get { return attributeCertificateValid; }
set { this.attributeCertificateValid = value; }
}
/// <summary>The criteria for validity</summary>
/// <remarks>If <c>null</c> is given any will do.</remarks>
public DateTimeObject AttributeCertificateValid
{
get { return attributeCertificateValid; }
set { this.attributeCertificateValid = value; }
}
/// <summary>The holder.</summary>
/// <remarks>If <c>null</c> is given any will do.</remarks>
public AttributeCertificateHolder Holder
{
get { return holder; }
set { this.holder = value; }
}
/// <summary>The issuer.</summary>
/// <remarks>If <c>null</c> is given any will do.</remarks>
public AttributeCertificateIssuer Issuer
{
get { return issuer; }
set { this.issuer = value; }
}
/// <summary>The serial number.</summary>
/// <remarks>If <c>null</c> is given any will do.</remarks>
public BigInteger SerialNumber
{
get { return serialNumber; }
set { this.serialNumber = value; }
}
/**
* Adds a target name criterion for the attribute certificate to the target
* information extension criteria. The <code>X509AttributeCertificate</code>
* must contain at least one of the specified target names.
* <p>
* Each attribute certificate may contain a target information extension
* limiting the servers where this attribute certificate can be used. If
* this extension is not present, the attribute certificate is not targeted
* and may be accepted by any server.
* </p>
*
* @param name The name as a GeneralName (not <code>null</code>)
*/
public void AddTargetName(
GeneralName name)
{
targetNames.Add(name);
}
/**
* Adds a target name criterion for the attribute certificate to the target
* information extension criteria. The <code>X509AttributeCertificate</code>
* must contain at least one of the specified target names.
* <p>
* Each attribute certificate may contain a target information extension
* limiting the servers where this attribute certificate can be used. If
* this extension is not present, the attribute certificate is not targeted
* and may be accepted by any server.
* </p>
*
* @param name a byte array containing the name in ASN.1 DER encoded form of a GeneralName
* @throws IOException if a parsing error occurs.
*/
public void AddTargetName(
byte[] name)
{
AddTargetName(GeneralName.GetInstance(Asn1Object.FromByteArray(name)));
}
/**
* Adds a collection with target names criteria. If <code>null</code> is
* given any will do.
* <p>
* The collection consists of either GeneralName objects or byte[] arrays representing
* DER encoded GeneralName structures.
* </p>
*
* @param names A collection of target names.
* @throws IOException if a parsing error occurs.
* @see #AddTargetName(byte[])
* @see #AddTargetName(GeneralName)
*/
public void SetTargetNames(
IEnumerable names)
{
targetNames = ExtractGeneralNames(names);
}
/**
* Gets the target names. The collection consists of <code>List</code>s
* made up of an <code>Integer</code> in the first entry and a DER encoded
* byte array or a <code>String</code> in the second entry.
* <p>The returned collection is immutable.</p>
*
* @return The collection of target names
* @see #setTargetNames(Collection)
*/
public IEnumerable GetTargetNames()
{
return new EnumerableProxy(targetNames);
}
/**
* Adds a target group criterion for the attribute certificate to the target
* information extension criteria. The <code>X509AttributeCertificate</code>
* must contain at least one of the specified target groups.
* <p>
* Each attribute certificate may contain a target information extension
* limiting the servers where this attribute certificate can be used. If
* this extension is not present, the attribute certificate is not targeted
* and may be accepted by any server.
* </p>
*
* @param group The group as GeneralName form (not <code>null</code>)
*/
public void AddTargetGroup(
GeneralName group)
{
targetGroups.Add(group);
}
/**
* Adds a target group criterion for the attribute certificate to the target
* information extension criteria. The <code>X509AttributeCertificate</code>
* must contain at least one of the specified target groups.
* <p>
* Each attribute certificate may contain a target information extension
* limiting the servers where this attribute certificate can be used. If
* this extension is not present, the attribute certificate is not targeted
* and may be accepted by any server.
* </p>
*
* @param name a byte array containing the group in ASN.1 DER encoded form of a GeneralName
* @throws IOException if a parsing error occurs.
*/
public void AddTargetGroup(
byte[] name)
{
AddTargetGroup(GeneralName.GetInstance(Asn1Object.FromByteArray(name)));
}
/**
* Adds a collection with target groups criteria. If <code>null</code> is
* given any will do.
* <p>
* The collection consists of <code>GeneralName</code> objects or <code>byte[]</code>
* representing DER encoded GeneralNames.
* </p>
*
* @param names A collection of target groups.
* @throws IOException if a parsing error occurs.
* @see #AddTargetGroup(byte[])
* @see #AddTargetGroup(GeneralName)
*/
public void SetTargetGroups(
IEnumerable names)
{
targetGroups = ExtractGeneralNames(names);
}
/**
* Gets the target groups. The collection consists of <code>List</code>s
* made up of an <code>Integer</code> in the first entry and a DER encoded
* byte array or a <code>String</code> in the second entry.
* <p>The returned collection is immutable.</p>
*
* @return The collection of target groups.
* @see #setTargetGroups(Collection)
*/
public IEnumerable GetTargetGroups()
{
return new EnumerableProxy(targetGroups);
}
private ISet ExtractGeneralNames(
IEnumerable names)
{
ISet result = new HashSet();
if (names != null)
{
foreach (object o in names)
{
if (o is GeneralName)
{
result.Add(o);
}
else
{
result.Add(GeneralName.GetInstance(Asn1Object.FromByteArray((byte[]) o)));
}
}
}
return result;
}
}
}

View File

@@ -0,0 +1,92 @@
using System;
namespace Org.BouncyCastle.X509.Store
{
/// <remarks>
/// This class is an <code>IX509Selector</code> implementation to select
/// certificate pairs, which are e.g. used for cross certificates. The set of
/// criteria is given from two <code>X509CertStoreSelector</code> objects,
/// each of which, if present, must match the respective component of a pair.
/// </remarks>
public class X509CertPairStoreSelector
: IX509Selector
{
private static X509CertStoreSelector CloneSelector(
X509CertStoreSelector s)
{
return s == null ? null : (X509CertStoreSelector) s.Clone();
}
private X509CertificatePair certPair;
private X509CertStoreSelector forwardSelector;
private X509CertStoreSelector reverseSelector;
public X509CertPairStoreSelector()
{
}
private X509CertPairStoreSelector(
X509CertPairStoreSelector o)
{
this.certPair = o.CertPair;
this.forwardSelector = o.ForwardSelector;
this.reverseSelector = o.ReverseSelector;
}
/// <summary>The certificate pair which is used for testing on equality.</summary>
public X509CertificatePair CertPair
{
get { return certPair; }
set { this.certPair = value; }
}
/// <summary>The certificate selector for the forward part.</summary>
public X509CertStoreSelector ForwardSelector
{
get { return CloneSelector(forwardSelector); }
set { this.forwardSelector = CloneSelector(value); }
}
/// <summary>The certificate selector for the reverse part.</summary>
public X509CertStoreSelector ReverseSelector
{
get { return CloneSelector(reverseSelector); }
set { this.reverseSelector = CloneSelector(value); }
}
/// <summary>
/// Decides if the given certificate pair should be selected. If
/// <c>obj</c> is not a <code>X509CertificatePair</code>, this method
/// returns <code>false</code>.
/// </summary>
/// <param name="obj">The <code>X509CertificatePair</code> to be tested.</param>
/// <returns><code>true</code> if the object matches this selector.</returns>
public bool Match(
object obj)
{
if (obj == null)
throw new ArgumentNullException("obj");
X509CertificatePair pair = obj as X509CertificatePair;
if (pair == null)
return false;
if (certPair != null && !certPair.Equals(pair))
return false;
if (forwardSelector != null && !forwardSelector.Match(pair.Forward))
return false;
if (reverseSelector != null && !reverseSelector.Match(pair.Reverse))
return false;
return true;
}
public object Clone()
{
return new X509CertPairStoreSelector(this);
}
}
}

View File

@@ -0,0 +1,329 @@
using System;
using System.Collections;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.Collections;
using Org.BouncyCastle.Utilities.Date;
using Org.BouncyCastle.X509.Extension;
namespace Org.BouncyCastle.X509.Store
{
public class X509CertStoreSelector
: IX509Selector
{
// TODO Missing criteria?
private byte[] authorityKeyIdentifier;
private int basicConstraints = -1;
private X509Certificate certificate;
private DateTimeObject certificateValid;
private ISet extendedKeyUsage;
private X509Name issuer;
private bool[] keyUsage;
private ISet policy;
private DateTimeObject privateKeyValid;
private BigInteger serialNumber;
private X509Name subject;
private byte[] subjectKeyIdentifier;
private SubjectPublicKeyInfo subjectPublicKey;
private DerObjectIdentifier subjectPublicKeyAlgID;
public X509CertStoreSelector()
{
}
public X509CertStoreSelector(
X509CertStoreSelector o)
{
this.authorityKeyIdentifier = o.AuthorityKeyIdentifier;
this.basicConstraints = o.BasicConstraints;
this.certificate = o.Certificate;
this.certificateValid = o.CertificateValid;
this.extendedKeyUsage = o.ExtendedKeyUsage;
this.issuer = o.Issuer;
this.keyUsage = o.KeyUsage;
this.policy = o.Policy;
this.privateKeyValid = o.PrivateKeyValid;
this.serialNumber = o.SerialNumber;
this.subject = o.Subject;
this.subjectKeyIdentifier = o.SubjectKeyIdentifier;
this.subjectPublicKey = o.SubjectPublicKey;
this.subjectPublicKeyAlgID = o.SubjectPublicKeyAlgID;
}
public virtual object Clone()
{
return new X509CertStoreSelector(this);
}
public byte[] AuthorityKeyIdentifier
{
get { return Arrays.Clone(authorityKeyIdentifier); }
set { authorityKeyIdentifier = Arrays.Clone(value); }
}
public int BasicConstraints
{
get { return basicConstraints; }
set
{
if (value < -2)
throw new ArgumentException("value can't be less than -2", "value");
basicConstraints = value;
}
}
public X509Certificate Certificate
{
get { return certificate; }
set { this.certificate = value; }
}
public DateTimeObject CertificateValid
{
get { return certificateValid; }
set { certificateValid = value; }
}
public ISet ExtendedKeyUsage
{
get { return CopySet(extendedKeyUsage); }
set { extendedKeyUsage = CopySet(value); }
}
public X509Name Issuer
{
get { return issuer; }
set { issuer = value; }
}
public string IssuerAsString
{
get { return issuer != null ? issuer.ToString() : null; }
}
public bool[] KeyUsage
{
get { return CopyBoolArray(keyUsage); }
set { keyUsage = CopyBoolArray(value); }
}
/// <summary>
/// An <code>ISet</code> of <code>DerObjectIdentifier</code> objects.
/// </summary>
public ISet Policy
{
get { return CopySet(policy); }
set { policy = CopySet(value); }
}
public DateTimeObject PrivateKeyValid
{
get { return privateKeyValid; }
set { privateKeyValid = value; }
}
public BigInteger SerialNumber
{
get { return serialNumber; }
set { serialNumber = value; }
}
public X509Name Subject
{
get { return subject; }
set { subject = value; }
}
public string SubjectAsString
{
get { return subject != null ? subject.ToString() : null; }
}
public byte[] SubjectKeyIdentifier
{
get { return Arrays.Clone(subjectKeyIdentifier); }
set { subjectKeyIdentifier = Arrays.Clone(value); }
}
public SubjectPublicKeyInfo SubjectPublicKey
{
get { return subjectPublicKey; }
set { subjectPublicKey = value; }
}
public DerObjectIdentifier SubjectPublicKeyAlgID
{
get { return subjectPublicKeyAlgID; }
set { subjectPublicKeyAlgID = value; }
}
public virtual bool Match(
object obj)
{
X509Certificate c = obj as X509Certificate;
if (c == null)
return false;
if (!MatchExtension(authorityKeyIdentifier, c, X509Extensions.AuthorityKeyIdentifier))
return false;
if (basicConstraints != -1)
{
int bc = c.GetBasicConstraints();
if (basicConstraints == -2)
{
if (bc != -1)
return false;
}
else
{
if (bc < basicConstraints)
return false;
}
}
if (certificate != null && !certificate.Equals(c))
return false;
if (certificateValid != null && !c.IsValid(certificateValid.Value))
return false;
if (extendedKeyUsage != null)
{
IList eku = c.GetExtendedKeyUsage();
// Note: if no extended key usage set, all key purposes are implicitly allowed
if (eku != null)
{
foreach (DerObjectIdentifier oid in extendedKeyUsage)
{
if (!eku.Contains(oid.Id))
return false;
}
}
}
if (issuer != null && !issuer.Equivalent(c.IssuerDN))
return false;
if (keyUsage != null)
{
bool[] ku = c.GetKeyUsage();
// Note: if no key usage set, all key purposes are implicitly allowed
if (ku != null)
{
for (int i = 0; i < 9; ++i)
{
if (keyUsage[i] && !ku[i])
return false;
}
}
}
if (policy != null)
{
Asn1OctetString extVal = c.GetExtensionValue(X509Extensions.CertificatePolicies);
if (extVal == null)
return false;
Asn1Sequence certPolicies = Asn1Sequence.GetInstance(
X509ExtensionUtilities.FromExtensionValue(extVal));
if (policy.Count < 1 && certPolicies.Count < 1)
return false;
bool found = false;
foreach (PolicyInformation pi in certPolicies)
{
if (policy.Contains(pi.PolicyIdentifier))
{
found = true;
break;
}
}
if (!found)
return false;
}
if (privateKeyValid != null)
{
Asn1OctetString extVal = c.GetExtensionValue(X509Extensions.PrivateKeyUsagePeriod);
if (extVal == null)
return false;
PrivateKeyUsagePeriod pkup = PrivateKeyUsagePeriod.GetInstance(
X509ExtensionUtilities.FromExtensionValue(extVal));
DateTime dt = privateKeyValid.Value;
DateTime notAfter = pkup.NotAfter.ToDateTime();
DateTime notBefore = pkup.NotBefore.ToDateTime();
if (dt.CompareTo(notAfter) > 0 || dt.CompareTo(notBefore) < 0)
return false;
}
if (serialNumber != null && !serialNumber.Equals(c.SerialNumber))
return false;
if (subject != null && !subject.Equivalent(c.SubjectDN))
return false;
if (!MatchExtension(subjectKeyIdentifier, c, X509Extensions.SubjectKeyIdentifier))
return false;
if (subjectPublicKey != null && !subjectPublicKey.Equals(GetSubjectPublicKey(c)))
return false;
if (subjectPublicKeyAlgID != null
&& !subjectPublicKeyAlgID.Equals(GetSubjectPublicKey(c).AlgorithmID))
return false;
return true;
}
private bool[] CopyBoolArray(
bool[] b)
{
return b == null ? null : (bool[]) b.Clone();
}
private ISet CopySet(
ISet s)
{
return s == null ? null : new HashSet(s);
}
private SubjectPublicKeyInfo GetSubjectPublicKey(
X509Certificate c)
{
return SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(c.GetPublicKey());
}
private bool MatchExtension(
byte[] b,
X509Certificate c,
DerObjectIdentifier oid)
{
if (b == null)
return true;
Asn1OctetString extVal = c.GetExtensionValue(oid);
if (extVal == null)
return false;
return extVal != null && Arrays.AreEqual(b, extVal.GetEncoded());
}
}
}

View File

@@ -0,0 +1,49 @@
using System;
using System.Collections;
namespace Org.BouncyCastle.X509.Store
{
/**
* A simple collection backed store.
*/
internal class X509CollectionStore
: IX509Store
{
private ICollection _local;
/**
* Basic constructor.
*
* @param collection - initial contents for the store, this is copied.
*/
internal X509CollectionStore(
ICollection collection)
{
_local = new ArrayList(collection);
}
/**
* Return the matches in the collection for the passed in selector.
*
* @param selector the selector to match against.
* @return a possibly empty collection of matching objects.
*/
public ICollection GetMatches(
IX509Selector selector)
{
if (selector == null)
{
return new ArrayList(_local);
}
IList result = new ArrayList();
foreach (object obj in _local)
{
if (selector.Match(obj))
result.Add(obj);
}
return result;
}
}
}

View File

@@ -0,0 +1,58 @@
using System;
using System.Collections;
using System.Text;
namespace Org.BouncyCastle.X509.Store
{
/// <remarks>This class contains a collection for collection based <code>X509Store</code>s.</remarks>
public class X509CollectionStoreParameters
: IX509StoreParameters
{
private readonly ArrayList collection;
/// <summary>
/// Constructor.
/// <p>
/// The collection is copied.
/// </p>
/// </summary>
/// <param name="collection">The collection containing X.509 object types.</param>
/// <exception cref="ArgumentNullException">If collection is null.</exception>
public X509CollectionStoreParameters(
ICollection collection)
{
if (collection == null)
throw new ArgumentNullException("collection");
this.collection = new ArrayList(collection);
}
// TODO Do we need to be able to Clone() these, and should it really be shallow?
// /**
// * Returns a shallow clone. The returned contents are not copied, so adding
// * or removing objects will effect this.
// *
// * @return a shallow clone.
// */
// public object Clone()
// {
// return new X509CollectionStoreParameters(collection);
// }
/// <summary>Returns a copy of the <code>ICollection</code>.</summary>
public ICollection GetCollection()
{
return new ArrayList(collection);
}
/// <summary>Returns a formatted string describing the parameters.</summary>
public override string ToString()
{
StringBuilder sb = new StringBuilder();
sb.Append("X509CollectionStoreParameters: [\n");
sb.Append(" collection: " + collection + "\n");
sb.Append("]");
return sb.ToString();
}
}
}

View File

@@ -0,0 +1,283 @@
using System;
using System.Collections;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.Date;
using Org.BouncyCastle.X509;
using Org.BouncyCastle.X509.Extension;
namespace Org.BouncyCastle.X509.Store
{
public class X509CrlStoreSelector
: IX509Selector
{
// TODO Missing criteria?
private X509Certificate certificateChecking;
private DateTimeObject dateAndTime;
private ICollection issuers;
private BigInteger maxCrlNumber;
private BigInteger minCrlNumber;
private IX509AttributeCertificate attrCertChecking;
private bool completeCrlEnabled;
private bool deltaCrlIndicatorEnabled;
private byte[] issuingDistributionPoint;
private bool issuingDistributionPointEnabled;
private BigInteger maxBaseCrlNumber;
public X509CrlStoreSelector()
{
}
public X509CrlStoreSelector(
X509CrlStoreSelector o)
{
this.certificateChecking = o.CertificateChecking;
this.dateAndTime = o.DateAndTime;
this.issuers = o.Issuers;
this.maxCrlNumber = o.MaxCrlNumber;
this.minCrlNumber = o.MinCrlNumber;
this.deltaCrlIndicatorEnabled = o.DeltaCrlIndicatorEnabled;
this.completeCrlEnabled = o.CompleteCrlEnabled;
this.maxBaseCrlNumber = o.MaxBaseCrlNumber;
this.attrCertChecking = o.AttrCertChecking;
this.issuingDistributionPointEnabled = o.IssuingDistributionPointEnabled;
this.issuingDistributionPoint = o.IssuingDistributionPoint;
}
public virtual object Clone()
{
return new X509CrlStoreSelector(this);
}
public X509Certificate CertificateChecking
{
get { return certificateChecking; }
set { certificateChecking = value; }
}
public DateTimeObject DateAndTime
{
get { return dateAndTime; }
set { dateAndTime = value; }
}
/// <summary>
/// An <code>ICollection</code> of <code>X509Name</code> objects
/// </summary>
public ICollection Issuers
{
get { return new ArrayList(issuers); }
set { issuers = new ArrayList(value); }
}
public BigInteger MaxCrlNumber
{
get { return maxCrlNumber; }
set { maxCrlNumber = value; }
}
public BigInteger MinCrlNumber
{
get { return minCrlNumber; }
set { minCrlNumber = value; }
}
/**
* The attribute certificate being checked. This is not a criterion.
* Rather, it is optional information that may help a {@link X509Store} find
* CRLs that would be relevant when checking revocation for the specified
* attribute certificate. If <code>null</code> is specified, then no such
* optional information is provided.
*
* @param attrCert the <code>IX509AttributeCertificate</code> being checked (or
* <code>null</code>)
* @see #getAttrCertificateChecking()
*/
public IX509AttributeCertificate AttrCertChecking
{
get { return attrCertChecking; }
set { this.attrCertChecking = value; }
}
/**
* If <code>true</code> only complete CRLs are returned. Defaults to
* <code>false</code>.
*
* @return <code>true</code> if only complete CRLs are returned.
*/
public bool CompleteCrlEnabled
{
get { return completeCrlEnabled; }
set { this.completeCrlEnabled = value; }
}
/**
* Returns if this selector must match CRLs with the delta CRL indicator
* extension set. Defaults to <code>false</code>.
*
* @return Returns <code>true</code> if only CRLs with the delta CRL
* indicator extension are selected.
*/
public bool DeltaCrlIndicatorEnabled
{
get { return deltaCrlIndicatorEnabled; }
set { this.deltaCrlIndicatorEnabled = value; }
}
/**
* The issuing distribution point.
* <p>
* The issuing distribution point extension is a CRL extension which
* identifies the scope and the distribution point of a CRL. The scope
* contains among others information about revocation reasons contained in
* the CRL. Delta CRLs and complete CRLs must have matching issuing
* distribution points.</p>
* <p>
* The byte array is cloned to protect against subsequent modifications.</p>
* <p>
* You must also enable or disable this criteria with
* {@link #setIssuingDistributionPointEnabled(bool)}.</p>
*
* @param issuingDistributionPoint The issuing distribution point to set.
* This is the DER encoded OCTET STRING extension value.
* @see #getIssuingDistributionPoint()
*/
public byte[] IssuingDistributionPoint
{
get { return Arrays.Clone(issuingDistributionPoint); }
set { this.issuingDistributionPoint = Arrays.Clone(value); }
}
/**
* Whether the issuing distribution point criteria should be applied.
* Defaults to <code>false</code>.
* <p>
* You may also set the issuing distribution point criteria if not a missing
* issuing distribution point should be assumed.</p>
*
* @return Returns if the issuing distribution point check is enabled.
*/
public bool IssuingDistributionPointEnabled
{
get { return issuingDistributionPointEnabled; }
set { this.issuingDistributionPointEnabled = value; }
}
/**
* The maximum base CRL number. Defaults to <code>null</code>.
*
* @return Returns the maximum base CRL number.
* @see #setMaxBaseCRLNumber(BigInteger)
*/
public BigInteger MaxBaseCrlNumber
{
get { return maxBaseCrlNumber; }
set { this.maxBaseCrlNumber = value; }
}
public virtual bool Match(
object obj)
{
X509Crl c = obj as X509Crl;
if (c == null)
return false;
if (dateAndTime != null)
{
DateTime dt = dateAndTime.Value;
DateTime tu = c.ThisUpdate;
DateTimeObject nu = c.NextUpdate;
if (dt.CompareTo(tu) < 0 || nu == null || dt.CompareTo(nu.Value) >= 0)
return false;
}
if (issuers != null)
{
X509Name i = c.IssuerDN;
bool found = false;
foreach (X509Name issuer in issuers)
{
if (issuer.Equivalent(i))
{
found = true;
break;
}
}
if (!found)
return false;
}
if (maxCrlNumber != null || minCrlNumber != null)
{
Asn1OctetString extVal = c.GetExtensionValue(X509Extensions.CrlNumber);
if (extVal == null)
return false;
BigInteger cn = CrlNumber.GetInstance(
X509ExtensionUtilities.FromExtensionValue(extVal)).PositiveValue;
if (maxCrlNumber != null && cn.CompareTo(maxCrlNumber) > 0)
return false;
if (minCrlNumber != null && cn.CompareTo(minCrlNumber) < 0)
return false;
}
DerInteger dci = null;
try
{
Asn1OctetString bytes = c.GetExtensionValue(X509Extensions.DeltaCrlIndicator);
if (bytes != null)
{
dci = DerInteger.GetInstance(X509ExtensionUtilities.FromExtensionValue(bytes));
}
}
catch (Exception)
{
return false;
}
if (dci == null)
{
if (DeltaCrlIndicatorEnabled)
return false;
}
else
{
if (CompleteCrlEnabled)
return false;
if (maxBaseCrlNumber != null && dci.PositiveValue.CompareTo(maxBaseCrlNumber) > 0)
return false;
}
if (issuingDistributionPointEnabled)
{
Asn1OctetString idp = c.GetExtensionValue(X509Extensions.IssuingDistributionPoint);
if (issuingDistributionPoint == null)
{
if (idp != null)
return false;
}
else
{
if (!Arrays.AreEqual(idp.GetOctets(), issuingDistributionPoint))
return false;
}
}
return true;
}
}
}

View File

@@ -0,0 +1,25 @@
using System;
namespace Org.BouncyCastle.X509.Store
{
public class X509StoreException
: Exception
{
public X509StoreException()
{
}
public X509StoreException(
string message)
: base(message)
{
}
public X509StoreException(
string message,
Exception e)
: base(message, e)
{
}
}
}

View File

@@ -0,0 +1,44 @@
using System;
using System.Globalization;
namespace Org.BouncyCastle.X509.Store
{
public sealed class X509StoreFactory
{
private X509StoreFactory()
{
}
public static IX509Store Create(
string type,
IX509StoreParameters parameters)
{
if (type == null)
throw new ArgumentNullException("type");
string[] parts = type.ToUpper(CultureInfo.InvariantCulture).Split('/');
if (parts.Length < 2)
throw new ArgumentException("type");
switch (parts[0])
{
case "ATTRIBUTECERTIFICATE":
case "CERTIFICATE":
case "CERTIFICATEPAIR":
case "CRL":
{
if (parts[1] == "COLLECTION")
{
X509CollectionStoreParameters p = (X509CollectionStoreParameters) parameters;
return new X509CollectionStore(p.GetCollection());
}
break;
}
}
throw new NoSuchStoreException("X.509 store type '" + type + "' not available.");
}
}
}