Initial Commit
This commit is contained in:
420
iTechSharp/srcbc/x509/AttributeCertificateHolder.cs
Normal file
420
iTechSharp/srcbc/x509/AttributeCertificateHolder.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
177
iTechSharp/srcbc/x509/AttributeCertificateIssuer.cs
Normal file
177
iTechSharp/srcbc/x509/AttributeCertificateIssuer.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
57
iTechSharp/srcbc/x509/IX509AttributeCertificate.cs
Normal file
57
iTechSharp/srcbc/x509/IX509AttributeCertificate.cs
Normal 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();
|
||||
}
|
||||
}
|
27
iTechSharp/srcbc/x509/IX509Extension.cs
Normal file
27
iTechSharp/srcbc/x509/IX509Extension.cs
Normal 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);
|
||||
}
|
||||
}
|
94
iTechSharp/srcbc/x509/PEMParser.cs
Normal file
94
iTechSharp/srcbc/x509/PEMParser.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
70
iTechSharp/srcbc/x509/PrincipalUtil.cs
Normal file
70
iTechSharp/srcbc/x509/PrincipalUtil.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
178
iTechSharp/srcbc/x509/SubjectPublicKeyInfoFactory.cs
Normal file
178
iTechSharp/srcbc/x509/SubjectPublicKeyInfoFactory.cs
Normal 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];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
172
iTechSharp/srcbc/x509/X509AttrCertParser.cs
Normal file
172
iTechSharp/srcbc/x509/X509AttrCertParser.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
76
iTechSharp/srcbc/x509/X509Attribute.cs
Normal file
76
iTechSharp/srcbc/x509/X509Attribute.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
94
iTechSharp/srcbc/x509/X509CertPairParser.cs
Normal file
94
iTechSharp/srcbc/x509/X509CertPairParser.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
579
iTechSharp/srcbc/x509/X509Certificate.cs
Normal file
579
iTechSharp/srcbc/x509/X509Certificate.cs
Normal 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");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
117
iTechSharp/srcbc/x509/X509CertificatePair.cs
Normal file
117
iTechSharp/srcbc/x509/X509CertificatePair.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
182
iTechSharp/srcbc/x509/X509CertificateParser.cs
Normal file
182
iTechSharp/srcbc/x509/X509CertificateParser.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
409
iTechSharp/srcbc/x509/X509Crl.cs
Normal file
409
iTechSharp/srcbc/x509/X509Crl.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
201
iTechSharp/srcbc/x509/X509CrlEntry.cs
Normal file
201
iTechSharp/srcbc/x509/X509CrlEntry.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
194
iTechSharp/srcbc/x509/X509CrlParser.cs
Normal file
194
iTechSharp/srcbc/x509/X509CrlParser.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
82
iTechSharp/srcbc/x509/X509ExtensionBase.cs
Normal file
82
iTechSharp/srcbc/x509/X509ExtensionBase.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
59
iTechSharp/srcbc/x509/X509KeyUsage.cs
Normal file
59
iTechSharp/srcbc/x509/X509KeyUsage.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
128
iTechSharp/srcbc/x509/X509SignatureUtil.cs
Normal file
128
iTechSharp/srcbc/x509/X509SignatureUtil.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
183
iTechSharp/srcbc/x509/X509Utilities.cs
Normal file
183
iTechSharp/srcbc/x509/X509Utilities.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
205
iTechSharp/srcbc/x509/X509V1CertificateGenerator.cs
Normal file
205
iTechSharp/srcbc/x509/X509V1CertificateGenerator.cs
Normal 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(); }
|
||||
}
|
||||
}
|
||||
}
|
239
iTechSharp/srcbc/x509/X509V2AttributeCertificate.cs
Normal file
239
iTechSharp/srcbc/x509/X509V2AttributeCertificate.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
180
iTechSharp/srcbc/x509/X509V2AttributeCertificateGenerator.cs
Normal file
180
iTechSharp/srcbc/x509/X509V2AttributeCertificateGenerator.cs
Normal 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(); }
|
||||
}
|
||||
}
|
||||
}
|
261
iTechSharp/srcbc/x509/X509V2CRLGenerator.cs
Normal file
261
iTechSharp/srcbc/x509/X509V2CRLGenerator.cs
Normal 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(); }
|
||||
}
|
||||
}
|
||||
}
|
303
iTechSharp/srcbc/x509/X509V3CertificateGenerator.cs
Normal file
303
iTechSharp/srcbc/x509/X509V3CertificateGenerator.cs
Normal 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(); }
|
||||
}
|
||||
}
|
||||
}
|
@@ -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))
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@@ -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))
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
88
iTechSharp/srcbc/x509/extension/X509ExtensionUtil.cs
Normal file
88
iTechSharp/srcbc/x509/extension/X509ExtensionUtil.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
10
iTechSharp/srcbc/x509/store/IX509Selector.cs
Normal file
10
iTechSharp/srcbc/x509/store/IX509Selector.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
using System;
|
||||
|
||||
namespace Org.BouncyCastle.X509.Store
|
||||
{
|
||||
public interface IX509Selector
|
||||
: ICloneable
|
||||
{
|
||||
bool Match(object obj);
|
||||
}
|
||||
}
|
11
iTechSharp/srcbc/x509/store/IX509Store.cs
Normal file
11
iTechSharp/srcbc/x509/store/IX509Store.cs
Normal 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);
|
||||
}
|
||||
}
|
8
iTechSharp/srcbc/x509/store/IX509StoreParameters.cs
Normal file
8
iTechSharp/srcbc/x509/store/IX509StoreParameters.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
using System;
|
||||
|
||||
namespace Org.BouncyCastle.X509.Store
|
||||
{
|
||||
public interface IX509StoreParameters
|
||||
{
|
||||
}
|
||||
}
|
25
iTechSharp/srcbc/x509/store/NoSuchStoreException.cs
Normal file
25
iTechSharp/srcbc/x509/store/NoSuchStoreException.cs
Normal 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)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
376
iTechSharp/srcbc/x509/store/X509AttrCertStoreSelector.cs
Normal file
376
iTechSharp/srcbc/x509/store/X509AttrCertStoreSelector.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
92
iTechSharp/srcbc/x509/store/X509CertPairStoreSelector.cs
Normal file
92
iTechSharp/srcbc/x509/store/X509CertPairStoreSelector.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
329
iTechSharp/srcbc/x509/store/X509CertStoreSelector.cs
Normal file
329
iTechSharp/srcbc/x509/store/X509CertStoreSelector.cs
Normal 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());
|
||||
}
|
||||
}
|
||||
}
|
49
iTechSharp/srcbc/x509/store/X509CollectionStore.cs
Normal file
49
iTechSharp/srcbc/x509/store/X509CollectionStore.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
58
iTechSharp/srcbc/x509/store/X509CollectionStoreParameters.cs
Normal file
58
iTechSharp/srcbc/x509/store/X509CollectionStoreParameters.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
283
iTechSharp/srcbc/x509/store/X509CrlStoreSelector.cs
Normal file
283
iTechSharp/srcbc/x509/store/X509CrlStoreSelector.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
25
iTechSharp/srcbc/x509/store/X509StoreException.cs
Normal file
25
iTechSharp/srcbc/x509/store/X509StoreException.cs
Normal 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)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
44
iTechSharp/srcbc/x509/store/X509StoreFactory.cs
Normal file
44
iTechSharp/srcbc/x509/store/X509StoreFactory.cs
Normal 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.");
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user