/// <summary> /// Decrypts the encrypted data to the given stream /// </summary> /// <param name="outputPlaintextStream">The resulting plain text stream.</param> public void DecryptTo(Stream outputPlaintextStream) { if (outputPlaintextStream == null) { throw new ArgumentNullException("outputPlaintextStream"); } if (!PassphraseIsValid) { throw new InternalErrorException("Passphrase is not valid!"); } using (Stream encryptedDataStream = CreateEncryptedDataStream()) { encryptedDataStream.DecryptTo(outputPlaintextStream, DocumentHeaders.DataCrypto().DecryptingTransform(), DocumentHeaders.IsCompressed); } DocumentHeaders.Trailers(_reader); if (DocumentHeaders.HmacCalculator.Hmac != DocumentHeaders.Hmac) { throw new Axantum.AxCrypt.Core.Runtime.IncorrectDataException("HMAC validation error.", ErrorStatus.HmacValidationError); } }
/// <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(); } } }