using System; using System.IO; using Org.BouncyCastle.Asn1; using Org.BouncyCastle.Asn1.X509; using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Math; using Org.BouncyCastle.Security; using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Tls.Crypto.Impl.BC { /// Implementation class for a single X.509 certificate based on the BC light-weight API. public class BcTlsCertificate : TlsCertificate { /// public static BcTlsCertificate Convert(BcTlsCrypto crypto, TlsCertificate certificate) { if (certificate is BcTlsCertificate) return (BcTlsCertificate)certificate; return new BcTlsCertificate(crypto, certificate.GetEncoded()); } /// public static X509CertificateStructure ParseCertificate(byte[] encoding) { try { return X509CertificateStructure.GetInstance(encoding); } catch (Exception e) { throw new TlsFatalAlert(AlertDescription.bad_certificate, e); } } protected readonly BcTlsCrypto m_crypto; protected readonly X509CertificateStructure m_certificate; 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 BcTlsCertificate(BcTlsCrypto crypto, byte[] encoding) : this(crypto, ParseCertificate(encoding)) { } public BcTlsCertificate(BcTlsCrypto crypto, X509CertificateStructure certificate) { this.m_crypto = crypto; this.m_certificate = certificate; } /// public virtual TlsEncryptor CreateEncryptor(int tlsCertificateRole) { ValidateKeyUsage(KeyUsage.KeyEncipherment); switch (tlsCertificateRole) { case TlsCertificateRole.RsaEncryption: { #pragma warning disable CS0612 // 类型或成员已过时 this.m_pubKeyRsa = GetPubKeyRsa(); #pragma warning restore CS0612 // 类型或成员已过时 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.rsa_pss_rsae_sha256: case SignatureAlgorithm.rsa_pss_rsae_sha384: case SignatureAlgorithm.rsa_pss_rsae_sha512: case SignatureAlgorithm.ed25519: case SignatureAlgorithm.ed448: case SignatureAlgorithm.rsa_pss_pss_sha256: case SignatureAlgorithm.rsa_pss_pss_sha384: case SignatureAlgorithm.rsa_pss_pss_sha512: return CreateVerifier(SignatureScheme.From(HashAlgorithm.Intrinsic, signatureAlgorithm)); } ValidateKeyUsage(KeyUsage.DigitalSignature); switch (signatureAlgorithm) { case SignatureAlgorithm.rsa: ValidateRsa_Pkcs1(); #pragma warning disable CS0612 // 类型或成员已过时 return new BcTlsRsaVerifier(m_crypto, GetPubKeyRsa()); #pragma warning restore CS0612 // 类型或成员已过时 case SignatureAlgorithm.dsa: #pragma warning disable CS0612 // 类型或成员已过时 return new BcTlsDsaVerifier(m_crypto, GetPubKeyDss()); #pragma warning restore CS0612 // 类型或成员已过时 case SignatureAlgorithm.ecdsa: #pragma warning disable CS0612 // 类型或成员已过时 return new BcTlsECDsaVerifier(m_crypto, GetPubKeyEC()); #pragma warning restore CS0612 // 类型或成员已过时 default: throw new TlsFatalAlert(AlertDescription.certificate_unknown); } } /// public virtual TlsVerifier 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: #pragma warning disable CS0612 // 类型或成员已过时 return new BcTlsECDsa13Verifier(m_crypto, GetPubKeyEC(), signatureScheme); #pragma warning restore CS0612 // 类型或成员已过时 case SignatureScheme.ed25519: #pragma warning disable CS0612 // 类型或成员已过时 return new BcTlsEd25519Verifier(m_crypto, GetPubKeyEd25519()); #pragma warning restore CS0612 // 类型或成员已过时 case SignatureScheme.ed448: #pragma warning disable CS0612 // 类型或成员已过时 return new BcTlsEd448Verifier(m_crypto, GetPubKeyEd448()); #pragma warning restore CS0612 // 类型或成员已过时 case SignatureScheme.rsa_pkcs1_sha1: case SignatureScheme.rsa_pkcs1_sha256: case SignatureScheme.rsa_pkcs1_sha384: case SignatureScheme.rsa_pkcs1_sha512: { ValidateRsa_Pkcs1(); #pragma warning disable CS0612 // 类型或成员已过时 return new BcTlsRsaVerifier(m_crypto, GetPubKeyRsa()); #pragma warning restore CS0612 // 类型或成员已过时 } case SignatureScheme.rsa_pss_pss_sha256: case SignatureScheme.rsa_pss_pss_sha384: case SignatureScheme.rsa_pss_pss_sha512: { ValidateRsa_Pss_Pss(SignatureScheme.GetSignatureAlgorithm(signatureScheme)); #pragma warning disable CS0612 // 类型或成员已过时 return new BcTlsRsaPssVerifier(m_crypto, GetPubKeyRsa(), signatureScheme); #pragma warning restore CS0612 // 类型或成员已过时 } case SignatureScheme.rsa_pss_rsae_sha256: case SignatureScheme.rsa_pss_rsae_sha384: case SignatureScheme.rsa_pss_rsae_sha512: { ValidateRsa_Pss_Rsae(); #pragma warning disable CS0612 // 类型或成员已过时 return new BcTlsRsaPssVerifier(m_crypto, GetPubKeyRsa(), signatureScheme); #pragma warning restore CS0612 // 类型或成员已过时 } // TODO[RFC 8998] //case SignatureScheme.sm2sig_sm3: // return new BcTlsSM2Verifier(m_crypto, GetPubKeyEC(), Strings.ToByteArray("TLSv1.3+GM+Cipher+Suite")); default: throw new TlsFatalAlert(AlertDescription.certificate_unknown); } } /// public virtual byte[] GetEncoded() { return m_certificate.GetEncoded(Asn1Encodable.Der); } /// public virtual byte[] GetExtension(DerObjectIdentifier extensionOid) { X509Extensions extensions = m_certificate.TbsCertificate.Extensions; if (extensions != null) { X509Extension extension = extensions.GetExtension(extensionOid); if (extension != null) { return Arrays.Clone(extension.Value.GetOctets()); } } return null; } public virtual BigInteger SerialNumber { get { return m_certificate.SerialNumber.Value; } } public virtual string SigAlgOid { get { return m_certificate.SignatureAlgorithm.Algorithm.Id; } } public virtual Asn1Encodable GetSigAlgParams() { return m_certificate.SignatureAlgorithm.Parameters; } /// [Obsolete] 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; } /// [Obsolete] public virtual DHPublicKeyParameters GetPubKeyDH() { try { return (DHPublicKeyParameters)GetPublicKey(); } catch (InvalidCastException e) { throw new TlsFatalAlert(AlertDescription.certificate_unknown, e); } } /// [Obsolete] public virtual DsaPublicKeyParameters GetPubKeyDss() { try { return (DsaPublicKeyParameters)GetPublicKey(); } catch (InvalidCastException e) { throw new TlsFatalAlert(AlertDescription.certificate_unknown, e); } } /// [Obsolete] public virtual ECPublicKeyParameters GetPubKeyEC() { try { return (ECPublicKeyParameters)GetPublicKey(); } catch (InvalidCastException e) { throw new TlsFatalAlert(AlertDescription.certificate_unknown, e); } } /// [Obsolete] public virtual Ed25519PublicKeyParameters GetPubKeyEd25519() { try { return (Ed25519PublicKeyParameters)GetPublicKey(); } catch (InvalidCastException e) { throw new TlsFatalAlert(AlertDescription.certificate_unknown, e); } } /// [Obsolete] public virtual Ed448PublicKeyParameters GetPubKeyEd448() { try { return (Ed448PublicKeyParameters)GetPublicKey(); } catch (InvalidCastException e) { throw new TlsFatalAlert(AlertDescription.certificate_unknown, e); } } /// [Obsolete] public virtual RsaKeyParameters GetPubKeyRsa() { try { return (RsaKeyParameters)GetPublicKey(); } catch (InvalidCastException e) { throw new TlsFatalAlert(AlertDescription.certificate_unknown, e); } } /// public virtual bool SupportsSignatureAlgorithm(short signatureAlgorithm) { #pragma warning disable CS0612 // 类型或成员已过时 return SupportsSignatureAlgorithm(signatureAlgorithm, KeyUsage.DigitalSignature); #pragma warning restore CS0612 // 类型或成员已过时 } /// public virtual bool SupportsSignatureAlgorithmCA(short signatureAlgorithm) { #pragma warning disable CS0612 // 类型或成员已过时 return SupportsSignatureAlgorithm(signatureAlgorithm, KeyUsage.KeyCertSign); #pragma warning restore CS0612 // 类型或成员已过时 } /// public virtual TlsCertificate CheckUsageInRole(int tlsCertificateRole) { switch (tlsCertificateRole) { case TlsCertificateRole.DH: { ValidateKeyUsage(KeyUsage.KeyAgreement); #pragma warning disable CS0612 // 类型或成员已过时 this.m_pubKeyDH = GetPubKeyDH(); #pragma warning restore CS0612 // 类型或成员已过时 return this; } case TlsCertificateRole.ECDH: { ValidateKeyUsage(KeyUsage.KeyAgreement); #pragma warning disable CS0612 // 类型或成员已过时 this.m_pubKeyEC = GetPubKeyEC(); #pragma warning restore CS0612 // 类型或成员已过时 return this; } } throw new TlsFatalAlert(AlertDescription.certificate_unknown); } /// [Obsolete] protected virtual AsymmetricKeyParameter GetPublicKey() { SubjectPublicKeyInfo keyInfo = m_certificate.SubjectPublicKeyInfo; try { return PublicKeyFactory.CreateKey(keyInfo); } catch (Exception e) { throw new TlsFatalAlert(AlertDescription.unsupported_certificate, e); } } protected virtual bool SupportsKeyUsage(int keyUsageBits) { X509Extensions exts = m_certificate.TbsCertificate.Extensions; if (exts != null) { KeyUsage ku = KeyUsage.FromExtensions(exts); if (ku != null) { int bits = ku.GetBytes()[0] & 0xff; if ((bits & keyUsageBits) != keyUsageBits) return false; } } return true; } protected virtual bool SupportsRsa_Pkcs1() { AlgorithmIdentifier pubKeyAlgID = m_certificate.SubjectPublicKeyInfo.AlgorithmID; return RsaUtilities.SupportsPkcs1(pubKeyAlgID); } protected virtual bool SupportsRsa_Pss_Pss(short signatureAlgorithm) { AlgorithmIdentifier pubKeyAlgID = m_certificate.SubjectPublicKeyInfo.AlgorithmID; return RsaUtilities.SupportsPss_Pss(signatureAlgorithm, pubKeyAlgID); } protected virtual bool SupportsRsa_Pss_Rsae() { AlgorithmIdentifier pubKeyAlgID = m_certificate.SubjectPublicKeyInfo.AlgorithmID; return RsaUtilities.SupportsPss_Rsae(pubKeyAlgID); } /// [Obsolete] 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); } } }