#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR) #pragma warning disable using System; using System.IO; using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto; using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Agreement; using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Generators; using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters; using Best.HTTP.SecureProtocol.Org.BouncyCastle.Math; using Best.HTTP.SecureProtocol.Org.BouncyCastle.Utilities; namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Tls.Crypto.Impl.BC { /// BC light-weight support class for Diffie-Hellman key pair generation and key agreement over a /// specified Diffie-Hellman configuration. public class BcTlsDHDomain : TlsDHDomain { private static byte[] EncodeValue(DHParameters dh, bool padded, BigInteger x) { return padded ? BigIntegers.AsUnsignedByteArray(GetValueLength(dh), x) : BigIntegers.AsUnsignedByteArray(x); } private static int GetValueLength(DHParameters dh) { return BigIntegers.GetUnsignedByteLength(dh.P); } public static BcTlsSecret CalculateDHAgreement(BcTlsCrypto crypto, DHPrivateKeyParameters privateKey, DHPublicKeyParameters publicKey, bool padded) { DHBasicAgreement basicAgreement = new DHBasicAgreement(); basicAgreement.Init(privateKey); BigInteger agreementValue = basicAgreement.CalculateAgreement(publicKey); byte[] secret = EncodeValue(privateKey.Parameters, padded, agreementValue); return crypto.AdoptLocalSecret(secret); } public static DHParameters GetDomainParameters(TlsDHConfig dhConfig) { DHGroup dhGroup = TlsDHUtilities.GetDHGroup(dhConfig); if (dhGroup == null) throw new ArgumentException("No DH configuration provided"); return new DHParameters(dhGroup.P, dhGroup.G, dhGroup.Q, dhGroup.L); } protected readonly BcTlsCrypto m_crypto; protected readonly TlsDHConfig m_config; protected readonly DHParameters m_domainParameters; public BcTlsDHDomain(BcTlsCrypto crypto, TlsDHConfig dhConfig) { this.m_crypto = crypto; this.m_config = dhConfig; this.m_domainParameters = GetDomainParameters(dhConfig); } public virtual BcTlsSecret CalculateDHAgreement(DHPrivateKeyParameters privateKey, DHPublicKeyParameters publicKey) { return CalculateDHAgreement(m_crypto, privateKey, publicKey, m_config.IsPadded); } public virtual TlsAgreement CreateDH() { return new BcTlsDH(this); } /// public virtual BigInteger DecodeParameter(byte[] encoding) { if (m_config.IsPadded && GetValueLength(m_domainParameters) != encoding.Length) throw new TlsFatalAlert(AlertDescription.illegal_parameter); return new BigInteger(1, encoding); } /// public virtual DHPublicKeyParameters DecodePublicKey(byte[] encoding) { /* * RFC 7919 3. [..] the client MUST verify that dh_Ys is in the range 1 < dh_Ys < dh_p - 1. * If dh_Ys is not in this range, the client MUST terminate the connection with a fatal * handshake_failure(40) alert. */ try { BigInteger y = DecodeParameter(encoding); return new DHPublicKeyParameters(y, m_domainParameters); } catch (Exception e) { throw new TlsFatalAlert(AlertDescription.handshake_failure, e); } } public virtual byte[] EncodeParameter(BigInteger x) { return EncodeValue(m_domainParameters, m_config.IsPadded, x); } public virtual byte[] EncodePublicKey(DHPublicKeyParameters publicKey) { return EncodeValue(m_domainParameters, true, publicKey.Y); } public virtual AsymmetricCipherKeyPair GenerateKeyPair() { DHBasicKeyPairGenerator keyPairGenerator = new DHBasicKeyPairGenerator(); keyPairGenerator.Init(new DHKeyGenerationParameters(m_crypto.SecureRandom, m_domainParameters)); return keyPairGenerator.GenerateKeyPair(); } } } #pragma warning restore #endif