private static void TestEncryptWithHmacHelper(int length, AxCryptOptions options) { byte[] output; byte[] hmacKey; using (MemoryStream inputStream = new MemoryStream()) { byte[] text = Resolve.RandomGenerator.Generate(length); inputStream.Write(text, 0, text.Length); inputStream.Position = 0; using (MemoryStream outputStream = new MemoryStream()) { using (V2AxCryptDocument document = new V2AxCryptDocument(new EncryptionParameters(new V2Aes256CryptoFactory().CryptoId, new Passphrase("Secret")), 100)) { document.EncryptTo(inputStream, outputStream, options); output = outputStream.ToArray(); hmacKey = document.DocumentHeaders.GetHmacKey(); } } } byte[] hmacBytesFromHeaders = new byte[V2Hmac.RequiredLength]; Array.Copy(output, output.Length - V2Hmac.RequiredLength, hmacBytesFromHeaders, 0, V2Hmac.RequiredLength); V2Hmac hmacFromHeaders = new V2Hmac(hmacBytesFromHeaders); byte[] dataToHmac = new byte[output.Length - (V2Hmac.RequiredLength + 5)]; Array.Copy(output, 0, dataToHmac, 0, dataToHmac.Length); HMACSHA512 hmac = new HMACSHA512(hmacKey); hmac.TransformFinalBlock(dataToHmac, 0, dataToHmac.Length); V2Hmac hmacFromCalculation = new V2Hmac(hmac.Hash); Assert.That(hmacFromHeaders, Is.EqualTo(hmacFromCalculation)); }
private static void TestEncryptDecryptHelper(int length, AxCryptOptions options) { using (MemoryStream inputStream = new MemoryStream()) { byte[] text = Resolve.RandomGenerator.Generate(length); inputStream.Write(text, 0, text.Length); inputStream.Position = 0; byte[] buffer = new byte[5500 + length]; using (IAxCryptDocument document = new V2AxCryptDocument(new EncryptionParameters(new V2Aes256CryptoFactory().CryptoId, new Passphrase("passphrase")), 113)) { document.EncryptTo(inputStream, new MemoryStream(buffer), options); } using (V2AxCryptDocument decryptedDocument = new V2AxCryptDocument()) { Assert.That(decryptedDocument.Load(new Passphrase("passphrase"), new V2Aes256CryptoFactory().CryptoId, new MemoryStream(buffer)), Is.True); byte[] plain; using (MemoryStream decryptedStream = new MemoryStream()) { decryptedDocument.DecryptTo(decryptedStream); plain = decryptedStream.ToArray(); } Assert.That(plain.IsEquivalentTo(text)); } } }
/// <summary> /// Decrypt a source file to a destination file, given a passphrase /// </summary> /// <param name="sourceFile">The source file</param> /// <param name="destinationFile">The destination file</param> /// <param name="passphrase">The passphrase</param> /// <returns>true if the passphrase was correct</returns> public static bool Decrypt(IRuntimeFileInfo sourceFile, IRuntimeFileInfo destinationFile, AesKey key, AxCryptOptions options, ProgressContext progress) { if (sourceFile == null) { throw new ArgumentNullException("sourceFile"); } if (destinationFile == null) { throw new ArgumentNullException("destinationFile"); } if (key == null) { throw new ArgumentNullException("key"); } if (progress == null) { throw new ArgumentNullException("progress"); } using (AxCryptDocument document = Document(sourceFile, key, new ProgressContext())) { if (!document.PassphraseIsValid) { return false; } Decrypt(document, destinationFile, options, progress); } return true; }
/// <summary> /// Encrypt a stream with a given set of headers and write to an output stream. The caller is responsible for consistency and completeness /// of the headers. Headers that are not known until encryption and compression are added here. /// </summary> /// <param name="outputDocumentHeaders"></param> /// <param name="inputStream"></param> /// <param name="outputStream"></param> public void EncryptTo(Stream inputStream, Stream outputStream, AxCryptOptions options) { if (inputStream == null) { throw new ArgumentNullException("inputStream"); } if (outputStream == null) { throw new ArgumentNullException("outputStream"); } if (options.HasMask(AxCryptOptions.EncryptWithCompression) && options.HasMask(AxCryptOptions.EncryptWithoutCompression)) { throw new ArgumentException("Invalid options, cannot specify both with and without compression."); } if (!options.HasMask(AxCryptOptions.EncryptWithCompression) && !options.HasMask(AxCryptOptions.EncryptWithoutCompression)) { throw new ArgumentException("Invalid options, must specify either with or without compression."); } DocumentHeaders.IsCompressed = options.HasMask(AxCryptOptions.EncryptWithCompression); V2HmacCalculator hmacCalculator = new V2HmacCalculator(new SymmetricKey(DocumentHeaders.GetHmacKey())); V2HmacStream <Stream> outputHmacStream = V2HmacStream.Create(hmacCalculator, outputStream); CryptoStreamBase encryptingStream = New <CryptoStreamBase>().Initialize(V2AxCryptDataStream.Create(outputHmacStream), DocumentHeaders.DataCrypto().EncryptingTransform(), CryptoStreamMode.Write); DocumentHeaders.WriteStartWithHmac(outputHmacStream); if (DocumentHeaders.IsCompressed) { using (ZOutputStream deflatingStream = new ZOutputStream(encryptingStream, -1)) { deflatingStream.FlushMode = JZlib.Z_SYNC_FLUSH; inputStream.CopyTo(deflatingStream); deflatingStream.FlushMode = JZlib.Z_FINISH; deflatingStream.Finish(); _plaintextLength = deflatingStream.TotalIn; _compressedPlaintextLength = deflatingStream.TotalOut; encryptingStream.FinalFlush(); DocumentHeaders.WriteEndWithHmac(hmacCalculator, outputHmacStream, _plaintextLength, _compressedPlaintextLength); } } else { try { _compressedPlaintextLength = _plaintextLength = StreamExtensions.CopyTo(inputStream, encryptingStream); encryptingStream.FinalFlush(); DocumentHeaders.WriteEndWithHmac(hmacCalculator, outputHmacStream, _plaintextLength, _compressedPlaintextLength); } finally { encryptingStream.Dispose(); } } }
public void EncryptTo(Stream inputStream, Stream outputStream, AxCryptOptions options) { if (inputStream == null) { throw new ArgumentNullException("inputStream"); } if (outputStream == null) { throw new ArgumentNullException("outputStream"); } if (!outputStream.CanSeek) { throw new ArgumentException("The output stream must support seek in order to back-track and write the HMAC."); } if (options.HasMask(AxCryptOptions.EncryptWithCompression) && options.HasMask(AxCryptOptions.EncryptWithoutCompression)) { throw new ArgumentException("Invalid options, cannot specify both with and without compression."); } if (!options.HasMask(AxCryptOptions.EncryptWithCompression) && !options.HasMask(AxCryptOptions.EncryptWithoutCompression)) { throw new ArgumentException("Invalid options, must specify either with or without compression."); } bool isCompressed = options.HasMask(AxCryptOptions.EncryptWithCompression); DocumentHeaders.IsCompressed = isCompressed; DocumentHeaders.WriteWithoutHmac(outputStream); using (ICryptoTransform encryptor = DataCrypto.EncryptingTransform()) { long outputStartPosition = outputStream.Position; using (Stream encryptingStream = New <CryptoStreamBase>().Initialize(new NonClosingStream(outputStream), encryptor, CryptoStreamMode.Write)) { if (isCompressed) { EncryptWithCompressionInternal(DocumentHeaders, inputStream, encryptingStream); } else { DocumentHeaders.PlaintextLength = StreamExtensions.CopyTo(inputStream, encryptingStream); } } outputStream.Flush(); DocumentHeaders.CipherTextLength = outputStream.Position - outputStartPosition; using (V1HmacStream outputHmacStream = new V1HmacStream(DocumentHeaders.HmacSubkey.Key, outputStream)) { DocumentHeaders.WriteWithHmac(outputHmacStream); outputHmacStream.ReadFrom(outputStream); DocumentHeaders.Headers.Hmac = outputHmacStream.HmacResult; } // Rewind and rewrite the headers, now with the updated HMAC DocumentHeaders.WriteWithoutHmac(outputStream); outputStream.Position = outputStream.Length; } }
/// <summary> /// Decrypt from loaded AxCryptDocument to a destination file /// </summary> /// <param name="document">The loaded AxCryptDocument</param> /// <param name="destinationStore">The destination file</param> /// <param name="options">The options.</param> /// <param name="progress">The progress.</param> /// <exception cref="System.ArgumentNullException"> /// document /// or /// destinationStore /// or /// progress /// </exception> public void Decrypt(IAxCryptDocument document, FileLock destinationLock, AxCryptOptions options, IProgressContext progress) { if (document == null) { throw new ArgumentNullException(nameof(document)); } if (destinationLock == null) { throw new ArgumentNullException(nameof(destinationLock)); } if (progress == null) { throw new ArgumentNullException(nameof(progress)); } IDataStore destinationStore = destinationLock.DataStore; try { if (Resolve.Log.IsInfoEnabled) { Resolve.Log.LogInfo("Decrypting to '{0}'.".InvariantFormat(destinationStore.Name)); } using (Stream destinationStream = destinationStore.OpenWrite()) { document.DecryptTo(destinationStream); } if (Resolve.Log.IsInfoEnabled) { Resolve.Log.LogInfo("Decrypted to '{0}'.".InvariantFormat(destinationStore.Name)); } } catch (Exception) { if (destinationStore.IsAvailable) { Wipe(destinationLock, progress); } throw; } if (options.HasMask(AxCryptOptions.SetFileTimes)) { destinationStore.SetFileTimes(document.CreationTimeUtc, document.LastAccessTimeUtc, document.LastWriteTimeUtc); } }
/// <summary> /// Decrypt a source file to a destination file, given a passphrase /// </summary> /// <param name="sourceStore">The source file</param> /// <param name="destinationItem">The destination file</param> /// <param name="logOnIdentity">The passphrase</param> /// <returns>true if the passphrase was correct</returns> public bool Decrypt(IDataStore sourceStore, IDataItem destinationItem, LogOnIdentity logOnIdentity, AxCryptOptions options, IProgressContext progress) { if (sourceStore == null) { throw new ArgumentNullException(nameof(sourceStore)); } if (destinationItem == null) { throw new ArgumentNullException(nameof(destinationItem)); } if (logOnIdentity == null) { throw new ArgumentNullException(nameof(logOnIdentity)); } if (progress == null) { throw new ArgumentNullException(nameof(progress)); } using (FileLock sourceLock = New <FileLocker>().Acquire(sourceStore)) { using (IAxCryptDocument document = Document(sourceStore, logOnIdentity, new ProgressContext())) { if (!document.PassphraseIsValid) { return(false); } using (FileLock destinationLock = New <FileLocker>().Acquire(destinationItem)) { Decrypt(document, destinationLock, options, progress); } } } return(true); }
public static void Encrypt(Stream sourceStream, string sourceFileName, IDataStore destinationStore, EncryptionParameters encryptionParameters, AxCryptOptions options, IProgressContext progress) { if (sourceStream == null) { throw new ArgumentNullException("sourceStream"); } if (sourceFileName == null) { throw new ArgumentNullException("sourceFileName"); } if (destinationStore == null) { throw new ArgumentNullException("destinationStore"); } if (encryptionParameters == null) { throw new ArgumentNullException("encryptionParameters"); } if (progress == null) { throw new ArgumentNullException("progress"); } using (Stream destinationStream = destinationStore.OpenWrite()) { using (IAxCryptDocument document = New <AxCryptFactory>().CreateDocument(encryptionParameters)) { document.FileName = sourceFileName; document.CreationTimeUtc = New <INow>().Utc; document.LastAccessTimeUtc = document.CreationTimeUtc; document.LastWriteTimeUtc = document.CreationTimeUtc; document.EncryptTo(sourceStream, destinationStream, options); } } }
public static void Encrypt(Stream sourceStream, Stream destinationStream, EncryptedProperties properties, EncryptionParameters encryptionParameters, AxCryptOptions options, IProgressContext progress) { if (sourceStream == null) { throw new ArgumentNullException("sourceStream"); } if (destinationStream == null) { throw new ArgumentNullException("destinationStream"); } if (properties == null) { throw new ArgumentNullException("properties"); } if (encryptionParameters == null) { throw new ArgumentNullException("encryptionParameters"); } if (progress == null) { throw new ArgumentNullException("progress"); } using (IAxCryptDocument document = New <AxCryptFactory>().CreateDocument(encryptionParameters)) { document.FileName = properties.FileMetaData.FileName; document.CreationTimeUtc = properties.FileMetaData.CreationTimeUtc; document.LastAccessTimeUtc = properties.FileMetaData.LastAccessTimeUtc; document.LastWriteTimeUtc = properties.FileMetaData.LastWriteTimeUtc; document.EncryptTo(sourceStream, destinationStream, options); } }
public virtual void Encrypt(IDataStore sourceFile, Stream destinationStream, EncryptionParameters encryptionParameters, AxCryptOptions options, IProgressContext progress) { if (sourceFile == null) { throw new ArgumentNullException("sourceFile"); } if (destinationStream == null) { throw new ArgumentNullException("destinationStream"); } if (encryptionParameters == null) { throw new ArgumentNullException("encryptionParameters"); } if (progress == null) { throw new ArgumentNullException("progress"); } using (Stream sourceStream = new ProgressStream(sourceFile.OpenRead(), progress)) { using (IAxCryptDocument document = New <AxCryptFactory>().CreateDocument(encryptionParameters)) { document.FileName = sourceFile.Name; document.CreationTimeUtc = sourceFile.CreationTimeUtc; document.LastAccessTimeUtc = sourceFile.LastAccessTimeUtc; document.LastWriteTimeUtc = sourceFile.LastWriteTimeUtc; document.EncryptTo(sourceStream, destinationStream, options); } } }
public AxSdkStreamEncryptor(AxSdkConfiguration configuration) { _cryptoId = configuration.CryptoId; _options = configuration.Copmress ? AxCryptOptions.EncryptWithCompression : AxCryptOptions.EncryptWithoutCompression; _options |= AxCryptOptions.SetFileTimes; }
public virtual void Encrypt(IDataStore sourceStore, IDataStore destinationStore, EncryptionParameters encryptionParameters, AxCryptOptions options, IProgressContext progress) { if (sourceStore == null) { throw new ArgumentNullException("sourceStore"); } if (destinationStore == null) { throw new ArgumentNullException("destinationStore"); } if (encryptionParameters == null) { throw new ArgumentNullException("encryptionParameters"); } if (progress == null) { throw new ArgumentNullException("progress"); } using (Stream destinationStream = destinationStore.OpenWrite()) { Encrypt(sourceStore, destinationStream, encryptionParameters, options, progress); } if (options.HasMask(AxCryptOptions.SetFileTimes)) { destinationStore.SetFileTimes(sourceStore.CreationTimeUtc, sourceStore.LastAccessTimeUtc, sourceStore.LastWriteTimeUtc); } }
/// <summary> /// Decrypt from loaded AxCryptDocument to a destination file /// </summary> /// <param name="document">The loaded AxCryptDocument</param> /// <param name="destinationFile">The destination file</param> public static void Decrypt(AxCryptDocument document, IRuntimeFileInfo destinationFile, AxCryptOptions options, ProgressContext progress) { if (document == null) { throw new ArgumentNullException("document"); } if (destinationFile == null) { throw new ArgumentNullException("destinationFile"); } if (progress == null) { throw new ArgumentNullException("progress"); } try { if (OS.Log.IsInfoEnabled) { OS.Log.LogInfo("Decrypting to '{0}'.".InvariantFormat(destinationFile.Name)); } using (Stream destinationStream = destinationFile.OpenWrite()) { document.DecryptTo(destinationStream, progress); } if (OS.Log.IsInfoEnabled) { OS.Log.LogInfo("Decrypted to '{0}'.".InvariantFormat(destinationFile.Name)); } } catch (OperationCanceledException) { if (destinationFile.Exists) { AxCryptFile.Wipe(destinationFile, progress); } throw; } if (options.HasMask(AxCryptOptions.SetFileTimes)) { DocumentHeaders headers = document.DocumentHeaders; destinationFile.SetFileTimes(headers.CreationTimeUtc, headers.LastAccessTimeUtc, headers.LastWriteTimeUtc); } }
/// <summary> /// Decrypt a source file to a destination file, given a passphrase /// </summary> /// <param name="sourceFile">The source file</param> /// <param name="destinationFile">The destination file</param> /// <param name="passphrase">The passphrase</param> /// <returns>true if the passphrase was correct</returns> public static string Decrypt(IRuntimeFileInfo sourceFile, string destinationDirectory, AesKey key, AxCryptOptions options, ProgressContext progress) { if (sourceFile == null) { throw new ArgumentNullException("sourceFile"); } if (destinationDirectory == null) { throw new ArgumentNullException("destinationDirectory"); } if (key == null) { throw new ArgumentNullException("key"); } if (progress == null) { throw new ArgumentNullException("progress"); } string destinationFileName = null; using (AxCryptDocument document = Document(sourceFile, key, new ProgressContext())) { if (!document.PassphraseIsValid) { return(destinationFileName); } destinationFileName = document.DocumentHeaders.FileName; IRuntimeFileInfo destinationFullPath = OS.Current.FileInfo(Path.Combine(destinationDirectory, destinationFileName)); Decrypt(document, destinationFullPath, options, progress); } return(destinationFileName); }
/// <summary> /// Decrypt a source file to a destination file, given a passphrase /// </summary> /// <param name="sourceFile">The source file</param> /// <param name="destinationFile">The destination file</param> /// <param name="passphrase">The passphrase</param> /// <returns>true if the passphrase was correct</returns> public static bool Decrypt(IRuntimeFileInfo sourceFile, IRuntimeFileInfo destinationFile, AesKey key, AxCryptOptions options, ProgressContext progress) { if (sourceFile == null) { throw new ArgumentNullException("sourceFile"); } if (destinationFile == null) { throw new ArgumentNullException("destinationFile"); } if (key == null) { throw new ArgumentNullException("key"); } if (progress == null) { throw new ArgumentNullException("progress"); } using (AxCryptDocument document = Document(sourceFile, key, new ProgressContext())) { if (!document.PassphraseIsValid) { return(false); } Decrypt(document, destinationFile, options, progress); } return(true); }
public static bool HasMask(this AxCryptOptions options, AxCryptOptions mask) { return((options & mask) == mask); }
public static bool HasMask(this AxCryptOptions options, AxCryptOptions mask) { return (options & mask) == mask; }
/// <summary> /// Decrypt a source file to a destination file, given a passphrase /// </summary> /// <param name="sourceFile">The source file</param> /// <param name="destinationFile">The destination file</param> /// <param name="passphrase">The passphrase</param> /// <returns>true if the passphrase was correct</returns> public static string Decrypt(IRuntimeFileInfo sourceFile, string destinationDirectory, AesKey key, AxCryptOptions options, ProgressContext progress) { if (sourceFile == null) { throw new ArgumentNullException("sourceFile"); } if (destinationDirectory == null) { throw new ArgumentNullException("destinationDirectory"); } if (key == null) { throw new ArgumentNullException("key"); } if (progress == null) { throw new ArgumentNullException("progress"); } string destinationFileName = null; using (AxCryptDocument document = Document(sourceFile, key, new ProgressContext())) { if (!document.PassphraseIsValid) { return destinationFileName; } destinationFileName = document.DocumentHeaders.FileName; IRuntimeFileInfo destinationFullPath = OS.Current.FileInfo(Path.Combine(destinationDirectory, destinationFileName)); Decrypt(document, destinationFullPath, options, progress); } return destinationFileName; }
/// <summary> /// Decrypt a source file to a destination file, given a passphrase /// </summary> /// <param name="sourceStore">The source file</param> /// <param name="destinationContainerName">Name of the destination container.</param> /// <param name="logOnIdentity">The key.</param> /// <param name="options">The options.</param> /// <param name="progress">The progress.</param> /// <returns> /// true if the passphrase was correct /// </returns> /// <exception cref="System.ArgumentNullException">sourceStore /// or /// destinationContainerName /// or /// key /// or /// progress</exception> public string Decrypt(IDataStore sourceStore, string destinationContainerName, LogOnIdentity logOnIdentity, AxCryptOptions options, IProgressContext progress) { if (sourceStore == null) { throw new ArgumentNullException("sourceStore"); } if (destinationContainerName == null) { throw new ArgumentNullException("destinationContainerName"); } if (logOnIdentity == null) { throw new ArgumentNullException("logOnIdentity"); } if (progress == null) { throw new ArgumentNullException("progress"); } string destinationFileName = null; using (IAxCryptDocument document = Document(sourceStore, logOnIdentity, new ProgressContext())) { if (!document.PassphraseIsValid) { return(destinationFileName); } destinationFileName = document.FileName; IDataStore destinationDataStore = New <IDataStore>(Resolve.Portable.Path().Combine(destinationContainerName, destinationFileName)); using (FileLock destinationFileLock = New <FileLocker>().Acquire(destinationDataStore)) { Decrypt(document, destinationFileLock, options, progress); } } return(destinationFileName); }
/// <summary> /// Encrypt a file /// </summary> /// <param name="file">The file to encrypt</param> /// <param name="destination">The destination file</param> /// <remarks>It is the callers responsibility to ensure that the source file exists, that the destination file /// does not exist and can be created etc.</remarks> public static void Encrypt(IRuntimeFileInfo sourceFile, IRuntimeFileInfo destinationFile, Passphrase passphrase, AxCryptOptions options, ProgressContext progress) { if (sourceFile == null) { throw new ArgumentNullException("sourceFile"); } if (destinationFile == null) { throw new ArgumentNullException("destinationFile"); } if (passphrase == null) { throw new ArgumentNullException("passphrase"); } if (progress == null) { throw new ArgumentNullException("progress"); } using (Stream sourceStream = sourceFile.OpenRead()) { using (Stream destinationStream = destinationFile.OpenWrite()) { using (AxCryptDocument document = new AxCryptDocument()) { DocumentHeaders headers = new DocumentHeaders(passphrase.DerivedPassphrase); headers.FileName = sourceFile.Name; headers.CreationTimeUtc = sourceFile.CreationTimeUtc; headers.LastAccessTimeUtc = sourceFile.LastAccessTimeUtc; headers.LastWriteTimeUtc = sourceFile.LastWriteTimeUtc; document.DocumentHeaders = headers; document.EncryptTo(headers, sourceStream, destinationStream, options, progress); } } if (options.HasMask(AxCryptOptions.SetFileTimes)) { destinationFile.SetFileTimes(sourceFile.CreationTimeUtc, sourceFile.LastAccessTimeUtc, sourceFile.LastWriteTimeUtc); } } }
private static byte[] EncrytionHelper(EncryptionParameters encryptionParameters, string fileName, AxCryptOptions options, byte[] plainText) { byte[] output; using (MemoryStream inputStream = new MemoryStream(plainText)) { using (MemoryStream outputStream = new MemoryStream()) { using (V2AxCryptDocument document = new V2AxCryptDocument(encryptionParameters, 1000)) { document.FileName = fileName; document.CreationTimeUtc = New <INow>().Utc; document.LastAccessTimeUtc = document.CreationTimeUtc; document.LastWriteTimeUtc = document.CreationTimeUtc; document.EncryptTo(inputStream, outputStream, options); output = outputStream.ToArray(); } } } return(output); }
public static void Encrypt(IRuntimeFileInfo sourceFile, Stream destinationStream, AesKey key, AxCryptOptions options, ProgressContext progress) { if (sourceFile == null) { throw new ArgumentNullException("sourceFile"); } if (destinationStream == null) { throw new ArgumentNullException("destinationStream"); } if (key == null) { throw new ArgumentNullException("key"); } if (progress == null) { throw new ArgumentNullException("progress"); } using (Stream sourceStream = sourceFile.OpenRead()) { using (AxCryptDocument document = new AxCryptDocument()) { DocumentHeaders headers = new DocumentHeaders(key); headers.FileName = sourceFile.Name; headers.CreationTimeUtc = sourceFile.CreationTimeUtc; headers.LastAccessTimeUtc = sourceFile.LastAccessTimeUtc; headers.LastWriteTimeUtc = sourceFile.LastWriteTimeUtc; document.DocumentHeaders = headers; document.EncryptTo(headers, sourceStream, destinationStream, options, progress); } } }
/// <summary> /// Encrypt a stream with a given set of headers and write to an output stream. The caller is responsible for consistency and completeness /// of the headers. Headers that are not known until encryption and compression are added here. /// </summary> /// <param name="outputDocumentHeaders"></param> /// <param name="inputStream"></param> /// <param name="outputStream"></param> public void EncryptTo(DocumentHeaders outputDocumentHeaders, Stream inputStream, Stream outputStream, AxCryptOptions options, ProgressContext progress) { if (outputDocumentHeaders == null) { throw new ArgumentNullException("outputDocumentHeaders"); } if (inputStream == null) { throw new ArgumentNullException("inputStream"); } if (outputStream == null) { throw new ArgumentNullException("outputStream"); } if (progress == null) { throw new ArgumentNullException("progress"); } if (!outputStream.CanSeek) { throw new ArgumentException("The output stream must support seek in order to back-track and write the HMAC."); } if (options.HasMask(AxCryptOptions.EncryptWithCompression) && options.HasMask(AxCryptOptions.EncryptWithoutCompression)) { throw new ArgumentException("Invalid options, cannot specify both with and without compression."); } if (!options.HasMask(AxCryptOptions.EncryptWithCompression) && !options.HasMask(AxCryptOptions.EncryptWithoutCompression)) { throw new ArgumentException("Invalid options, must specify either with or without compression."); } bool isCompressed = options.HasMask(AxCryptOptions.EncryptWithCompression); outputDocumentHeaders.IsCompressed = isCompressed; outputDocumentHeaders.WriteWithoutHmac(outputStream); using (ICryptoTransform encryptor = DataCrypto.CreateEncryptingTransform()) { long outputStartPosition = outputStream.Position; using (CryptoStream encryptingStream = new CryptoStream(new NonClosingStream(outputStream), encryptor, CryptoStreamMode.Write)) { if (isCompressed) { EncryptWithCompressionInternal(outputDocumentHeaders, inputStream, encryptingStream, progress); } else { outputDocumentHeaders.PlaintextLength = CopyToWithCount(inputStream, encryptingStream, progress); } } outputStream.Flush(); outputDocumentHeaders.CipherTextLength = outputStream.Position - outputStartPosition; using (HmacStream outputHmacStream = new HmacStream(outputDocumentHeaders.HmacSubkey.Key, outputStream)) { outputDocumentHeaders.WriteWithHmac(outputHmacStream); outputHmacStream.ReadFrom(outputStream); outputDocumentHeaders.Hmac = outputHmacStream.HmacResult; } // Rewind and rewrite the headers, now with the updated HMAC outputDocumentHeaders.WriteWithoutHmac(outputStream); outputStream.Position = outputStream.Length; } }