using Org.BouncyCastle.Security; using Org.BouncyCastle.Tls; using Org.BouncyCastle.Tls.Crypto; using Org.BouncyCastle.Tls.Crypto.Impl.BC; using System.Collections; using System.IO; using System.Linq; using System.Text; using BcTlsClient = Org.BouncyCastle.Tls.TlsClient; namespace Cryville.Common.Network { public class TlsClient { readonly TlsClientProtocol _protocol; readonly BcTlsClient _tlsClient; public Stream Stream { get; private set; } public TlsClient(Stream baseStream, string hostname) { _protocol = new TlsClientProtocol(baseStream); _tlsClient = new InternalTlsClient(hostname, new BcTlsCrypto(new SecureRandom())); } public void Connect() { _protocol.Connect(_tlsClient); Stream = _protocol.Stream; } public void Close() { _protocol.Close(); } private class InternalTlsClient : DefaultTlsClient { readonly string _host; public InternalTlsClient(string host, TlsCrypto crypto) : base(crypto) { _host = host; } protected override ProtocolVersion[] GetSupportedVersions() { return ProtocolVersion.TLSv13.DownTo(ProtocolVersion.TLSv12); } protected override IList GetProtocolNames() { IList list = new ArrayList { ProtocolName.Http_1_1 }; return list; } private static readonly int[] supportedCipherSuites = { CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_AES_256_GCM_SHA384, CipherSuite.TLS_CHACHA20_POLY1305_SHA256, CipherSuite.TLS_AES_128_CCM_SHA256, CipherSuite.TLS_AES_128_CCM_8_SHA256, }; protected override int[] GetSupportedCipherSuites() { return base.GetSupportedCipherSuites().Union(supportedCipherSuites).ToArray(); } protected override IList GetSupportedSignatureAlgorithms() { var result = base.GetSupportedSignatureAlgorithms(); result.Add(SignatureAndHashAlgorithm.ecdsa_brainpoolP256r1tls13_sha256); result.Add(SignatureAndHashAlgorithm.ecdsa_brainpoolP384r1tls13_sha384); result.Add(SignatureAndHashAlgorithm.ecdsa_brainpoolP512r1tls13_sha512); return result; } protected override IList GetSniServerNames() { return new ArrayList { new ServerName(0, Encoding.ASCII.GetBytes(_host)) }; } public override TlsAuthentication GetAuthentication() { return new NullTlsAuthentication(); } public override void NotifyAlertReceived(short alertLevel, short alertDescription) { Logger.Log("main", 0, "Network/TLS", "TLS Alert {0} {1}", alertLevel, alertDescription); } public override void NotifyServerVersion(ProtocolVersion serverVersion) { base.NotifyServerVersion(serverVersion); Logger.Log("main", 0, "Network/TLS", "NotifyServerVersion {0}", serverVersion); } public override void NotifySelectedCipherSuite(int selectedCipherSuite) { base.NotifySelectedCipherSuite(selectedCipherSuite); Logger.Log("main", 0, "Network/TLS", "NotifySelectedCipherSuite {0}", selectedCipherSuite); } } private class NullTlsAuthentication : TlsAuthentication { public TlsCredentials GetClientCredentials(CertificateRequest certificateRequest) { return null; } public void NotifyServerCertificate(TlsServerCertificate serverCertificate) { } } } }