Esempio n. 1
0
        public void TestStreamReadWrite()
        {
            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);

                for (var bc = 1; bc < writeRepeatCount; bc++)
                {
                    for (var offset = 0; offset < bc; offset++)
                    {
                        var span1 = new SpanStream(mem);
                        var span2 = new SpanStream(mem);

                        span1.Write(answer, offset, bc - offset);
                        var buffer = new byte[bc + offset];
                        span2.Read(buffer, offset, bc - offset);

                        Assert.Equal(new Span <byte>(answer).Slice(offset, bc - offset).ToArray(), new Span <byte>(buffer).Slice(offset, bc - offset).ToArray());
                    }
                }

                Assert.Throws <ArgumentNullException>(() =>
                {
                    var s = new SpanStream(mem);
                    s.Read(null, 0, 1);
                });
            }
        }
Esempio n. 2
0
        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));
        }