示例#1
0
        private Message PrepareAckForCommonKeyProposition(int propositionKeyChunkId)
        {
            var keyChunk = new BlockIdAndKeyAllocation(propositionKeyChunkId, CommonKeyStore.GetKeyAllocation());
            var mac      = MessageAuthenticator.GetMAC(keyChunk.GetBytes());

            return(new AddingKeyAck(mac, keyChunk));
        }
示例#2
0
        private Message PrepareMessageForNewKeyChunk(int lastSendKeyIndex)
        {
            var keyChunk = new BlockIdAndKeyAllocation(lastSendKeyIndex, CommonKeyStore.GetKeyAllocation());
            var mac      = MessageAuthenticator.GetMAC(keyChunk.GetBytes());

            return(new AddKey(mac, keyChunk));
        }
示例#3
0
 protected override Message ReceiveAuthenticatedMessage(AuthenticatedMessage message)
 {
     if (message is BlocksParityRequest)
     {
         var blockParityRequestMessage = message as BlocksParityRequest;
         var blocksPayload             = message.Payload as Blocks;
         for (int i = 0; i < blocksPayload.BlocksArray.Length; i++)
         {
             var block  = blocksPayload.BlocksArray[i];
             var parity = Cascade.Parity(DestilationBuffer.GetBits(block.Index, block.Length));
             blocksPayload.BlocksArray[i].Parity = parity;
         }
         var mac = MessageAuthenticator.GetMAC(blocksPayload.GetBytes());
         return(new BlocksParityResponse(mac, blocksPayload));
     }
     if (message is CheckParity)
     {
         var checkParityMessage  = message as CheckParity;
         var blockIdentification = checkParityMessage.Payload as BlockIdentifiaction;
         var parity  = Cascade.Parity(DestilationBuffer.GetBits(blockIdentification.Index, blockIdentification.Length));
         var payload = new ParityPayload(blockIdentification.Index, blockIdentification.Length, parity);
         var mac     = MessageAuthenticator.GetMAC(payload.GetBytes());
         return(new Parity(mac, payload));
     }
     if (message is RequestBits)
     {
         var requestBitsMessage  = message as RequestBits;
         var blockIdentification = requestBitsMessage.Payload as BlockIdentifiaction;
         var bytes   = DestilationBuffer.GetBytes(blockIdentification.Index, blockIdentification.Length);
         var payload = new BitsAsBytes(blockIdentification.Index, blockIdentification.Length, bytes);
         var mac     = MessageAuthenticator.GetMAC(payload.GetBytes());
         return(new Bytes(mac, payload, requestBitsMessage.Demand));
     }
     if (message is AddKey)
     {
         var addKeyMessage = message as AddKey;
         var messagPayload = (addKeyMessage.Payload as BlockIdAndKeyAllocation);
         if (messagPayload.BlockId == _currentKeyChunk + 1)
         {
             var key = LocalKeyStore.GetKey();
             CommonKeyStore.AddNewKey(key, messagPayload.KeyAllocation);
             _currentKeyChunk += 1;
             return(PrepareAckForCommonKeyProposition(_currentKeyChunk));
         }
         else
         {
             if (messagPayload.BlockId == _currentKeyChunk)
             {
                 return(PrepareAckForCommonKeyProposition(_currentKeyChunk));
             }
             else
             {
                 return(new NOP());
             }
         }
     }
     return(new NOP());
 }
示例#4
0
        /// <summary>
        /// TODO
        /// </summary>
        /// <param name="request"></param>
        /// <param name="password"></param>
        /// <param name="desiredKeyDerivationMilliseconds"></param>
        public void EncryptDataWithHeader(RequestStateRecord request, SecureString password,
                                          int desiredKeyDerivationMilliseconds)
        {
            if (request.Contract.InstanceKeyContract == null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            ((IProgress <int>) this._progress)?.Report(0);
            password.MakeReadOnly();


            var salt = new byte[request.Contract.InstanceKeyContract.Value.SaltLengthBytes];

            var iv  = new byte[request.Contract.TransformationContract.InitializationVectorSizeBytes];
            var rng = new RNGCryptoServiceProvider();

            try
            {
                rng.GetBytes(salt);
                rng.GetBytes(iv);
            }
            catch (CryptographicException exception)
            {
                FileStatics.WriteToLogFile(exception);
                MessageBox.Show(
                    "There was an error generating secure random numbers. Please try again - check log file for more details");
            }

            var performanceDerivative =
                new PerformanceDerivative(request.Contract.InstanceKeyContract.Value.PerformanceDerivative);


            ((IProgress <int>) this._progress)?.Report(25);

            // Get the password

            if (password.Length == 0)
            {
                MessageBox.Show("You must enter a password");

                ((IProgress <int>) this._progress)?.Report(0);
                return;
            }
#if TRACE
            if (password.Length < App.This.CurrentSettings.MinPasswordLength)
            {
                MessageBox.Show("Password too short");
                ((IProgress <int>)_progress)?.Report(0);
                return;
            }
#endif
            GCHandle byteHandle = SecureStringConverter.SecureStringToKeyDerive(password, salt,
                                                                                performanceDerivative, request.Contract.InstanceKeyContract.Value.KeyAlgorithm, out KeyDerive keyDevice);

            ((IProgress <int>) this._progress)?.Report(35);

            HMAC hmacAlg = null;

            if (request.Contract.HmacContract != null)
            {
                // Create the algorithm using reflection
                hmacAlg = (HMAC)Activator.CreateInstance(request.Contract.HmacContract.Value.HashAlgorithm);
            }

            Aes aesAlgorithm = new AesCng
            {
                BlockSize = (int)request.Contract.TransformationContract.BlockSize,
                KeySize   = (int)request.Contract.TransformationContract.KeySize,
                Mode      = request.Contract.TransformationContract.CipherMode,
                Padding   = request.Contract.TransformationContract.PaddingMode
            };

            var @params = new object[] { 1024 * 1024 * 1024, aesAlgorithm };

            var encryptor =
                (SymmetricCryptoManager)Activator.CreateInstance(request.Contract.TransformationContract.CryptoManager,
                                                                 @params);


            byte[] key = keyDevice.GetBytes((int)request.Contract.TransformationContract.KeySize / 8);

            Externals.ZeroMemory(byteHandle.AddrOfPinnedObject(), ((byte[])byteHandle.Target).Length);

            byteHandle.Free();

            // Create a handle to the key to allow control of it
            GCHandle keyHandle = GCHandle.Alloc(key, GCHandleType.Pinned);

            // Encrypt the data to a temporary file
            encryptor.EncryptFileBytes(this._filePath, App.This.DataTempFile, key, iv);

            ((IProgress <int>) this._progress)?.Report(90);


            byte[] hash = null;

            if (request.Contract.HmacContract != null)
            {
                // Create the signature derived from the encrypted data and key
                byte[] signature = MessageAuthenticator.CreateHmac(App.This.DataTempFile, key, hmacAlg);

                // Set the signature correctly in the CryptographicRepresentative object
                hash = signature;
            }

            HmacRepresentative?hmac = request.Contract.HmacContract.HasValue
                                        ? new HmacRepresentative(request.Contract.HmacContract.Value.HashAlgorithm, hash)
                                        : (HmacRepresentative?)null;

            KeyRepresentative?keyRepresentative = new KeyRepresentative
                                                  (
                request.Contract.InstanceKeyContract.Value.KeyAlgorithm,
                request.Contract.InstanceKeyContract.Value.PerformanceDerivative,
                salt
                                                  );

            // Delete the key from memory for security
            Externals.ZeroMemory(keyHandle.AddrOfPinnedObject(), key.Length);
            keyHandle.Free();

            var cryptographicInfo = new SymmetricCryptographicRepresentative
                                    (
                new TransformationRepresentative
                (
                    request.Contract.TransformationContract.CryptoManager,
                    iv,
                    request.Contract.TransformationContract.CipherMode,
                    request.Contract.TransformationContract.PaddingMode,
                    request.Contract.TransformationContract.KeySize,
                    request.Contract.TransformationContract.BlockSize
                ),
                keyRepresentative,
                hmac
                                    );

            // Write the CryptographicRepresentative object to a file
            cryptographicInfo.WriteHeaderToFile(this._filePath);

            ((IProgress <int>) this._progress)?.Report(98);
            FileStatics.AppendToFile(this._filePath, App.This.DataTempFile);

            ((IProgress <int>) this._progress)?.Report(100);
        }
示例#5
0
        ///  <summary>
        ///
        ///  </summary>
        ///  <param name="cryptographicRepresentative"></param>
        /// <param name="key"></param>
        /// TODO decompose
        public void DecryptDataWithHeader([NotNull] SymmetricCryptographicRepresentative cryptographicRepresentative, byte[] key)
        {
            ((IProgress <int>) this._progress)?.Report(0);

            ((IProgress <int>) this._progress)?.Report(10);

            HMAC hmacAlg = null;

            if (cryptographicRepresentative.HmacRepresentative != null)
            {
                hmacAlg = (HMAC)Activator.CreateInstance(cryptographicRepresentative.HmacRepresentative.Value.HashAlgorithm);
            }

            var @params = new object[]
            {
                1024 * 1024 * 8, new AesCng
                {
                    BlockSize = (int)cryptographicRepresentative.TransformationModeInfo.BlockSize,
                    KeySize   = (int)cryptographicRepresentative.TransformationModeInfo.KeySize,
                    Mode      = cryptographicRepresentative.TransformationModeInfo.CipherMode,
                    Padding   = cryptographicRepresentative.TransformationModeInfo.PaddingMode
                }
            };


            var decryptor = (SymmetricCryptoManager)Activator.CreateInstance(cryptographicRepresentative.TransformationModeInfo.CryptoManager, @params);

            FileStatics.RemovePrependData(this._filePath, App.This.HeaderLessTempFile, cryptographicRepresentative.HeaderLength);

            ((IProgress <int>) this._progress)?.Report(20);

            GCHandle keyHandle = GCHandle.Alloc(key, GCHandleType.Pinned);

            var isVerified = false;

            if (cryptographicRepresentative.HmacRepresentative != null)
            {
                // Check if the file and key make the same HMAC
                isVerified = MessageAuthenticator.VerifyHmac(App.This.HeaderLessTempFile, key,
                                                             cryptographicRepresentative.HmacRepresentative.Value.HashBytes, hmacAlg);
            }

            ((IProgress <int>) this._progress)?.Report(35);

            // If that didn't succeed, the file has been tampered with
            if (cryptographicRepresentative.HmacRepresentative != null && !isVerified)
            {
                throw new UnverifiableDataException("File could not be verified - may have been tampered, or the password is incorrect");
            }

            // Try decrypting the remaining data
            try
            {
                decryptor.DecryptFileBytes(App.This.HeaderLessTempFile, App.This.DataTempFile, key, cryptographicRepresentative.TransformationModeInfo.InitializationVector);

                ((IProgress <int>) this._progress)?.Report(75);

                // Move the file to the original file location
                File.Copy(App.This.DataTempFile, this._filePath, true);

                ((IProgress <int>) this._progress)?.Report(100);
            }
            finally
            {
                // Delete the key from memory for security
                Externals.ZeroMemory(keyHandle.AddrOfPinnedObject(), key.Length);
                keyHandle.Free();
            }
        }
示例#6
0
        ///  <summary>
        ///
        ///  </summary>
        ///  <param name="request"></param>
        /// <param name="key"></param>
        /// <param name="desiredKeyDerivationMilliseconds"></param>
        public void EncryptDataWithHeader(RequestStateRecord request, byte[] key,
                                          int desiredKeyDerivationMilliseconds)
        {
            ((IProgress <int>) this._progress)?.Report(0);

            var iv  = new byte[request.Contract.TransformationContract.InitializationVectorSizeBytes];
            var rng = new RNGCryptoServiceProvider();

            try
            {
                rng.GetBytes(iv);
            }
            catch (CryptographicException exception)
            {
                FileStatics.WriteToLogFile(exception);
                MessageBox.Show(
                    "There was an error generating secure random numbers. Please try again - check log file for more details");
            }

            ((IProgress <int>) this._progress)?.Report(25);

            HMAC hmacAlg = null;

            if (request.Contract.HmacContract != null)
            {
                // Create the algorithm using reflection
                hmacAlg = (HMAC)Activator.CreateInstance(request.Contract.HmacContract.Value.HashAlgorithm);
            }

            var @params = new object[] { 1024 * 1024 * 1024, new AesCryptoServiceProvider() };

            var encryptor =
                (SymmetricCryptoManager)Activator.CreateInstance(request.Contract.TransformationContract.CryptoManager,
                                                                 @params);

            // Create a handle to the key to allow control of it
            GCHandle keyHandle = GCHandle.Alloc(key, GCHandleType.Pinned);

            // Encrypt the data to a temporary file
            encryptor.EncryptFileBytes(this._filePath, App.This.DataTempFile, key, iv);

            ((IProgress <int>) this._progress)?.Report(90);


            byte[] hash = null;

            if (request.Contract.HmacContract != null)
            {
                // Create the signature derived from the encrypted data and key
                byte[] signature = MessageAuthenticator.CreateHmac(App.This.DataTempFile, key, hmacAlg);

                // Set the signature correctly in the CryptographicRepresentative object
                hash = signature;
            }

            HmacRepresentative?hmac = request.Contract.HmacContract != null && hash != null
                                        ? new HmacRepresentative(request.Contract.HmacContract.Value.HashAlgorithm, hash)
                                        : (HmacRepresentative?)null;

            // Delete the key from memory for security
            Externals.ZeroMemory(keyHandle.AddrOfPinnedObject(), key.Length);
            keyHandle.Free();

            var cryptographicInfo = new SymmetricCryptographicRepresentative
                                    (
                new TransformationRepresentative
                (
                    request.Contract.TransformationContract.CryptoManager,
                    iv,
                    request.Contract.TransformationContract.CipherMode,
                    request.Contract.TransformationContract.PaddingMode,
                    request.Contract.TransformationContract.KeySize,
                    request.Contract.TransformationContract.BlockSize
                ),
                null,
                hmac
                                    );

            // Write the CryptographicRepresentative object to a file
            cryptographicInfo.WriteHeaderToFile(this._filePath);

            ((IProgress <int>) this._progress)?.Report(98);

            FileStatics.AppendToFile(this._filePath, App.This.DataTempFile);

            ((IProgress <int>) this._progress)?.Report(100);
        }
示例#7
0
        public void MixedDataTest(byte[] testBytes, byte[] key)
        {
            byte[] hashedBytes = MessageAuthenticator.CreateHmac(testBytes, key);

            Assert.True(MessageAuthenticator.VerifyHmac(testBytes, key, hashedBytes));
        }
示例#8
0
        protected override Message ReceiveOfflineMessage(OfflineMessage message)
        {
            if (message is AmplifiePrivacy)
            {
                var privacyLevel = (message as AmplifiePrivacy).PrivacyLevel;

                DestilationBuffer.Permute(CommonKeyStore.ServiceKeyBuffer.GetKey().GetBytes());
                DestilationBuffer.ShiftedXOr(CommonKeyStore.ServiceKeyBuffer.GetKey().GetBytes());
                DestilationBuffer.Slice(1 - privacyLevel);
            }
            if (message is InitiateCascade)
            {
                var initMesssage           = message as InitiateCascade;
                var alpha                  = 0.6;
                var initialBlockSize       = (int)(alpha / DestilationBuffer.GetEstimatedQBER());
                var cascade                = new Cascade(this, initMesssage.Service, initMesssage.Bus);
                var properInitialBlockSize = initialBlockSize;
                int rem;
                int div           = Math.DivRem(DestilationBuffer.GetSize(), properInitialBlockSize, out rem);
                var initialBlocks = new List <Block>();
                for (int i = 0; i < div; i++)
                {
                    initialBlocks.Add(new Block()
                    {
                        Index = i * properInitialBlockSize, Length = properInitialBlockSize
                    });
                }
                if (rem != 0)
                {
                    initialBlocks.Add(new Block()
                    {
                        Index = properInitialBlockSize * div, Length = rem
                    });
                }
                cascade.CorrectErrors(initialBlocks);
            }
            if (message is MoreUndestiledBitsArrived)
            {
                var moreUndestiledBits = message as MoreUndestiledBitsArrived;
                DestilationBuffer.AddBytes(moreUndestiledBits.Bytes);
            }
            if (message is InitiateDestilation)
            {
                if (!DestilationBuffer.IsEmpty())
                {
                    return(new NOP());
                }
                throw new DestilationBufferIsEmptyExeption();
            }
            if (message is EstimateQBER)
            {
                var estimateQBERMessage = message as EstimateQBER;
                var payload             = new BlockIdentifiaction(estimateQBERMessage.Index, estimateQBERMessage.Length);
                var mac = MessageAuthenticator.GetMAC(payload.GetBytes());
                return(new RequestBits(mac, payload, Demand.Estimation));
            }
            if (message is MoreBitsArrived)
            {
                var moreBitArrivedMessage = message as MoreBitsArrived;
                foreach (var key in moreBitArrivedMessage.Keys)
                {
                    LocalKeyStore.AddKey(key);
                }
                return(new NOP());
            }
            if (message is Initiate)
            {
                if (!LocalKeyStore.IsEmpty())
                {
                    if (DoesLasReceivedAckCorrespondsToLastSentKeyIndex())
                    {
                        _lastSendKeyIndex += 1;
                        return(PrepareMessageForNewKeyChunk(_lastSendKeyIndex));
                    }
                    else
                    {
                        return(PrepareMessageForNewKeyChunk(_lastSendKeyIndex));
                    }
                }
            }
            if (message is GetOutBufferKey)
            {
                var getOutBufferKeyMessage = message as GetOutBufferKey;
                ApplicationKeyBuffer keyStore;
                CommonKeyStore.ApplicationKeyBuffers.TryGetValue(getOutBufferKeyMessage.Handle, out keyStore);
                if (keyStore != null)
                {
                    if (keyStore.GetLength() >= getOutBufferKeyMessage.Count)
                    {
                        return(new OutKey(keyStore.GetKey(getOutBufferKeyMessage.Count)));
                    }
                    else
                    {
                        return(new NOP());
                    }
                }
                else
                {
                    return(new NOP());
                }
            }
            if (message is OutKey)
            {
                Console.WriteLine((message as OutKey).Key.ToString());
                return(new NOP());
            }
            if (message is CreateKeyBuffer)
            {
                var createKeyBufferMessage = message as CreateKeyBuffer;
                CommonKeyStore.AddKeyBuffer(createKeyBufferMessage.Handle, createKeyBufferMessage.QualityOfService);
                return(new NOP());
            }
            if (message is CloseKeyBuffer)
            {
                var closeKeyBuffer = message as CloseKeyBuffer;
                CommonKeyStore.RemoveKeyBuffer(closeKeyBuffer.Handle);
                return(new NOP());
            }
            return(new NOP());
        }
        private void DecryptDataWithHeader(CryptographicInfo cryptographicInfo, SecureString password, string filePath)
        {
#if DEBUG
            Stopwatch watch = Stopwatch.StartNew();
#endif
            KeyDerive keyDevice;

#if DEBUG
            Console.WriteLine(Encryption_App.Resources.MainWindow_DecryptDataWithHeader_Start_time__ + watch.ElapsedMilliseconds);
#endif
            // Load the assemblies necessary for reflection
            Assembly securityAsm = Assembly.LoadFile(Path.Combine(RuntimeEnvironment.GetRuntimeDirectory(), "System.Security.dll"));
            Assembly coreAsm     = Assembly.LoadFile(Path.Combine(RuntimeEnvironment.GetRuntimeDirectory(), "System.Core.dll"));

#if DEBUG
            Console.WriteLine(Encryption_App.Resources.MainWindow_DecryptDataWithHeader_Assembly_loaded_time__ + watch.ElapsedMilliseconds);
#endif
            var performanceDerivative = new PerformanceDerivative(cryptographicInfo.InstanceKeyCreator.PerformanceDerivative);

            // Marshal the secure string to a managed string
            using (password)
            {
                // Turn the secure string into a string to pass it into keyDevice for the shortest interval possible
                IntPtr valuePtr = IntPtr.Zero;
                try
                {
                    valuePtr = Marshal.SecureStringToGlobalAllocUnicode(password);
                    // Create an object array of parameters
                    var parameters = new object[] { Marshal.PtrToStringUni(valuePtr), cryptographicInfo.InstanceKeyCreator.salt, null };

                    var tempTransformationDevice = (KeyDerive)Activator.CreateInstance(Type.GetType(cryptographicInfo.InstanceKeyCreator.root_HashAlgorithm)
                                                                                       ?? securityAsm.GetType(cryptographicInfo.InstanceKeyCreator.root_HashAlgorithm)
                                                                                       ?? coreAsm.GetType(cryptographicInfo.InstanceKeyCreator.root_HashAlgorithm));

                    tempTransformationDevice.TransformPerformance(performanceDerivative, 2000); // TODO put in crypto-info
                    parameters[2] = tempTransformationDevice.PerformanceValues;
                    keyDevice     = (KeyDerive)Activator.CreateInstance(Type.GetType(cryptographicInfo.InstanceKeyCreator.root_HashAlgorithm)
                                                                        ?? securityAsm.GetType(cryptographicInfo.InstanceKeyCreator.root_HashAlgorithm)
                                                                        ?? coreAsm.GetType(cryptographicInfo.InstanceKeyCreator.root_HashAlgorithm), parameters);
                }
                finally
                {
                    // Destroy the unmanaged string
                    Marshal.ZeroFreeGlobalAllocUnicode(valuePtr);
                }
            }

#if DEBUG
            Console.WriteLine(Encryption_App.Resources.MainWindow_DecryptDataWithHeader_Password_managed_time__ + watch.ElapsedMilliseconds);
#endif
            HMAC hmacAlg = null;

            if (cryptographicInfo.Hmac != null)
            {
                hmacAlg = (HMAC)Activator.CreateInstance(Type.GetType(cryptographicInfo.Hmac.HashAlgorithm)
                                                         ?? securityAsm.GetType(cryptographicInfo.Hmac.HashAlgorithm)
                                                         ?? coreAsm.GetType(cryptographicInfo.Hmac.HashAlgorithm));
            }

#if DEBUG
            Console.WriteLine(Encryption_App.Resources.MainWindow_DecryptDataWithHeader_Object_built_time__ + watch.ElapsedMilliseconds);
#endif

            var decryptor = (SymmetricCryptoManager)Activator.CreateInstance(Type.GetType(cryptographicInfo.CryptoManager)
                                                                             ?? securityAsm.GetType(cryptographicInfo.CryptoManager)
                                                                             ?? coreAsm.GetType(cryptographicInfo.CryptoManager));

#if DEBUG
            Console.WriteLine(Encryption_App.Resources.MainWindow_DecryptDataWithHeader_Object_built_time__ + watch.ElapsedMilliseconds);
#endif
            FileStatics.RemovePrependData(filePath, _headerLessTempFile, cryptographicInfo.HeaderLength);

#if DEBUG
            Console.WriteLine(Encryption_App.Resources.MainWindow_DecryptDataWithHeader_Header_removed_time__ + watch.ElapsedMilliseconds);
#endif
            byte[] key = keyDevice.GetBytes((int)cryptographicInfo.EncryptionModeInfo.KeySize / 8);

            GCHandle gch = GCHandle.Alloc(key, GCHandleType.Pinned);

            var isVerified = false;

            if (cryptographicInfo.Hmac != null)
            {
                // Check if the file and key make the same HMAC
                isVerified = MessageAuthenticator.VerifyHmac(_headerLessTempFile, key,
                                                             cryptographicInfo.Hmac.root_Hash, hmacAlg);
            }

#if DEBUG
            Console.WriteLine(Encryption_App.Resources.MainWindow_DecryptDataWithHeader_HMAC_verified_time__ + watch.ElapsedMilliseconds);
#endif

            // If that didn't succeed, the file has been tampered with
            if (cryptographicInfo.Hmac != null && !isVerified)
            {
                throw new CryptographicException("File could not be verified - may have been tampered, or the password is incorrect");
            }

            // Try decrypting the remaining data
            try
            {
#if DEBUG
                Console.WriteLine(Encryption_App.Resources.MainWindow_DecryptDataWithHeader_Pre_decryption_time__ + watch.ElapsedMilliseconds);
#endif
                decryptor.DecryptFileBytes(_headerLessTempFile, _dataTempFile, key, cryptographicInfo.EncryptionModeInfo.InitializationVector);

                StepDecryptStrings();
#if DEBUG
                Console.WriteLine(Encryption_App.Resources.MainWindow_DecryptDataWithHeader_Post_decryption_time__ + watch.ElapsedMilliseconds);
#endif
                // Move the file to the original file location
                File.Copy(_dataTempFile, filePath, true);

#if DEBUG
                Console.WriteLine(Encryption_App.Resources.MainWindow_DecryptDataWithHeader_File_copied_time__ + watch.ElapsedMilliseconds);
#endif
                MessageBox.Show("Successfully Decrypted");
            }
            catch (CryptographicException)
            {
                MessageBox.Show("Wrong password or corrupted file");
            }
            finally
            {
                // Delete the key from memory for security
                ZeroMemory(gch.AddrOfPinnedObject(), key.Length);
                gch.Free();
                GC.Collect();
            }
        }
        private void EncryptDataWithHeader(CryptographicInfo cryptographicInfo, SecureString password, string filePath)
        {
#if DEBUG
            Stopwatch watch = Stopwatch.StartNew();
#endif
            // Forward declaration of the device used to derive the key
            KeyDerive keyDevice = null;

            // Load the assemblies necessary for reflection
            Assembly securityAsm = Assembly.LoadFile(Path.Combine(RuntimeEnvironment.GetRuntimeDirectory(), "System.Security.dll"));
            Assembly coreAsm     = Assembly.LoadFile(Path.Combine(RuntimeEnvironment.GetRuntimeDirectory(), "System.Core.dll"));

            var performanceDerivative = new PerformanceDerivative(cryptographicInfo.InstanceKeyCreator.PerformanceDerivative);

            // Get the password
            using (password)
            {
                if (password.Length == 0)
                {
                    EncryptOutput.Content = "You must enter a password";
                    return;
                }
                if (password.Length < 4)
                {
                    EncryptOutput.Content = "Password to short";
                    return;
                }

                // Turn the secure string into a string to pass it into keyDevice for the shortest interval possible
                IntPtr valuePtr = IntPtr.Zero;
                try
                {
                    valuePtr = Marshal.SecureStringToGlobalAllocUnicode(password);

                    // Create an object array of parameters
                    var parameters = new object[] { Marshal.PtrToStringUni(valuePtr), cryptographicInfo.InstanceKeyCreator.salt, null };

                    var tempTransformationDevice = (KeyDerive)Activator.CreateInstance(Type.GetType(cryptographicInfo.InstanceKeyCreator.root_HashAlgorithm)
                                                                                       ?? securityAsm.GetType(cryptographicInfo.InstanceKeyCreator.root_HashAlgorithm)
                                                                                       ?? coreAsm.GetType(cryptographicInfo.InstanceKeyCreator.root_HashAlgorithm));

                    tempTransformationDevice.TransformPerformance(performanceDerivative, 2000UL);

#if DEBUG
                    Console.WriteLine(Encryption_App.Resources.MainWindow_EncryptDataWithHeader_Iteration_value__ + tempTransformationDevice.PerformanceValues);
#endif
                    parameters[2] = tempTransformationDevice.PerformanceValues;

                    keyDevice = (KeyDerive)Activator.CreateInstance(Type.GetType(cryptographicInfo.InstanceKeyCreator.root_HashAlgorithm)
                                                                    ?? securityAsm.GetType(cryptographicInfo.InstanceKeyCreator.root_HashAlgorithm)
                                                                    ?? coreAsm.GetType(cryptographicInfo.InstanceKeyCreator.root_HashAlgorithm), parameters);
                }
                finally
                {
                    // Destroy the managed string
                    Marshal.ZeroFreeGlobalAllocUnicode(valuePtr);
                }
            }

            HMAC hmacAlg = null;

            if (cryptographicInfo.Hmac != null)
            {
                // Create the algorithm using reflection
                hmacAlg = (HMAC)Activator.CreateInstance(Type.GetType(cryptographicInfo.Hmac.HashAlgorithm)
                                                         ?? securityAsm.GetType(cryptographicInfo.Hmac
                                                                                .HashAlgorithm)
                                                         ?? coreAsm.GetType(cryptographicInfo.Hmac.HashAlgorithm));
            }

            var encryptor = (SymmetricCryptoManager)Activator.CreateInstance(Type.GetType(cryptographicInfo.CryptoManager)
                                                                             ?? securityAsm.GetType(cryptographicInfo.CryptoManager)
                                                                             ?? coreAsm.GetType(cryptographicInfo.CryptoManager));

#if DEBUG
            long offset = watch.ElapsedMilliseconds;
#endif
            byte[] key = keyDevice.GetBytes(KeySize / 8);
#if DEBUG
            Console.WriteLine(Encryption_App.Resources.MainWindow_EncryptDataWithHeader_Actual_key_derivation_time__ + (watch.ElapsedMilliseconds - offset));
            Console.WriteLine(Encryption_App.Resources.MainWindow_EncryptDataWithHeader_Expected_key_derivation_time__ + DesiredKeyDerivationMilliseconds);
#endif
            // Create a handle to the key to allow control of it
            GCHandle keyHandle = GCHandle.Alloc(key, GCHandleType.Pinned);

#if DEBUG
            Console.WriteLine(Encryption_App.Resources.MainWindow_EncryptDataWithHeader_Pre_encryption_time__ + watch.ElapsedMilliseconds);
#endif
            // Encrypt the data to a temporary file
            encryptor.EncryptFileBytes(filePath, _dataTempFile, key, cryptographicInfo.EncryptionModeInfo.InitializationVector);

#if DEBUG
            Console.WriteLine(Encryption_App.Resources.MainWindow_EncryptDataWithHeader_Post_encryption_time__ + watch.ElapsedMilliseconds);
#endif
            if (cryptographicInfo.Hmac != null)
            {
                // Create the signature derived from the encrypted data and key
                byte[] signature = MessageAuthenticator.CreateHmac(_dataTempFile, key, hmacAlg);

                // Set the signature correctly in the CryptographicInfo object
                cryptographicInfo.Hmac.root_Hash = signature;
            }
            // Delete the key from memory for security
            ZeroMemory(keyHandle.AddrOfPinnedObject(), key.Length);
            keyHandle.Free();

            StepEncryptStrings();
#if DEBUG
            Console.WriteLine(Encryption_App.Resources.MainWindow_EncryptDataWithHeader_Post_authenticate_time__ + watch.ElapsedMilliseconds);
#endif
            // Write the CryptographicInfo object to a file
            cryptographicInfo.WriteHeaderToFile(filePath);
#if DEBUG
            // We have to use Dispatcher.Invoke as the current thread can't access these objects this.dispatcher.Invoke(() => { EncryptOutput.Content = "Transferring the data to the file"; });
            Console.WriteLine(Encryption_App.Resources.MainWindow_EncryptDataWithHeader_Post_header_time___0_, watch.ElapsedMilliseconds);
#endif
            FileStatics.AppendToFile(filePath, _dataTempFile);

#if DEBUG
            Console.WriteLine(Encryption_App.Resources.MainWindow_EncryptDataWithHeader_File_write_time__ + watch.ElapsedMilliseconds);
#endif
            StepEncryptStrings();
            GC.Collect();
        }