You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
714 lines
25 KiB
714 lines
25 KiB
8 months ago
|
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||
|
#pragma warning disable
|
||
|
using System;
|
||
|
using System.Collections;
|
||
|
using System.IO;
|
||
|
using System.Text;
|
||
|
|
||
|
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1;
|
||
|
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Misc;
|
||
|
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Utilities;
|
||
|
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.X509;
|
||
|
using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto;
|
||
|
using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Operators;
|
||
|
using BestHTTP.SecureProtocol.Org.BouncyCastle.Math;
|
||
|
using BestHTTP.SecureProtocol.Org.BouncyCastle.Security;
|
||
|
using BestHTTP.SecureProtocol.Org.BouncyCastle.Security.Certificates;
|
||
|
using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
|
||
|
using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Encoders;
|
||
|
using BestHTTP.SecureProtocol.Org.BouncyCastle.X509.Extension;
|
||
|
|
||
|
namespace BestHTTP.SecureProtocol.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 class CachedEncoding
|
||
|
{
|
||
|
private readonly byte[] encoding;
|
||
|
private readonly CertificateEncodingException exception;
|
||
|
|
||
|
internal CachedEncoding(byte[] encoding, CertificateEncodingException exception)
|
||
|
{
|
||
|
this.encoding = encoding;
|
||
|
this.exception = exception;
|
||
|
}
|
||
|
|
||
|
internal byte[] Encoding
|
||
|
{
|
||
|
get { return encoding; }
|
||
|
}
|
||
|
|
||
|
internal byte[] GetEncoded()
|
||
|
{
|
||
|
if (null != exception)
|
||
|
throw exception;
|
||
|
|
||
|
if (null == encoding)
|
||
|
throw new CertificateEncodingException();
|
||
|
|
||
|
return encoding;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private readonly X509CertificateStructure c;
|
||
|
//private Hashtable pkcs12Attributes = BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.CreateHashtable();
|
||
|
//private ArrayList pkcs12Ordering = BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.CreateArrayList();
|
||
|
private readonly string sigAlgName;
|
||
|
private readonly byte[] sigAlgParams;
|
||
|
private readonly BasicConstraints basicConstraints;
|
||
|
private readonly bool[] keyUsage;
|
||
|
|
||
|
private readonly object cacheLock = new object();
|
||
|
private AsymmetricKeyParameter publicKeyValue;
|
||
|
private CachedEncoding cachedEncoding;
|
||
|
|
||
|
private volatile bool hashValueSet;
|
||
|
private volatile int hashValue;
|
||
|
|
||
|
protected X509Certificate()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
public X509Certificate(byte[] certData)
|
||
|
: this(X509CertificateStructure.GetInstance(certData))
|
||
|
{
|
||
|
}
|
||
|
|
||
|
public X509Certificate(X509CertificateStructure c)
|
||
|
{
|
||
|
this.c = c;
|
||
|
|
||
|
try
|
||
|
{
|
||
|
this.sigAlgName = X509SignatureUtilities.GetSignatureName(c.SignatureAlgorithm);
|
||
|
|
||
|
Asn1Encodable parameters = c.SignatureAlgorithm.Parameters;
|
||
|
this.sigAlgParams = (null == parameters) ? null : parameters.GetEncoded(Asn1Encodable.Der);
|
||
|
}
|
||
|
catch (Exception e)
|
||
|
{
|
||
|
throw new CertificateParsingException("Certificate contents invalid: " + e);
|
||
|
}
|
||
|
|
||
|
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;
|
||
|
}
|
||
|
}
|
||
|
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())
|
||
|
// {
|
||
|
// }
|
||
|
|
||
|
public virtual X509CertificateStructure CertificateStructure
|
||
|
{
|
||
|
get { return c; }
|
||
|
}
|
||
|
|
||
|
/// <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="BestHTTP.SecureProtocol.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.GetSignatureOctets();
|
||
|
}
|
||
|
|
||
|
/// <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 sigAlgName; }
|
||
|
}
|
||
|
|
||
|
/// <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.Algorithm.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()
|
||
|
{
|
||
|
return Arrays.Clone(sigAlgParams);
|
||
|
}
|
||
|
|
||
|
/// <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 Arrays.Clone(keyUsage);
|
||
|
}
|
||
|
|
||
|
// 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));
|
||
|
|
||
|
IList list = BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.CreateArrayList();
|
||
|
|
||
|
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);
|
||
|
|
||
|
IList result = BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.CreateArrayList();
|
||
|
foreach (GeneralName gn in gns.GetNames())
|
||
|
{
|
||
|
IList entry = BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.CreateArrayList();
|
||
|
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()
|
||
|
{
|
||
|
// Cache the public key to support repeated-use optimizations
|
||
|
lock (cacheLock)
|
||
|
{
|
||
|
if (null != publicKeyValue)
|
||
|
return publicKeyValue;
|
||
|
}
|
||
|
|
||
|
AsymmetricKeyParameter temp = PublicKeyFactory.CreateKey(c.SubjectPublicKeyInfo);
|
||
|
|
||
|
lock (cacheLock)
|
||
|
{
|
||
|
if (null == publicKeyValue)
|
||
|
{
|
||
|
publicKeyValue = temp;
|
||
|
}
|
||
|
|
||
|
return publicKeyValue;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Return the DER encoding of this certificate.
|
||
|
/// </summary>
|
||
|
/// <returns>A byte array containing the DER encoding of this certificate.</returns>
|
||
|
/// <exception cref="CertificateEncodingException">If there is an error encoding the certificate.</exception>
|
||
|
public virtual byte[] GetEncoded()
|
||
|
{
|
||
|
return Arrays.Clone(GetCachedEncoding().GetEncoded());
|
||
|
}
|
||
|
|
||
|
public override bool Equals(object other)
|
||
|
{
|
||
|
if (this == other)
|
||
|
return true;
|
||
|
|
||
|
X509Certificate that = other as X509Certificate;
|
||
|
if (null == that)
|
||
|
return false;
|
||
|
|
||
|
if (this.hashValueSet && that.hashValueSet)
|
||
|
{
|
||
|
if (this.hashValue != that.hashValue)
|
||
|
return false;
|
||
|
}
|
||
|
else if (null == this.cachedEncoding || null == that.cachedEncoding)
|
||
|
{
|
||
|
DerBitString signature = c.Signature;
|
||
|
if (null != signature && !signature.Equals(that.c.Signature))
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
byte[] thisEncoding = this.GetCachedEncoding().Encoding;
|
||
|
byte[] thatEncoding = that.GetCachedEncoding().Encoding;
|
||
|
|
||
|
return null != thisEncoding
|
||
|
&& null != thatEncoding
|
||
|
&& Arrays.AreEqual(thisEncoding, thatEncoding);
|
||
|
}
|
||
|
|
||
|
public override int GetHashCode()
|
||
|
{
|
||
|
if (!hashValueSet)
|
||
|
{
|
||
|
byte[] thisEncoding = this.GetCachedEncoding().Encoding;
|
||
|
|
||
|
hashValue = Arrays.GetHashCode(thisEncoding);
|
||
|
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 = BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.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();
|
||
|
buf.Append(" Signature: ").Append(Hex.ToHexString(sig, 0, 20)).Append(nl);
|
||
|
|
||
|
for (int i = 20; i < sig.Length; i += 20)
|
||
|
{
|
||
|
int len = System.Math.Min(20, sig.Length - i);
|
||
|
buf.Append(" ").Append(Hex.ToHexString(sig, i, len)).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)
|
||
|
{
|
||
|
Asn1Object obj = X509ExtensionUtilities.FromExtensionValue(ext.Value);
|
||
|
|
||
|
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)
|
||
|
{
|
||
|
CheckSignature(new Asn1VerifierFactory(c.SignatureAlgorithm, key));
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Verify the certificate's signature using a verifier created using the passed in verifier provider.
|
||
|
/// </summary>
|
||
|
/// <param name="verifierProvider">An appropriate provider for verifying the certificate's signature.</param>
|
||
|
/// <returns>True if the signature is valid.</returns>
|
||
|
/// <exception cref="Exception">If verifier provider is not appropriate or the certificate algorithm is invalid.</exception>
|
||
|
public virtual void Verify(
|
||
|
IVerifierFactoryProvider verifierProvider)
|
||
|
{
|
||
|
CheckSignature(verifierProvider.CreateVerifierFactory(c.SignatureAlgorithm));
|
||
|
}
|
||
|
|
||
|
protected virtual void CheckSignature(
|
||
|
IVerifierFactory verifier)
|
||
|
{
|
||
|
if (!IsAlgIDEqual(c.SignatureAlgorithm, c.TbsCertificate.Signature))
|
||
|
throw new CertificateException("signature algorithm in TBS cert not same as outer cert");
|
||
|
|
||
|
Asn1Encodable parameters = c.SignatureAlgorithm.Parameters;
|
||
|
|
||
|
IStreamCalculator streamCalculator = verifier.CreateCalculator();
|
||
|
|
||
|
byte[] b = this.GetTbsCertificate();
|
||
|
|
||
|
streamCalculator.Stream.Write(b, 0, b.Length);
|
||
|
|
||
|
BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.Dispose(streamCalculator.Stream);
|
||
|
|
||
|
if (!((IVerifier)streamCalculator.GetResult()).IsVerified(this.GetSignature()))
|
||
|
{
|
||
|
throw new InvalidKeyException("Public key presented not for certificate signature");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private CachedEncoding GetCachedEncoding()
|
||
|
{
|
||
|
lock (cacheLock)
|
||
|
{
|
||
|
if (null != cachedEncoding)
|
||
|
return cachedEncoding;
|
||
|
}
|
||
|
|
||
|
byte[] encoding = null;
|
||
|
CertificateEncodingException exception = null;
|
||
|
try
|
||
|
{
|
||
|
encoding = c.GetEncoded(Asn1Encodable.Der);
|
||
|
}
|
||
|
catch (IOException e)
|
||
|
{
|
||
|
exception = new CertificateEncodingException("Failed to DER-encode certificate", e);
|
||
|
}
|
||
|
|
||
|
CachedEncoding temp = new CachedEncoding(encoding, exception);
|
||
|
|
||
|
lock (cacheLock)
|
||
|
{
|
||
|
if (null == cachedEncoding)
|
||
|
{
|
||
|
cachedEncoding = temp;
|
||
|
}
|
||
|
|
||
|
return cachedEncoding;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private static bool IsAlgIDEqual(AlgorithmIdentifier id1, AlgorithmIdentifier id2)
|
||
|
{
|
||
|
if (!id1.Algorithm.Equals(id2.Algorithm))
|
||
|
return false;
|
||
|
|
||
|
Asn1Encodable p1 = id1.Parameters;
|
||
|
Asn1Encodable p2 = id2.Parameters;
|
||
|
|
||
|
if ((p1 == null) == (p2 == null))
|
||
|
return BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.Equals(p1, p2);
|
||
|
|
||
|
// Exactly one of p1, p2 is null at this point
|
||
|
return p1 == null
|
||
|
? p2.ToAsn1Object() is Asn1Null
|
||
|
: p1.ToAsn1Object() is Asn1Null;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
#pragma warning restore
|
||
|
#endif
|