public void Update_ThrowsAfterGetHashCalled() { using (var hashFunc = new Sha512HashFunction()) { hashFunc.Update(_input, 0, count: 1); hashFunc.GetHash(); Assert.Throws <InvalidOperationException>(() => hashFunc.Update(_input, 1, count: 1)); } }
public void Update_SupportsIncrementalUpdates() { using (var hashFunc = new Sha512HashFunction()) { for (var i = 0; i < _input.Length; ++i) { hashFunc.Update(_input, i, count: 1); } var actualResult = hashFunc.GetHash(); Assert.Equal(_expectedResult, actualResult); } }
/// <summary> /// Hashes given byte array with a specified HashAlgorithm wrapper which works cross platform. /// </summary> /// <param name="hashFunc">HashAlgorithm wrapper used to hash contents cross platform</param> /// <param name="bytes">Content to hash</param> internal static void HashBytes(Sha512HashFunction hashFunc, byte[] bytes) { if (hashFunc == null) { throw new ArgumentNullException(nameof(hashFunc)); } if (bytes == null || bytes.Length == 0) { throw new ArgumentException(Strings.ArgumentCannotBeNullOrEmpty, nameof(bytes)); } hashFunc.Update(bytes, 0, bytes.Length); }
/// <summary> /// Hashes given byte array with a specified HashAlgorithm wrapper which works cross platform. /// </summary> /// <param name="hashFunc">HashAlgorithm wrapper used to hash contents cross platform</param> /// <param name="bytes">Content to hash</param> /// <param name="count">The number of bytes in the input byte array to use as data.</param> internal static void HashBytes(Sha512HashFunction hashFunc, byte[] bytes, int count) { if (hashFunc == null) { throw new ArgumentNullException(nameof(hashFunc)); } if (bytes == null || bytes.Length == 0) { throw new ArgumentException(Strings.ArgumentCannotBeNullOrEmpty, nameof(bytes)); } if (count <= 0 || bytes.Length < count) { throw new ArgumentOutOfRangeException(nameof(count)); } hashFunc.Update(bytes, offset: 0, count); }
internal static string GetPackageContentHash(BinaryReader reader) { using (var hashFunc = new Sha512HashFunction()) { // skip validating signature entry since we're just trying to get the content hash here instead of // verifying signature entry. var metadata = SignedPackageArchiveIOUtility.ReadSignedArchiveMetadata(reader, validateSignatureEntry: false); var signatureCentralDirectoryHeader = metadata.GetPackageSignatureFileCentralDirectoryHeaderMetadata(); var centralDirectoryRecordsWithoutSignature = RemoveSignatureAndOrderByOffset(metadata); // Read and hash from the start of the archive to the start of the file headers reader.BaseStream.Seek(offset: 0, origin: SeekOrigin.Begin); SignedPackageArchiveIOUtility.ReadAndHashUntilPosition(reader, hashFunc, metadata.StartOfLocalFileHeaders); // Read and hash file headers foreach (var record in centralDirectoryRecordsWithoutSignature) { reader.BaseStream.Seek(offset: record.OffsetToLocalFileHeader, origin: SeekOrigin.Begin); SignedPackageArchiveIOUtility.ReadAndHashUntilPosition(reader, hashFunc, record.OffsetToLocalFileHeader + record.FileEntryTotalSize); } // Order central directory records by their position centralDirectoryRecordsWithoutSignature.Sort((x, y) => x.Position.CompareTo(y.Position)); // Update offset of any central directory record that has a file entry after signature foreach (var record in centralDirectoryRecordsWithoutSignature) { reader.BaseStream.Seek(offset: record.Position, origin: SeekOrigin.Begin); // Hash from the start of the central directory record until the relative offset of local file header (42 from the start of central directory record, including signature length) SignedPackageArchiveIOUtility.ReadAndHashUntilPosition(reader, hashFunc, reader.BaseStream.Position + 42); var relativeOffsetOfLocalFileHeader = (uint)(reader.ReadUInt32() + record.ChangeInOffset); HashUInt32(hashFunc, relativeOffsetOfLocalFileHeader); // Continue hashing file name, extra field, and file comment fields. SignedPackageArchiveIOUtility.ReadAndHashUntilPosition(reader, hashFunc, reader.BaseStream.Position + record.HeaderSize - CentralDirectoryHeader.SizeInBytesOfFixedLengthFields); } reader.BaseStream.Seek(offset: metadata.EndOfCentralDirectory, origin: SeekOrigin.Begin); // Hash until total entries in end of central directory record (8 bytes from the start of EOCDR) SignedPackageArchiveIOUtility.ReadAndHashUntilPosition(reader, hashFunc, metadata.EndOfCentralDirectory + 8); var eocdrTotalEntries = (ushort)(reader.ReadUInt16() - 1); var eocdrTotalEntriesOnDisk = (ushort)(reader.ReadUInt16() - 1); HashUInt16(hashFunc, eocdrTotalEntries); HashUInt16(hashFunc, eocdrTotalEntriesOnDisk); // update the central directory size by substracting the size of the package signature file's central directory header var eocdrSizeOfCentralDirectory = (uint)(reader.ReadUInt32() - signatureCentralDirectoryHeader.HeaderSize); HashUInt32(hashFunc, eocdrSizeOfCentralDirectory); var eocdrOffsetOfCentralDirectory = reader.ReadUInt32() - (uint)signatureCentralDirectoryHeader.FileEntryTotalSize; HashUInt32(hashFunc, eocdrOffsetOfCentralDirectory); // Hash until the end of the reader SignedPackageArchiveIOUtility.ReadAndHashUntilPosition(reader, hashFunc, reader.BaseStream.Length); hashFunc.Update(new byte[0], offset: 0, count: 0); return(hashFunc.GetHash()); } }