public override int Read(byte[] buffer, int offset, int count)
        {
            HashStream.Position = CurrentSector * DigestSize;
            HashStream.Read(_hashBuffer, 0, DigestSize);

            int bytesRead = base.Read(buffer, 0, count);

            // If a hash is zero the data for the entire block is zero
            if (Type == IntegrityStreamType.Save && _hashBuffer.IsEmpty())
            {
                Array.Clear(buffer, 0, SectorSize);
                return(bytesRead);
            }

            if (bytesRead < SectorSize)
            {
                // Pad out unused portion of block
                Array.Clear(buffer, bytesRead, SectorSize - bytesRead);
            }

            if (!EnableIntegrityChecks)
            {
                return(bytesRead);
            }

            _hash.Initialize();

            if (Type == IntegrityStreamType.Save)
            {
                _hash.TransformBlock(Salt, 0, Salt.Length, null, 0);
            }

            _hash.TransformBlock(buffer, 0, SectorSize, null, 0);
            _hash.TransformFinalBlock(buffer, 0, 0);

            byte[] hash = _hash.Hash;

            if (Type == IntegrityStreamType.Save)
            {
                // This bit is set on all save hashes
                hash[0x1F] |= 0x80;
            }

            if (!Util.ArraysEqual(_hashBuffer, hash))
            {
                throw new InvalidDataException("Hash error!");
            }

            return(bytesRead);
        }
示例#2
0
        public unsafe void TestByteArrayAndStream(int length)
        {
            var array  = new byte[length];
            var random = new Random(0);

            random.NextBytes(array);

            var hash = Create();

            hash.Write(array, 0, array.Length);
            var value = ComputeAndPrint(hash);

            var hash1 = Create();

            fixed(void *parray = array)
            {
                hash1.Write(new IntPtr(parray), (ulong)array.Length);
            }

            var value1 = ComputeAndPrint(hash);

            var stream     = new MemoryStream();
            var hashStream = new HashStream <THash>(stream, Create());

            hashStream.Write(array, 0, array.Length);
            var valueStreamWrite = ComputeAndPrint(hashStream.Hash);

            // Check that backend stream is fine as well
            var outputArray = stream.ToArray();

            Assert.AreEqual(array, outputArray);

            // Reset stream
            hashStream.Position = 0;
            Reset(ref hashStream.Hash);

            var inputArray = new byte[array.Length];
            var readCount  = hashStream.Read(inputArray, 0, array.Length);

            Assert.AreEqual(array.Length, readCount);
            var valueStreamRead = ComputeAndPrint(hashStream.Hash);

            Assert.AreEqual(value, value1);
            Assert.AreEqual(value, valueStreamWrite);
            Assert.AreEqual(value, valueStreamRead);
        }
        public void TestHashStreamRead()
        {
            Random r = new Random();

            byte[] bytes = new byte[1000];
            r.NextBytes(bytes);

            using (HashStream hs = new HashStream(new SHA256Managed(), new MemoryStream(bytes)))
            {
                for (int i = 0; i < 5; i++)
                {
                    while (hs.Position < hs.Length)
                    {
                        hs.ReadByte();
                        int    amt = r.Next(255);
                        byte[] tmp = new byte[amt];
                        hs.Read(tmp, 0, tmp.Length);
                    }
                }

                Hash expect = Hash.SHA256(bytes);
                Hash actual = hs.FinalizeHash();

                Assert.AreEqual(expect, actual);
                Assert.AreEqual(expect.ToArray(), actual.ToArray());
                Assert.AreEqual(expect.ToString(), actual.ToString());

                //still valid after FinalizeHash(); however, hash is restarted
                hs.Position = 0;
                IOStream.Read(hs, bytes.Length);
                actual = hs.FinalizeHash();

                Assert.AreEqual(expect, actual);
                Assert.AreEqual(expect.ToArray(), actual.ToArray());
                Assert.AreEqual(expect.ToString(), actual.ToString());
            }
        }
示例#4
0
        public int Read(byte[] buffer, int offset, int count, IntegrityCheckLevel integrityCheckLevel)
        {
            long blockNum = CurrentSector;

            HashStream.Position = blockNum * DigestSize;
            HashStream.Read(_hashBuffer, 0, DigestSize);

            int bytesRead   = base.Read(buffer, offset, count);
            int bytesToHash = SectorSize;

            if (bytesRead == 0)
            {
                return(0);
            }

            // If a hash is zero the data for the entire block is zero
            if (Type == IntegrityStreamType.Save && _hashBuffer.IsEmpty())
            {
                Array.Clear(buffer, offset, SectorSize);
                BlockValidities[blockNum] = Validity.Valid;
                return(bytesRead);
            }

            if (bytesRead < SectorSize)
            {
                // Pad out unused portion of block
                Array.Clear(buffer, offset + bytesRead, SectorSize - bytesRead);

                // Partition FS hashes don't pad out an incomplete block
                if (Type == IntegrityStreamType.PartitionFs)
                {
                    bytesToHash = bytesRead;
                }
            }

            if (BlockValidities[blockNum] == Validity.Invalid && integrityCheckLevel == IntegrityCheckLevel.ErrorOnInvalid)
            {
                throw new InvalidDataException("Hash error!");
            }

            if (integrityCheckLevel == IntegrityCheckLevel.None)
            {
                return(bytesRead);
            }

            if (BlockValidities[blockNum] != Validity.Unchecked)
            {
                return(bytesRead);
            }

            byte[] hash = DoHash(buffer, offset, bytesToHash);

            Validity validity = Util.ArraysEqual(_hashBuffer, hash) ? Validity.Valid : Validity.Invalid;

            BlockValidities[blockNum] = validity;

            if (validity == Validity.Invalid && integrityCheckLevel == IntegrityCheckLevel.ErrorOnInvalid)
            {
                throw new InvalidDataException("Hash error!");
            }

            return(bytesRead);
        }