public CryptoContainer ValidateDecrypt(CryptoRequest request) { CryptoContainer container = null; if (!request.SkipValidations) { container = CryptoContainer.CreateForDecryption(request); var validationResult = container.ReadAndValidateDataForDecryption(); if (!validationResult.IsValid) { throw validationResult.ExceptionToThrow ?? new Exception("Unknown error"); } request.IV = container.GetIV(); if (request.Password != null) { request.Key = container.CalculateKey(); } } if (request.Key == null || request.Key.Length != 32) { throw new ArgumentException("Key must be 32 bytes long."); } if (request.IV == null || request.IV.Length != 16) { throw new ArgumentException($"IV must be 16 bytes in length"); } return(container); }
/// <summary> /// Adds additional data to encrypted data. Additional data is not protected, but it isn't added in plain text either. /// </summary> /// <param name="encryptedData">The encrypted data to which to add additional data.</param> /// <param name="additionalData">The additional data to add. Dictionary items where key or value is null or empty will be ignored/</param> /// <param name="destination">Stream to which to write encrypted data with added additional data</param> public static void AddAdditionalData(Stream encryptedData, Dictionary <string, string> additionalData, Stream destination) { if (additionalData == null) { throw new ArgumentNullException(nameof(additionalData)); } byte[] dataBytes = new AdditionalData(additionalData).GetBytes(); CryptoContainer.WriteAdditionalData(encryptedData, dataBytes, destination); }
internal static void Decrypt(CryptoRequest request) { CryptoContainer container = null; if (!request.SkipValidations) { container = CryptoContainer.CreateForDecryption(request); var validationResult = container.ReadAndValidateDataForDecryption(); if (!validationResult.IsValid) { throw validationResult.ExceptionToThrow ?? new Exception("Unknown error"); } request.IV = container.GetIV(); if (request.Password != null) { request.Key = container.CalculateKey(); } } if (request.Key == null || request.Key.Length != 32) { throw new ArgumentException("Key must be 32 bytes long."); } if (request.IV == null || request.IV.Length != 16) { throw new ArgumentException($"IV must be 16 bytes in length"); } using (var aes = new AesManaged()) { aes.IV = request.IV; aes.Key = request.Key; aes.Padding = PaddingMode.ISO10126; if (request.SkipValidations) { aes.Padding = PaddingMode.PKCS7; } aes.BlockSize = 128; using (var decryptor = aes.CreateDecryptor()) { CryptoStream cs = new CryptoStream(request.OutData, decryptor, CryptoStreamMode.Write); int bufferSize = aes.BlockSize; byte[] buffer = new byte[bufferSize]; int read = 0; while ((read = request.InData.Read(buffer, 0, bufferSize)) > 0) { cs.Write(buffer, 0, read); cs.Flush(); } cs.FlushFinalBlock(); } } }
internal static void Encrypt(CryptoRequest request) { if (request.Key.Length != 32) { throw new ArgumentException("Key must be 32 bytes long."); } if (request.IV == null || request.IV.Length != 16) { throw new ArgumentException("IV must be 16 bytes in length"); } CryptoContainer container = null; if (!request.SkipValidations) { container = CryptoContainer.CreateForEncryption(request); container.WriteEmptyHeaderData(); } using (var aes = new AesManaged()) { aes.IV = request.IV; aes.Key = request.Key; aes.Padding = PaddingMode.ISO10126; aes.BlockSize = 128; if (request.SkipValidations) { aes.Padding = PaddingMode.PKCS7; } using (var encryptor = aes.CreateEncryptor()) { CryptoStream cs = new CryptoStream(request.OutData, encryptor, CryptoStreamMode.Write); int bufferSize = aes.BlockSize; byte[] buffer = new byte[bufferSize]; int read = 0; while ((read = request.InData.Read(buffer, 0, bufferSize)) > 0) { cs.Write(buffer, 0, read); cs.Flush(); } cs.FlushFinalBlock(); } } if (!request.SkipValidations) { container.WriteChecksAndEmbeddedData(); } }
internal static async Task EncryptAsync(CryptoRequest request) { CryptoContainer container = request.ValidateEncryption(); ReportAndCancellationToken token = request.Token ?? new ReportAndCancellationToken(); token.CanReportProgress = request.InData.CanSeek; using (var aes = GetAes()) using (var encryptor = GetEncryptorAndSetAes(aes, request)) { int bufferSize = aes.BlockSize; if (token.CanReportProgress ?? false) { token.NumberOfIterations = (int)Math.Ceiling(request.InData.Length / (double)bufferSize); } CryptoStream cs = new CryptoStream(request.OutData, encryptor, CryptoStreamMode.Write); byte[] buffer = new byte[bufferSize]; int read = 0; int iterationCount = 0; while ((read = await request.InData.ReadAsync(buffer, 0, bufferSize)) > 0) { await cs.WriteAsync(buffer, 0, read); await cs.FlushAsync(); if (token.IsCanceled) { break; } iterationCount++; token.ReportProgressInternal(iterationCount); } if (token.IsCanceled) { return; } cs.FlushFinalBlock(); } if (!request.SkipValidations) { await container.WriteChecksAndEmbeddedDataAsync(); } }
public CryptoContainer ValidateEncryption() { if (Key.Length != 32) { throw new ArgumentException("Key must be 32 bytes long."); } if (IV == null || IV.Length != 16) { throw new ArgumentException("IV must be 16 bytes in length"); } CryptoContainer container = null; if (!SkipValidations) { container = CryptoContainer.CreateForEncryption(this); container.WriteEmptyHeaderData(); } return(container); }
internal static void Decrypt(CryptoRequest request) { CryptoContainer container = request.ValidateDecrypt(request); ReportAndCancellationToken token = request.Token ?? new ReportAndCancellationToken(); token.CanReportProgress = request.InData.CanSeek; using (var aes = GetAes()) using (ICryptoTransform decryptor = GetDecryptorAndSetAes(aes, request)) { int bufferSize = aes.BlockSize; if (token.CanReportProgress ?? false) { token.NumberOfIterations = (int)Math.Ceiling(request.InData.Length / (double)bufferSize); } CryptoStream cs = new CryptoStream(request.OutData, decryptor, CryptoStreamMode.Write); byte[] buffer = new byte[bufferSize]; int read = 0; int iterationCount = 0; while ((read = request.InData.Read(buffer, 0, bufferSize)) > 0) { cs.Write(buffer, 0, read); cs.Flush(); if (token.IsCanceled) { break; } iterationCount++; token.ReportProgressInternal(iterationCount); } if (token.IsCanceled) { return; } cs.FlushFinalBlock(); } }
internal static ValidationResult ValidateEncryptedData(CryptoRequest request) => CryptoContainer.CreateForDecryption(request).ReadAndValidateDataForDecryption();
/// <summary> /// Reads the additional data from encrypted data if present. /// </summary> /// <param name="encryptedData">The encrypted data.</param> /// <returns>Additional data</returns> public static Dictionary <string, string> ReadAdditionalData(Stream encryptedData) { byte[] data = CryptoContainer.ReadAdditionalData(encryptedData); return(AdditionalData.LoadFromBytes(data).Data); }