#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR) #pragma warning disable using System; using System.IO; using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto; using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Agreement; using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Generators; using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters; using BestHTTP.SecureProtocol.Org.BouncyCastle.Math; using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities; namespace BestHTTP.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 (dh.P.BitLength + 7) / 8; } 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 GetParameters(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 crypto; protected readonly TlsDHConfig dhConfig; protected readonly DHParameters dhParameters; public BcTlsDHDomain(BcTlsCrypto crypto, TlsDHConfig dhConfig) { this.crypto = crypto; this.dhConfig = dhConfig; this.dhParameters = GetParameters(dhConfig); } public virtual BcTlsSecret CalculateDHAgreement(DHPrivateKeyParameters privateKey, DHPublicKeyParameters publicKey) { return CalculateDHAgreement(crypto, privateKey, publicKey, dhConfig.IsPadded); } public virtual TlsAgreement CreateDH() { return new BcTlsDH(this); } /// public virtual BigInteger DecodeParameter(byte[] encoding) { if (dhConfig.IsPadded && GetValueLength(dhParameters) != 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, dhParameters); } catch (Exception e) { throw new TlsFatalAlert(AlertDescription.handshake_failure, e); } } /// public virtual byte[] EncodeParameter(BigInteger x) { return EncodeValue(dhParameters, dhConfig.IsPadded, x); } /// public virtual byte[] EncodePublicKey(DHPublicKeyParameters publicKey) { return EncodeValue(dhParameters, true, publicKey.Y); } public virtual AsymmetricCipherKeyPair GenerateKeyPair() { DHBasicKeyPairGenerator keyPairGenerator = new DHBasicKeyPairGenerator(); keyPairGenerator.Init(new DHKeyGenerationParameters(crypto.SecureRandom, dhParameters)); return keyPairGenerator.GenerateKeyPair(); } } } #pragma warning restore #endif