예제 #1
0
        /// <summary>
        /// Read the encrypted file header information from a stream
        /// </summary>
        /// <param name="stream">The stream to read</param>
        /// <returns>The encrypted header object</returns>
        public static EncryptedFileHeader ReadFromStream(Stream stream)
        {
            Pre.ThrowIfArgumentNull(stream, nameof(stream));

            // Read the entire header from the stream
            byte[] buffer = stream.ReadByteArray(HeaderSize);

            // Verify the header's checksum
            using (SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider())
            {
                byte[] computedHash = sha1.ComputeHash(buffer, 0, HeaderSize - ChecksumSize);
                byte[] headerHash   = BufferUtil.CopyBytes(buffer, buffer.Length - ChecksumSize, ChecksumSize);

                if (!NativeMethods.ByteArrayEquals(computedHash, headerHash))
                {
                    // TODO: Replace with a better exception
                    throw new Exception("The header checksum failed");
                }
            }

            // Create a new stream for reading the header data. This will make it easier to process the
            // fields in the header and will avoid having to reposition the original stream.
            using (MemoryStream headerStream = new MemoryStream(buffer))
            {
                EncryptedFileHeader header = new EncryptedFileHeader();

                int encryptedKeyLength = headerStream.ReadInt32();

                // Ensure the key is not longer than the buffer
                Pre.Assert(encryptedKeyLength < HeaderSize, "encryptedKeyLength < HeaderSize");

                // Read the encrypted key field.
                header.EncryptedKey = headerStream.ReadByteArray(encryptedKeyLength);

                // Read the IV length. This should be 16 bytes (asserted below).
                int ivLength = headerStream.ReadInt32();

                Pre.Assert(ivLength == IVStorageSize, "ivLength == ivStorageSize");

                // Read the initialization vector
                header.IV = headerStream.ReadByteArray(ivLength);

                // Read the file sizes, thumbprint, and padding
                header.OriginalFileLength    = headerStream.ReadInt64();
                header.EncryptedFileLength   = headerStream.ReadInt64();
                header.CertificateThumbprint = headerStream.ReadByteArray(CertificateThumbprintSize);
                header.PaddingLength         = headerStream.ReadInt16();

                return(header);
            }
        }