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); }
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()); } }
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); }