예제 #1
0
        /// <summary>
        /// Ensures the writer's serialization settings are correct for the given user preferences.
        /// </summary>
        /// <param name="cipher">The algorithm to use for encrypting the database.</param>
        /// <param name="rngAlgorithm">The random number generator used for String protection.</param>
        /// <param name="compression">The document compression algorithm.</param>
        /// <param name="kdfParams">Recipe for transforming the raw key. This will be reseeded.</param>
        private void SeedHeaderData(
            EncryptionAlgorithm cipher,
            RngAlgorithm rngAlgorithm,
            CompressionAlgorithm compression,
            KdfParameters kdfParams
            )
        {
            if (kdfParams == null)
            {
                throw new ArgumentNullException(nameof(kdfParams));
            }

            KdbxVersion version = KdbxVersion.Three;

            if (cipher == EncryptionAlgorithm.ChaCha20 || rngAlgorithm == RngAlgorithm.ChaCha20 ||
                !kdfParams.Uuid.Equals(AesParameters.AesUuid))
            {
                DebugHelper.Trace("Using KDBX4 for serialization due to header parameters");
                version = KdbxVersion.Four;
            }

            this.parameters = new KdbxSerializationParameters(version)
            {
                Compression = compression
            };

            // "Stream start bytes" are random data encrypted at the beginning
            // of the KDBX data block. They have been superceded by HMAC authentication.
            IBuffer streamStartBytes;

            if (this.parameters.UseHmacBlocks)
            {
                streamStartBytes = new byte[0].AsBuffer();
            }
            else
            {
                streamStartBytes = CryptographicBuffer.GenerateRandom(32);
            }

            HeaderData = new KdbxHeaderData(KdbxHeaderData.Mode.Write)
            {
                Cipher               = cipher, // This will automatically set EncryptionIV
                Compression          = compression,
                MasterSeed           = CryptographicBuffer.GenerateRandom(32),
                KdfParameters        = kdfParams.Reseed(),
                StreamStartBytes     = streamStartBytes,
                InnerRandomStreamKey = CryptographicBuffer.GenerateRandom(32).ToArray(),
                InnerRandomStream    = rngAlgorithm
            };
        }
예제 #2
0
        /// <summary>
        /// Validates that the document has a valid, supported KeePass version.
        /// </summary>
        /// <param name="reader">A DataReader over the document file.</param>
        /// <returns>A Task representing the result of the validation.</returns>
        private async Task <ReaderResult> ValidateVersion(DataReader reader)
        {
            await reader.LoadAsync(4);

            uint version            = reader.ReadUInt32();
            uint maskedVersion      = version & FileVersionMask;
            uint maskedLegacyFormat = FileVersion32_3 & FileVersionMask;
            uint maskedModernFormat = FileVersion32_4 & FileVersionMask;

            if (maskedVersion <= maskedLegacyFormat)
            {
                this.parameters = new KdbxSerializationParameters(KdbxVersion.Three);
            }
            else if (maskedVersion == maskedModernFormat)
            {
                this.parameters = new KdbxSerializationParameters(KdbxVersion.Four);
            }
            else
            {
                DebugHelper.Assert(maskedVersion > maskedModernFormat);
                return(new ReaderResult(KdbxParserCode.Version));
            }

            // Based on the version, initialize a map of required headers
            foreach (OuterHeaderField value in Enum.GetValues(typeof(OuterHeaderField))
                     .Cast <OuterHeaderField>())
            {
                MemberInfo enumMember = typeof(OuterHeaderField).GetMember(value.ToString())
                                        .FirstOrDefault();

                // Skip optional headers regardless of version
                if (enumMember.GetCustomAttribute <OptionalAttribute>() != null)
                {
                    continue;
                }

                // Get the headers that support this version
                KdbxVersionSupportAttribute versionAttr = enumMember.GetCustomAttribute <KdbxVersionSupportAttribute>();
                if (versionAttr == null || versionAttr.Supports(this.parameters.Version))
                {
                    this.headerInitializationMap[value] = false;
                }
            }

            return(ReaderResult.Success);
        }