#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
#pragma warning disable
using System;
using System.IO;
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Asn1;
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Asn1.Cmp;
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Asn1.X509;
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto;
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Engines;
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Signers;
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Math;
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Security;
using Best.HTTP.SecureProtocol.Org.BouncyCastle.Utilities;
namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Tls.Crypto.Impl.BC
{
/// Implementation class for a single X.509 certificate based on the BC light-weight API.
public class BcTlsRawKeyCertificate
: TlsCertificate
{
protected readonly BcTlsCrypto m_crypto;
protected readonly SubjectPublicKeyInfo m_keyInfo;
protected DHPublicKeyParameters m_pubKeyDH = null;
protected ECPublicKeyParameters m_pubKeyEC = null;
protected Ed25519PublicKeyParameters m_pubKeyEd25519 = null;
protected Ed448PublicKeyParameters m_pubKeyEd448 = null;
protected RsaKeyParameters m_pubKeyRsa = null;
///
public BcTlsRawKeyCertificate(BcTlsCrypto crypto, byte[] encoding)
: this(crypto, SubjectPublicKeyInfo.GetInstance(encoding))
{
}
public BcTlsRawKeyCertificate(BcTlsCrypto crypto, SubjectPublicKeyInfo keyInfo)
{
m_crypto = crypto;
m_keyInfo = keyInfo;
}
public virtual SubjectPublicKeyInfo SubjectPublicKeyInfo => m_keyInfo;
///
public virtual TlsEncryptor CreateEncryptor(int tlsCertificateRole)
{
ValidateKeyUsage(KeyUsage.KeyEncipherment);
switch (tlsCertificateRole)
{
case TlsCertificateRole.RsaEncryption:
{
this.m_pubKeyRsa = GetPubKeyRsa();
return new BcTlsRsaEncryptor(m_crypto, m_pubKeyRsa);
}
// TODO[gmssl]
//case TlsCertificateRole.Sm2Encryption:
//{
// this.m_pubKeyEC = GetPubKeyEC();
// return new BcTlsSM2Encryptor(m_crypto, m_pubKeyEC);
//}
}
throw new TlsFatalAlert(AlertDescription.certificate_unknown);
}
///
public virtual TlsVerifier CreateVerifier(short signatureAlgorithm)
{
switch (signatureAlgorithm)
{
case SignatureAlgorithm.ed25519:
case SignatureAlgorithm.ed448:
{
int signatureScheme = SignatureScheme.From(HashAlgorithm.Intrinsic, signatureAlgorithm);
Tls13Verifier tls13Verifier = CreateVerifier(signatureScheme);
return new LegacyTls13Verifier(signatureScheme, tls13Verifier);
}
}
ValidateKeyUsage(KeyUsage.DigitalSignature);
switch (signatureAlgorithm)
{
case SignatureAlgorithm.dsa:
return new BcTlsDsaVerifier(m_crypto, GetPubKeyDss());
case SignatureAlgorithm.ecdsa:
return new BcTlsECDsaVerifier(m_crypto, GetPubKeyEC());
case SignatureAlgorithm.rsa:
{
ValidateRsa_Pkcs1();
return new BcTlsRsaVerifier(m_crypto, GetPubKeyRsa());
}
case SignatureAlgorithm.rsa_pss_pss_sha256:
case SignatureAlgorithm.rsa_pss_pss_sha384:
case SignatureAlgorithm.rsa_pss_pss_sha512:
{
ValidateRsa_Pss_Pss(signatureAlgorithm);
int signatureScheme = SignatureScheme.From(HashAlgorithm.Intrinsic, signatureAlgorithm);
return new BcTlsRsaPssVerifier(m_crypto, GetPubKeyRsa(), signatureScheme);
}
case SignatureAlgorithm.rsa_pss_rsae_sha256:
case SignatureAlgorithm.rsa_pss_rsae_sha384:
case SignatureAlgorithm.rsa_pss_rsae_sha512:
{
ValidateRsa_Pss_Rsae();
int signatureScheme = SignatureScheme.From(HashAlgorithm.Intrinsic, signatureAlgorithm);
return new BcTlsRsaPssVerifier(m_crypto, GetPubKeyRsa(), signatureScheme);
}
default:
throw new TlsFatalAlert(AlertDescription.certificate_unknown);
}
}
///
public virtual Tls13Verifier CreateVerifier(int signatureScheme)
{
ValidateKeyUsage(KeyUsage.DigitalSignature);
switch (signatureScheme)
{
case SignatureScheme.ecdsa_brainpoolP256r1tls13_sha256:
case SignatureScheme.ecdsa_brainpoolP384r1tls13_sha384:
case SignatureScheme.ecdsa_brainpoolP512r1tls13_sha512:
case SignatureScheme.ecdsa_secp256r1_sha256:
case SignatureScheme.ecdsa_secp384r1_sha384:
case SignatureScheme.ecdsa_secp521r1_sha512:
case SignatureScheme.ecdsa_sha1:
{
int cryptoHashAlgorithm = SignatureScheme.GetCryptoHashAlgorithm(signatureScheme);
IDigest digest = m_crypto.CreateDigest(cryptoHashAlgorithm);
ISigner verifier = new DsaDigestSigner(new ECDsaSigner(), digest);
verifier.Init(false, GetPubKeyEC());
return new BcTls13Verifier(verifier);
}
case SignatureScheme.ed25519:
{
Ed25519Signer verifier = new Ed25519Signer();
verifier.Init(false, GetPubKeyEd25519());
return new BcTls13Verifier(verifier);
}
case SignatureScheme.ed448:
{
Ed448Signer verifier = new Ed448Signer(TlsUtilities.EmptyBytes);
verifier.Init(false, GetPubKeyEd448());
return new BcTls13Verifier(verifier);
}
case SignatureScheme.rsa_pkcs1_sha1:
case SignatureScheme.rsa_pkcs1_sha256:
case SignatureScheme.rsa_pkcs1_sha384:
case SignatureScheme.rsa_pkcs1_sha512:
{
ValidateRsa_Pkcs1();
int cryptoHashAlgorithm = SignatureScheme.GetCryptoHashAlgorithm(signatureScheme);
IDigest digest = m_crypto.CreateDigest(cryptoHashAlgorithm);
RsaDigestSigner verifier = new RsaDigestSigner(digest,
TlsCryptoUtilities.GetOidForHash(cryptoHashAlgorithm));
verifier.Init(false, GetPubKeyRsa());
return new BcTls13Verifier(verifier);
}
case SignatureScheme.rsa_pss_pss_sha256:
case SignatureScheme.rsa_pss_pss_sha384:
case SignatureScheme.rsa_pss_pss_sha512:
{
ValidateRsa_Pss_Pss(SignatureScheme.GetSignatureAlgorithm(signatureScheme));
int cryptoHashAlgorithm = SignatureScheme.GetCryptoHashAlgorithm(signatureScheme);
IDigest digest = m_crypto.CreateDigest(cryptoHashAlgorithm);
PssSigner verifier = new PssSigner(new RsaEngine(), digest, digest.GetDigestSize());
verifier.Init(false, GetPubKeyRsa());
return new BcTls13Verifier(verifier);
}
case SignatureScheme.rsa_pss_rsae_sha256:
case SignatureScheme.rsa_pss_rsae_sha384:
case SignatureScheme.rsa_pss_rsae_sha512:
{
ValidateRsa_Pss_Rsae();
int cryptoHashAlgorithm = SignatureScheme.GetCryptoHashAlgorithm(signatureScheme);
IDigest digest = m_crypto.CreateDigest(cryptoHashAlgorithm);
PssSigner verifier = new PssSigner(new RsaEngine(), digest, digest.GetDigestSize());
verifier.Init(false, GetPubKeyRsa());
return new BcTls13Verifier(verifier);
}
// TODO[RFC 8998]
//case SignatureScheme.sm2sig_sm3:
//{
// ParametersWithID parametersWithID = new ParametersWithID(GetPubKeyEC(),
// Strings.ToByteArray("TLSv1.3+GM+Cipher+Suite"));
// SM2Signer verifier = new SM2Signer();
// verifier.Init(false, parametersWithID);
// return new BcTls13Verifier(verifier);
//}
default:
throw new TlsFatalAlert(AlertDescription.certificate_unknown);
}
}
///
public virtual byte[] GetEncoded()
{
return m_keyInfo.GetEncoded(Asn1Encodable.Der);
}
///
public virtual byte[] GetExtension(DerObjectIdentifier extensionOid)
{
return null;
}
public virtual BigInteger SerialNumber => null;
public virtual string SigAlgOid => null;
public virtual Asn1Encodable GetSigAlgParams() => null;
///
public virtual short GetLegacySignatureAlgorithm()
{
AsymmetricKeyParameter publicKey = GetPublicKey();
if (publicKey.IsPrivate)
throw new TlsFatalAlert(AlertDescription.internal_error);
if (!SupportsKeyUsage(KeyUsage.DigitalSignature))
return -1;
/*
* RFC 5246 7.4.6. Client Certificate
*/
/*
* RSA public key; the certificate MUST allow the key to be used for signing with the
* signature scheme and hash algorithm that will be employed in the certificate verify
* message.
*/
if (publicKey is RsaKeyParameters)
return SignatureAlgorithm.rsa;
/*
* DSA public key; the certificate MUST allow the key to be used for signing with the
* hash algorithm that will be employed in the certificate verify message.
*/
if (publicKey is DsaPublicKeyParameters)
return SignatureAlgorithm.dsa;
/*
* ECDSA-capable public key; the certificate MUST allow the key to be used for signing
* with the hash algorithm that will be employed in the certificate verify message; the
* public key MUST use a curve and point format supported by the server.
*/
if (publicKey is ECPublicKeyParameters)
{
// TODO Check the curve and point format
return SignatureAlgorithm.ecdsa;
}
return -1;
}
///
public virtual DHPublicKeyParameters GetPubKeyDH()
{
try
{
return (DHPublicKeyParameters)GetPublicKey();
}
catch (InvalidCastException e)
{
throw new TlsFatalAlert(AlertDescription.certificate_unknown, e);
}
}
///
public virtual DsaPublicKeyParameters GetPubKeyDss()
{
try
{
return (DsaPublicKeyParameters)GetPublicKey();
}
catch (InvalidCastException e)
{
throw new TlsFatalAlert(AlertDescription.certificate_unknown, e);
}
}
///
public virtual ECPublicKeyParameters GetPubKeyEC()
{
try
{
return (ECPublicKeyParameters)GetPublicKey();
}
catch (InvalidCastException e)
{
throw new TlsFatalAlert(AlertDescription.certificate_unknown, e);
}
}
///
public virtual Ed25519PublicKeyParameters GetPubKeyEd25519()
{
try
{
return (Ed25519PublicKeyParameters)GetPublicKey();
}
catch (InvalidCastException e)
{
throw new TlsFatalAlert(AlertDescription.certificate_unknown, e);
}
}
///
public virtual Ed448PublicKeyParameters GetPubKeyEd448()
{
try
{
return (Ed448PublicKeyParameters)GetPublicKey();
}
catch (InvalidCastException e)
{
throw new TlsFatalAlert(AlertDescription.certificate_unknown, e);
}
}
///
public virtual RsaKeyParameters GetPubKeyRsa()
{
try
{
return (RsaKeyParameters)GetPublicKey();
}
catch (InvalidCastException e)
{
throw new TlsFatalAlert(AlertDescription.certificate_unknown, e);
}
}
///
public virtual bool SupportsSignatureAlgorithm(short signatureAlgorithm)
{
return SupportsSignatureAlgorithm(signatureAlgorithm, KeyUsage.DigitalSignature);
}
///
public virtual bool SupportsSignatureAlgorithmCA(short signatureAlgorithm)
{
return SupportsSignatureAlgorithm(signatureAlgorithm, KeyUsage.KeyCertSign);
}
///
public virtual TlsCertificate CheckUsageInRole(int tlsCertificateRole)
{
switch (tlsCertificateRole)
{
case TlsCertificateRole.DH:
{
ValidateKeyUsage(KeyUsage.KeyAgreement);
this.m_pubKeyDH = GetPubKeyDH();
return this;
}
case TlsCertificateRole.ECDH:
{
ValidateKeyUsage(KeyUsage.KeyAgreement);
this.m_pubKeyEC = GetPubKeyEC();
return this;
}
}
throw new TlsFatalAlert(AlertDescription.certificate_unknown);
}
///
protected virtual AsymmetricKeyParameter GetPublicKey()
{
try
{
return PublicKeyFactory.CreateKey(m_keyInfo);
}
catch (Exception e)
{
throw new TlsFatalAlert(AlertDescription.unsupported_certificate, e);
}
}
protected virtual bool SupportsKeyUsage(int keyUsageBits)
{
return true;
}
protected virtual bool SupportsRsa_Pkcs1()
{
AlgorithmIdentifier pubKeyAlgID = m_keyInfo.AlgorithmID;
return RsaUtilities.SupportsPkcs1(pubKeyAlgID);
}
protected virtual bool SupportsRsa_Pss_Pss(short signatureAlgorithm)
{
AlgorithmIdentifier pubKeyAlgID = m_keyInfo.AlgorithmID;
return RsaUtilities.SupportsPss_Pss(signatureAlgorithm, pubKeyAlgID);
}
protected virtual bool SupportsRsa_Pss_Rsae()
{
AlgorithmIdentifier pubKeyAlgID = m_keyInfo.AlgorithmID;
return RsaUtilities.SupportsPss_Rsae(pubKeyAlgID);
}
///
protected virtual bool SupportsSignatureAlgorithm(short signatureAlgorithm, int keyUsage)
{
if (!SupportsKeyUsage(keyUsage))
return false;
AsymmetricKeyParameter publicKey = GetPublicKey();
switch (signatureAlgorithm)
{
case SignatureAlgorithm.rsa:
return SupportsRsa_Pkcs1()
&& publicKey is RsaKeyParameters;
case SignatureAlgorithm.dsa:
return publicKey is DsaPublicKeyParameters;
case SignatureAlgorithm.ecdsa:
case SignatureAlgorithm.ecdsa_brainpoolP256r1tls13_sha256:
case SignatureAlgorithm.ecdsa_brainpoolP384r1tls13_sha384:
case SignatureAlgorithm.ecdsa_brainpoolP512r1tls13_sha512:
return publicKey is ECPublicKeyParameters;
case SignatureAlgorithm.ed25519:
return publicKey is Ed25519PublicKeyParameters;
case SignatureAlgorithm.ed448:
return publicKey is Ed448PublicKeyParameters;
case SignatureAlgorithm.rsa_pss_rsae_sha256:
case SignatureAlgorithm.rsa_pss_rsae_sha384:
case SignatureAlgorithm.rsa_pss_rsae_sha512:
return SupportsRsa_Pss_Rsae()
&& publicKey is RsaKeyParameters;
case SignatureAlgorithm.rsa_pss_pss_sha256:
case SignatureAlgorithm.rsa_pss_pss_sha384:
case SignatureAlgorithm.rsa_pss_pss_sha512:
return SupportsRsa_Pss_Pss(signatureAlgorithm)
&& publicKey is RsaKeyParameters;
default:
return false;
}
}
///
public virtual void ValidateKeyUsage(int keyUsageBits)
{
if (!SupportsKeyUsage(keyUsageBits))
throw new TlsFatalAlert(AlertDescription.certificate_unknown);
}
///
protected virtual void ValidateRsa_Pkcs1()
{
if (!SupportsRsa_Pkcs1())
throw new TlsFatalAlert(AlertDescription.certificate_unknown);
}
///
protected virtual void ValidateRsa_Pss_Pss(short signatureAlgorithm)
{
if (!SupportsRsa_Pss_Pss(signatureAlgorithm))
throw new TlsFatalAlert(AlertDescription.certificate_unknown);
}
///
protected virtual void ValidateRsa_Pss_Rsae()
{
if (!SupportsRsa_Pss_Rsae())
throw new TlsFatalAlert(AlertDescription.certificate_unknown);
}
}
}
#pragma warning restore
#endif