/// <summary> /// Write a copy of the current encrypted stream. Used to change meta-data /// and encryption key(s) etc. /// </summary> /// <param name="outputStream"></param> public void CopyEncryptedTo(DocumentHeaders outputDocumentHeaders, Stream cipherStream, ProgressContext progress) { if (outputDocumentHeaders == null) { throw new ArgumentNullException("outputDocumentHeaders"); } if (cipherStream == null) { throw new ArgumentNullException("cipherStream"); } if (!cipherStream.CanSeek) { throw new ArgumentException("The output stream must support seek in order to back-track and write the HMAC."); } if (DocumentHeaders == null) { throw new InternalErrorException("Document headers are not loaded"); } using (HmacStream hmacStreamOutput = new HmacStream(outputDocumentHeaders.HmacSubkey.Key, cipherStream)) { outputDocumentHeaders.WriteWithHmac(hmacStreamOutput); using (AxCryptDataStream encryptedDataStream = _reader.CreateEncryptedDataStream(DocumentHeaders.HmacSubkey.Key, DocumentHeaders.CipherTextLength, progress)) { CopyToWithCount(encryptedDataStream, hmacStreamOutput, progress); if (_reader.Hmac != DocumentHeaders.Hmac) { throw new Axantum.AxCrypt.Core.Runtime.InvalidDataException("HMAC validation error in the input stream.", ErrorStatus.HmacValidationError); } } outputDocumentHeaders.Hmac = hmacStreamOutput.HmacResult; // Rewind and rewrite the headers, now with the updated HMAC outputDocumentHeaders.WriteWithoutHmac(cipherStream); cipherStream.Position = cipherStream.Length; } }