Пример #1
0
        /// <summary>
        /// Write password data with filtering original data. Available filters must be added to instance before this method is called.
        /// </summary>
        public virtual void WritePasswordToFile(byte[] masterPasswordHash, PasswordFileBody passwordData)
        {
            if (!PasswordFile.CheckDirectoryWritable(Directory.GetParent(this.Filepath).FullName))
            {
                throw new IOException();
            }

            MemoryStream decryptedData = new MemoryStream();
            BinaryFormatter formatter = new BinaryFormatter();

            // Apply data filters
            FilteredData filteredData = IOFilterProcessor.ApplyFilter(passwordData, this.FilterOrder);

            // Convert FilteredData object into MemoryStream
            formatter.Serialize(decryptedData, filteredData);
            decryptedData.Position = 0;

            // Get token
            byte[] token = Utility.Get16BytesHash(DateTime.Now);

            // Do encryption here
            byte[] encryptedBytes = Utility.Encrypt(decryptedData.ToArray(), masterPasswordHash, token);

            // Construct header
            PasswordHeader header = new PasswordHeader();
            header.Token = token;
            header.CombinedMasterPasswordHash = Utility.Scramble(masterPasswordHash, token, LocalConfig.MasterPasswordHashedKeySize);

            // Write filtered data to the file
            using (FileStream fs = new FileStream(this.Filepath, FileMode.Create, FileAccess.Write))
            {
                // Write header
                using (BinaryWriter writer = new BinaryWriter(fs))
                {
                    writer.Write(header.Token); // Write token
                    writer.Write(header.CombinedMasterPasswordHash); // Write hash
                    // Write Filtered data which has been encrypted
                    writer.Write(encryptedBytes);
                }
            }
        }
Пример #2
0
        /// <summary>
        /// Check whether password hash is valid for specified password file.
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        public static bool ChallengeHashedMasterPassword(string filePath, byte[] challengingPasswordHash)
        {
            // When password file does not exist, throw an exception.
            if (!File.Exists(filePath))
            {
                throw new FileNotFoundException(filePath);
            }

            // Parse file header
            using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
            {
                using (BinaryReader reader = new BinaryReader(fs))
                {
                    PasswordHeader header = new PasswordHeader();
                    header.Token = reader.ReadBytes(LocalConfig.HeaderTokenSize);
                    header.CombinedMasterPasswordHash = reader.ReadBytes(LocalConfig.MasterPasswordHashedKeySize);

                    return CompareHashes(header.CombinedMasterPasswordHash, Utility.Scramble(challengingPasswordHash, header.Token, LocalConfig.MasterPasswordHashedKeySize));
                }
            }
        }
Пример #3
0
        /// <summary>
        /// Read password file with removing data filter. Available filters must be added to instance before this method is called.
        /// </summary>
        /// <exception cref="FileNotFoundException">Password file does not exist</exception>
        /// <exception cref="InvalidMasterPasswordException">Master password is invalid</exception>
        public virtual PasswordFileBody ReadPasswordFromFile(byte[] masterPasswordHash, PasswordFileBody defaultPasswordFileBody = null)
        {
            if (masterPasswordHash.Length != LocalConfig.MasterPasswordHashedKeySize)
            {
                throw new ArgumentException();
            }

            // When password file does not exist, throw an exception.
            if (!File.Exists(this.Filepath))
            {
                throw new FileNotFoundException(this.Filepath);
            }

            FilteredData filteredData;

            // Parse file header
            using (FileStream fs = new FileStream(this.Filepath, FileMode.Open, FileAccess.Read))
            {
                using (BinaryReader reader = new BinaryReader(fs))
                {
                    PasswordHeader header = new PasswordHeader();
                    header.Token = reader.ReadBytes(LocalConfig.HeaderTokenSize);
                    header.CombinedMasterPasswordHash = reader.ReadBytes(LocalConfig.MasterPasswordHashedKeySize);

                    // Check masterPasswordHash is valid
                    if (!CheckMasterPasswordHash(header.CombinedMasterPasswordHash, masterPasswordHash, header.Token))
                    {
                        throw new InvalidMasterPasswordException();
                    }

                    MemoryStream encryptedData = new MemoryStream();
                    BinaryFormatter formatter = new BinaryFormatter();

                    encryptedData = Utility.GetMemoryStream(reader);
                    encryptedData.Position = 0;
                    // Do decryption against loaded MemoryStream
                    byte[] decryptedBytes = Utility.Decrypt(encryptedData.ToArray(), masterPasswordHash, header.Token);
                    MemoryStream decryptedData = new MemoryStream(decryptedBytes);
                    decryptedData.Position = 0;

                    // Get filtered data
                    filteredData = (FilteredData)formatter.Deserialize(decryptedData);
                }
            }

            // Parse filter data
            return (PasswordFileBody)IOFilterProcessor.RemoveFilter(filteredData);
        }