コード例 #1
0
ファイル: FileFormat.cs プロジェクト: Confuset/7Pass-Remake
        /// <summary>
        /// Decrypts the specified input stream.
        /// </summary>
        /// <param name="input">The input stream.</param>
        /// <param name="masterKey">The master key.</param>
        /// <param name="headers">The database file headers.</param>
        /// <returns>The decrypted buffer.</returns>
        /// <exception cref="ArgumentNullException">
        /// The <paramref name="input"/>, <paramref name="masterKey"/>,
        /// <paramref name="headers"/> cannot be <c>null</c>.
        /// </exception>
        public static Task<IInputStream> Decrypt(IRandomAccessStream input,
            IBuffer masterKey, FileHeaders headers)
        {
            if (headers == null)
                throw new ArgumentNullException("headers");

            return Decrypt(input, masterKey,
                headers.MasterSeed, headers.EncryptionIV);
        }
コード例 #2
0
        public async Task ParseContent_should_decrypt_passwords()
        {
            using (var decrypted = TestFiles.Read("IO.Demo7Pass.Decrypted.bin"))
            {
                var headers = new FileHeaders
                {
                    RandomAlgorithm = CrsAlgorithm.Salsa20,
                    ProtectedStreamKey = CryptographicBuffer.DecodeFromBase64String(
                        "FDNbUwE9jt6Y9+syU+btBIOGRxYt2tiUqnb6FXWIF1E="),
                };

                var doc = await FileFormat.ParseContent(
                    decrypted, true, headers);
                Assert.NotNull(doc);

                var entry = doc.Descendants("Entry")
                    .Where(x => (string)x.Element("UUID") == "H/DqrrE1mEKScz8VpPrafg==")
                    .SelectMany(x => x.Elements("String"))
                    .Where(x => (string)x.Element("Key") == "Password")
                    .Select(x => (string)x.Element("Value"))
                    .Single();

                Assert.Equal("Password", entry);
            }
        }
コード例 #3
0
        public async Task ParseContent_should_decompress_content()
        {
            using (var decrypted = TestFiles.Read("IO.Demo7Pass.Decrypted.bin"))
            {
                var headers = new FileHeaders
                {
                    RandomAlgorithm = CrsAlgorithm.Salsa20,
                    ProtectedStreamKey = CryptographicBuffer.DecodeFromBase64String(
                        "FDNbUwE9jt6Y9+syU+btBIOGRxYt2tiUqnb6FXWIF1E="),
                };

                var doc = await FileFormat.ParseContent(
                    decrypted, true, headers);
                Assert.NotNull(doc);

                var root = doc.Root;
                Assert.NotNull(root);
                Assert.Equal("KeePassFile", root.Name.LocalName);
            }
        }
コード例 #4
0
ファイル: PasswordData.cs プロジェクト: Confuset/7Pass-Remake
            GetMasterKey(FileHeaders headers)
        {
            if (headers == null)
                throw new ArgumentNullException("headers");

            return GetMasterKey(headers.TransformSeed,
                headers.TransformRounds);
        }
コード例 #5
0
ファイル: FileFormat.cs プロジェクト: Confuset/7Pass-Remake
        /// <summary>
        /// Parse the headers fields.
        /// </summary>
        /// <param name="input">The input stream.</param>
        /// <param name="buffer">The header bytes reader.</param>
        /// <returns>The file headers.</returns>
        private static async Task<FileHeaders> GetHeaders(
            IInputStream input, IBuffer buffer)
        {
            var result = new FileHeaders();

            while (true)
            {
                buffer = await input.ReadAsync(buffer, 3);
                var field = (HeaderFields)buffer.GetByte(0);
                var size = BitConverter.ToUInt16(buffer.ToArray(1, 2), 0);

                if (size > 0)
                    buffer = await input.ReadAsync(buffer, size);

                switch (field)
                {
                    case HeaderFields.EndOfHeader:
                        return result;

                    case HeaderFields.CompressionFlags:
                        result.UseGZip = buffer.GetByte(0) == 1;
                        break;

                    case HeaderFields.EncryptionIV:
                        result.EncryptionIV = buffer
                            .ToArray().AsBuffer();
                        break;

                    case HeaderFields.MasterSeed:
                        result.MasterSeed = buffer
                            .ToArray().AsBuffer();
                        break;

                    case HeaderFields.StreamStartBytes:
                        result.StartBytes = buffer
                            .ToArray().AsBuffer();
                        break;

                    case HeaderFields.TransformSeed:
                        result.TransformSeed = buffer
                            .ToArray().AsBuffer();
                        break;

                    case HeaderFields.TransformRounds:
                        result.TransformRounds = BitConverter.ToUInt64(
                            buffer.ToArray(), 0);
                        break;

                    case HeaderFields.ProtectedStreamKey:
                        result.ProtectedStreamKey = buffer
                            .ToArray().AsBuffer();
                        break;

                    case HeaderFields.InnerRandomStreamID:
                        result.RandomAlgorithm = (CrsAlgorithm)
                            BitConverter.ToUInt32(buffer.ToArray(), 0);
                        break;
                }
            }
        }
コード例 #6
0
ファイル: FileFormat.cs プロジェクト: Confuset/7Pass-Remake
        private static void Decrypt(FileHeaders headers, XDocument doc)
        {
            var protectedStrings = doc.Descendants("Entry")
                .SelectMany(x => x.Elements("String"))
                .Select(x => x.Element("Value"))
                .Where(x =>
                {
                    var protect = x.Attribute("Protected");
                    return protect != null && (bool)protect;
                });

            IRandomGenerator generator;
            switch (headers.RandomAlgorithm)
            {
                case CrsAlgorithm.ArcFourVariant:
                    generator = new Rc4RandomGenerator(
                        headers.ProtectedStreamKey);
                    break;

                default:
                    generator = new Salsa20RandomGenerator(
                        headers.ProtectedStreamKey);
                    break;
            }

            foreach (var protectedString in protectedStrings)
            {
                var encrypted = Convert.FromBase64String(
                    protectedString.Value);
                var length = encrypted.Length;

                var padding = generator.GetRandomBytes(length);

                for (var i = 0U; i < length; i++)
                    encrypted[i] ^= padding.GetByte(i);

                protectedString.Value = Encoding.UTF8
                    .GetString(encrypted, 0, length);
            }
        }
コード例 #7
0
ファイル: FileFormat.cs プロジェクト: Confuset/7Pass-Remake
        /// <summary>
        /// Verifies the start bytes of the decrypted content stream.
        /// </summary>
        /// <param name="input">The decrypted content stream.</param>
        /// <param name="headers">The database file headers.</param>
        /// <returns><c>true</c> if the bytes match; otherwise, <c>false</c>.</returns>
        /// <exception cref="System.ArgumentNullException">
        /// <paramref name="input"/> and <paramref name="headers"/> cannot be <c>null</c>.
        /// </exception>
        public static Task<bool> VerifyStartBytes(IInputStream input, FileHeaders headers)
        {
            if (headers == null)
                throw new ArgumentNullException("headers");

            return VerifyStartBytes(input, headers.StartBytes);
        }
コード例 #8
0
ファイル: FileFormat.cs プロジェクト: Confuset/7Pass-Remake
 /// <summary>
 /// Verifies the database file headers integrity.
 /// </summary>
 /// <param name="headers">The database file headers.</param>
 /// <param name="doc">The database content.</param>
 /// <returns><c>true</c> if the header is valid; otherwise, <c>false</c>.</returns>
 /// <exception cref="ArgumentNullException">
 /// The <paramref name="headers"/> and <paramref name="doc"/> cannot be <c>null</c>.
 /// </exception>
 public static bool VerifyHeaders(FileHeaders headers, XDocument doc)
 {
     return VerifyHeaders(headers.Hash, doc);
 }
コード例 #9
0
ファイル: FileFormat.cs プロジェクト: Confuset/7Pass-Remake
        /// <summary>
        /// Parses the decrypted content.
        /// </summary>
        /// <param name="decrypted">The input stream.</param>
        /// <param name="useGZip">Set to <c>true</c> to decompress the input stream before parsing.</param>
        /// <returns>The decrypted content.</returns>
        /// <param name="headers">The database file headers.</param>
        /// <exception cref="System.ArgumentNullException">
        /// The <paramref name="decrypted"/> or <paramref name="headers"/> parameter cannot be <c>null</c>.
        /// </exception>
        public static async Task<XDocument> ParseContent(
            IInputStream decrypted, bool useGZip, FileHeaders headers)
        {
            if (decrypted == null) throw new ArgumentNullException("decrypted");
            if (headers == null) throw new ArgumentNullException("headers");

            var deHashed = await HashedBlockFileFormat.Read(decrypted);
            var input = deHashed;

            try
            {
                if (useGZip)
                {
                    input = new GZipStream(input,
                        CompressionMode.Decompress);
                }

                var doc = XDocument.Load(input);
                Decrypt(headers, doc);

                return doc;
            }
            finally
            {
                deHashed.Dispose();
                input.Dispose();
            }
        }