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)); }
public void TestReadOnlySpan() { var rnd = new Random(); for (var c = 0; c < count; c++) { var memSize = rnd.Next(1, 10_000); var mem = new byte[(memSize + 4) * writeRepeatCount]; var answer = new byte[memSize * writeRepeatCount]; rnd.NextBytes(answer); var span1 = new SpanStream(mem); var span2 = new SpanStream(mem); for (var i = 0; i < writeRepeatCount; i++) { var a = new Span <byte>(answer).Slice(memSize * i, memSize); span1.Write(a); } // Ensure span is not zero var ac = 0; for (var wrc = 0; wrc < writeRepeatCount; wrc++) { var r = span2.ReadBytes(memSize); for (var i = 0; i < r.Length; i++) { Assert.Equal(answer[ac++], r[i]); } } Assert.Throws <ArgumentException>(() => { var s = new SpanStream(mem); s.Write(new Span <byte>(new byte[mem.Length + 1])); }); } }