internal static DatabaseInfo ParseHeader(SpanStream io, byte[] compositeKey)
        {
            var header = io.Read <Header>();

            if (header.Signature1 != Magic1)
            {
                throw MakeInvalidFormatError($"primary file signature is invalid: {header.Signature1:x8}");
            }

            if (!Magic2.Contains(header.Signature2))
            {
                throw MakeInvalidFormatError($"secondary file signature is invalid: {header.Signature2:x8}");
            }

            if (header.MajorVersion != Version4)
            {
                throw MakeUnsupportedError($"Version {header.MajorVersion}.{header.MinorVersion}");
            }

            var info = ReadEncryptionInfo(ref io);

            var headerSize = io.Position;

            io.Rewind();
            var headerBytes = io.ReadBytes(headerSize);

            var computedHash = Crypto.Sha256(headerBytes);
            var storedHash   = io.ReadBytes(32);

            if (!Crypto.AreEqual(storedHash, computedHash))
            {
                throw MakeInvalidFormatError("Header hash doesn't match");
            }

            var storedHeaderMac = io.ReadBytes(32);

            var derivedKey = DeriveMasterKey(compositeKey, info.Kdf);

            var(encryptionKey, hmacKey) = Util.DeriveDatabaseKeys(derivedKey, info.Seed);

            var blockHmacKey      = Util.ComputeBlockHmacKey(hmacKey, ulong.MaxValue);
            var computedHeaderMac = Crypto.HmacSha256(blockHmacKey, headerBytes);

            if (!Crypto.AreEqual(storedHeaderMac, computedHeaderMac))
            {
                throw MakeInvalidFormatError("Header MAC doesn't match");
            }

            return(new DatabaseInfo(headerSize: io.Position,
                                    isCompressed: info.IsCompressed,
                                    cipher: info.Cipher,
                                    encryptionKey: encryptionKey,
                                    iv: info.Iv,
                                    hmacKey: hmacKey));
        }