/// <summary>
        /// Update session key according to section 5.3.7 Session Key Updates.
        /// </summary>
        internal void UpdateSessionKey()
        {
            if (encryptionMethod == EncryptionMethods.ENCRYPTION_METHOD_40BIT ||
                encryptionMethod == EncryptionMethods.ENCRYPTION_METHOD_56BIT ||
                encryptionMethod == EncryptionMethods.ENCRYPTION_METHOD_128BIT)
            {
                currentClientEncryptKey = UpdateKey(initialClientEncryptKey,
                                                    currentClientEncryptKey,
                                                    encryptionMethod);

                currentClientDecryptKey = UpdateKey(initialClientDecryptKey,
                                                    currentClientDecryptKey,
                                                    encryptionMethod);

                currentServerEncryptKey = UpdateKey(initialServerEncryptKey,
                                                    currentServerEncryptKey,
                                                    encryptionMethod);

                currentServerDecryptKey = UpdateKey(initialServerDecryptKey,
                                                    currentServerDecryptKey,
                                                    encryptionMethod);

                RC4 rc4Enc = RC4.Create();
                rc4Encrypt       = rc4Enc.CreateEncryptor(currentClientEncryptKey, null);
                rc4EncryptServer = rc4Enc.CreateEncryptor(currentServerEncryptKey, null);

                RC4 rc4Dec = RC4.Create();
                rc4Decrypt       = rc4Dec.CreateDecryptor(currentClientDecryptKey, null);
                rc4DecryptServer = rc4Dec.CreateDecryptor(currentServerDecryptKey, null);
            }
            // else in other cases we don't need to update session key
        }
Example #2
0
        protected int TestEncryption()
        {
            int tests            = 0;
            RC4 rc4              = GetRC4Instance();
            ICryptoTransform enc = null;

            byte[] ret = null;
            // test TransformBlock
            for (int i = 0; i < keys.Length; i++)
            {
                try {
                    enc = rc4.CreateEncryptor(keys[i], null);
                } catch {
                    AddError("RC4-TE1");
                }
                try {
                    ret = new byte[inputs[i].Length];
                    enc.TransformBlock(inputs[i], 0, inputs[i].Length, ret, 0);
                } catch {
                    AddError("RC4-TE2");
                }
                if (!ArrayEquals(ret, outputs[i]))
                {
                    AddError("RC4-TE3");
                }
                if (enc != null)
                {
                    enc.Dispose();
                }
                tests += 3;
            }
            // test TransformFinalBlock
            for (int i = 0; i < keys.Length; i++)
            {
                try {
                    enc = rc4.CreateEncryptor(keys[i], null);
                } catch {
                    AddError("RC4-TE4");
                }
                try {
                    ret = enc.TransformFinalBlock(inputs[i], 0, inputs[i].Length);
                } catch {
                    AddError("RC4-TE5");
                }
                if (!ArrayEquals(ret, outputs[i]))
                {
                    AddError("RC4-TE6");
                }
                if (enc != null)
                {
                    enc.Dispose();
                }
                tests += 3;
            }
            return(tests);
        }
Example #3
0
        public void TestArgumentExceptions()
        {
            using (var rc4 = new RC4()) {
                var buffer = new byte[16];

                Assert.AreEqual(1, rc4.InputBlockSize, "InputBlockSize");
                Assert.AreEqual(1, rc4.OutputBlockSize, "OutputBlockSize");
                Assert.IsFalse(rc4.CanReuseTransform, "CanReuseTransform");
                Assert.IsTrue(rc4.CanTransformMultipleBlocks, "CanTransformMultipleBlocks");

                Assert.Throws <InvalidOperationException> (() => { var x = rc4.Key; });
                Assert.Throws <ArgumentNullException> (() => { rc4.Key = null; });
                Assert.Throws <ArgumentException> (() => { rc4.Key = new byte[0]; });

                rc4.GenerateIV();
                rc4.GenerateKey();
                rc4.CreateDecryptor();
                rc4.CreateEncryptor();

                // TransformBlock input buffer parameters
                Assert.Throws <ArgumentNullException> (() => rc4.TransformBlock(null, 0, buffer.Length, buffer, 0));
                Assert.Throws <ArgumentOutOfRangeException> (() => rc4.TransformBlock(buffer, -1, buffer.Length, buffer, 0));
                Assert.Throws <ArgumentOutOfRangeException> (() => rc4.TransformBlock(buffer, 0, -1, buffer, 0));

                // TransformBlock output buffer parameters
                Assert.Throws <ArgumentNullException> (() => rc4.TransformBlock(buffer, 0, buffer.Length, null, 0));
                Assert.Throws <ArgumentOutOfRangeException> (() => rc4.TransformBlock(buffer, 0, buffer.Length, buffer, -1));

                // TransformFinalBlock
                Assert.Throws <ArgumentNullException> (() => rc4.TransformFinalBlock(null, 0, buffer.Length));
                Assert.Throws <ArgumentOutOfRangeException> (() => rc4.TransformFinalBlock(buffer, -1, buffer.Length));
                Assert.Throws <ArgumentOutOfRangeException> (() => rc4.TransformFinalBlock(buffer, 0, -1));
            }
        }
        public static _LSAPR_TRUSTED_DOMAIN_AUTH_BLOB CreateTrustedDomainAuthorizedBlob(
            _LSAPR_AUTH_INFORMATION[] currentOutgoingAuthInfos,
            _LSAPR_AUTH_INFORMATION[] previousOutgoingAuthInfos,
            _LSAPR_AUTH_INFORMATION[] currentIncomingAuthInfos,
            _LSAPR_AUTH_INFORMATION[] previousIncomingAuthInfos,
            byte[] sessionKey)
        {
            _LSAPR_TRUSTED_DOMAIN_AUTH_BLOB retVal = new _LSAPR_TRUSTED_DOMAIN_AUTH_BLOB();
            LsaTrustedDomainAuthBlob        blob   = new LsaTrustedDomainAuthBlob();
            Random random = new Random();

            blob.randomData = new byte[BLOB_AUTH_RANDOM_LENGTH]; //leads with 512 bytes of random data
            random.NextBytes(blob.randomData);
            blob.CurrentOutgoingAuthInfos  = MarshalAuthInfos(currentOutgoingAuthInfos);
            blob.PreviousOutgoingAuthInfos = MarshalAuthInfos(previousOutgoingAuthInfos);
            blob.CurrentIncomingAuthInfos  = MarshalAuthInfos(currentIncomingAuthInfos);
            blob.PreviousIncomingAuthInfos = MarshalAuthInfos(previousIncomingAuthInfos);

            blob.CountOutgoingAuthInfos = (uint)(currentOutgoingAuthInfos == null ? 0 : currentOutgoingAuthInfos.Length);
            //blob.ByteOffsetCurrentOutgoingAuthInfo is the sum of sizeof CountOutgoingAuthInfos,
            //sizeof ByteOffsetCurrentOutgoingAuthInfo ,sizeof ByteOffsetCurrentOutgoingAuthInfo;
            blob.ByteOffsetCurrentOutgoingAuthInfo = (uint)(Marshal.SizeOf(blob.CountOutgoingAuthInfos) + Marshal.SizeOf(
                                                                blob.ByteOffsetCurrentOutgoingAuthInfo) + Marshal.SizeOf(blob.ByteOffsetPreviousOutgoingAuthInfo));
            blob.ByteOffsetPreviousOutgoingAuthInfo = (uint)(blob.ByteOffsetCurrentOutgoingAuthInfo
                                                             + blob.CurrentOutgoingAuthInfos.Length);
            blob.CountIncomingAuthInfos = (uint)(currentIncomingAuthInfos == null ? 0 : currentIncomingAuthInfos.Length);
            //same as blob.ByteOffsetCurrentOutgoingAuthInfo
            blob.ByteOffsetCurrentIncomingAuthInfo = (uint)(Marshal.SizeOf(blob.CountIncomingAuthInfos) + Marshal.SizeOf(
                                                                blob.ByteOffsetCurrentIncomingAuthInfo) + Marshal.SizeOf(blob.ByteOffsetPreviousIncomingAuthInfo));
            blob.ByteOffsetPreviousIncomingAuthInfo = (uint)(blob.ByteOffsetCurrentIncomingAuthInfo
                                                             + blob.CurrentIncomingAuthInfos.Length);
            blob.OutgoingAuthInfoSize = (uint)(blob.ByteOffsetPreviousOutgoingAuthInfo
                                               + blob.PreviousOutgoingAuthInfos.Length);
            blob.IncomingAuthInfoSize = (uint)(blob.ByteOffsetPreviousIncomingAuthInfo
                                               + blob.PreviousIncomingAuthInfos.Length);

            byte[] input = ArrayUtility.ConcatenateArrays(
                blob.randomData,
                TypeMarshal.ToBytes(blob.CountOutgoingAuthInfos),
                TypeMarshal.ToBytes(blob.ByteOffsetCurrentOutgoingAuthInfo),
                TypeMarshal.ToBytes(blob.ByteOffsetPreviousOutgoingAuthInfo),
                blob.CurrentOutgoingAuthInfos,
                blob.PreviousOutgoingAuthInfos,
                TypeMarshal.ToBytes(blob.CountIncomingAuthInfos),
                TypeMarshal.ToBytes(blob.ByteOffsetCurrentIncomingAuthInfo),
                TypeMarshal.ToBytes(blob.ByteOffsetPreviousIncomingAuthInfo),
                blob.CurrentIncomingAuthInfos,
                blob.PreviousIncomingAuthInfos,
                TypeMarshal.ToBytes(blob.OutgoingAuthInfoSize),
                TypeMarshal.ToBytes(blob.IncomingAuthInfoSize));

            using (RC4 rc4 = RC4.Create())
            {
                rc4.Key         = sessionKey;
                retVal.AuthBlob = rc4.CreateEncryptor().TransformFinalBlock(input, 0, input.Length);
            }
            retVal.AuthSize = (uint)(retVal.AuthBlob.Length);

            return(retVal);
        }
        /// <summary>
        /// Encrypts input data with RC4
        /// </summary>
        /// <param name="input">The input data to be encrypted</param>
        /// <param name="inputOffset">Offset of input from which the data will be encrypted </param>
        /// <param name="inputLength">Length of data to be encrypted</param>
        /// <param name="key">The encryption key</param>
        private static byte[] RC4Encrypt(byte[] input, int inputOffset, int inputLength, byte[] key)
        {
            RC4 rc4 = RC4.Create();
            ICryptoTransform crypto = rc4.CreateEncryptor(key, null);

            byte[] output = crypto.TransformFinalBlock(input, inputOffset, inputLength);

            return(output);
        }
        /// <summary>
        /// RC4 is used to encrypt and decrypt data according to [MS-RDPELE] 5.1.3 & 5.1.4
        /// </summary>
        private byte[] RC4(byte[] input)
        {
            RC4 rc4Enc = Microsoft.Protocols.TestTools.StackSdk.Security.Cryptographic.RC4.Create();
            ICryptoTransform rc4Encrypt = rc4Enc.CreateEncryptor(licensingEncryptionKey, null);

            byte[] output = new byte[input.Length];
            rc4Encrypt.TransformBlock(input, 0, input.Length, output, 0);
            return(output);
        }
Example #7
0
        public override void Init(int mode, Key keyspec)
        {
            SecretKeySpec key = (SecretKeySpec)keyspec;

            if (mode == Cipher.ENCRYPT_MODE)
            {
                transformer = rc4.CreateEncryptor(key.Key, new byte[0]);
            }
            else
            {
                transformer = rc4.CreateDecryptor(key.Key, new byte[0]);
            }
        }
        /// <summary>
        /// Update session key for Non-FIPS according to section 5.3.7 Session Key Updates.
        /// </summary>
        /// <param name="initialKey">The initial session key.</param>
        /// <param name="currentKey">The current session key.</param>
        /// <param name="encryptionMethod">The current encryption method.</param>
        /// <returns>The new session key.</returns>
        private static byte[] UpdateKey(byte[] initialKey, byte[] currentKey, EncryptionMethods encryptionMethod)
        {
            byte[] pad1   = ConstValue.NON_FIPS_PAD1;
            byte[] pad2   = ConstValue.NON_FIPS_PAD2;
            byte[] newKey = null;

            // SHAComponent = SHA(InitialEncryptKey + Pad1 + CurrentEncryptKey)
            byte[] shaComponentBuffer = RdpbcgrUtility.ConcatenateArrays(initialKey, pad1, currentKey);
            byte[] shaComponent       = ShaHash(shaComponentBuffer);

            // TempKey128 = MD5(InitialEncryptKey + Pad2 + SHAComponent)
            byte[] tempKey128Buffer = RdpbcgrUtility.ConcatenateArrays(initialKey, pad2, shaComponent);
            byte[] tempKey128       = MD5Hash(tempKey128Buffer);

            if (encryptionMethod == EncryptionMethods.ENCRYPTION_METHOD_128BIT)
            {
                // S-TableEncrypt = InitRC4(TempKey128)
                RC4 rc4 = RC4.Create();
                ICryptoTransform ict = rc4.CreateEncryptor(tempKey128, null);

                // NewEncryptKey128 = RC4(TempKey128, S-TableEncrypt)
                newKey = ict.TransformFinalBlock(tempKey128, 0, tempKey128.Length);
            }
            else if (encryptionMethod == EncryptionMethods.ENCRYPTION_METHOD_40BIT ||
                     encryptionMethod == EncryptionMethods.ENCRYPTION_METHOD_56BIT)
            {
                // TempKey64 = First64Bits(TempKey128)
                byte[] tempKey64 = GetFirstNBits(64, tempKey128);

                // S-TableEncrypt = InitRC4(TempKey64)
                RC4 rc4 = RC4.Create();
                ICryptoTransform ict = rc4.CreateEncryptor(tempKey64, null);

                // PreSaltKey = RC4(TempKey64, S-TableEncrypt)
                byte[] preSaltKey = ict.TransformFinalBlock(tempKey64, 0, tempKey64.Length);

                if (encryptionMethod == EncryptionMethods.ENCRYPTION_METHOD_40BIT)
                {
                    // NewEncryptKey40 = 0xD1269E + Last40Bits(PreSaltKey)
                    newKey = RdpbcgrUtility.ConcatenateArrays(ConstValue.NON_FIPS_SALT_40BIT, GetLastNBits(40, preSaltKey));
                }
                else
                {
                    // NewEncryptKey56 = 0xD1 + Last56Bits(PreSaltKey)
                    newKey = RdpbcgrUtility.ConcatenateArrays(ConstValue.NON_FIPS_SALT_56BIT, GetLastNBits(56, preSaltKey));
                }
            }
            // else do nothing

            return(newKey);
        }
Example #9
0
    // =========================加密相关===================================
    // 加密通讯
    public void Encrypt(Int32 send_seed, Int32 receive_seed)
    {
        Byte[] _send = BitConverter.GetBytes(send_seed);
        if (BitConverter.IsLittleEndian)
        {
            Array.Reverse(_send);
        }
        Byte[] _recv = BitConverter.GetBytes(receive_seed);
        if (BitConverter.IsLittleEndian)
        {
            Array.Reverse(_recv);
        }
        string key1;
        string key2;

        Byte[]     _key1 = dhEnc.DecryptKeyExchange(_send);
        BigInteger bi1   = new BigInteger(_key1);

        key1 = Config.SALT + bi1.ToString();

        Byte[]     _key2 = dhDec.DecryptKeyExchange(_recv);
        BigInteger bi2   = new BigInteger(_key2);

        key2 = Config.SALT + bi2.ToString();

        RC4 rc4enc = RC4.Create();
        RC4 rc4dec = RC4.Create();

        Byte[] seed1 = Encoding.ASCII.GetBytes(key1);
        Byte[] seed2 = Encoding.ASCII.GetBytes(key2);

        // en/decryptor不为null时自动启动加密

        // Get an encryptor.
        encryptor = rc4enc.CreateEncryptor(seed1, null);
        // Get a decryptor.
        decryptor = rc4dec.CreateDecryptor(seed2, null);
    }
        public void Save(string filename, string password)
        {
            if (filename == null)
            {
                throw new ArgumentNullException("filename");
            }

            byte[]     blob = null;
            FileStream fs   = File.Open(filename, FileMode.Create, FileAccess.Write);

            try
            {
                // header
                byte[] empty = new byte [4];
                byte[] data  = BitConverterLE.GetBytes(magic);
                fs.Write(data, 0, 4);   // magic
                fs.Write(empty, 0, 4);  // reserved
                data = BitConverterLE.GetBytes(keyType);
                fs.Write(data, 0, 4);   // key type

                encrypted = (password != null);
                blob      = CryptoConvert.ToCapiPrivateKeyBlob(rsa);
                if (encrypted)
                {
                    data = BitConverterLE.GetBytes(1);
                    fs.Write(data, 0, 4); // encrypted
                    data = BitConverterLE.GetBytes(16);
                    fs.Write(data, 0, 4); // saltlen
                    data = BitConverterLE.GetBytes(blob.Length);
                    fs.Write(data, 0, 4); // keylen

                    byte[] salt = new byte [16];
                    RC4    rc4  = RC4.Create();
                    byte[] key  = null;
                    try
                    {
                        // generate new salt (16 bytes)
                        RandomNumberGenerator rng = RandomNumberGenerator.Create();
                        rng.GetBytes(salt);
                        fs.Write(salt, 0, salt.Length);
                        key = DeriveKey(salt, password);
                        if (Weak)
                        {
                            Array.Clear(key, 5, 11);
                        }
                        ICryptoTransform enc = rc4.CreateEncryptor(key, null);
                        // we don't encrypt the header part of the BLOB
                        enc.TransformBlock(blob, 8, blob.Length - 8, blob, 8);
                    }
                    finally
                    {
                        Array.Clear(salt, 0, salt.Length);
                        Array.Clear(key, 0, key.Length);
                        rc4.Clear();
                    }
                }
                else
                {
                    fs.Write(empty, 0, 4); // encrypted
                    fs.Write(empty, 0, 4); // saltlen
                    data = BitConverterLE.GetBytes(blob.Length);
                    fs.Write(data, 0, 4);  // keylen
                }

                fs.Write(blob, 0, blob.Length);
            }
            finally
            {
                // BLOB may include an uncrypted keypair
                Array.Clear(blob, 0, blob.Length);
                fs.Close();
            }
        }
Example #11
0
        public void Save(string filename, string password)
        {
            if (filename == null)
            {
                throw new ArgumentNullException(nameof(filename));
            }
            byte[]     numArray1  = (byte[])null;
            FileStream fileStream = File.Open(filename, FileMode.Create, FileAccess.Write);

            try
            {
                byte[] buffer = new byte[4];
                byte[] bytes1 = BitConverterLE.GetBytes(2964713758U);
                fileStream.Write(bytes1, 0, 4);
                fileStream.Write(buffer, 0, 4);
                byte[] bytes2 = BitConverterLE.GetBytes(this.keyType);
                fileStream.Write(bytes2, 0, 4);
                this.encrypted = password != null;
                numArray1      = CryptoConvert.ToCapiPrivateKeyBlob(this.rsa);
                if (this.encrypted)
                {
                    byte[] bytes3 = BitConverterLE.GetBytes(1);
                    fileStream.Write(bytes3, 0, 4);
                    byte[] bytes4 = BitConverterLE.GetBytes(16);
                    fileStream.Write(bytes4, 0, 4);
                    byte[] bytes5 = BitConverterLE.GetBytes(numArray1.Length);
                    fileStream.Write(bytes5, 0, 4);
                    byte[] numArray2 = new byte[16];
                    RC4    rc4       = RC4.Create();
                    byte[] rgbKey    = (byte[])null;
                    try
                    {
                        RandomNumberGenerator.Create().GetBytes(numArray2);
                        fileStream.Write(numArray2, 0, numArray2.Length);
                        rgbKey = this.DeriveKey(numArray2, password);
                        if (this.Weak)
                        {
                            Array.Clear((Array)rgbKey, 5, 11);
                        }
                        rc4.CreateEncryptor(rgbKey, (byte[])null).TransformBlock(numArray1, 8, numArray1.Length - 8, numArray1, 8);
                    }
                    finally
                    {
                        Array.Clear((Array)numArray2, 0, numArray2.Length);
                        Array.Clear((Array)rgbKey, 0, rgbKey.Length);
                        rc4.Clear();
                    }
                }
                else
                {
                    fileStream.Write(buffer, 0, 4);
                    fileStream.Write(buffer, 0, 4);
                    byte[] bytes3 = BitConverterLE.GetBytes(numArray1.Length);
                    fileStream.Write(bytes3, 0, 4);
                }
                fileStream.Write(numArray1, 0, numArray1.Length);
            }
            finally
            {
                Array.Clear((Array)numArray1, 0, numArray1.Length);
                fileStream.Close();
            }
        }
Example #12
0
        public void Save(string filename, string password)
        {
            if (filename == null)
            {
                throw new ArgumentNullException("filename");
            }
            byte[]     array      = null;
            FileStream fileStream = File.Open(filename, FileMode.Create, FileAccess.Write);

            try
            {
                byte[] array2 = new byte[4];
                byte[] bytes  = BitConverterLE.GetBytes(2964713758u);
                fileStream.Write(bytes, 0, 4);
                fileStream.Write(array2, 0, 4);
                bytes = BitConverterLE.GetBytes(this.keyType);
                fileStream.Write(bytes, 0, 4);
                this.encrypted = (password != null);
                array          = CryptoConvert.ToCapiPrivateKeyBlob(this.rsa);
                if (this.encrypted)
                {
                    bytes = BitConverterLE.GetBytes(1);
                    fileStream.Write(bytes, 0, 4);
                    bytes = BitConverterLE.GetBytes(16);
                    fileStream.Write(bytes, 0, 4);
                    bytes = BitConverterLE.GetBytes(array.Length);
                    fileStream.Write(bytes, 0, 4);
                    byte[] array3 = new byte[16];
                    RC4    rc     = RC4.Create();
                    byte[] array4 = null;
                    try
                    {
                        RandomNumberGenerator randomNumberGenerator = RandomNumberGenerator.Create();
                        randomNumberGenerator.GetBytes(array3);
                        fileStream.Write(array3, 0, array3.Length);
                        array4 = this.DeriveKey(array3, password);
                        if (this.Weak)
                        {
                            Array.Clear(array4, 5, 11);
                        }
                        ICryptoTransform cryptoTransform = rc.CreateEncryptor(array4, null);
                        cryptoTransform.TransformBlock(array, 8, array.Length - 8, array, 8);
                    }
                    finally
                    {
                        Array.Clear(array3, 0, array3.Length);
                        Array.Clear(array4, 0, array4.Length);
                        rc.Clear();
                    }
                }
                else
                {
                    fileStream.Write(array2, 0, 4);
                    fileStream.Write(array2, 0, 4);
                    bytes = BitConverterLE.GetBytes(array.Length);
                    fileStream.Write(bytes, 0, 4);
                }
                fileStream.Write(array, 0, array.Length);
            }
            finally
            {
                Array.Clear(array, 0, array.Length);
                fileStream.Close();
            }
        }
Example #13
0
        static void Main(string[] args)
        {
            // Put in the "Debug" folder of this Project "source.txt" file for debugging...
            byte[] key   = Encoding.ASCII.GetBytes("SecREt01pAssW0rd");
            string path1 = @"source.txt";
            string path2 = @"encoded.txt";
            string path3 = @"decoded.txt";

            // Example without reuse Encryptor (ICryptoTransform).
            // Allows you to get the same results every time you encrypt the same file.
            // To decrypt the result, you need to apply the algorithm again.
            byte[][] encoded1;
            using (RC4 rc4 = RC4.Create())
            {
                encoded1 = new byte[3][];
                for (int i = 0; i < 3; i++)
                {
                    using (var source = new FileStream(path1, FileMode.Open, FileAccess.Read))
                        using (var crypto = new CryptoStream(source, rc4.CreateEncryptor(key, null), CryptoStreamMode.Read))
                            using (var target = new MemoryStream())
                            {
                                crypto.CopyTo(target);
                                encoded1[i] = target.ToArray();
                            }
                }
            }

            // Example with reuse Encryptor (ICryptoTransform).
            // Allows you to get different results when encrypting even the same file.
            // To decrypt each file, you need to re-apply the algorithm in the same order.
            byte[][] encoded2;
            using (RC4 rc4 = RC4.Create())
            {
                ICryptoTransform encryptor = rc4.CreateEncryptor(key, null);
                encoded2 = new byte[3][];
                for (int i = 0; i < 3; i++)
                {
                    using (var source = new FileStream(path1, FileMode.Open, FileAccess.Read))
                        using (var crypto = new CryptoStream(source, encryptor, CryptoStreamMode.Read))
                            using (var target = new MemoryStream())
                            {
                                crypto.CopyTo(target);
                                encoded2[i] = target.ToArray();
                            }
                }
            }

            // All sorts of templates for encryption/decryption.

            // Encryption path1 to path2
            EncoderWrite(key, path1, path2);
            Console.WriteLine($"The contents of file {path1} is encrypted in file {path2}.");
            Console.WriteLine("Press any key...");
            Console.ReadLine();
            // Decryption path2 to path3
            EncoderWrite(key, path2, path3);
            Console.WriteLine($"The contents of file {path2} is decrypted in file {path3}.");
            Console.WriteLine("Press any key...");
            Console.ReadLine();
            // Encryption path3
            EncoderWrite(key, path3);
            Console.WriteLine($"The contents of file {path3} is encrypted.");
            Console.WriteLine("Press any key...");
            Console.ReadLine();
            // Decryption path3
            EncoderWrite(key, path3);
            Console.WriteLine($"The contents of file {path3} is decrypted.");
            Console.WriteLine("Press any key...");
            Console.ReadLine();
            // Encryption path1 to buffer
            byte[] buffer = EncoderRead(key, path1);
            Console.WriteLine($"The contents of file {path1} is encrypted in the buffer.");
            Console.WriteLine("Press any key...");
            Console.ReadLine();
            // Decryption buffer
            EncoderWrite(key, buffer);
            Console.WriteLine($"The contents of buffer is decrypted.");
            Console.WriteLine("Press any key...");
            Console.ReadLine();
            // Encryption buffer to buffer2
            byte[] buffer2 = new byte[123];
            EncoderWrite(key, buffer, out buffer2);
            Console.WriteLine($"The contents of buffer is encrypted in the buffer2.");
            Console.WriteLine("Press any key...");
            Console.ReadLine();
            // Decryption buffer2 to path3
            EncoderWrite(key, buffer2, path3);
            Console.WriteLine($"The contents of buffer2 is decrypted in file {path3}.");
            Console.WriteLine("Press any key...");
            Console.ReadLine();
        }
        internal void GenerateSessionKey(byte[] clientRandom, byte[] serverRandom)
        {
            if (encryptionMethod == EncryptionMethods.ENCRYPTION_METHOD_40BIT ||
                encryptionMethod == EncryptionMethods.ENCRYPTION_METHOD_56BIT ||
                encryptionMethod == EncryptionMethods.ENCRYPTION_METHOD_128BIT)
            {
                byte[] mackey       = null;
                byte[] clientEncKey = null;
                byte[] clientDecKey = null;

                GenerateNonFIPSSessionKey(clientRandom, serverRandom, out mackey, out clientEncKey, out clientDecKey);
                if (encryptionMethod == EncryptionMethods.ENCRYPTION_METHOD_40BIT)
                {
                    // MACKey40 = 0xD1269E + Last40Bits(First64Bits(MACKey128))
                    byte[] salt  = ConstValue.NON_FIPS_SALT_40BIT;
                    byte[] first = GetFirstNBits(64, mackey);
                    byte[] last  = GetLastNBits(40, first);
                    macKey = RdpbcgrUtility.ConcatenateArrays(salt, last);

                    // InitialClientEncryptKey40 = 0xD1269E + Last40Bits(First64Bits(InitialClientEncryptKey128))
                    first = GetFirstNBits(64, clientEncKey);
                    last  = GetLastNBits(40, first);
                    currentClientEncryptKey = RdpbcgrUtility.ConcatenateArrays(salt, last);
                    currentServerDecryptKey = RdpbcgrUtility.ConcatenateArrays(salt, last);

                    // InitialClientDecryptKey40 = 0xD1269E + Last40Bits(First64Bits(InitialClientDecryptKey128))
                    first = GetFirstNBits(64, clientDecKey);
                    last  = GetLastNBits(40, first);
                    currentClientDecryptKey = RdpbcgrUtility.ConcatenateArrays(salt, last);
                    currentServerEncryptKey = RdpbcgrUtility.ConcatenateArrays(salt, last);
                }
                else if (encryptionMethod == EncryptionMethods.ENCRYPTION_METHOD_56BIT)
                {
                    // MACKey56 = 0xD1 + Last56Bits(First64Bits(MACKey128))
                    byte[] salt  = ConstValue.NON_FIPS_SALT_56BIT;
                    byte[] first = GetFirstNBits(64, mackey);
                    byte[] last  = GetLastNBits(56, first);
                    macKey = RdpbcgrUtility.ConcatenateArrays(salt, last);

                    // InitialClientEncryptKey56 = 0xD1 + Last56Bits(First64Bits(InitialClientEncryptKey128))
                    first = GetFirstNBits(64, clientEncKey);
                    last  = GetLastNBits(56, first);
                    currentClientEncryptKey = RdpbcgrUtility.ConcatenateArrays(salt, last);
                    currentServerDecryptKey = RdpbcgrUtility.ConcatenateArrays(salt, last);

                    // InitialClientDecryptKey56 = 0xD1 + Last56Bits(First64Bits(InitialClientDecryptKey128))
                    first = GetFirstNBits(64, clientDecKey);
                    last  = GetLastNBits(56, first);
                    currentClientDecryptKey = RdpbcgrUtility.ConcatenateArrays(salt, last);
                    currentServerEncryptKey = RdpbcgrUtility.ConcatenateArrays(salt, last);
                }
                else // encryptionMethod == EncryptionMethods.ENCRYPTION_METHOD_128BIT
                {
                    macKey = mackey;
                    currentClientEncryptKey = clientEncKey;
                    currentServerDecryptKey = clientEncKey;
                    currentClientDecryptKey = clientDecKey;
                    currentServerEncryptKey = clientDecKey;
                }

                initialClientDecryptKey = currentClientDecryptKey;
                initialClientEncryptKey = currentClientEncryptKey;
                initialServerEncryptKey = currentServerEncryptKey;
                initialServerDecryptKey = currentServerDecryptKey;
                RC4 rc4Enc = RC4.Create();
                rc4Encrypt       = rc4Enc.CreateEncryptor(currentClientEncryptKey, null);
                rc4EncryptServer = rc4Enc.CreateEncryptor(currentServerEncryptKey, null);
                RC4 rc4Dec = RC4.Create();
                rc4Decrypt       = rc4Dec.CreateDecryptor(currentClientDecryptKey, null);
                rc4DecryptServer = rc4Dec.CreateDecryptor(currentServerDecryptKey, null);
            }
            else if (encryptionMethod == EncryptionMethods.ENCRYPTION_METHOD_FIPS)
            {
                GenerateFIPSSessionKey(clientRandom, serverRandom, out macKey,
                                       out currentClientEncryptKey, out currentClientDecryptKey,
                                       out currentServerEncryptKey, out currentServerDecryptKey);
                initialClientDecryptKey = currentClientDecryptKey;
                initialClientEncryptKey = currentClientEncryptKey;
                initialServerDecryptKey = currentServerDecryptKey;
                initialServerEncryptKey = currentServerEncryptKey;

                // suppress "CA5353:TripleDESCannotBeUsed" message, since TripleDES is used according protocol definition in MS-RDPBCGR
                desEncrypt      = new TripleDESCryptoServiceProvider();
                desEncrypt.IV   = ConstValue.TRPLE_DES_IV;
                desEncrypt.Key  = currentClientEncryptKey;
                desEncrypt.Mode = CipherMode.CBC;

                desDecrypt      = new TripleDESCryptoServiceProvider();
                desDecrypt.IV   = ConstValue.TRPLE_DES_IV;
                desDecrypt.Key  = currentClientDecryptKey;
                desDecrypt.Mode = CipherMode.CBC;

                desEncryptServer      = new TripleDESCryptoServiceProvider();
                desEncryptServer.IV   = ConstValue.TRPLE_DES_IV;
                desEncryptServer.Key  = currentServerEncryptKey;
                desEncryptServer.Mode = CipherMode.CBC;

                desDecryptServer      = new TripleDESCryptoServiceProvider();
                desDecryptServer.IV   = ConstValue.TRPLE_DES_IV;
                desDecryptServer.Key  = currentServerDecryptKey;
                desDecryptServer.Mode = CipherMode.CBC;
            }
            else  // the encryption method is ENCRYPTION_METHOD_NONE or error
            {
                macKey = null;
                initialClientEncryptKey = null;
                initialClientDecryptKey = null;
                currentClientEncryptKey = null;
                currentClientDecryptKey = null;
                initialServerEncryptKey = null;
                initialServerDecryptKey = null;
                currentServerEncryptKey = null;
                currentServerDecryptKey = null;
                rc4Encrypt       = null;
                rc4Decrypt       = null;
                rc4EncryptServer = null;
                rc4DecryptServer = null;
                desEncrypt       = null;
                desDecrypt       = null;
                desEncryptServer = null;
                desDecryptServer = null;
            }

            // the cumulative encryption/decryption count
            // indicating how many encryptions/decryptions have been carried out.
            encryptionCount = 0;  // the first encryption start with 0
            decryptionCount = -1; // after the first decryption, decryptionCount++ up to 0
        }