/// <summary> /// Create a RC4 decryptor /// </summary> /// <param name="key">the key</param> /// <returns>the RC4 decryptor</returns> internal static ICryptoTransform CreateRc4Decryptor(byte[] key) { // check input if (null == key) { throw new ArgumentNullException("key"); } // CryptoLib RC4 needs no initial vector RC4CryptoServiceProvider rc4 = new RC4CryptoServiceProvider(); return(rc4.CreateDecryptor(key, null)); }
/// <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) { RC4CryptoServiceProvider rc4 = new RC4CryptoServiceProvider(); ICryptoTransform crypto = rc4.CreateEncryptor(key, null); byte[] output = crypto.TransformFinalBlock(input, inputOffset, inputLength); return output; }
/// <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); RC4CryptoServiceProvider rc4Enc = new RC4CryptoServiceProvider(); rc4Encrypt = rc4Enc.CreateEncryptor(currentClientEncryptKey, null); rc4EncryptServer = rc4Enc.CreateEncryptor(currentServerEncryptKey, null); RC4CryptoServiceProvider rc4Dec = new RC4CryptoServiceProvider(); rc4Decrypt = rc4Dec.CreateDecryptor(currentClientDecryptKey, null); rc4DecryptServer = rc4Dec.CreateDecryptor(currentServerDecryptKey, null); } // else in other cases we don't need to update session key }
/// <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) RC4CryptoServiceProvider rc4 = new RC4CryptoServiceProvider(); 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) RC4CryptoServiceProvider rc4 = new RC4CryptoServiceProvider(); 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; }
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; RC4CryptoServiceProvider rc4Enc = new RC4CryptoServiceProvider(); rc4Encrypt = rc4Enc.CreateEncryptor(currentClientEncryptKey, null); rc4EncryptServer = rc4Enc.CreateEncryptor(currentServerEncryptKey, null); RC4CryptoServiceProvider rc4Dec = new RC4CryptoServiceProvider(); 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 }