示例#1
0
        public AxCryptDataStream CreateEncryptedDataStream(AesKey hmacKey, long cipherTextLength, ProgressContext progress)
        {
            if (hmacKey == null)
            {
                throw new ArgumentNullException("hmacKey");
            }
            if (progress == null)
            {
                throw new ArgumentNullException("progress");
            }
            if (_disposed)
            {
                throw new ObjectDisposedException(GetType().FullName);
            }
            if (CurrentItemType != AxCryptItemType.Data)
            {
                throw new InvalidOperationException("GetEncryptedDataStream() was called when the reader is not positioned at the data.");
            }

            CurrentItemType = AxCryptItemType.EndOfStream;

            _hmacStream = new HmacStream(hmacKey);
            _hmacBufferStream.Position = 0;
            _hmacBufferStream.CopyTo(_hmacStream, OS.Current.StreamBufferSize);

            _expectedTotalHmacLength = _hmacBufferStream.Length + cipherTextLength;

            AxCryptDataStream encryptedDataStream = new AxCryptDataStream(_inputStream, _hmacStream, cipherTextLength);

            return(encryptedDataStream);
        }
示例#2
0
        /// <summary>
        /// Decrypts the encrypted data to the given stream
        /// </summary>
        /// <param name="outputPlaintextStream">The resulting plain text stream.</param>
        public void DecryptTo(Stream outputPlaintextStream, ProgressContext progress)
        {
            if (DocumentHeaders == null)
            {
                throw new InternalErrorException("Document headers are not loaded");
            }

            using (ICryptoTransform decryptor = DataCrypto.CreateDecryptingTransform())
            {
                using (AxCryptDataStream encryptedDataStream = _reader.CreateEncryptedDataStream(DocumentHeaders.HmacSubkey.Key, DocumentHeaders.CipherTextLength, progress))
                {
                    DecryptEncryptedDataStream(outputPlaintextStream, decryptor, encryptedDataStream, progress);
                }
            }

            if (_reader.Hmac != DocumentHeaders.Hmac)
            {
                throw new Axantum.AxCrypt.Core.Runtime.InvalidDataException("HMAC validation error.", ErrorStatus.HmacValidationError);
            }
        }
示例#3
0
        /// <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;
            }
        }
示例#4
0
        public static void TestAxCryptDataStream()
        {
            string streamData = "This is some data in the streamEXTRA";

            using (Stream inputStream = new MemoryStream())
            {
                byte[] streamBytes = Encoding.UTF8.GetBytes(streamData);
                inputStream.Write(streamBytes, 0, streamBytes.Length);

                using (Stream hmacStream = new MemoryStream())
                {
                    Assert.Throws <ArgumentNullException>(() =>
                    {
                        using (AxCryptDataStream axCryptDataStream = new AxCryptDataStream(null, hmacStream, inputStream.Length)) { }
                    }, "An input stream must be given, it cannot be null.");
                    Assert.Throws <ArgumentNullException>(() =>
                    {
                        using (AxCryptDataStream axCryptDataStream = new AxCryptDataStream(inputStream, null, inputStream.Length)) { }
                    }, "An HmacStream must be given, it cannot be null.");
                    Assert.Throws <ArgumentOutOfRangeException>(() =>
                    {
                        using (AxCryptDataStream axCryptDataStream = new AxCryptDataStream(inputStream, hmacStream, -inputStream.Length)) { }
                    }, "Negative length is not allowed.");

                    inputStream.Position = 0;
                    using (AxCryptDataStream axCryptDataStream = new AxCryptDataStream(inputStream, hmacStream, inputStream.Length - 5))
                    {
                        Assert.Throws <NotSupportedException>(() =>
                        {
                            axCryptDataStream.Seek(0, SeekOrigin.Begin);
                        }, "Seek is not supported.");

                        Assert.Throws <NotSupportedException>(() =>
                        {
                            axCryptDataStream.SetLength(0);
                        }, "SetLength is not supported.");

                        Assert.Throws <NotSupportedException>(() =>
                        {
                            axCryptDataStream.Write(new byte[1], 0, 1);
                        }, "Write is not supported.");

                        Assert.Throws <NotSupportedException>(() =>
                        {
                            axCryptDataStream.Position = 0;
                        }, "Setting the position is not supported.");

                        Assert.Throws <NotSupportedException>(() =>
                        {
                            axCryptDataStream.Flush();
                        }, "Flush is not supported, and not meaningful on a read-only stream.");

                        Assert.That(axCryptDataStream.CanRead, Is.True, "AxCryptDataStream can be read.");
                        Assert.That(axCryptDataStream.CanSeek, Is.True, "AxCryptDataStream is a forward only reader stream, but it does support Length and Position therefore it reports that it can Seek.");
                        Assert.That(axCryptDataStream.CanWrite, Is.False, "AxCryptDataStream is a forward only reader stream, it does not support writing.");
                        Assert.That(axCryptDataStream.Length, Is.EqualTo(inputStream.Length - 5), "The stream should report the length provided in the constructor.");
                        inputStream.Position = 5;
                        Assert.That(axCryptDataStream.Position, Is.EqualTo(0), "The original position should be zero, regardless of the actual position of the input stream.");
                        inputStream.Position = 0;

                        byte[] buffer = new byte[3];
                        int    count;
                        int    total = 0;
                        while ((count = axCryptDataStream.Read(buffer, 0, buffer.Length)) > 0)
                        {
                            total += count;
                        }
                        Assert.That(total, Is.EqualTo(inputStream.Length - 5), "The AxCryptDataStream should be limited to the length provided, not the backing stream.");
                        Assert.That(hmacStream.Length, Is.EqualTo(total), "The hmac stream should have all data read written to it.");
                    }
                }
            }
        }
示例#5
0
        private void DecryptEncryptedDataStream(Stream outputPlaintextStream, ICryptoTransform decryptor, AxCryptDataStream encryptedDataStream, ProgressContext progress)
        {
            Exception savedExceptionIfCloseCausesCryptographicException = null;

            try
            {
                if (DocumentHeaders.IsCompressed)
                {
                    using (CryptoStream deflatedPlaintextStream = new CryptoStream(encryptedDataStream, decryptor, CryptoStreamMode.Read))
                    {
                        using (ZInputStream inflatedPlaintextStream = new ZInputStream(deflatedPlaintextStream))
                        {
                            try
                            {
                                CopyToWithCount(inflatedPlaintextStream, outputPlaintextStream, encryptedDataStream, progress);
                            }
                            catch (Exception ex)
                            {
                                savedExceptionIfCloseCausesCryptographicException = ex;
                                throw;
                            }
                        }
                    }
                }
                else
                {
                    using (Stream plainStream = new CryptoStream(encryptedDataStream, decryptor, CryptoStreamMode.Read))
                    {
                        try
                        {
                            CopyToWithCount(plainStream, outputPlaintextStream, encryptedDataStream, progress);
                        }
                        catch (Exception ex)
                        {
                            savedExceptionIfCloseCausesCryptographicException = ex;
                            throw;
                        }
                    }
                }
            }
            catch (CryptographicException)
            {
                throw savedExceptionIfCloseCausesCryptographicException;
            }
        }