public static (IntPtr, int) SecureStringToKeyDeriveReturnPointer(SecureString password, IEnumerable salt, PerformanceDerivative performanceDerivative, Type keyDeriveAlgorithm, out KeyDerive keyDerive) { // Turn the secure string into a string to pass it into keyDevice for the shortest interval possible IntPtr ptrSecureString = IntPtr.Zero; try { ptrSecureString = Marshal.SecureStringToGlobalAllocUnicode(password); var dataInsecureBytes = new byte[password.Length * sizeof(char)]; GCHandle bytesHandle = GCHandle.Alloc(dataInsecureBytes, GCHandleType.Pinned); for (var i = 0; i < password.Length * sizeof(char); i++) { dataInsecureBytes[i] = Marshal.ReadByte(ptrSecureString, i); } // Create an object array of parameters var parametersForInstance = new object[] { dataInsecureBytes, salt, null }; // Parameters for static function call var parametersForStatic = new object[] { performanceDerivative, performanceDerivative.Milliseconds }; object val = keyDeriveAlgorithm.GetMethod("TransformPerformance")?.Invoke(null, parametersForStatic); parametersForInstance[2] = val; keyDerive = (KeyDerive)Activator.CreateInstance(keyDeriveAlgorithm, parametersForInstance); password.Dispose(); return(bytesHandle.AddrOfPinnedObject(), dataInsecureBytes.Length); } catch (NotSupportedException e) { password.Dispose(); FileStatics.WriteToLogFile(e); MessageBox.Show("Fatal error while managing password. Check log file for details"); throw; } catch (OutOfMemoryException e) { password.Dispose(); FileStatics.WriteToLogFile(e); MessageBox.Show("Fatal error while managing password. Check log file for details"); throw; } finally { // Destroy the managed string Marshal.ZeroFreeGlobalAllocUnicode(ptrSecureString); } }
internal static Dictionary <string, Assembly> GetAssemblies(params string[] simpleNames) { var assemblies = new Dictionary <string, Assembly>(); foreach (string name in simpleNames) { Assembly loadedAsm = null; try { if (File.Exists(Path.Combine(RuntimeEnvironment.GetRuntimeDirectory(), name))) { loadedAsm = Assembly.LoadFile(Path.Combine(RuntimeEnvironment.GetRuntimeDirectory(), name)); } if (File.Exists(name)) { loadedAsm = Assembly.LoadFile(name); } } catch (FileLoadException e) { FileStatics.WriteToLogFile(e); MessageBox.Show( $"Error loading assemblies - assembly \"{e.FileName}\" could be found but not loaded"); loadedAsm = null; } catch (BadImageFormatException e) { FileStatics.WriteToLogFile(e); MessageBox.Show( $"Error loading assemblies - assembly \"{e.FileName}\" is corrupted"); loadedAsm = null; } assemblies.Add(name, loadedAsm); } return(assemblies); }
/// <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); }
/// <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(); } }
/// <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); }