mirror of
https://gitee.com/jisol/jisol-game/
synced 2025-11-11 16:48:30 +00:00
提交Unity 联机Pro
This commit is contained in:
@@ -0,0 +1,427 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.X509;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto;
|
||||
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.Collections;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.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
|
||||
: ISelector<X509Certificate>
|
||||
{
|
||||
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(new DerObjectIdentifier(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.IntValueExact;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.Algorithm.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)
|
||||
{
|
||||
int count = 0;
|
||||
for (int i = 0; i != names.Length; i++)
|
||||
{
|
||||
if (names[i].TagNo == GeneralName.DirectoryName)
|
||||
{
|
||||
++count;
|
||||
}
|
||||
}
|
||||
|
||||
object[] result = new object[count];
|
||||
|
||||
int pos = 0;
|
||||
for (int i = 0; i != names.Length; i++)
|
||||
{
|
||||
if (names[i].TagNo == GeneralName.DirectoryName)
|
||||
{
|
||||
result[pos++] = X509Name.GetInstance(names[i].Name);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private X509Name[] GetPrincipals(
|
||||
GeneralNames names)
|
||||
{
|
||||
object[] p = this.GetNames(names.GetNames());
|
||||
|
||||
int count = 0;
|
||||
|
||||
for (int i = 0; i != p.Length; i++)
|
||||
{
|
||||
if (p[i] is X509Name)
|
||||
{
|
||||
++count;
|
||||
}
|
||||
}
|
||||
|
||||
X509Name[] result = new X509Name[count];
|
||||
|
||||
int pos = 0;
|
||||
for (int i = 0; i != p.Length; i++)
|
||||
{
|
||||
if (p[i] is X509Name)
|
||||
{
|
||||
result[pos++] = (X509Name)p[i];
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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(X509Certificate x509Cert)
|
||||
{
|
||||
if (x509Cert == null)
|
||||
return false;
|
||||
|
||||
try
|
||||
{
|
||||
if (holder.BaseCertificateID != null)
|
||||
{
|
||||
return holder.BaseCertificateID.Serial.HasValue(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();
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 938387042cf639245ad61e6176058eca
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,182 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.X509;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Collections;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.X509
|
||||
{
|
||||
/**
|
||||
* Carrying class for an attribute certificate issuer.
|
||||
*/
|
||||
public class AttributeCertificateIssuer
|
||||
//: CertSelector, Selector
|
||||
: ISelector<X509Certificate>
|
||||
{
|
||||
internal readonly Asn1Encodable form;
|
||||
|
||||
/**
|
||||
* Set the issuer directly with the ASN.1 structure.
|
||||
*
|
||||
* @param issuer The issuer
|
||||
*/
|
||||
public 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();
|
||||
|
||||
int count = 0;
|
||||
for (int i = 0; i != names.Length; i++)
|
||||
{
|
||||
if (names[i].TagNo == GeneralName.DirectoryName)
|
||||
{
|
||||
++count;
|
||||
}
|
||||
}
|
||||
|
||||
object[] result = new object[count];
|
||||
|
||||
int pos = 0;
|
||||
for (int i = 0; i != names.Length; i++)
|
||||
{
|
||||
if (names[i].TagNo == GeneralName.DirectoryName)
|
||||
{
|
||||
result[pos++] = X509Name.GetInstance(names[i].Name);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <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();
|
||||
|
||||
int count = 0;
|
||||
for (int i = 0; i != p.Length; i++)
|
||||
{
|
||||
if (p[i] is X509Name)
|
||||
{
|
||||
++count;
|
||||
}
|
||||
}
|
||||
|
||||
X509Name[] result = new X509Name[count];
|
||||
|
||||
int pos = 0;
|
||||
for (int i = 0; i != p.Length; i++)
|
||||
{
|
||||
if (p[i] is X509Name)
|
||||
{
|
||||
result[pos++] = (X509Name)p[i];
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
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(X509Certificate x509Cert)
|
||||
{
|
||||
if (x509Cert == null)
|
||||
return false;
|
||||
|
||||
if (form is V2Form)
|
||||
{
|
||||
V2Form issuer = (V2Form) form;
|
||||
if (issuer.BaseCertificateID != null)
|
||||
{
|
||||
return issuer.BaseCertificateID.Serial.HasValue(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();
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: acf2171ca98d9a84b9b2f630c3ed992f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,28 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.X509
|
||||
{
|
||||
public interface IX509Extension
|
||||
{
|
||||
/// <summary>
|
||||
/// Get all critical extension values, by oid
|
||||
/// </summary>
|
||||
/// <returns>IDictionary with string (OID) keys and Asn1OctetString values</returns>
|
||||
ISet<string> GetCriticalExtensionOids();
|
||||
|
||||
/// <summary>
|
||||
/// Get all non-critical extension values, by oid
|
||||
/// </summary>
|
||||
/// <returns>IDictionary with string (OID) keys and Asn1OctetString values</returns>
|
||||
ISet<string> GetNonCriticalExtensionOids();
|
||||
|
||||
Asn1OctetString GetExtensionValue(DerObjectIdentifier oid);
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8a0d122875ecdab4796b2617ab2d97eb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,99 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Encoders;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.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 (Org.BouncyCastle.Utilities.Platform.StartsWith(line, _header1) || Org.BouncyCastle.Utilities.Platform.StartsWith(line, _header2))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
while ((line = ReadLine(inStream)) != null)
|
||||
{
|
||||
if (Org.BouncyCastle.Utilities.Platform.StartsWith(line, _footer1) || Org.BouncyCastle.Utilities.Platform.StartsWith(line, _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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6c0af44d6133b484fad764d838af9600
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,74 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.X509;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Security.Certificates;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: afc0a35c1a82d7047807b55049604a40
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,277 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.CryptoPro;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.EdEC;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Oiw;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Pkcs;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Rosstandart;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.X509;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.X9;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Math;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Math.EC;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.X509
|
||||
{
|
||||
/// <summary>
|
||||
/// A factory to produce Public Key Info Objects.
|
||||
/// </summary>
|
||||
public static class SubjectPublicKeyInfoFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// Create a Subject Public Key Info object for a given public key.
|
||||
/// </summary>
|
||||
/// <param name="publicKey">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 publicKey)
|
||||
{
|
||||
if (publicKey == null)
|
||||
throw new ArgumentNullException("publicKey");
|
||||
if (publicKey.IsPrivate)
|
||||
throw new ArgumentException("Private key passed - public key expected.", "publicKey");
|
||||
|
||||
if (publicKey is ElGamalPublicKeyParameters)
|
||||
{
|
||||
ElGamalPublicKeyParameters _key = (ElGamalPublicKeyParameters)publicKey;
|
||||
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 (publicKey is DsaPublicKeyParameters)
|
||||
{
|
||||
DsaPublicKeyParameters _key = (DsaPublicKeyParameters) publicKey;
|
||||
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 (publicKey is DHPublicKeyParameters)
|
||||
{
|
||||
DHPublicKeyParameters _key = (DHPublicKeyParameters) publicKey;
|
||||
DHParameters kp = _key.Parameters;
|
||||
|
||||
SubjectPublicKeyInfo info = new SubjectPublicKeyInfo(
|
||||
new AlgorithmIdentifier(
|
||||
_key.AlgorithmOid,
|
||||
new DHParameter(kp.P, kp.G, kp.L).ToAsn1Object()),
|
||||
new DerInteger(_key.Y));
|
||||
|
||||
return info;
|
||||
} // End of DH
|
||||
|
||||
if (publicKey is RsaKeyParameters)
|
||||
{
|
||||
RsaKeyParameters _key = (RsaKeyParameters) publicKey;
|
||||
|
||||
SubjectPublicKeyInfo info = new SubjectPublicKeyInfo(
|
||||
new AlgorithmIdentifier(PkcsObjectIdentifiers.RsaEncryption, DerNull.Instance),
|
||||
new RsaPublicKeyStructure(_key.Modulus, _key.Exponent).ToAsn1Object());
|
||||
|
||||
return info;
|
||||
} // End of RSA.
|
||||
|
||||
if (publicKey is ECPublicKeyParameters)
|
||||
{
|
||||
|
||||
ECPublicKeyParameters _key = (ECPublicKeyParameters) publicKey;
|
||||
|
||||
|
||||
if (_key.Parameters is ECGost3410Parameters)
|
||||
{
|
||||
ECGost3410Parameters gostParams = (ECGost3410Parameters)_key.Parameters;
|
||||
|
||||
BigInteger bX = _key.Q.AffineXCoord.ToBigInteger();
|
||||
BigInteger bY = _key.Q.AffineYCoord.ToBigInteger();
|
||||
bool is512 = (bX.BitLength > 256);
|
||||
|
||||
Gost3410PublicKeyAlgParameters parameters = new Gost3410PublicKeyAlgParameters(
|
||||
gostParams.PublicKeyParamSet,
|
||||
gostParams.DigestParamSet,
|
||||
gostParams.EncryptionParamSet);
|
||||
|
||||
int encKeySize;
|
||||
int offset;
|
||||
DerObjectIdentifier algIdentifier;
|
||||
if (is512)
|
||||
{
|
||||
encKeySize = 128;
|
||||
offset = 64;
|
||||
algIdentifier = RosstandartObjectIdentifiers.id_tc26_gost_3410_12_512;
|
||||
}
|
||||
else
|
||||
{
|
||||
encKeySize = 64;
|
||||
offset = 32;
|
||||
algIdentifier = RosstandartObjectIdentifiers.id_tc26_gost_3410_12_256;
|
||||
}
|
||||
|
||||
byte[] encKey = new byte[encKeySize];
|
||||
|
||||
ExtractBytes(encKey, encKeySize / 2, 0, bX);
|
||||
ExtractBytes(encKey, encKeySize / 2, offset, bY);
|
||||
|
||||
return new SubjectPublicKeyInfo(new AlgorithmIdentifier(algIdentifier, parameters), new DerOctetString(encKey));
|
||||
|
||||
|
||||
} // End of ECGOST3410_2012
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if (_key.AlgorithmName == "ECGOST3410")
|
||||
{
|
||||
if (_key.PublicKeyParamSet == null)
|
||||
throw new NotImplementedException("Not a CryptoPro parameter set");
|
||||
|
||||
ECPoint q = _key.Q.Normalize();
|
||||
BigInteger bX = q.AffineXCoord.ToBigInteger();
|
||||
BigInteger bY = q.AffineYCoord.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
|
||||
{
|
||||
X962Parameters x962;
|
||||
if (_key.PublicKeyParamSet == null)
|
||||
{
|
||||
ECDomainParameters kp = _key.Parameters;
|
||||
X9ECParameters ecP = new X9ECParameters(kp.Curve, new X9ECPoint(kp.G, false), kp.N, kp.H,
|
||||
kp.GetSeed());
|
||||
|
||||
x962 = new X962Parameters(ecP);
|
||||
}
|
||||
else
|
||||
{
|
||||
x962 = new X962Parameters(_key.PublicKeyParamSet);
|
||||
}
|
||||
|
||||
byte[] pubKey = _key.Q.GetEncoded(false);
|
||||
|
||||
AlgorithmIdentifier algID = new AlgorithmIdentifier(
|
||||
X9ObjectIdentifiers.IdECPublicKey, x962.ToAsn1Object());
|
||||
|
||||
return new SubjectPublicKeyInfo(algID, pubKey);
|
||||
}
|
||||
} // End of EC
|
||||
|
||||
if (publicKey is Gost3410PublicKeyParameters)
|
||||
{
|
||||
Gost3410PublicKeyParameters _key = (Gost3410PublicKeyParameters) publicKey;
|
||||
|
||||
if (_key.PublicKeyParamSet == null)
|
||||
throw new NotImplementedException("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));
|
||||
}
|
||||
|
||||
if (publicKey is X448PublicKeyParameters)
|
||||
{
|
||||
X448PublicKeyParameters key = (X448PublicKeyParameters)publicKey;
|
||||
|
||||
return new SubjectPublicKeyInfo(new AlgorithmIdentifier(EdECObjectIdentifiers.id_X448), key.GetEncoded());
|
||||
}
|
||||
|
||||
if (publicKey is X25519PublicKeyParameters)
|
||||
{
|
||||
X25519PublicKeyParameters key = (X25519PublicKeyParameters)publicKey;
|
||||
|
||||
return new SubjectPublicKeyInfo(new AlgorithmIdentifier(EdECObjectIdentifiers.id_X25519), key.GetEncoded());
|
||||
}
|
||||
|
||||
if (publicKey is Ed448PublicKeyParameters)
|
||||
{
|
||||
Ed448PublicKeyParameters key = (Ed448PublicKeyParameters)publicKey;
|
||||
|
||||
return new SubjectPublicKeyInfo(new AlgorithmIdentifier(EdECObjectIdentifiers.id_Ed448), key.GetEncoded());
|
||||
}
|
||||
|
||||
if (publicKey is Ed25519PublicKeyParameters)
|
||||
{
|
||||
Ed25519PublicKeyParameters key = (Ed25519PublicKeyParameters)publicKey;
|
||||
|
||||
return new SubjectPublicKeyInfo(new AlgorithmIdentifier(EdECObjectIdentifiers.id_Ed25519), key.GetEncoded());
|
||||
}
|
||||
|
||||
throw new ArgumentException("Class provided no convertible: " + Org.BouncyCastle.Utilities.Platform.GetTypeName(publicKey));
|
||||
}
|
||||
|
||||
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];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void ExtractBytes(byte[] encKey, int size, int offSet, BigInteger bI)
|
||||
{
|
||||
byte[] val = bI.ToByteArray();
|
||||
if (val.Length < size)
|
||||
{
|
||||
byte[] tmp = new byte[size];
|
||||
Array.Copy(val, 0, tmp, tmp.Length - val.Length, val.Length);
|
||||
val = tmp;
|
||||
}
|
||||
|
||||
for (int i = 0; i != size; i++)
|
||||
{
|
||||
encKey[offSet + i] = val[val.Length - 1 - i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cd36b9e69934c4e4a841a43e6b65c904
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,175 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Pkcs;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.X509;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Security.Certificates;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.IO;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.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 X509V2AttributeCertificate 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(AttributeCertificate.GetInstance(seq));
|
||||
}
|
||||
|
||||
private X509V2AttributeCertificate GetCertificate()
|
||||
{
|
||||
if (sData != null)
|
||||
{
|
||||
while (sDataObjectCount < sData.Count)
|
||||
{
|
||||
Asn1Encodable ae = sData[sDataObjectCount++];
|
||||
|
||||
if (ae.ToAsn1Object() is Asn1TaggedObject t && t.TagNo == 2)
|
||||
{
|
||||
return new X509V2AttributeCertificate(
|
||||
AttributeCertificate.GetInstance(Asn1Sequence.GetInstance(t, false)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private X509V2AttributeCertificate ReadPemCertificate(
|
||||
Stream inStream)
|
||||
{
|
||||
Asn1Sequence seq = PemAttrCertParser.ReadPemObject(inStream);
|
||||
|
||||
return seq == null
|
||||
? null
|
||||
: new X509V2AttributeCertificate(AttributeCertificate.GetInstance(seq));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create loading data from byte array.
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
public X509V2AttributeCertificate ReadAttrCert(byte[] input)
|
||||
{
|
||||
return ReadAttrCert(new MemoryStream(input, false));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create loading data from byte array.
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
public IList<X509V2AttributeCertificate> 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 X509V2AttributeCertificate 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;
|
||||
}
|
||||
|
||||
int tag = inStream.ReadByte();
|
||||
if (tag < 0)
|
||||
return null;
|
||||
|
||||
if (inStream.CanSeek)
|
||||
{
|
||||
inStream.Seek(-1L, SeekOrigin.Current);
|
||||
}
|
||||
else
|
||||
{
|
||||
PushbackStream pis = new PushbackStream(inStream);
|
||||
pis.Unread(tag);
|
||||
inStream = pis;
|
||||
}
|
||||
|
||||
if (tag != 0x30) // assume ascii PEM encoded.
|
||||
{
|
||||
return ReadPemCertificate(inStream);
|
||||
}
|
||||
|
||||
return ReadDerCertificate(new Asn1InputStream(inStream));
|
||||
}
|
||||
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 IList<X509V2AttributeCertificate> ReadAttrCerts(Stream inStream)
|
||||
{
|
||||
var attrCerts = new List<X509V2AttributeCertificate>();
|
||||
|
||||
X509V2AttributeCertificate attrCert;
|
||||
while ((attrCert = ReadAttrCert(inStream)) != null)
|
||||
{
|
||||
attrCerts.Add(attrCert);
|
||||
}
|
||||
|
||||
return attrCerts;
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fb17e3130c56fdb44a2169c7946d70f2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,80 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.X509;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.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();
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8689ae3e6241dab498e32e4185da76fc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,101 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.X509;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Security.Certificates;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.IO;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.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 IList<X509CertificatePair> 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
|
||||
{
|
||||
int tag = inStream.ReadByte();
|
||||
if (tag < 0)
|
||||
return null;
|
||||
|
||||
if (inStream.CanSeek)
|
||||
{
|
||||
inStream.Seek(-1L, SeekOrigin.Current);
|
||||
}
|
||||
else
|
||||
{
|
||||
PushbackStream pis = new PushbackStream(inStream);
|
||||
pis.Unread(tag);
|
||||
inStream = pis;
|
||||
}
|
||||
|
||||
return ReadDerCrossCertificatePair(inStream);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new CertificateException(e.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
public IList<X509CertificatePair> ReadCertPairs(Stream inStream)
|
||||
{
|
||||
var certPairs = new List<X509CertificatePair>();
|
||||
|
||||
X509CertificatePair certPair;
|
||||
while ((certPair = ReadCertPair(inStream)) != null)
|
||||
{
|
||||
certPairs.Add(certPair);
|
||||
}
|
||||
|
||||
return certPairs;
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8127558424a84ff4b96f41dbcb52b8f7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,748 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
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 Dictionary<> pkcs12Attributes = new Dictionary<>();
|
||||
//private List<> pkcs12Ordering = new List<>();
|
||||
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 = GetExtensionValue(X509Extensions.BasicConstraints);
|
||||
if (str != null)
|
||||
{
|
||||
basicConstraints = BasicConstraints.GetInstance(X509ExtensionUtilities.FromExtensionValue(str));
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new CertificateParsingException("cannot construct BasicConstraints: " + e);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Asn1OctetString str = GetExtensionValue(X509Extensions.KeyUsage);
|
||||
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);
|
||||
if (time.CompareTo(NotBefore) < 0)
|
||||
throw new CertificateNotYetValidException("certificate not valid until " + c.StartDate);
|
||||
}
|
||||
|
||||
/// <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<DerObjectIdentifier> GetExtendedKeyUsage()
|
||||
{
|
||||
Asn1OctetString str = GetExtensionValue(X509Extensions.ExtendedKeyUsage);
|
||||
|
||||
if (str == null)
|
||||
return null;
|
||||
|
||||
try
|
||||
{
|
||||
Asn1Sequence seq = Asn1Sequence.GetInstance(X509ExtensionUtilities.FromExtensionValue(str));
|
||||
|
||||
var result = new List<DerObjectIdentifier>();
|
||||
foreach (DerObjectIdentifier oid in seq)
|
||||
{
|
||||
result.Add(oid);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
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 GeneralNames GetIssuerAlternativeNameExtension()
|
||||
{
|
||||
return GetAlternativeNameExtension(X509Extensions.IssuerAlternativeName);
|
||||
}
|
||||
|
||||
public virtual GeneralNames GetSubjectAlternativeNameExtension()
|
||||
{
|
||||
return GetAlternativeNameExtension(X509Extensions.SubjectAlternativeName);
|
||||
}
|
||||
|
||||
public virtual IList<IList<object>> GetIssuerAlternativeNames()
|
||||
{
|
||||
return GetAlternativeNames(X509Extensions.IssuerAlternativeName);
|
||||
}
|
||||
|
||||
public virtual IList<IList<object>> GetSubjectAlternativeNames()
|
||||
{
|
||||
return GetAlternativeNames(X509Extensions.SubjectAlternativeName);
|
||||
}
|
||||
|
||||
protected virtual GeneralNames GetAlternativeNameExtension(DerObjectIdentifier oid)
|
||||
{
|
||||
Asn1OctetString altNames = GetExtensionValue(oid);
|
||||
if (altNames == null)
|
||||
return null;
|
||||
|
||||
Asn1Object asn1Object = X509ExtensionUtilities.FromExtensionValue(altNames);
|
||||
|
||||
return GeneralNames.GetInstance(asn1Object);
|
||||
}
|
||||
|
||||
protected virtual IList<IList<object>> GetAlternativeNames(DerObjectIdentifier oid)
|
||||
{
|
||||
var generalNames = GetAlternativeNameExtension(oid);
|
||||
if (generalNames == null)
|
||||
return null;
|
||||
|
||||
var gns = generalNames.GetNames();
|
||||
|
||||
var result = new List<IList<object>>(gns.Length);
|
||||
foreach (GeneralName gn in gns)
|
||||
{
|
||||
var entry = new List<object>(2);
|
||||
entry.Add(gn.TagNo);
|
||||
|
||||
switch (gn.TagNo)
|
||||
{
|
||||
case GeneralName.EdiPartyName:
|
||||
case GeneralName.X400Address:
|
||||
case GeneralName.OtherName:
|
||||
entry.Add(gn.GetEncoded());
|
||||
break;
|
||||
case GeneralName.DirectoryName:
|
||||
// TODO Styles
|
||||
//entry.Add(X509Name.GetInstance(Rfc4519Style.Instance, gn.Name).ToString());
|
||||
entry.Add(X509Name.GetInstance(gn.Name).ToString());
|
||||
break;
|
||||
case GeneralName.DnsName:
|
||||
case GeneralName.Rfc822Name:
|
||||
case GeneralName.UniformResourceIdentifier:
|
||||
entry.Add(((IAsn1String)gn.Name).GetString());
|
||||
break;
|
||||
case GeneralName.RegisteredID:
|
||||
entry.Add(DerObjectIdentifier.GetInstance(gn.Name).Id);
|
||||
break;
|
||||
case GeneralName.IPAddress:
|
||||
byte[] addrBytes = Asn1OctetString.GetInstance(gn.Name).GetOctets();
|
||||
IPAddress ipAddress = new IPAddress(addrBytes);
|
||||
entry.Add(ipAddress.ToString());
|
||||
break;
|
||||
default:
|
||||
throw new IOException("Bad tag number: " + gn.TagNo);
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
buf.Append(" [0] Version: ").Append(this.Version).AppendLine();
|
||||
buf.Append(" SerialNumber: ").Append(this.SerialNumber).AppendLine();
|
||||
buf.Append(" IssuerDN: ").Append(this.IssuerDN).AppendLine();
|
||||
buf.Append(" Start Date: ").Append(this.NotBefore).AppendLine();
|
||||
buf.Append(" Final Date: ").Append(this.NotAfter).AppendLine();
|
||||
buf.Append(" SubjectDN: ").Append(this.SubjectDN).AppendLine();
|
||||
buf.Append(" Public Key: ").Append(this.GetPublicKey()).AppendLine();
|
||||
buf.Append(" Signature Algorithm: ").Append(this.SigAlgName).AppendLine();
|
||||
|
||||
byte[] sig = this.GetSignature();
|
||||
buf.Append(" Signature: ").Append(Hex.ToHexString(sig, 0, 20)).AppendLine();
|
||||
|
||||
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)).AppendLine();
|
||||
}
|
||||
|
||||
X509Extensions extensions = c.TbsCertificate.Extensions;
|
||||
|
||||
if (extensions != null)
|
||||
{
|
||||
var e = extensions.ExtensionOids.GetEnumerator();
|
||||
|
||||
if (e.MoveNext())
|
||||
{
|
||||
buf.Append(" Extensions: \n");
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
DerObjectIdentifier oid = 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("*****").AppendLine();
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
buf.Append(oid.Id);
|
||||
//buf.Append(" value = ").Append(new string(Hex.encode(ext.getValue().getOctets()))).AppendLine();
|
||||
buf.Append(" value = ").Append("*****");
|
||||
}
|
||||
}
|
||||
|
||||
buf.AppendLine();
|
||||
}
|
||||
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");
|
||||
|
||||
byte[] b = GetTbsCertificate();
|
||||
|
||||
IStreamCalculator<IVerifier> streamCalculator = verifier.CreateCalculator();
|
||||
using (var stream = streamCalculator.Stream)
|
||||
{
|
||||
stream.Write(b, 0, b.Length);
|
||||
}
|
||||
|
||||
if (!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 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
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6beadff9e85279b4e98431dba56a094f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,127 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.X509;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Security.Certificates;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.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 (f == null)
|
||||
throw new CertificateEncodingException("unable to get encoding for forward");
|
||||
}
|
||||
|
||||
if (reverse != null)
|
||||
{
|
||||
r = X509CertificateStructure.GetInstance(
|
||||
Asn1Object.FromByteArray(reverse.GetEncoded()));
|
||||
|
||||
if (r == null)
|
||||
throw new CertificateEncodingException("unable to get encoding for reverse");
|
||||
}
|
||||
|
||||
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 Org.BouncyCastle.Utilities.Platform.Equals(this.forward, other.forward)
|
||||
&& Org.BouncyCastle.Utilities.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;
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ebb6773b53a2eae45aff0fc7c7f03d8c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,171 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Pkcs;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.X509;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Security.Certificates;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.IO;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.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 new X509Certificate(X509CertificateStructure.GetInstance(seq));
|
||||
}
|
||||
|
||||
private X509Certificate ReadPemCertificate(Stream inStream)
|
||||
{
|
||||
Asn1Sequence seq = PemCertParser.ReadPemObject(inStream);
|
||||
|
||||
return seq == null ? null : new X509Certificate(X509CertificateStructure.GetInstance(seq));
|
||||
}
|
||||
|
||||
private X509Certificate GetCertificate()
|
||||
{
|
||||
if (sData != null)
|
||||
{
|
||||
while (sDataObjectCount < sData.Count)
|
||||
{
|
||||
object obj = sData[sDataObjectCount++];
|
||||
|
||||
if (obj is Asn1Sequence)
|
||||
return new X509Certificate(X509CertificateStructure.GetInstance(obj));
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <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 IList<X509Certificate> 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;
|
||||
}
|
||||
|
||||
int tag = inStream.ReadByte();
|
||||
if (tag < 0)
|
||||
return null;
|
||||
|
||||
if (inStream.CanSeek)
|
||||
{
|
||||
inStream.Seek(-1L, SeekOrigin.Current);
|
||||
}
|
||||
else
|
||||
{
|
||||
PushbackStream pis = new PushbackStream(inStream);
|
||||
pis.Unread(tag);
|
||||
inStream = pis;
|
||||
}
|
||||
|
||||
if (tag != 0x30) // assume ascii PEM encoded.
|
||||
return ReadPemCertificate(inStream);
|
||||
|
||||
return ReadDerCertificate(new Asn1InputStream(inStream));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new CertificateException("Failed to read certificate", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a (possibly empty) collection view of the certificates
|
||||
* read from the given input stream inStream.
|
||||
*/
|
||||
public IList<X509Certificate> ReadCertificates(Stream inStream)
|
||||
{
|
||||
return new List<X509Certificate>(ParseCertificates(inStream));
|
||||
}
|
||||
|
||||
public IEnumerable<X509Certificate> ParseCertificates(Stream inStream)
|
||||
{
|
||||
X509Certificate cert;
|
||||
while ((cert = ReadCertificate(inStream)) != null)
|
||||
{
|
||||
yield return cert;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d7c29c36b4684094d864d3cae4db30f7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,497 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1;
|
||||
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
|
||||
{
|
||||
/**
|
||||
* 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 class CachedEncoding
|
||||
{
|
||||
private readonly byte[] encoding;
|
||||
private readonly CrlException exception;
|
||||
|
||||
internal CachedEncoding(byte[] encoding, CrlException 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 CrlException();
|
||||
|
||||
return encoding;
|
||||
}
|
||||
}
|
||||
|
||||
private readonly CertificateList c;
|
||||
private readonly string sigAlgName;
|
||||
private readonly byte[] sigAlgParams;
|
||||
private readonly bool isIndirect;
|
||||
|
||||
private readonly object cacheLock = new object();
|
||||
private CachedEncoding cachedEncoding;
|
||||
|
||||
private volatile bool hashValueSet;
|
||||
private volatile int hashValue;
|
||||
|
||||
public X509Crl(byte[] encoding)
|
||||
: this(CertificateList.GetInstance(encoding))
|
||||
{
|
||||
}
|
||||
|
||||
public X509Crl(CertificateList 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);
|
||||
|
||||
this.isIndirect = IsIndirectCrl;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new CrlException("CRL contents invalid: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual CertificateList CertificateList
|
||||
{
|
||||
get { return c; }
|
||||
}
|
||||
|
||||
protected override X509Extensions GetX509Extensions()
|
||||
{
|
||||
return c.Version >= 2
|
||||
? c.TbsCertList.Extensions
|
||||
: null;
|
||||
}
|
||||
|
||||
public virtual void Verify(
|
||||
AsymmetricKeyParameter publicKey)
|
||||
{
|
||||
Verify(new Asn1VerifierFactoryProvider(publicKey));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verify the CRL's signature using a verifier created using the passed in verifier provider.
|
||||
/// </summary>
|
||||
/// <param name="verifierProvider">An appropriate provider for verifying the CRL's signature.</param>
|
||||
/// <returns>True if the signature is valid.</returns>
|
||||
/// <exception cref="Exception">If verifier provider is not appropriate or the CRL algorithm is invalid.</exception>
|
||||
public virtual void Verify(
|
||||
IVerifierFactoryProvider verifierProvider)
|
||||
{
|
||||
CheckSignature(verifierProvider.CreateVerifierFactory(c.SignatureAlgorithm));
|
||||
}
|
||||
|
||||
protected virtual void CheckSignature(
|
||||
IVerifierFactory verifier)
|
||||
{
|
||||
// TODO Compare IsAlgIDEqual in X509Certificate.CheckSignature
|
||||
if (!c.SignatureAlgorithm.Equals(c.TbsCertList.Signature))
|
||||
throw new CrlException("Signature algorithm on CertificateList does not match TbsCertList.");
|
||||
|
||||
byte[] b = GetTbsCertList();
|
||||
|
||||
IStreamCalculator<IVerifier> streamCalculator = verifier.CreateCalculator();
|
||||
using (var stream = streamCalculator.Stream)
|
||||
{
|
||||
stream.Write(b, 0, b.Length);
|
||||
}
|
||||
|
||||
if (!streamCalculator.GetResult().IsVerified(GetSignature()))
|
||||
throw new InvalidKeyException("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 DateTime? NextUpdate => c.NextUpdate?.ToDateTime();
|
||||
|
||||
private ISet<X509CrlEntry> LoadCrlEntries()
|
||||
{
|
||||
var entrySet = new HashSet<X509CrlEntry>();
|
||||
var revoked = c.GetRevokedCertificateEnumeration();
|
||||
|
||||
X509Name previousCertificateIssuer = IssuerDN;
|
||||
foreach (CrlEntry entry in revoked)
|
||||
{
|
||||
X509CrlEntry crlEntry = new X509CrlEntry(entry, isIndirect, previousCertificateIssuer);
|
||||
entrySet.Add(crlEntry);
|
||||
previousCertificateIssuer = crlEntry.GetCertificateIssuer();
|
||||
}
|
||||
|
||||
return entrySet;
|
||||
}
|
||||
|
||||
public virtual X509CrlEntry GetRevokedCertificate(
|
||||
BigInteger serialNumber)
|
||||
{
|
||||
var 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<X509CrlEntry> GetRevokedCertificates()
|
||||
{
|
||||
var entrySet = LoadCrlEntries();
|
||||
|
||||
if (entrySet.Count > 0)
|
||||
return 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.GetSignatureOctets();
|
||||
}
|
||||
|
||||
public virtual string SigAlgName
|
||||
{
|
||||
get { return sigAlgName; }
|
||||
}
|
||||
|
||||
public virtual string SigAlgOid
|
||||
{
|
||||
get { return c.SignatureAlgorithm.Algorithm.Id; }
|
||||
}
|
||||
|
||||
public virtual byte[] GetSigAlgParams()
|
||||
{
|
||||
return Arrays.Clone(sigAlgParams);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the DER encoding of this CRL.
|
||||
/// </summary>
|
||||
/// <returns>A byte array containing the DER encoding of this CRL.</returns>
|
||||
/// <exception cref="CrlException">If there is an error encoding the CRL.</exception>
|
||||
public virtual byte[] GetEncoded()
|
||||
{
|
||||
return Arrays.Clone(GetCachedEncoding().GetEncoded());
|
||||
}
|
||||
|
||||
public override bool Equals(object other)
|
||||
{
|
||||
if (this == other)
|
||||
return true;
|
||||
|
||||
X509Crl that = other as X509Crl;
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of this CRL.
|
||||
*
|
||||
* @return a string representation of this CRL.
|
||||
*/
|
||||
public override string ToString()
|
||||
{
|
||||
StringBuilder buf = new StringBuilder();
|
||||
|
||||
buf.Append(" Version: ").Append(this.Version).AppendLine();
|
||||
buf.Append(" IssuerDN: ").Append(this.IssuerDN).AppendLine();
|
||||
buf.Append(" This update: ").Append(this.ThisUpdate).AppendLine();
|
||||
buf.Append(" Next update: ").Append(this.NextUpdate).AppendLine();
|
||||
buf.Append(" Signature Algorithm: ").Append(this.SigAlgName).AppendLine();
|
||||
|
||||
byte[] sig = this.GetSignature();
|
||||
|
||||
buf.Append(" Signature: ");
|
||||
buf.Append(Hex.ToHexString(sig, 0, 20)).AppendLine();
|
||||
|
||||
for (int i = 20; i < sig.Length; i += 20)
|
||||
{
|
||||
int count = System.Math.Min(20, sig.Length - i);
|
||||
buf.Append(" ");
|
||||
buf.Append(Hex.ToHexString(sig, i, count)).AppendLine();
|
||||
}
|
||||
|
||||
X509Extensions extensions = c.TbsCertList.Extensions;
|
||||
|
||||
if (extensions != null)
|
||||
{
|
||||
var e = extensions.ExtensionOids.GetEnumerator();
|
||||
|
||||
if (e.MoveNext())
|
||||
{
|
||||
buf.Append(" Extensions: ").AppendLine();
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
DerObjectIdentifier oid = 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)).AppendLine();
|
||||
}
|
||||
else if (oid.Equals(X509Extensions.DeltaCrlIndicator))
|
||||
{
|
||||
buf.Append(
|
||||
"Base CRL: "
|
||||
+ new CrlNumber(DerInteger.GetInstance(
|
||||
asn1Value).PositiveValue))
|
||||
.AppendLine();
|
||||
}
|
||||
else if (oid.Equals(X509Extensions.IssuingDistributionPoint))
|
||||
{
|
||||
buf.Append(IssuingDistributionPoint.GetInstance((Asn1Sequence) asn1Value)).AppendLine();
|
||||
}
|
||||
else if (oid.Equals(X509Extensions.CrlDistributionPoints))
|
||||
{
|
||||
buf.Append(CrlDistPoint.GetInstance((Asn1Sequence) asn1Value)).AppendLine();
|
||||
}
|
||||
else if (oid.Equals(X509Extensions.FreshestCrl))
|
||||
{
|
||||
buf.Append(CrlDistPoint.GetInstance((Asn1Sequence) asn1Value)).AppendLine();
|
||||
}
|
||||
else
|
||||
{
|
||||
buf.Append(oid.Id);
|
||||
buf.Append(" value = ").Append(
|
||||
Asn1Dump.DumpAsString(asn1Value))
|
||||
.AppendLine();
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
buf.Append(oid.Id);
|
||||
buf.Append(" value = ").Append("*****").AppendLine();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
buf.AppendLine();
|
||||
}
|
||||
}
|
||||
while (e.MoveNext());
|
||||
}
|
||||
|
||||
var certSet = GetRevokedCertificates();
|
||||
if (certSet != null)
|
||||
{
|
||||
foreach (X509CrlEntry entry in certSet)
|
||||
{
|
||||
buf.Append(entry);
|
||||
buf.AppendLine();
|
||||
}
|
||||
}
|
||||
|
||||
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 = cert.SerialNumber;
|
||||
|
||||
for (int i = 0; i < certs.Length; i++)
|
||||
{
|
||||
if (certs[i].UserCertificate.HasValue(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;
|
||||
}
|
||||
}
|
||||
|
||||
private CachedEncoding GetCachedEncoding()
|
||||
{
|
||||
lock (cacheLock)
|
||||
{
|
||||
if (null != cachedEncoding)
|
||||
return cachedEncoding;
|
||||
}
|
||||
|
||||
byte[] encoding = null;
|
||||
CrlException exception = null;
|
||||
try
|
||||
{
|
||||
encoding = c.GetEncoded(Asn1Encodable.Der);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
exception = new CrlException("Failed to DER-encode CRL", e);
|
||||
}
|
||||
|
||||
CachedEncoding temp = new CachedEncoding(encoding, exception);
|
||||
|
||||
lock (cacheLock)
|
||||
{
|
||||
if (null == cachedEncoding)
|
||||
{
|
||||
cachedEncoding = temp;
|
||||
}
|
||||
|
||||
return cachedEncoding;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9a154750ed1601f4b80aa4d215d54e31
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,234 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Utilities;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.X509;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Math;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Security.Certificates;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.X509.Extension;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.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;
|
||||
|
||||
private volatile bool hashValueSet;
|
||||
private volatile int hashValue;
|
||||
|
||||
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 bool Equals(object other)
|
||||
{
|
||||
if (this == other)
|
||||
return true;
|
||||
|
||||
X509CrlEntry that = other as X509CrlEntry;
|
||||
if (null == that)
|
||||
return false;
|
||||
|
||||
if (this.hashValueSet && that.hashValueSet)
|
||||
{
|
||||
if (this.hashValue != that.hashValue)
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.c.Equals(that.c);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
if (!hashValueSet)
|
||||
{
|
||||
hashValue = this.c.GetHashCode();
|
||||
hashValueSet = true;
|
||||
}
|
||||
|
||||
return hashValue;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
StringBuilder buf = new StringBuilder();
|
||||
|
||||
buf.Append(" userCertificate: ").Append(this.SerialNumber).AppendLine();
|
||||
buf.Append(" revocationDate: ").Append(this.RevocationDate).AppendLine();
|
||||
buf.Append(" certificateIssuer: ").Append(this.GetCertificateIssuer()).AppendLine();
|
||||
|
||||
X509Extensions extensions = c.Extensions;
|
||||
|
||||
if (extensions != null)
|
||||
{
|
||||
var e = extensions.ExtensionOids.GetEnumerator();
|
||||
if (e.MoveNext())
|
||||
{
|
||||
buf.Append(" crlEntryExtensions:").AppendLine();
|
||||
|
||||
do
|
||||
{
|
||||
DerObjectIdentifier oid = 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.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.AppendLine();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
buf.Append(oid.Id);
|
||||
buf.Append(" value = ").Append("*****").AppendLine();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
buf.AppendLine();
|
||||
}
|
||||
}
|
||||
while (e.MoveNext());
|
||||
}
|
||||
}
|
||||
|
||||
return buf.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bc6c6a5eead859647b11f57143e492fb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,176 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Pkcs;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.X509;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Security.Certificates;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.IO;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.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(bool lazyAsn1 = false)
|
||||
{
|
||||
this.lazyAsn1 = lazyAsn1;
|
||||
}
|
||||
|
||||
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 new X509Crl(CertificateList.GetInstance(seq));
|
||||
}
|
||||
|
||||
private X509Crl ReadPemCrl(Stream inStream)
|
||||
{
|
||||
Asn1Sequence seq = PemCrlParser.ReadPemObject(inStream);
|
||||
|
||||
return seq == null ? null : new X509Crl(CertificateList.GetInstance(seq));
|
||||
}
|
||||
|
||||
private X509Crl GetCrl()
|
||||
{
|
||||
if (sCrlData == null || sCrlDataObjectCount >= sCrlData.Count)
|
||||
return null;
|
||||
|
||||
return new X509Crl(CertificateList.GetInstance(sCrlData[sCrlDataObjectCount++]));
|
||||
}
|
||||
|
||||
/// <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 IList<X509Crl> 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;
|
||||
}
|
||||
|
||||
int tag = inStream.ReadByte();
|
||||
if (tag < 0)
|
||||
return null;
|
||||
|
||||
if (inStream.CanSeek)
|
||||
{
|
||||
inStream.Seek(-1L, SeekOrigin.Current);
|
||||
}
|
||||
else
|
||||
{
|
||||
PushbackStream pis = new PushbackStream(inStream);
|
||||
pis.Unread(tag);
|
||||
inStream = pis;
|
||||
}
|
||||
|
||||
if (tag != 0x30) // assume ascii PEM encoded.
|
||||
return ReadPemCrl(inStream);
|
||||
|
||||
Asn1InputStream asn1 = lazyAsn1
|
||||
? new LazyAsn1InputStream(inStream)
|
||||
: new Asn1InputStream(inStream);
|
||||
|
||||
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 IList<X509Crl> ReadCrls(Stream inStream)
|
||||
{
|
||||
return new List<X509Crl>(ParseCrls(inStream));
|
||||
}
|
||||
|
||||
public IEnumerable<X509Crl> ParseCrls(Stream inStream)
|
||||
{
|
||||
X509Crl crl;
|
||||
while ((crl = ReadCrl(inStream)) != null)
|
||||
{
|
||||
yield return crl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e3886777ef4aa57469f8e79b6e1c14ac
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,59 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.X509;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.X509
|
||||
{
|
||||
public abstract class X509ExtensionBase
|
||||
: IX509Extension
|
||||
{
|
||||
protected abstract X509Extensions GetX509Extensions();
|
||||
|
||||
protected virtual ISet<string> GetExtensionOids(bool critical)
|
||||
{
|
||||
X509Extensions extensions = GetX509Extensions();
|
||||
if (extensions == null)
|
||||
return null;
|
||||
|
||||
var set = new HashSet<string>();
|
||||
foreach (DerObjectIdentifier oid in extensions.ExtensionOids)
|
||||
{
|
||||
X509Extension ext = extensions.GetExtension(oid);
|
||||
if (ext.IsCritical == critical)
|
||||
{
|
||||
set.Add(oid.Id);
|
||||
}
|
||||
}
|
||||
return set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get non critical extensions.
|
||||
/// </summary>
|
||||
/// <returns>A set of non critical extension oids.</returns>
|
||||
public virtual ISet<string> GetNonCriticalExtensionOids()
|
||||
{
|
||||
return GetExtensionOids(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get any critical extensions.
|
||||
/// </summary>
|
||||
/// <returns>A sorted list of critical entension.</returns>
|
||||
public virtual ISet<string> GetCriticalExtensionOids()
|
||||
{
|
||||
return GetExtensionOids(true);
|
||||
}
|
||||
|
||||
public virtual Asn1OctetString GetExtensionValue(DerObjectIdentifier oid)
|
||||
{
|
||||
return GetX509Extensions()?.GetExtension(oid)?.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c9d43943931445544867d6e0c63383f6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,63 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.X509;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.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);
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 856abba21185f344ba24e505be6a75e4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,139 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.CryptoPro;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Nist;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Oiw;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Pkcs;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.TeleTrust;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.X509;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.X9;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Security;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.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 (Org.BouncyCastle.Utilities.Platform.EndsWith(signature.getAlgorithm(), "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.Algorithm.Equals(PkcsObjectIdentifiers.IdRsassaPss))
|
||||
{
|
||||
RsassaPssParameters rsaParams = RsassaPssParameters.GetInstance(parameters);
|
||||
|
||||
return GetDigestAlgName(rsaParams.HashAlgorithm.Algorithm) + "withRSAandMGF1";
|
||||
}
|
||||
if (sigAlgId.Algorithm.Equals(X9ObjectIdentifiers.ECDsaWithSha2))
|
||||
{
|
||||
Asn1Sequence ecDsaParams = Asn1Sequence.GetInstance(parameters);
|
||||
|
||||
return GetDigestAlgName((DerObjectIdentifier)ecDsaParams[0]) + "withECDSA";
|
||||
}
|
||||
}
|
||||
|
||||
string sigName = SignerUtilities.GetEncodingName(sigAlgId.Algorithm);
|
||||
if (null != sigName)
|
||||
{
|
||||
return sigName;
|
||||
}
|
||||
|
||||
return sigAlgId.Algorithm.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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 622a207c30957f04fb37399eac610155
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,167 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.CryptoPro;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Nist;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Oiw;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Pkcs;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.TeleTrust;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.X509;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.X9;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Collections;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.X509
|
||||
{
|
||||
internal class X509Utilities
|
||||
{
|
||||
private static readonly Dictionary<string, DerObjectIdentifier> m_algorithms =
|
||||
new Dictionary<string, DerObjectIdentifier>(StringComparer.OrdinalIgnoreCase);
|
||||
private static readonly Dictionary<string, Asn1Encodable> m_exParams =
|
||||
new Dictionary<string, Asn1Encodable>(StringComparer.OrdinalIgnoreCase);
|
||||
private static readonly HashSet<DerObjectIdentifier> m_noParams = new HashSet<DerObjectIdentifier>();
|
||||
|
||||
static X509Utilities()
|
||||
{
|
||||
m_algorithms.Add("MD2WITHRSAENCRYPTION", PkcsObjectIdentifiers.MD2WithRsaEncryption);
|
||||
m_algorithms.Add("MD2WITHRSA", PkcsObjectIdentifiers.MD2WithRsaEncryption);
|
||||
m_algorithms.Add("MD5WITHRSAENCRYPTION", PkcsObjectIdentifiers.MD5WithRsaEncryption);
|
||||
m_algorithms.Add("MD5WITHRSA", PkcsObjectIdentifiers.MD5WithRsaEncryption);
|
||||
m_algorithms.Add("SHA1WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha1WithRsaEncryption);
|
||||
m_algorithms.Add("SHA-1WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha1WithRsaEncryption);
|
||||
m_algorithms.Add("SHA1WITHRSA", PkcsObjectIdentifiers.Sha1WithRsaEncryption);
|
||||
m_algorithms.Add("SHA-1WITHRSA", PkcsObjectIdentifiers.Sha1WithRsaEncryption);
|
||||
m_algorithms.Add("SHA224WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha224WithRsaEncryption);
|
||||
m_algorithms.Add("SHA-224WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha224WithRsaEncryption);
|
||||
m_algorithms.Add("SHA224WITHRSA", PkcsObjectIdentifiers.Sha224WithRsaEncryption);
|
||||
m_algorithms.Add("SHA-224WITHRSA", PkcsObjectIdentifiers.Sha224WithRsaEncryption);
|
||||
m_algorithms.Add("SHA256WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha256WithRsaEncryption);
|
||||
m_algorithms.Add("SHA-256WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha256WithRsaEncryption);
|
||||
m_algorithms.Add("SHA256WITHRSA", PkcsObjectIdentifiers.Sha256WithRsaEncryption);
|
||||
m_algorithms.Add("SHA-256WITHRSA", PkcsObjectIdentifiers.Sha256WithRsaEncryption);
|
||||
m_algorithms.Add("SHA384WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha384WithRsaEncryption);
|
||||
m_algorithms.Add("SHA-384WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha384WithRsaEncryption);
|
||||
m_algorithms.Add("SHA384WITHRSA", PkcsObjectIdentifiers.Sha384WithRsaEncryption);
|
||||
m_algorithms.Add("SHA-384WITHRSA", PkcsObjectIdentifiers.Sha384WithRsaEncryption);
|
||||
m_algorithms.Add("SHA512WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha512WithRsaEncryption);
|
||||
m_algorithms.Add("SHA-512WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha512WithRsaEncryption);
|
||||
m_algorithms.Add("SHA512WITHRSA", PkcsObjectIdentifiers.Sha512WithRsaEncryption);
|
||||
m_algorithms.Add("SHA-512WITHRSA", PkcsObjectIdentifiers.Sha512WithRsaEncryption);
|
||||
m_algorithms.Add("SHA512(224)WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha512_224WithRSAEncryption);
|
||||
m_algorithms.Add("SHA-512(224)WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha512_224WithRSAEncryption);
|
||||
m_algorithms.Add("SHA512(224)WITHRSA", PkcsObjectIdentifiers.Sha512_224WithRSAEncryption);
|
||||
m_algorithms.Add("SHA-512(224)WITHRSA", PkcsObjectIdentifiers.Sha512_224WithRSAEncryption);
|
||||
m_algorithms.Add("SHA512(256)WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha512_256WithRSAEncryption);
|
||||
m_algorithms.Add("SHA-512(256)WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha512_256WithRSAEncryption);
|
||||
m_algorithms.Add("SHA512(256)WITHRSA", PkcsObjectIdentifiers.Sha512_256WithRSAEncryption);
|
||||
m_algorithms.Add("SHA-512(256)WITHRSA", PkcsObjectIdentifiers.Sha512_256WithRSAEncryption);
|
||||
m_algorithms.Add("SHA1WITHRSAANDMGF1", PkcsObjectIdentifiers.IdRsassaPss);
|
||||
m_algorithms.Add("SHA224WITHRSAANDMGF1", PkcsObjectIdentifiers.IdRsassaPss);
|
||||
m_algorithms.Add("SHA256WITHRSAANDMGF1", PkcsObjectIdentifiers.IdRsassaPss);
|
||||
m_algorithms.Add("SHA384WITHRSAANDMGF1", PkcsObjectIdentifiers.IdRsassaPss);
|
||||
m_algorithms.Add("SHA512WITHRSAANDMGF1", PkcsObjectIdentifiers.IdRsassaPss);
|
||||
m_algorithms.Add("RIPEMD160WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD160);
|
||||
m_algorithms.Add("RIPEMD160WITHRSA", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD160);
|
||||
m_algorithms.Add("RIPEMD128WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD128);
|
||||
m_algorithms.Add("RIPEMD128WITHRSA", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD128);
|
||||
m_algorithms.Add("RIPEMD256WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD256);
|
||||
m_algorithms.Add("RIPEMD256WITHRSA", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD256);
|
||||
m_algorithms.Add("SHA1WITHDSA", X9ObjectIdentifiers.IdDsaWithSha1);
|
||||
m_algorithms.Add("DSAWITHSHA1", X9ObjectIdentifiers.IdDsaWithSha1);
|
||||
m_algorithms.Add("SHA224WITHDSA", NistObjectIdentifiers.DsaWithSha224);
|
||||
m_algorithms.Add("SHA256WITHDSA", NistObjectIdentifiers.DsaWithSha256);
|
||||
m_algorithms.Add("SHA384WITHDSA", NistObjectIdentifiers.DsaWithSha384);
|
||||
m_algorithms.Add("SHA512WITHDSA", NistObjectIdentifiers.DsaWithSha512);
|
||||
m_algorithms.Add("SHA1WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha1);
|
||||
m_algorithms.Add("ECDSAWITHSHA1", X9ObjectIdentifiers.ECDsaWithSha1);
|
||||
m_algorithms.Add("SHA224WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha224);
|
||||
m_algorithms.Add("SHA256WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha256);
|
||||
m_algorithms.Add("SHA384WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha384);
|
||||
m_algorithms.Add("SHA512WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha512);
|
||||
m_algorithms.Add("GOST3411WITHGOST3410", CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x94);
|
||||
m_algorithms.Add("GOST3411WITHGOST3410-94", CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x94);
|
||||
m_algorithms.Add("GOST3411WITHECGOST3410", CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001);
|
||||
m_algorithms.Add("GOST3411WITHECGOST3410-2001", CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001);
|
||||
m_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.
|
||||
//
|
||||
m_noParams.Add(X9ObjectIdentifiers.ECDsaWithSha1);
|
||||
m_noParams.Add(X9ObjectIdentifiers.ECDsaWithSha224);
|
||||
m_noParams.Add(X9ObjectIdentifiers.ECDsaWithSha256);
|
||||
m_noParams.Add(X9ObjectIdentifiers.ECDsaWithSha384);
|
||||
m_noParams.Add(X9ObjectIdentifiers.ECDsaWithSha512);
|
||||
m_noParams.Add(X9ObjectIdentifiers.IdDsaWithSha1);
|
||||
m_noParams.Add(OiwObjectIdentifiers.DsaWithSha1);
|
||||
m_noParams.Add(NistObjectIdentifiers.DsaWithSha224);
|
||||
m_noParams.Add(NistObjectIdentifiers.DsaWithSha256);
|
||||
m_noParams.Add(NistObjectIdentifiers.DsaWithSha384);
|
||||
m_noParams.Add(NistObjectIdentifiers.DsaWithSha512);
|
||||
|
||||
//
|
||||
// RFC 4491
|
||||
//
|
||||
m_noParams.Add(CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x94);
|
||||
m_noParams.Add(CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001);
|
||||
|
||||
//
|
||||
// explicit params
|
||||
//
|
||||
AlgorithmIdentifier sha1AlgId = new AlgorithmIdentifier(OiwObjectIdentifiers.IdSha1, DerNull.Instance);
|
||||
m_exParams.Add("SHA1WITHRSAANDMGF1", CreatePssParams(sha1AlgId, 20));
|
||||
|
||||
AlgorithmIdentifier sha224AlgId = new AlgorithmIdentifier(NistObjectIdentifiers.IdSha224, DerNull.Instance);
|
||||
m_exParams.Add("SHA224WITHRSAANDMGF1", CreatePssParams(sha224AlgId, 28));
|
||||
|
||||
AlgorithmIdentifier sha256AlgId = new AlgorithmIdentifier(NistObjectIdentifiers.IdSha256, DerNull.Instance);
|
||||
m_exParams.Add("SHA256WITHRSAANDMGF1", CreatePssParams(sha256AlgId, 32));
|
||||
|
||||
AlgorithmIdentifier sha384AlgId = new AlgorithmIdentifier(NistObjectIdentifiers.IdSha384, DerNull.Instance);
|
||||
m_exParams.Add("SHA384WITHRSAANDMGF1", CreatePssParams(sha384AlgId, 48));
|
||||
|
||||
AlgorithmIdentifier sha512AlgId = new AlgorithmIdentifier(NistObjectIdentifiers.IdSha512, DerNull.Instance);
|
||||
m_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)
|
||||
{
|
||||
if (m_algorithms.TryGetValue(algorithmName, out var oid))
|
||||
return oid;
|
||||
|
||||
return new DerObjectIdentifier(algorithmName);
|
||||
}
|
||||
|
||||
internal static AlgorithmIdentifier GetSigAlgID(DerObjectIdentifier sigOid, string algorithmName)
|
||||
{
|
||||
if (m_noParams.Contains(sigOid))
|
||||
return new AlgorithmIdentifier(sigOid);
|
||||
|
||||
if (m_exParams.TryGetValue(algorithmName, out var explicitParameters))
|
||||
return new AlgorithmIdentifier(sigOid, explicitParameters);
|
||||
|
||||
return new AlgorithmIdentifier(sigOid, DerNull.Instance);
|
||||
}
|
||||
|
||||
internal static IEnumerable<string> GetAlgNames()
|
||||
{
|
||||
return CollectionUtilities.Proxy(m_algorithms.Keys);
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 05c143c2146115a488ce5733be22c489
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,151 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.X509;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Math;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.X509
|
||||
{
|
||||
/// <summary>
|
||||
/// Class to Generate X509V1 Certificates.
|
||||
/// </summary>
|
||||
public class X509V1CertificateGenerator
|
||||
{
|
||||
private V1TbsCertificateGenerator tbsGen;
|
||||
|
||||
/// <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>
|
||||
/// Generate a new <see cref="X509Certificate"/> using the provided <see cref="ISignatureFactory"/>.
|
||||
/// </summary>
|
||||
/// <param name="signatureFactory">A <see cref="ISignatureFactory">signature factory</see> with the necessary
|
||||
/// algorithm details.</param>
|
||||
/// <returns>An <see cref="X509Certificate"/>.</returns>
|
||||
public X509Certificate Generate(ISignatureFactory signatureFactory)
|
||||
{
|
||||
var sigAlgID = (AlgorithmIdentifier)signatureFactory.AlgorithmDetails;
|
||||
|
||||
tbsGen.SetSignature(sigAlgID);
|
||||
|
||||
TbsCertificateStructure tbsCert = tbsGen.GenerateTbsCertificate();
|
||||
|
||||
IStreamCalculator<IBlockResult> streamCalculator = signatureFactory.CreateCalculator();
|
||||
using (Stream sigStream = streamCalculator.Stream)
|
||||
{
|
||||
tbsCert.EncodeTo(sigStream, Asn1Encodable.Der);
|
||||
}
|
||||
|
||||
var signature = streamCalculator.GetResult().Collect();
|
||||
|
||||
return new X509Certificate(
|
||||
new X509CertificateStructure(tbsCert, sigAlgID, new DerBitString(signature)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allows enumeration of the signature names supported by the generator.
|
||||
/// </summary>
|
||||
public IEnumerable<string> SignatureAlgNames
|
||||
{
|
||||
get { return X509Utilities.GetAlgNames(); }
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a9d644b2fa83d85409041f2aa7707d64
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,280 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1;
|
||||
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;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.X509
|
||||
{
|
||||
/// <summary>An implementation of a version 2 X.509 Attribute Certificate.</summary>
|
||||
public class X509V2AttributeCertificate
|
||||
: X509ExtensionBase
|
||||
{
|
||||
private readonly AttributeCertificate cert;
|
||||
private readonly DateTime notBefore;
|
||||
private readonly DateTime notAfter;
|
||||
|
||||
private static AttributeCertificate GetObject(Stream input)
|
||||
{
|
||||
try
|
||||
{
|
||||
return AttributeCertificate.GetInstance(Asn1Object.FromStream(input));
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new IOException("exception decoding certificate structure", e);
|
||||
}
|
||||
}
|
||||
|
||||
public X509V2AttributeCertificate(
|
||||
Stream encIn)
|
||||
: this(GetObject(encIn))
|
||||
{
|
||||
}
|
||||
|
||||
public X509V2AttributeCertificate(
|
||||
byte[] encoded)
|
||||
: this(new MemoryStream(encoded, false))
|
||||
{
|
||||
}
|
||||
|
||||
public 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 AttributeCertificate AttributeCertificate
|
||||
{
|
||||
get { return cert; }
|
||||
}
|
||||
|
||||
public virtual int Version
|
||||
{
|
||||
get { return cert.ACInfo.Version.IntValueExact + 1; }
|
||||
}
|
||||
|
||||
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 AlgorithmIdentifier SignatureAlgorithm
|
||||
{
|
||||
get { return cert.SignatureAlgorithm; }
|
||||
}
|
||||
|
||||
public virtual byte[] GetSignature()
|
||||
{
|
||||
return cert.GetSignatureOctets();
|
||||
}
|
||||
|
||||
public virtual void Verify(
|
||||
AsymmetricKeyParameter key)
|
||||
{
|
||||
CheckSignature(new Asn1VerifierFactory(cert.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(cert.SignatureAlgorithm));
|
||||
}
|
||||
|
||||
protected virtual void CheckSignature(
|
||||
IVerifierFactory verifier)
|
||||
{
|
||||
// TODO Compare IsAlgIDEqual in X509Certificate.CheckSignature
|
||||
if (!cert.SignatureAlgorithm.Equals(cert.ACInfo.Signature))
|
||||
throw new CertificateException("Signature algorithm in certificate info not same as outer certificate");
|
||||
|
||||
IStreamCalculator<IVerifier> streamCalculator = verifier.CreateCalculator();
|
||||
|
||||
try
|
||||
{
|
||||
byte[] b = this.cert.ACInfo.GetEncoded();
|
||||
|
||||
using (var stream = streamCalculator.Stream)
|
||||
{
|
||||
stream.Write(b, 0, b.Length);
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new SignatureException("Exception encoding certificate info object", e);
|
||||
}
|
||||
|
||||
if (!streamCalculator.GetResult().IsVerified(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;
|
||||
var list = new List<X509Attribute>();
|
||||
|
||||
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 list.ToArray();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8f91955083bfb1549aefb0e34a5159e0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,146 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.X509;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Math;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Security.Certificates;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.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;
|
||||
|
||||
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 Asn1GeneralizedTime(date));
|
||||
}
|
||||
|
||||
public void SetNotAfter(
|
||||
DateTime date)
|
||||
{
|
||||
acInfoGen.SetEndDate(new Asn1GeneralizedTime(date));
|
||||
}
|
||||
|
||||
/// <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 new NotImplementedException("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 a new <see cref="X509V2AttributeCertificate"/> using the provided <see cref="ISignatureFactory"/>.
|
||||
/// </summary>
|
||||
/// <param name="signatureFactory">A <see cref="ISignatureFactory">signature factory</see> with the necessary
|
||||
/// algorithm details.</param>
|
||||
/// <returns>An <see cref="X509V2AttributeCertificate"/>.</returns>
|
||||
public X509V2AttributeCertificate Generate(ISignatureFactory signatureFactory)
|
||||
{
|
||||
var sigAlgID = (AlgorithmIdentifier)signatureFactory.AlgorithmDetails;
|
||||
|
||||
acInfoGen.SetSignature(sigAlgID);
|
||||
|
||||
if (!extGenerator.IsEmpty)
|
||||
{
|
||||
acInfoGen.SetExtensions(extGenerator.Generate());
|
||||
}
|
||||
|
||||
AttributeCertificateInfo acInfo = acInfoGen.GenerateAttributeCertificateInfo();
|
||||
|
||||
IStreamCalculator<IBlockResult> streamCalculator = signatureFactory.CreateCalculator();
|
||||
using (Stream sigStream = streamCalculator.Stream)
|
||||
{
|
||||
acInfo.EncodeTo(sigStream, Asn1Encodable.Der);
|
||||
}
|
||||
|
||||
var signature = streamCalculator.GetResult().Collect();
|
||||
|
||||
return new X509V2AttributeCertificate(
|
||||
new AttributeCertificate(acInfo, sigAlgID, new DerBitString(signature)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allows enumeration of the signature names supported by the generator.
|
||||
/// </summary>
|
||||
public IEnumerable<string> SignatureAlgNames
|
||||
{
|
||||
get { return X509Utilities.GetAlgNames(); }
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 443d99da7fa37d344b2315855b869d71
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,214 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.X509;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Math;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Security.Certificates;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.X509
|
||||
{
|
||||
/**
|
||||
* class to produce an X.509 Version 2 CRL.
|
||||
*/
|
||||
public class X509V2CrlGenerator
|
||||
{
|
||||
private readonly X509ExtensionsGenerator extGenerator = new X509ExtensionsGenerator();
|
||||
|
||||
private V2TbsCertListGenerator tbsGen;
|
||||
|
||||
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 Asn1GeneralizedTime(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");
|
||||
|
||||
var 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 a new <see cref="X509Crl"/> using the provided <see cref="ISignatureFactory"/>.
|
||||
/// </summary>
|
||||
/// <param name="signatureFactory">A <see cref="ISignatureFactory">signature factory</see> with the necessary
|
||||
/// algorithm details.</param>
|
||||
/// <returns>An <see cref="X509Crl"/>.</returns>
|
||||
public X509Crl Generate(ISignatureFactory signatureFactory)
|
||||
{
|
||||
var sigAlgID = (AlgorithmIdentifier)signatureFactory.AlgorithmDetails;
|
||||
|
||||
tbsGen.SetSignature(sigAlgID);
|
||||
|
||||
if (!extGenerator.IsEmpty)
|
||||
{
|
||||
tbsGen.SetExtensions(extGenerator.Generate());
|
||||
}
|
||||
|
||||
TbsCertificateList tbsCertList = tbsGen.GenerateTbsCertList();
|
||||
|
||||
IStreamCalculator<IBlockResult> streamCalculator = signatureFactory.CreateCalculator();
|
||||
using (Stream sigStream = streamCalculator.Stream)
|
||||
{
|
||||
tbsCertList.EncodeTo(sigStream, Asn1Encodable.Der);
|
||||
}
|
||||
|
||||
var signature = streamCalculator.GetResult().Collect();
|
||||
|
||||
return new X509Crl(
|
||||
CertificateList.GetInstance(new DerSequence(tbsCertList, sigAlgID, new DerBitString(signature))));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allows enumeration of the signature names supported by the generator.
|
||||
/// </summary>
|
||||
public IEnumerable<string> SignatureAlgNames
|
||||
{
|
||||
get { return X509Utilities.GetAlgNames(); }
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4967cc865d9366a41bc51c9bc1a36da0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,285 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.X509;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Math;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Security.Certificates;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.X509.Extension;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.X509
|
||||
{
|
||||
/// <summary>
|
||||
/// A class to Generate Version 3 X509Certificates.
|
||||
/// </summary>
|
||||
public class X509V3CertificateGenerator
|
||||
{
|
||||
private readonly X509ExtensionsGenerator extGenerator = new X509ExtensionsGenerator();
|
||||
|
||||
private V3TbsCertificateGenerator tbsGen;
|
||||
|
||||
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 subject unique ID - note: it is very rare that it is correct to do this.
|
||||
/// </summary>
|
||||
/// <param name="uniqueID"/>
|
||||
public void SetSubjectUniqueID(
|
||||
bool[] uniqueID)
|
||||
{
|
||||
tbsGen.SetSubjectUniqueID(booleanToBitString(uniqueID));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the issuer unique ID - note: it is very rare that it is correct to do this.
|
||||
/// </summary>
|
||||
/// <param name="uniqueID"/>
|
||||
public void SetIssuerUniqueID(
|
||||
bool[] uniqueID)
|
||||
{
|
||||
tbsGen.SetIssuerUniqueID(booleanToBitString(uniqueID));
|
||||
}
|
||||
|
||||
private DerBitString booleanToBitString(
|
||||
bool[] id)
|
||||
{
|
||||
byte[] bytes = new byte[(id.Length + 7) / 8];
|
||||
|
||||
for (int i = 0; i != id.Length; i++)
|
||||
{
|
||||
if (id[i])
|
||||
{
|
||||
bytes[i / 8] |= (byte)(1 << ((7 - (i % 8))));
|
||||
}
|
||||
}
|
||||
|
||||
int pad = id.Length % 8;
|
||||
|
||||
if (pad == 0)
|
||||
{
|
||||
return new DerBitString(bytes);
|
||||
}
|
||||
|
||||
return new DerBitString(bytes, 8 - pad);
|
||||
}
|
||||
|
||||
/// <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 a new <see cref="X509Certificate"/> using the provided <see cref="ISignatureFactory"/>.
|
||||
/// </summary>
|
||||
/// <param name="signatureFactory">A <see cref="ISignatureFactory">signature factory</see> with the necessary
|
||||
/// algorithm details.</param>
|
||||
/// <returns>An <see cref="X509Certificate"/>.</returns>
|
||||
public X509Certificate Generate(ISignatureFactory signatureFactory)
|
||||
{
|
||||
var sigAlgID = (AlgorithmIdentifier)signatureFactory.AlgorithmDetails;
|
||||
|
||||
tbsGen.SetSignature(sigAlgID);
|
||||
|
||||
if (!extGenerator.IsEmpty)
|
||||
{
|
||||
tbsGen.SetExtensions(extGenerator.Generate());
|
||||
}
|
||||
|
||||
TbsCertificateStructure tbsCert = tbsGen.GenerateTbsCertificate();
|
||||
|
||||
IStreamCalculator<IBlockResult> streamCalculator = signatureFactory.CreateCalculator();
|
||||
using (Stream sigStream = streamCalculator.Stream)
|
||||
{
|
||||
tbsCert.EncodeTo(sigStream, Asn1Encodable.Der);
|
||||
}
|
||||
|
||||
var signature = streamCalculator.GetResult().Collect();
|
||||
|
||||
return new X509Certificate(new X509CertificateStructure(tbsCert, sigAlgID, new DerBitString(signature)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allows enumeration of the signature names supported by the generator.
|
||||
/// </summary>
|
||||
public IEnumerable<string> SignatureAlgNames
|
||||
{
|
||||
get { return X509Utilities.GetAlgNames(); }
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6a3594cad87c9b4439139843a48e223c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 26902280df03e254eb103b0cc513363f
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,106 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.X509;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Security;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Security.Certificates;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.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 = 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))
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bb0f4335ed25d2a4a9fd365799fdd64a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,53 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.X509;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Security.Certificates;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.X509.Extension
|
||||
{
|
||||
/**
|
||||
* A high level subject key identifier.
|
||||
*/
|
||||
public class SubjectKeyIdentifierStructure
|
||||
: SubjectKeyIdentifier
|
||||
{
|
||||
/**
|
||||
* 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))
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 004dfdf815abe524093ddfebf9234b73
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,31 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.X509.Extension
|
||||
{
|
||||
public class X509ExtensionUtilities
|
||||
{
|
||||
public static Asn1Object FromExtensionValue(Asn1OctetString extensionValue)
|
||||
{
|
||||
return Asn1Object.FromByteArray(extensionValue.GetOctets());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extract the value of the given extension, if it exists.
|
||||
/// </summary>
|
||||
/// <param name="extensions">The extensions object.</param>
|
||||
/// <param name="oid">The object identifier to obtain.</param>
|
||||
/// <returns>Asn1Object</returns>
|
||||
/// <exception cref="Exception">if the extension cannot be read.</exception>
|
||||
public static Asn1Object FromExtensionValue(IX509Extension extensions, DerObjectIdentifier oid)
|
||||
{
|
||||
Asn1OctetString extensionValue = extensions.GetExtensionValue(oid);
|
||||
return extensionValue == null ? null : FromExtensionValue(extensionValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c1e9b9d84df723247b8211204f278332
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5b7983a5c52108d458439861101ff522
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,363 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.X509;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Math;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Collections;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.X509.Extension;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.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
|
||||
: ISelector<X509V2AttributeCertificate>
|
||||
{
|
||||
// TODO: name constraints???
|
||||
|
||||
private X509V2AttributeCertificate attributeCert;
|
||||
private DateTime? attributeCertificateValid;
|
||||
private AttributeCertificateHolder holder;
|
||||
private AttributeCertificateIssuer issuer;
|
||||
private BigInteger serialNumber;
|
||||
private ISet<GeneralName> targetNames = new HashSet<GeneralName>();
|
||||
private ISet<GeneralName> targetGroups = new HashSet<GeneralName>();
|
||||
|
||||
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<GeneralName>(o.targetGroups);
|
||||
this.targetNames = new HashSet<GeneralName>(o.targetNames);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decides if the given attribute certificate should be selected.
|
||||
/// </summary>
|
||||
/// <param name="attrCert">The attribute certificate to be checked.</param>
|
||||
/// <returns><code>true</code> if the object matches this selector.</returns>
|
||||
public bool Match(X509V2AttributeCertificate attrCert)
|
||||
{
|
||||
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 X509V2AttributeCertificate AttributeCert
|
||||
{
|
||||
get { return attributeCert; }
|
||||
set { this.attributeCert = value; }
|
||||
}
|
||||
|
||||
/// <summary>The criteria for validity</summary>
|
||||
/// <remarks>If <c>null</c> is given any will do.</remarks>
|
||||
public DateTime? 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<object> 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<GeneralName> GetTargetNames()
|
||||
{
|
||||
return CollectionUtilities.Proxy(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<object> 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<GeneralName> GetTargetGroups()
|
||||
{
|
||||
return CollectionUtilities.Proxy(targetGroups);
|
||||
}
|
||||
|
||||
private ISet<GeneralName> ExtractGeneralNames(IEnumerable<object> names)
|
||||
{
|
||||
var result = new HashSet<GeneralName>();
|
||||
|
||||
if (names != null)
|
||||
{
|
||||
foreach (object o in names)
|
||||
{
|
||||
if (o is GeneralName gn)
|
||||
{
|
||||
result.Add(gn);
|
||||
}
|
||||
else if (o is byte[] bs)
|
||||
{
|
||||
result.Add(GeneralName.GetInstance(Asn1Object.FromByteArray(bs)));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 05a1711d73cac0449a5f694102783ad4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,92 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Collections;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.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
|
||||
: ISelector<X509CertificatePair>
|
||||
{
|
||||
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="pair">The <code>X509CertificatePair</code> to be tested.</param>
|
||||
/// <returns><code>true</code> if the object matches this selector.</returns>
|
||||
public bool Match(X509CertificatePair pair)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4b519c06b0ed0da4e8bca4f63037fea6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,333 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.X509;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Math;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Collections;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.X509.Extension;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.X509.Store
|
||||
{
|
||||
public class X509CertStoreSelector
|
||||
: ISelector<X509Certificate>
|
||||
{
|
||||
// TODO Missing criteria?
|
||||
|
||||
private byte[] authorityKeyIdentifier;
|
||||
private int basicConstraints = -1;
|
||||
private X509Certificate certificate;
|
||||
private DateTime? certificateValid;
|
||||
private ISet<DerObjectIdentifier> extendedKeyUsage;
|
||||
private bool ignoreX509NameOrdering;
|
||||
private X509Name issuer;
|
||||
private bool[] keyUsage;
|
||||
private ISet<DerObjectIdentifier> policy;
|
||||
private DateTime? 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.ignoreX509NameOrdering = o.IgnoreX509NameOrdering;
|
||||
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 DateTime? CertificateValid
|
||||
{
|
||||
get { return certificateValid; }
|
||||
set { certificateValid = value; }
|
||||
}
|
||||
|
||||
public ISet<DerObjectIdentifier> ExtendedKeyUsage
|
||||
{
|
||||
get { return CopySet(extendedKeyUsage); }
|
||||
set { extendedKeyUsage = CopySet(value); }
|
||||
}
|
||||
|
||||
public bool IgnoreX509NameOrdering
|
||||
{
|
||||
get { return ignoreX509NameOrdering; }
|
||||
set { this.ignoreX509NameOrdering = value; }
|
||||
}
|
||||
|
||||
public X509Name Issuer
|
||||
{
|
||||
get { return issuer; }
|
||||
set { issuer = value; }
|
||||
}
|
||||
|
||||
public bool[] KeyUsage
|
||||
{
|
||||
get { return CopyBoolArray(keyUsage); }
|
||||
set { keyUsage = CopyBoolArray(value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An <code>ISet</code> of <code>DerObjectIdentifier</code> objects.
|
||||
/// </summary>
|
||||
public ISet<DerObjectIdentifier> Policy
|
||||
{
|
||||
get { return CopySet(policy); }
|
||||
set { policy = CopySet(value); }
|
||||
}
|
||||
|
||||
public DateTime? 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 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(X509Certificate c)
|
||||
{
|
||||
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)
|
||||
{
|
||||
var 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))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (issuer != null && !issuer.Equivalent(c.IssuerDN, !ignoreX509NameOrdering))
|
||||
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, !ignoreX509NameOrdering))
|
||||
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;
|
||||
}
|
||||
|
||||
internal static bool IssuersMatch(
|
||||
X509Name a,
|
||||
X509Name b)
|
||||
{
|
||||
return a == null ? b == null : a.Equivalent(b, true);
|
||||
}
|
||||
|
||||
private static bool[] CopyBoolArray(
|
||||
bool[] b)
|
||||
{
|
||||
return b == null ? null : (bool[]) b.Clone();
|
||||
}
|
||||
|
||||
private static ISet<T> CopySet<T>(ISet<T> s)
|
||||
{
|
||||
return s == null ? null : new HashSet<T>(s);
|
||||
}
|
||||
|
||||
private static SubjectPublicKeyInfo GetSubjectPublicKey(
|
||||
X509Certificate c)
|
||||
{
|
||||
return SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(c.GetPublicKey());
|
||||
}
|
||||
|
||||
private static bool MatchExtension(
|
||||
byte[] b,
|
||||
X509Certificate c,
|
||||
DerObjectIdentifier oid)
|
||||
{
|
||||
if (b == null)
|
||||
return true;
|
||||
|
||||
Asn1OctetString extVal = c.GetExtensionValue(oid);
|
||||
|
||||
if (extVal == null)
|
||||
return false;
|
||||
|
||||
return Arrays.AreEqual(b, extVal.GetOctets());
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 12b4022923dff834aa70b6c746f2e976
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,3 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c44ab57be880acf4083d7227de673914
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,3 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c065ab63ea9da2a4dbca3a45cf5cf943
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,283 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#pragma warning disable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.X509;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Math;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Collections;
|
||||
using BestHTTP.SecureProtocol.Org.BouncyCastle.X509.Extension;
|
||||
|
||||
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.X509.Store
|
||||
{
|
||||
public class X509CrlStoreSelector
|
||||
: ISelector<X509Crl>
|
||||
{
|
||||
// TODO Missing criteria?
|
||||
|
||||
private X509Certificate certificateChecking;
|
||||
private DateTime? dateAndTime;
|
||||
private IList<X509Name> issuers;
|
||||
private BigInteger maxCrlNumber;
|
||||
private BigInteger minCrlNumber;
|
||||
|
||||
private X509V2AttributeCertificate 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 DateTime? DateAndTime
|
||||
{
|
||||
get { return dateAndTime; }
|
||||
set { dateAndTime = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An <code>ICollection</code> of <code>X509Name</code> objects
|
||||
/// </summary>
|
||||
public IList<X509Name> Issuers
|
||||
{
|
||||
get { return new List<X509Name>(issuers); }
|
||||
set { issuers = new List<X509Name>(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 X509V2AttributeCertificate 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(X509Crl c)
|
||||
{
|
||||
if (c == null)
|
||||
return false;
|
||||
|
||||
if (dateAndTime != null)
|
||||
{
|
||||
DateTime dt = dateAndTime.Value;
|
||||
DateTime tu = c.ThisUpdate;
|
||||
DateTime? 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, true))
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d8a2c8ce56d49414a89fd32d343d68c2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,3 @@
|
||||
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2756db2be5ed60c4a9f25ba9608ae2d0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user