public bool IsSignatureValid(SecureChannelHandshakeKeyExchange keyExchange, SecureChannelHandshakeHello serverHello, SecureChannelHandshakeHello clientHello)
        {
            if (!SecureChannelStream.IsUserIdValid(_publicKey, _userId))
            {
                return(false);
            }

            switch (serverHello.SupportedCiphers)
            {
            case SecureChannelCipherSuite.DHE2048_RSA2048_WITH_AES256_CBC_HMAC_SHA256:
                using (RSA rsa = RSA.Create())
                {
                    RSAParameters rsaPublicKey = DEREncoding.DecodeRSAPublicKey(_publicKey);
                    rsa.ImportParameters(rsaPublicKey);

                    if (rsa.KeySize != 2048)
                    {
                        throw new SecureChannelException(SecureChannelCode.PeerAuthenticationFailed, null, _userId, "RSA key size is not valid for selected crypto option: " + serverHello.SupportedCiphers.ToString());
                    }

                    using (MemoryStream mS = new MemoryStream())
                    {
                        mS.Write(keyExchange.EphemeralPublicKey, 0, keyExchange.EphemeralPublicKey.Length);
                        mS.Write(serverHello.Nonce.Value, 0, serverHello.Nonce.Value.Length);
                        mS.Write(clientHello.Nonce.Value, 0, clientHello.Nonce.Value.Length);
                        mS.Position = 0;

                        return(rsa.VerifyData(mS, _signature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1));
                    }
                }

            default:
                throw new SecureChannelException(SecureChannelCode.NoMatchingCipherAvailable, null, null);
            }
        }
        public SecureChannelHandshakeAuthentication(SecureChannelHandshakeKeyExchange keyExchange, SecureChannelHandshakeHello serverHello, SecureChannelHandshakeHello clientHello, BinaryNumber userId, byte[] privateKey)
            : base(SecureChannelCode.None)
        {
            _userId = userId;

            switch (serverHello.SupportedCiphers)
            {
            case SecureChannelCipherSuite.DHE2048_RSA2048_WITH_AES256_CBC_HMAC_SHA256:
            case SecureChannelCipherSuite.ECDHE256_RSA2048_WITH_AES256_CBC_HMAC_SHA256:
                using (RSA rsa = RSA.Create())
                {
                    RSAParameters rsaPrivateKey = DEREncoding.DecodeRSAPrivateKey(privateKey);
                    rsa.ImportParameters(rsaPrivateKey);

                    if (rsa.KeySize != 2048)
                    {
                        throw new SecureChannelException(SecureChannelCode.PeerAuthenticationFailed, null, _userId, "RSA key size is not valid for selected crypto option: " + serverHello.SupportedCiphers.ToString());
                    }

                    _publicKey = DEREncoding.EncodeRSAPublicKey(rsaPrivateKey);

                    if (!SecureChannelStream.IsUserIdValid(_publicKey, _userId))
                    {
                        throw new SecureChannelException(SecureChannelCode.PeerAuthenticationFailed, null, _userId, "UserId does not match with public key.");
                    }

                    using (MemoryStream mS = new MemoryStream())
                    {
                        mS.Write(keyExchange.EphemeralPublicKey);
                        mS.Write(serverHello.Nonce.Value);
                        mS.Write(clientHello.Nonce.Value);
                        mS.Position = 0;

                        _signature = rsa.SignData(mS, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
                    }
                }
                break;

            default:
                throw new SecureChannelException(SecureChannelCode.NoMatchingCipherAvailable, null, null);
            }
        }