// Helper methods

        protected void LoadOuterManifest()
        {
            if (InnerProxy.Manifest.RootDirectory.Files.ContainsKey(
                    DefaultOuterManifestFileName) == false)
            {
                throw new Exception("Encrypted manifest is not present.");
            }

            ManifestFileInfo outerManifestManifestFileInfo =
                InnerProxy.Manifest.RootDirectory.Files[
                    DefaultOuterManifestFileName];

            FileInfo outerManifestFileInfo =
                InnerProxy.GetFile(outerManifestManifestFileInfo);

            Stream outerManifestFileStream =
                outerManifestFileInfo.OpenRead();

            byte[] outerKeyBytes = CryptUtilities.MakeKeyBytesFromString(
                OuterKeyString,
                InnerProxy.Manifest.Guid.ToByteArray());

            Stream outerManifestCryptoStream =
                CryptUtilities.MakeDecryptionReadStreamFrom(
                    outerManifestFileStream,
                    outerKeyBytes);

            OuterManifest =
                Manifest.ReadManifestStream(outerManifestCryptoStream);

            outerManifestCryptoStream.Close();
        }
        public FileInfo CloneFile(
            ManifestFileInfo copyFile,
            DirectoryInfo copyToDirectory)
        {
            ManifestFileInfo innerManifestFileInfo =
                HashToInnerFileMap[copyFile.FileHash];

            FileInfo innerFileInfo =
                InnerProxy.GetFile(innerManifestFileInfo);

            byte[] keyData = CryptUtilities.MakeKeyBytesFromString(
                OuterKeyString,
                copyFile.FileHash.HashData);

            String destFilePath =
                Path.Combine(
                    copyToDirectory.FullName,
                    DefaultDecryptedTempFileName);

            ReadCryptFile(
                innerFileInfo,
                keyData,
                destFilePath);

            FileInfo fileInfo =
                new FileInfo(destFilePath);

            // Make sure that the last-modified date matches that of the
            // expected outer file.  This is necessary because one inner file
            // may correspond to several outer files - each of which might
            // have separate dates.
            fileInfo.LastWriteTimeUtc = copyFile.LastModifiedUtc;

            return(fileInfo);
        }
        protected void ValidateFile(
            ManifestFileInfo outerManFileInfo,
            Utilities.Console console)
        {
            ManifestFileInfo innerManifestFileInfo = null;

            try
            {
                innerManifestFileInfo =
                    HashToInnerFileMap[outerManFileInfo.FileHash];

                FileInfo innerFileInfo =
                    InnerProxy.GetFile(innerManifestFileInfo);

                byte[] keyData = CryptUtilities.MakeKeyBytesFromString(
                    OuterKeyString,
                    outerManFileInfo.FileHash.HashData);

                Stream sourceFileStream =
                    innerFileInfo.OpenRead();

                Stream cryptoStream =
                    CryptUtilities.MakeDecryptionReadStreamFrom(
                        sourceFileStream,
                        keyData);

                FileHash computedHash = FileHash.ComputeHash(
                    cryptoStream,
                    outerManFileInfo.FileHash.HashType);

                if (computedHash.Equals(outerManFileInfo.FileHash) == false)
                {
                    throw new Exception("FAILED VALIDATION");
                }
            }
            catch (Exception e)
            {
                console.WriteLine(
                    Manifest.MakeStandardPathString(outerManFileInfo));

                console.WriteLine(
                    Manifest.MakeNativePathString(innerManifestFileInfo));

                console.WriteLine(e.Message);

                console.WriteLine();
            }
        }