<PackageReference Include="Azure.Storage.Blobs" Version="12.26.0-beta.1" />

ContentHasher

static class ContentHasher
Hashes Storage content.
using Azure.Core; using System; using System.IO; using System.Runtime.CompilerServices; using System.Security.Cryptography; using System.Threading; using System.Threading.Tasks; namespace Azure.Storage { internal static class ContentHasher { internal class GetHashResult { public static GetHashResult Empty { get; } = new GetHashResult(1, default(ReadOnlyMemory<byte>)); public StorageChecksumAlgorithm Algorithm { get; } public ReadOnlyMemory<byte> Checksum { get; } public ReadOnlyMemory<byte> MD5 { get { if ((int)Algorithm != 2) return default(ReadOnlyMemory<byte>); return Checksum; } } public ReadOnlyMemory<byte> StorageCrc64 { get { if ((int)Algorithm != 3) return default(ReadOnlyMemory<byte>); return Checksum; } } public byte[] MD5AsArray { get { ReadOnlyMemory<byte> mD = MD5; if (!mD.IsEmpty) { mD = MD5; return mD.ToArray(); } return null; } } public byte[] StorageCrc64AsArray { get { ReadOnlyMemory<byte> storageCrc = StorageCrc64; if (!storageCrc.IsEmpty) { storageCrc = StorageCrc64; return storageCrc.ToArray(); } return null; } } private GetHashResult(StorageChecksumAlgorithm algorithm, ReadOnlyMemory<byte> checksum) { Algorithm = algorithm; Checksum = checksum; } public static GetHashResult FromStorageCrc64(ReadOnlyMemory<byte> checksum) { return new GetHashResult(3, checksum); } public static GetHashResult FromMD5(ReadOnlyMemory<byte> checksum) { return new GetHashResult(2, checksum); } } public delegate int GetFinalStreamHash (Span<byte> destination); internal static int GetHashSizeInBytes(StorageChecksumAlgorithm algorithm) { StorageChecksumAlgorithm val = algorithm.ResolveAuto(); switch (val - 1) { case 0: return 0; case 1: return 16; case 2: return 8; default: throw Errors.InvalidArgument("algorithm"); } } internal static UploadTransferValidationOptions ToUploadTransferValidationOptions(this GetHashResult hashResult) { if (hashResult == null) { UploadTransferValidationOptions val = new UploadTransferValidationOptions(); val.set_ChecksumAlgorithm(1); return val; } UploadTransferValidationOptions val2 = new UploadTransferValidationOptions(); val2.set_ChecksumAlgorithm(hashResult.Algorithm); val2.set_PrecalculatedChecksum(hashResult.Checksum); return val2; } [AsyncStateMachine(typeof(<AssertResponseHashMatchInternal>d__3))] public static Task AssertResponseHashMatchInternal(Stream content, StorageChecksumAlgorithm algorithm, Response response, bool async, CancellationToken cancellationToken) { <AssertResponseHashMatchInternal>d__3 stateMachine = default(<AssertResponseHashMatchInternal>d__3); stateMachine.<>t__builder = AsyncTaskMethodBuilder.Create(); stateMachine.content = content; stateMachine.algorithm = algorithm; stateMachine.response = response; stateMachine.async = async; stateMachine.cancellationToken = cancellationToken; stateMachine.<>1__state = -1; stateMachine.<>t__builder.Start(ref stateMachine); return stateMachine.<>t__builder.Task; } public static void AssertResponseHashMatch(byte[] content, int offset, int count, StorageChecksumAlgorithm algorithm, Response response) { AssertResponseHashMatch(GetHash(BinaryData.FromBytes(new ReadOnlyMemory<byte>(content, offset, count)), algorithm), algorithm, response); } private static void AssertResponseHashMatch(GetHashResult computedHash, StorageChecksumAlgorithm algorithm, Response response) { if (computedHash == null) throw Errors.ArgumentNull("computedHash"); if (response == null) throw Errors.ArgumentNull("response"); StorageChecksumAlgorithm val = algorithm.ResolveAuto(); ReadOnlyMemory<byte> readOnlyMemory; if ((int)val != 2) { if ((int)val != 3) throw Errors.InvalidArgument("algorithm"); readOnlyMemory = computedHash.StorageCrc64; if (!readOnlyMemory.Span.SequenceEqual(response.get_Headers().TryGetValue("x-ms-content-crc64", out byte[] value) ? value : null)) throw Errors.HashMismatch("x-ms-content-crc64"); } else { readOnlyMemory = computedHash.MD5; if (!readOnlyMemory.Span.SequenceEqual(response.get_Headers().TryGetValue("Content-MD5", out byte[] value2) ? value2 : null)) throw Errors.HashMismatch("Content-MD5"); } } [AsyncStateMachine(typeof(<GetHashOrDefaultInternal>d__6))] public static Task<GetHashResult> GetHashOrDefaultInternal(Stream content, UploadTransferValidationOptions options, bool async, CancellationToken cancellationToken) { <GetHashOrDefaultInternal>d__6 stateMachine = default(<GetHashOrDefaultInternal>d__6); stateMachine.<>t__builder = AsyncTaskMethodBuilder<GetHashResult>.Create(); stateMachine.content = content; stateMachine.options = options; stateMachine.async = async; stateMachine.cancellationToken = cancellationToken; stateMachine.<>1__state = -1; stateMachine.<>t__builder.Start(ref stateMachine); return stateMachine.<>t__builder.Task; } public static GetHashResult GetHashOrDefault(BinaryData content, UploadTransferValidationOptions options) { if (GetHashOrDefaultTryFromOptions(options, out GetHashResult result)) return result; return GetHash(content, options.get_ChecksumAlgorithm()); } private static bool GetHashOrDefaultTryFromOptions(UploadTransferValidationOptions options, out GetHashResult result) { if (options == null || (int)options.get_ChecksumAlgorithm() == 1) { result = null; return true; } if (!options.get_PrecalculatedChecksum().IsEmpty) { StorageChecksumAlgorithm val = options.get_ChecksumAlgorithm().ResolveAuto(); GetHashResult getHashResult; if ((int)val != 2) { if ((int)val != 3) throw Errors.InvalidArgument("ChecksumAlgorithm"); getHashResult = GetHashResult.FromStorageCrc64(options.get_PrecalculatedChecksum()); } else getHashResult = GetHashResult.FromMD5(options.get_PrecalculatedChecksum()); result = getHashResult; return true; } result = null; return false; } [AsyncStateMachine(typeof(<GetHashInternal>d__9))] public static Task<GetHashResult> GetHashInternal(Stream content, StorageChecksumAlgorithm algorithmIdentifier, bool async, CancellationToken cancellationToken) { <GetHashInternal>d__9 stateMachine = default(<GetHashInternal>d__9); stateMachine.<>t__builder = AsyncTaskMethodBuilder<GetHashResult>.Create(); stateMachine.content = content; stateMachine.algorithmIdentifier = algorithmIdentifier; stateMachine.async = async; stateMachine.cancellationToken = cancellationToken; stateMachine.<>1__state = -1; stateMachine.<>t__builder.Start(ref stateMachine); return stateMachine.<>t__builder.Task; } public static GetHashResult GetHash(BinaryData content, StorageChecksumAlgorithm algorithmIdentifier) { <>c__DisplayClass10_0 <>c__DisplayClass10_ = default(<>c__DisplayClass10_0); <>c__DisplayClass10_.content = content; StorageChecksumAlgorithm val = algorithmIdentifier.ResolveAuto(); if ((int)val == 2) return GetHashResult.FromMD5(MD5.Create().ComputeHash(<>c__DisplayClass10_.content.ToArray())); if ((int)val != 3) throw Errors.InvalidArgument("algorithmIdentifier"); return GetHashResult.FromStorageCrc64(<GetHash>g__computeCrc|10_0(StorageCrc64HashAlgorithm.Create(), ref <>c__DisplayClass10_)); } public static (Stream Stream, GetFinalStreamHash GetCurrentStreamHash, int HashSize, IDisposable Disposable) SetupChecksumCalculatingReadStream(Stream stream, StorageChecksumAlgorithm algorithmIdentifier) { IHasher hasher = GetHasher(algorithmIdentifier); IHasher hasher2 = hasher; Stream readStream = ChecksumCalculatingStream.GetReadStream(stream, hasher2.AppendHash); IHasher hasher3 = hasher; return (readStream, hasher3.GetFinalHash, hasher.HashSizeInBytes, hasher); } private static IHasher GetHasher(StorageChecksumAlgorithm algorithmIdentifier) { StorageChecksumAlgorithm val = algorithmIdentifier.ResolveAuto(); if ((int)val == 2) return new HashAlgorithmHasher(MD5.Create()); if ((int)val != 3) throw Errors.InvalidArgument("algorithmIdentifier"); return new NonCryptographicHashAlgorithmHasher(StorageCrc64HashAlgorithm.Create()); } [AsyncStateMachine(typeof(<ComputeHashInternal>d__14))] private static Task<byte[]> ComputeHashInternal(Stream content, IHasher hasher, bool async, CancellationToken cancellationToken) { <ComputeHashInternal>d__14 stateMachine = default(<ComputeHashInternal>d__14); stateMachine.<>t__builder = AsyncTaskMethodBuilder<byte[]>.Create(); stateMachine.content = content; stateMachine.hasher = hasher; stateMachine.async = async; stateMachine.cancellationToken = cancellationToken; stateMachine.<>1__state = -1; stateMachine.<>t__builder.Start(ref stateMachine); return stateMachine.<>t__builder.Task; } public static IHasher GetHasherFromAlgorithmId(StorageChecksumAlgorithm algorithm) { StorageChecksumAlgorithm val = algorithm.ResolveAuto(); switch (val - 1) { case 0: return null; case 1: return new HashAlgorithmHasher(MD5.Create()); case 2: return new NonCryptographicHashAlgorithmHasher(StorageCrc64HashAlgorithm.Create()); default: throw Errors.InvalidArgument("algorithm"); } } public static (ReadOnlyMemory<byte> Checksum, StorageChecksumAlgorithm Algorithm) GetResponseChecksumOrDefault(Response response) { if (response.get_Headers().TryGetValue("x-ms-content-crc64", out byte[] value)) return (value, 3); if (response.get_Headers().TryGetValue("Content-MD5", out byte[] value2)) return (value2, 2); return (ReadOnlyMemory<byte>.Empty, 1); } } }