diff --git a/src/Common/src/Internal/Cryptography/HashProviderCng.cs b/src/Common/src/Internal/Cryptography/HashProviderCng.cs index cf44a9ee8efe..83e117dcd5e1 100644 --- a/src/Common/src/Internal/Cryptography/HashProviderCng.cs +++ b/src/Common/src/Internal/Cryptography/HashProviderCng.cs @@ -3,7 +3,7 @@ // See the LICENSE file in the project root for more information. using System; - +using System.Diagnostics; using Microsoft.Win32.SafeHandles; using NTSTATUS = Interop.BCrypt.NTSTATUS; using BCryptOpenAlgorithmProviderFlags = Interop.BCrypt.BCryptOpenAlgorithmProviderFlags; @@ -68,12 +68,7 @@ public HashProviderCng(string hashAlgId, byte[] key) public sealed override unsafe void AppendHashData(ReadOnlySpan source) { - NTSTATUS ntStatus; - fixed (byte* pRgb = &source.DangerousGetPinnableReference()) - { - ntStatus = Interop.BCrypt.BCryptHashData(_hHash, pRgb, source.Length, 0); - - } + NTSTATUS ntStatus = Interop.BCrypt.BCryptHashData(_hHash, source, source.Length, 0); if (ntStatus != NTSTATUS.STATUS_SUCCESS) { throw Interop.BCrypt.CreateCryptographicException(ntStatus); @@ -82,18 +77,14 @@ public sealed override unsafe void AppendHashData(ReadOnlySpan source) public sealed override byte[] FinalizeHashAndReset() { - byte[] hash = new byte[_hashSize]; - NTSTATUS ntStatus = Interop.BCrypt.BCryptFinishHash(_hHash, hash, hash.Length, 0); - if (ntStatus != NTSTATUS.STATUS_SUCCESS) - { - throw Interop.BCrypt.CreateCryptographicException(ntStatus); - } - - ResetHashObject(); + var hash = new byte[_hashSize]; + bool success = TryFinalizeHashAndReset(hash, out int bytesWritten); + Debug.Assert(success); + Debug.Assert(hash.Length == bytesWritten); return hash; } - public override unsafe bool TryFinalizeHashAndReset(Span destination, out int bytesWritten) + public override bool TryFinalizeHashAndReset(Span destination, out int bytesWritten) { if (destination.Length < _hashSize) { @@ -101,11 +92,7 @@ public override unsafe bool TryFinalizeHashAndReset(Span destination, out return false; } - NTSTATUS ntStatus; - fixed (byte* ptr = &destination.DangerousGetPinnableReference()) - { - ntStatus = Interop.BCrypt.BCryptFinishHash(_hHash, ptr, _hashSize, 0); - } + NTSTATUS ntStatus = Interop.BCrypt.BCryptFinishHash(_hHash, destination, _hashSize, 0); if (ntStatus != NTSTATUS.STATUS_SUCCESS) { throw Interop.BCrypt.CreateCryptographicException(ntStatus); diff --git a/src/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Digest.cs b/src/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Digest.cs index ff3857a60308..c1a1cc6cac83 100644 --- a/src/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Digest.cs +++ b/src/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Digest.cs @@ -16,11 +16,27 @@ internal static partial class AppleCrypto [DllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_DigestCreate")] internal static extern SafeDigestCtxHandle DigestCreate(PAL_HashAlgorithm algorithm, out int cbDigest); + internal static unsafe int DigestUpdate(SafeDigestCtxHandle ctx, ReadOnlySpan pbData, int cbData) + { + fixed (byte* pbDataPtr = &pbData.DangerousGetPinnableReference()) + { + return DigestUpdate(ctx, pbDataPtr, cbData); + } + } + [DllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_DigestUpdate")] - internal static extern unsafe int DigestUpdate(SafeDigestCtxHandle ctx, byte* pbData, int cbData); + private static extern unsafe int DigestUpdate(SafeDigestCtxHandle ctx, byte* pbData, int cbData); + + internal static unsafe int DigestFinal(SafeDigestCtxHandle ctx, Span pbOutput, int cbOutput) + { + fixed (byte* pbOutputPtr = &pbOutput.DangerousGetPinnableReference()) + { + return DigestFinal(ctx, pbOutputPtr, cbOutput); + } + } [DllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_DigestFinal")] - internal static extern unsafe int DigestFinal(SafeDigestCtxHandle ctx, byte* pbOutput, int cbOutput); + private static extern unsafe int DigestFinal(SafeDigestCtxHandle ctx, byte* pbOutput, int cbOutput); } } diff --git a/src/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Hmac.cs b/src/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Hmac.cs index 117d3b4bcf83..f023f4aa7f24 100644 --- a/src/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Hmac.cs +++ b/src/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Hmac.cs @@ -17,13 +17,29 @@ internal static partial class AppleCrypto internal static extern SafeHmacHandle HmacCreate(PAL_HashAlgorithm algorithm, ref int cbDigest); [DllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_HmacInit")] - internal static extern unsafe int HmacInit(SafeHmacHandle ctx, byte* pbKey, int cbKey); + internal static extern unsafe int HmacInit(SafeHmacHandle ctx, [In] byte[] pbKey, int cbKey); + + internal static unsafe int HmacUpdate(SafeHmacHandle ctx, ReadOnlySpan pbData, int cbData) + { + fixed (byte* pbDataPtr = &pbData.DangerousGetPinnableReference()) + { + return HmacUpdate(ctx, pbDataPtr, cbData); + } + } [DllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_HmacUpdate")] - internal static extern unsafe int HmacUpdate(SafeHmacHandle ctx, byte* pbData, int cbData); + private static extern unsafe int HmacUpdate(SafeHmacHandle ctx, byte* pbData, int cbData); + + internal static unsafe int HmacFinal(SafeHmacHandle ctx, ReadOnlySpan pbOutput, int cbOutput) + { + fixed (byte* pbOutputPtr = &pbOutput.DangerousGetPinnableReference()) + { + return HmacFinal(ctx, pbOutputPtr, cbOutput); + } + } [DllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_HmacFinal")] - internal static extern unsafe int HmacFinal(SafeHmacHandle ctx, byte* pbOutput, int cbOutput); + private static extern unsafe int HmacFinal(SafeHmacHandle ctx, byte* pbOutput, int cbOutput); } } diff --git a/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EVP.cs b/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EVP.cs index b3e441702671..ee9ac3571686 100644 --- a/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EVP.cs +++ b/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EVP.cs @@ -19,8 +19,16 @@ internal static partial class Crypto [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpDigestReset")] internal extern static int EvpDigestReset(SafeEvpMdCtxHandle ctx, IntPtr type); + internal static unsafe int EvpDigestUpdate(SafeEvpMdCtxHandle ctx, ReadOnlySpan d, int cnt) + { + fixed (byte* dPtr = &d.DangerousGetPinnableReference()) + { + return EvpDigestUpdate(ctx, dPtr, cnt); + } + } + [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpDigestUpdate")] - internal extern static unsafe int EvpDigestUpdate(SafeEvpMdCtxHandle ctx, byte* d, int cnt); + private extern static unsafe int EvpDigestUpdate(SafeEvpMdCtxHandle ctx, byte* d, int cnt); [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpDigestFinalEx")] internal extern static unsafe int EvpDigestFinalEx(SafeEvpMdCtxHandle ctx, byte* md, ref uint s); diff --git a/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Hmac.cs b/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Hmac.cs index f57ebfb0a659..f740390b661c 100644 --- a/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Hmac.cs +++ b/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Hmac.cs @@ -19,8 +19,16 @@ internal static partial class Crypto [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_HmacReset")] internal extern static int HmacReset(SafeHmacCtxHandle ctx); + internal static unsafe int HmacUpdate(SafeHmacCtxHandle ctx, ReadOnlySpan data, int len) + { + fixed (byte* dataPtr = &data.DangerousGetPinnableReference()) + { + return HmacUpdate(ctx, dataPtr, len); + } + } + [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_HmacUpdate")] - internal extern static unsafe int HmacUpdate(SafeHmacCtxHandle ctx, byte* data, int len); + private extern static unsafe int HmacUpdate(SafeHmacCtxHandle ctx, byte* data, int len); [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_HmacFinal")] internal extern static unsafe int HmacFinal(SafeHmacCtxHandle ctx, byte* data, ref int len); diff --git a/src/Common/src/Interop/Windows/BCrypt/Interop.BCryptFinishHash.cs b/src/Common/src/Interop/Windows/BCrypt/Interop.BCryptFinishHash.cs index 3bc2f81710d7..929a6412e984 100644 --- a/src/Common/src/Interop/Windows/BCrypt/Interop.BCryptFinishHash.cs +++ b/src/Common/src/Interop/Windows/BCrypt/Interop.BCryptFinishHash.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System; using System.Runtime.InteropServices; using Microsoft.Win32.SafeHandles; @@ -9,16 +10,15 @@ internal partial class Interop { internal partial class BCrypt { - internal static unsafe NTSTATUS BCryptFinishHash(SafeBCryptHashHandle hHash, byte[] pbOutput, int cbOutput, int dwFlags) + internal static unsafe NTSTATUS BCryptFinishHash(SafeBCryptHashHandle hHash, Span pbOutput, int cbOutput, int dwFlags) { - fixed (byte* ptr = pbOutput) + fixed (byte* pbOutputPtr = &pbOutput.DangerousGetPinnableReference()) { - return BCryptFinishHash(hHash, ptr, cbOutput, dwFlags); + return BCryptFinishHash(hHash, pbOutputPtr, cbOutput, dwFlags); } } [DllImport(Libraries.BCrypt, CharSet = CharSet.Unicode)] - internal static unsafe extern NTSTATUS BCryptFinishHash(SafeBCryptHashHandle hHash, byte* pbOutput, int cbOutput, int dwFlags); + private static unsafe extern NTSTATUS BCryptFinishHash(SafeBCryptHashHandle hHash, byte* pbOutput, int cbOutput, int dwFlags); } } - diff --git a/src/Common/src/Interop/Windows/BCrypt/Interop.BCryptHashData.cs b/src/Common/src/Interop/Windows/BCrypt/Interop.BCryptHashData.cs index f8b0a12af2a1..cce5e6102e18 100644 --- a/src/Common/src/Interop/Windows/BCrypt/Interop.BCryptHashData.cs +++ b/src/Common/src/Interop/Windows/BCrypt/Interop.BCryptHashData.cs @@ -3,7 +3,6 @@ // See the LICENSE file in the project root for more information. using System; -using System.Diagnostics; using System.Runtime.InteropServices; using Microsoft.Win32.SafeHandles; @@ -12,8 +11,16 @@ internal partial class Interop { internal partial class BCrypt { + internal static unsafe NTSTATUS BCryptHashData(SafeBCryptHashHandle hHash, ReadOnlySpan pbInput, int cbInput, int dwFlags) + { + fixed (byte* pbInputPtr = &pbInput.DangerousGetPinnableReference()) + { + return BCryptHashData(hHash, pbInputPtr, cbInput, dwFlags); + } + } + [DllImport(Libraries.BCrypt, CharSet = CharSet.Unicode)] - internal static extern unsafe NTSTATUS BCryptHashData(SafeBCryptHashHandle hHash, byte* pbInput, int cbInput, int dwFlags); + private static extern unsafe NTSTATUS BCryptHashData(SafeBCryptHashHandle hHash, byte* pbInput, int cbInput, int dwFlags); } } diff --git a/src/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/HashProviderDispenser.OSX.cs b/src/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/HashProviderDispenser.OSX.cs index f3bcf8eed66a..b663864fd839 100644 --- a/src/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/HashProviderDispenser.OSX.cs +++ b/src/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/HashProviderDispenser.OSX.cs @@ -86,36 +86,22 @@ internal AppleHmacProvider(Interop.AppleCrypto.PAL_HashAlgorithm algorithm, byte HashSizeInBytes = hashSizeInBytes; } - public override unsafe void AppendHashData(ReadOnlySpan data) + public override void AppendHashData(ReadOnlySpan data) { if (!_running) { SetKey(); } - int ret; - - fixed (byte* pData = &data.DangerousGetPinnableReference()) - { - ret = Interop.AppleCrypto.HmacUpdate(_ctx, pData, data.Length); - } - - if (ret != 1) + if (Interop.AppleCrypto.HmacUpdate(_ctx, data, data.Length) != 1) { throw new CryptographicException(); } } - private unsafe void SetKey() + private void SetKey() { - int ret; - - fixed (byte* pbKey = _key) - { - ret = Interop.AppleCrypto.HmacInit(_ctx, pbKey, _key.Length); - } - - if (ret != 1) + if (Interop.AppleCrypto.HmacInit(_ctx, _key, _key.Length) != 1) { throw new CryptographicException(); } @@ -125,47 +111,27 @@ private unsafe void SetKey() public override unsafe byte[] FinalizeHashAndReset() { - if (!_running) - { - SetKey(); - } - - byte[] output = new byte[HashSizeInBytes]; - int ret; - - fixed (byte* pbOutput = output) - { - ret = Interop.AppleCrypto.HmacFinal(_ctx, pbOutput, output.Length); - } - - if (ret != 1) - { - throw new CryptographicException(); - } - - _running = false; + var output = new byte[HashSizeInBytes]; + bool success = TryFinalizeHashAndReset(output, out int bytesWritten); + Debug.Assert(success); + Debug.Assert(bytesWritten == output.Length); return output; } - public override unsafe bool TryFinalizeHashAndReset(Span destination, out int bytesWritten) + public override bool TryFinalizeHashAndReset(Span destination, out int bytesWritten) { - if (!_running) - { - SetKey(); - } - if (destination.Length < HashSizeInBytes) { bytesWritten = 0; return false; } - int ret; - fixed (byte* pbOutput = &destination.DangerousGetPinnableReference()) + if (!_running) { - ret = Interop.AppleCrypto.HmacFinal(_ctx, pbOutput, destination.Length); + SetKey(); } - if (ret != 1) + + if (Interop.AppleCrypto.HmacFinal(_ctx, destination, destination.Length) != 1) { throw new CryptographicException(); } @@ -214,15 +180,9 @@ internal AppleDigestProvider(Interop.AppleCrypto.PAL_HashAlgorithm algorithm) HashSizeInBytes = hashSizeInBytes; } - public override unsafe void AppendHashData(ReadOnlySpan data) + public override void AppendHashData(ReadOnlySpan data) { - int ret; - - fixed (byte* pData = &data.DangerousGetPinnableReference()) - { - ret = Interop.AppleCrypto.DigestUpdate(_ctx, pData, data.Length); - } - + int ret = Interop.AppleCrypto.DigestUpdate(_ctx, data, data.Length); if (ret != 1) { Debug.Assert(ret == 0, $"DigestUpdate return value {ret} was not 0 or 1"); @@ -230,26 +190,16 @@ public override unsafe void AppendHashData(ReadOnlySpan data) } } - public override unsafe byte[] FinalizeHashAndReset() + public override byte[] FinalizeHashAndReset() { - byte[] hash = new byte[HashSizeInBytes]; - int ret; - - fixed (byte* pHash = hash) - { - ret = Interop.AppleCrypto.DigestFinal(_ctx, pHash, hash.Length); - } - - if (ret != 1) - { - Debug.Assert(ret == 0, $"DigestFinal return value {ret} was not 0 or 1"); - throw new CryptographicException(); - } - + var hash = new byte[HashSizeInBytes]; + bool success = TryFinalizeHashAndReset(hash, out int bytesWritten); + Debug.Assert(success); + Debug.Assert(bytesWritten == hash.Length); return hash; } - public override unsafe bool TryFinalizeHashAndReset(Span destination, out int bytesWritten) + public override bool TryFinalizeHashAndReset(Span destination, out int bytesWritten) { if (destination.Length < HashSizeInBytes) { @@ -257,11 +207,7 @@ public override unsafe bool TryFinalizeHashAndReset(Span destination, out return false; } - int ret; - fixed (byte* pHash = &destination.DangerousGetPinnableReference()) - { - ret = Interop.AppleCrypto.DigestFinal(_ctx, pHash, destination.Length); - } + int ret = Interop.AppleCrypto.DigestFinal(_ctx, destination, destination.Length); if (ret != 1) { Debug.Assert(ret == 0, $"DigestFinal return value {ret} was not 0 or 1"); diff --git a/src/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/HashProviderDispenser.Unix.cs b/src/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/HashProviderDispenser.Unix.cs index bdbc438460df..3626fa7f67b4 100644 --- a/src/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/HashProviderDispenser.Unix.cs +++ b/src/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/HashProviderDispenser.Unix.cs @@ -74,26 +74,15 @@ public EvpHashProvider(IntPtr algorithmEvp) Interop.Crypto.CheckValidOpenSslHandle(_ctx); } - public override unsafe void AppendHashData(ReadOnlySpan data) - { - fixed (byte* md = &data.DangerousGetPinnableReference()) - { - Check(Interop.Crypto.EvpDigestUpdate(_ctx, md, data.Length)); - } - } + public override void AppendHashData(ReadOnlySpan data) => + Check(Interop.Crypto.EvpDigestUpdate(_ctx, data, data.Length)); - public override unsafe byte[] FinalizeHashAndReset() + public override byte[] FinalizeHashAndReset() { - byte* md = stackalloc byte[Interop.Crypto.EVP_MAX_MD_SIZE]; - uint length = (uint)Interop.Crypto.EVP_MAX_MD_SIZE; - Check(Interop.Crypto.EvpDigestFinalEx(_ctx, md, ref length)); - Debug.Assert(length == _hashSize); - - // Reset the algorithm provider. - Check(Interop.Crypto.EvpDigestReset(_ctx, _algorithmEvp)); - - byte[] result = new byte[(int)length]; - Marshal.Copy((IntPtr)md, result, 0, (int)length); + var result = new byte[_hashSize]; + bool success = TryFinalizeHashAndReset(result, out int bytesWritten); + Debug.Assert(success); + Debug.Assert(result.Length == bytesWritten); return result; } @@ -156,26 +145,16 @@ public unsafe HmacHashProvider(IntPtr algorithmEvp, byte[] key) } } - public override unsafe void AppendHashData(ReadOnlySpan data) - { - fixed (byte* md = &data.DangerousGetPinnableReference()) - { - Check(Interop.Crypto.HmacUpdate(_hmacCtx, md, data.Length)); - } - } + public override void AppendHashData(ReadOnlySpan data) => + Check(Interop.Crypto.HmacUpdate(_hmacCtx, data, data.Length)); - public override unsafe byte[] FinalizeHashAndReset() + public override byte[] FinalizeHashAndReset() { - byte* md = stackalloc byte[Interop.Crypto.EVP_MAX_MD_SIZE]; - int length = Interop.Crypto.EVP_MAX_MD_SIZE; - Check(Interop.Crypto.HmacFinal(_hmacCtx, md, ref length)); - Debug.Assert(length == _hashSize); - - Check(Interop.Crypto.HmacReset(_hmacCtx)); - - byte[] result = new byte[length]; - Marshal.Copy((IntPtr)md, result, 0, length); - return result; + var hash = new byte[_hashSize]; + bool success = TryFinalizeHashAndReset(hash, out int bytesWritten); + Debug.Assert(success); + Debug.Assert(hash.Length == bytesWritten); + return hash; } public override unsafe bool TryFinalizeHashAndReset(Span destination, out int bytesWritten) diff --git a/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/MD5.cs b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/MD5.cs index 1ab1f4571d72..0049613885bd 100644 --- a/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/MD5.cs +++ b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/MD5.cs @@ -33,13 +33,13 @@ public Implementation() protected sealed override void HashCore(byte[] array, int ibStart, int cbSize) => _hashProvider.AppendHashData(array, ibStart, cbSize); - protected override void HashCore(ReadOnlySpan source) => + protected sealed override void HashCore(ReadOnlySpan source) => _hashProvider.AppendHashData(source); protected sealed override byte[] HashFinal() => _hashProvider.FinalizeHashAndReset(); - protected override bool TryHashFinal(Span destination, out int bytesWritten) => + protected sealed override bool TryHashFinal(Span destination, out int bytesWritten) => _hashProvider.TryFinalizeHashAndReset(destination, out bytesWritten); public sealed override void Initialize() diff --git a/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA1.cs b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA1.cs index 51a302e1a967..d9ad3a8b59ca 100644 --- a/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA1.cs +++ b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA1.cs @@ -34,13 +34,13 @@ public Implementation() protected sealed override void HashCore(byte[] array, int ibStart, int cbSize) => _hashProvider.AppendHashData(array, ibStart, cbSize); - protected override void HashCore(ReadOnlySpan source) => + protected sealed override void HashCore(ReadOnlySpan source) => _hashProvider.AppendHashData(source); protected sealed override byte[] HashFinal() => _hashProvider.FinalizeHashAndReset(); - protected override bool TryHashFinal(Span destination, out int bytesWritten) => + protected sealed override bool TryHashFinal(Span destination, out int bytesWritten) => _hashProvider.TryFinalizeHashAndReset(destination, out bytesWritten); public sealed override void Initialize() diff --git a/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA1Managed.cs b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA1Managed.cs index 5f968d9192ce..fab9ff8252f7 100644 --- a/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA1Managed.cs +++ b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA1Managed.cs @@ -22,13 +22,13 @@ public SHA1Managed() protected sealed override void HashCore(byte[] array, int ibStart, int cbSize) => _hashProvider.AppendHashData(array, ibStart, cbSize); - protected override void HashCore(ReadOnlySpan source) => + protected sealed override void HashCore(ReadOnlySpan source) => _hashProvider.AppendHashData(source); protected sealed override byte[] HashFinal() => _hashProvider.FinalizeHashAndReset(); - protected override bool TryHashFinal(Span destination, out int bytesWritten) => + protected sealed override bool TryHashFinal(Span destination, out int bytesWritten) => _hashProvider.TryFinalizeHashAndReset(destination, out bytesWritten); public sealed override void Initialize() diff --git a/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA256.cs b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA256.cs index c805c97b4cb6..9fe667b55a13 100644 --- a/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA256.cs +++ b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA256.cs @@ -33,13 +33,13 @@ public Implementation() protected sealed override void HashCore(byte[] array, int ibStart, int cbSize) => _hashProvider.AppendHashData(array, ibStart, cbSize); - protected override void HashCore(ReadOnlySpan source) => + protected sealed override void HashCore(ReadOnlySpan source) => _hashProvider.AppendHashData(source); protected sealed override byte[] HashFinal() => _hashProvider.FinalizeHashAndReset(); - protected override bool TryHashFinal(Span destination, out int bytesWritten) => + protected sealed override bool TryHashFinal(Span destination, out int bytesWritten) => _hashProvider.TryFinalizeHashAndReset(destination, out bytesWritten); public sealed override void Initialize() diff --git a/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA256Managed.cs b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA256Managed.cs index 236a4eb8d146..77496bed44ac 100644 --- a/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA256Managed.cs +++ b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA256Managed.cs @@ -22,13 +22,13 @@ public SHA256Managed() protected sealed override void HashCore(byte[] array, int ibStart, int cbSize) => _hashProvider.AppendHashData(array, ibStart, cbSize); - protected override void HashCore(ReadOnlySpan source) => + protected sealed override void HashCore(ReadOnlySpan source) => _hashProvider.AppendHashData(source); protected sealed override byte[] HashFinal() => _hashProvider.FinalizeHashAndReset(); - protected override bool TryHashFinal(Span destination, out int bytesWritten) => + protected sealed override bool TryHashFinal(Span destination, out int bytesWritten) => _hashProvider.TryFinalizeHashAndReset(destination, out bytesWritten); public sealed override void Initialize() diff --git a/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA384.cs b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA384.cs index 74fe0a5367e1..f5e6b80c5243 100644 --- a/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA384.cs +++ b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA384.cs @@ -33,13 +33,13 @@ public Implementation() protected sealed override void HashCore(byte[] array, int ibStart, int cbSize) => _hashProvider.AppendHashData(array, ibStart, cbSize); - protected override void HashCore(ReadOnlySpan source) => + protected sealed override void HashCore(ReadOnlySpan source) => _hashProvider.AppendHashData(source); protected sealed override byte[] HashFinal() => _hashProvider.FinalizeHashAndReset(); - protected override bool TryHashFinal(Span destination, out int bytesWritten) => + protected sealed override bool TryHashFinal(Span destination, out int bytesWritten) => _hashProvider.TryFinalizeHashAndReset(destination, out bytesWritten); public sealed override void Initialize() diff --git a/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA384Managed.cs b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA384Managed.cs index 2860c3a86f55..6c7780fce852 100644 --- a/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA384Managed.cs +++ b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA384Managed.cs @@ -22,13 +22,13 @@ public SHA384Managed() protected sealed override void HashCore(byte[] array, int ibStart, int cbSize) => _hashProvider.AppendHashData(array, ibStart, cbSize); - protected override void HashCore(ReadOnlySpan source) => + protected sealed override void HashCore(ReadOnlySpan source) => _hashProvider.AppendHashData(source); protected sealed override byte[] HashFinal() => _hashProvider.FinalizeHashAndReset(); - protected override bool TryHashFinal(Span destination, out int bytesWritten) => + protected sealed override bool TryHashFinal(Span destination, out int bytesWritten) => _hashProvider.TryFinalizeHashAndReset(destination, out bytesWritten); public sealed override void Initialize() diff --git a/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA512.cs b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA512.cs index 23e27d56709f..1c62d97cc534 100644 --- a/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA512.cs +++ b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA512.cs @@ -33,13 +33,13 @@ public Implementation() protected sealed override void HashCore(byte[] array, int ibStart, int cbSize) => _hashProvider.AppendHashData(array, ibStart, cbSize); - protected override void HashCore(ReadOnlySpan source) => + protected sealed override void HashCore(ReadOnlySpan source) => _hashProvider.AppendHashData(source); protected sealed override byte[] HashFinal() => _hashProvider.FinalizeHashAndReset(); - protected override bool TryHashFinal(Span destination, out int bytesWritten) => + protected sealed override bool TryHashFinal(Span destination, out int bytesWritten) => _hashProvider.TryFinalizeHashAndReset(destination, out bytesWritten); public sealed override void Initialize() diff --git a/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA512Managed.cs b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA512Managed.cs index 9f74905022a4..95435ebe905f 100644 --- a/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA512Managed.cs +++ b/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA512Managed.cs @@ -22,13 +22,13 @@ public SHA512Managed() protected sealed override void HashCore(byte[] array, int ibStart, int cbSize) => _hashProvider.AppendHashData(array, ibStart, cbSize); - protected override void HashCore(ReadOnlySpan source) => + protected sealed override void HashCore(ReadOnlySpan source) => _hashProvider.AppendHashData(source); protected sealed override byte[] HashFinal() => _hashProvider.FinalizeHashAndReset(); - protected override bool TryHashFinal(Span destination, out int bytesWritten) => + protected sealed override bool TryHashFinal(Span destination, out int bytesWritten) => _hashProvider.TryFinalizeHashAndReset(destination, out bytesWritten); public sealed override void Initialize() diff --git a/src/System.Security.Cryptography.Algorithms/tests/HashAlgorithmTest.netcoreapp.cs b/src/System.Security.Cryptography.Algorithms/tests/HashAlgorithmTest.netcoreapp.cs index 84a299944e8a..c76951d8dc70 100644 --- a/src/System.Security.Cryptography.Algorithms/tests/HashAlgorithmTest.netcoreapp.cs +++ b/src/System.Security.Cryptography.Algorithms/tests/HashAlgorithmTest.netcoreapp.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System.Linq; using Test.Cryptography; using Xunit; @@ -17,15 +18,43 @@ partial void Verify_Span(byte[] input, string output) using (HashAlgorithm hash = Create()) { + // Too small actual = new byte[expected.Length - 1]; Assert.False(hash.TryComputeHash(input, actual, out bytesWritten)); Assert.Equal(0, bytesWritten); + // Just right actual = new byte[expected.Length]; Assert.True(hash.TryComputeHash(input, actual, out bytesWritten)); Assert.Equal(expected.Length, bytesWritten); Assert.Equal(expected, actual); - Assert.Throws(() => hash.Hash); // byte[] not initialized + + // Bigger than needed + actual = new byte[expected.Length + 1]; + actual[actual.Length - 1] = 42; + Assert.True(hash.TryComputeHash(input, actual, out bytesWritten)); + Assert.Equal(expected.Length, bytesWritten); + Assert.Equal(expected, actual.AsSpan().Slice(0, expected.Length).ToArray()); + Assert.Equal(42, actual[actual.Length - 1]); + } + } + + [Fact] + public void ComputeHash_TryComputeHash_HashSetExplicitlyByBoth() + { + using (HashAlgorithm hash = Create()) + { + byte[] input = Enumerable.Range(0, 100).Select(i => (byte)i).ToArray(); + + byte[] computeHashResult = hash.ComputeHash(input); + Assert.NotNull(computeHashResult); + Assert.NotNull(hash.Hash); + Assert.NotSame(computeHashResult, hash.Hash); + Assert.Equal(computeHashResult, hash.Hash); + + Assert.True(hash.TryComputeHash(input, computeHashResult, out int bytesWritten)); + Assert.Equal(computeHashResult.Length, bytesWritten); + Assert.Null(hash.Hash); } } diff --git a/src/System.Security.Cryptography.Algorithms/tests/IncrementalHashTests.cs b/src/System.Security.Cryptography.Algorithms/tests/IncrementalHashTests.cs index 0b03fcbb0d0d..ee0e6cd5d07f 100644 --- a/src/System.Security.Cryptography.Algorithms/tests/IncrementalHashTests.cs +++ b/src/System.Security.Cryptography.Algorithms/tests/IncrementalHashTests.cs @@ -112,8 +112,8 @@ private static void VerifyIncrementalResult(HashAlgorithm referenceAlgorithm, In while (position < s_inputBytes.Length - StepB) { - incrementalHash.AppendData(s_inputBytes, position, StepA); - position += StepA; + incrementalHash.AppendData(s_inputBytes, position, StepB); + position += StepB; } incrementalHash.AppendData(s_inputBytes, position, s_inputBytes.Length - position); diff --git a/src/System.Security.Cryptography.Algorithms/tests/IncrementalHashTests.netcoreapp.cs b/src/System.Security.Cryptography.Algorithms/tests/IncrementalHashTests.netcoreapp.cs index 33c17a8c76cd..a4372f084657 100644 --- a/src/System.Security.Cryptography.Algorithms/tests/IncrementalHashTests.netcoreapp.cs +++ b/src/System.Security.Cryptography.Algorithms/tests/IncrementalHashTests.netcoreapp.cs @@ -65,8 +65,8 @@ private static void VerifyIncrementalResult_Span(HashAlgorithm referenceAlgorith while (position < s_inputBytes.Length - StepB) { - incrementalHash.AppendData(new ReadOnlySpan(s_inputBytes, position, StepA)); - position += StepA; + incrementalHash.AppendData(new ReadOnlySpan(s_inputBytes, position, StepB)); + position += StepB; } incrementalHash.AppendData(new ReadOnlySpan(s_inputBytes, position, s_inputBytes.Length - position)); diff --git a/src/System.Security.Cryptography.Csp/src/System/Security/Cryptography/MD5CryptoServiceProvider.cs b/src/System.Security.Cryptography.Csp/src/System/Security/Cryptography/MD5CryptoServiceProvider.cs index e72a027e8f5c..a3517b0a49ac 100644 --- a/src/System.Security.Cryptography.Csp/src/System/Security/Cryptography/MD5CryptoServiceProvider.cs +++ b/src/System.Security.Cryptography.Csp/src/System/Security/Cryptography/MD5CryptoServiceProvider.cs @@ -38,7 +38,7 @@ protected override bool TryHashFinal(Span destination, out int bytesWritte // The Hash and HashSize properties are not overridden since the correct values are returned from base. - protected sealed override void Dispose(bool disposing) + protected override void Dispose(bool disposing) { if (disposing) { diff --git a/src/System.Security.Cryptography.Csp/src/System/Security/Cryptography/SHA1CryptoServiceProvider.cs b/src/System.Security.Cryptography.Csp/src/System/Security/Cryptography/SHA1CryptoServiceProvider.cs index d665d1adbb0c..bfee5c9f1a4e 100644 --- a/src/System.Security.Cryptography.Csp/src/System/Security/Cryptography/SHA1CryptoServiceProvider.cs +++ b/src/System.Security.Cryptography.Csp/src/System/Security/Cryptography/SHA1CryptoServiceProvider.cs @@ -41,7 +41,7 @@ protected override bool TryHashFinal(Span destination, out int bytesWritte // The Hash and HashSize properties are not overridden since the correct values are returned from base. - protected sealed override void Dispose(bool disposing) + protected override void Dispose(bool disposing) { if (disposing) { diff --git a/src/System.Security.Cryptography.Csp/src/System/Security/Cryptography/SHA256CryptoServiceProvider.cs b/src/System.Security.Cryptography.Csp/src/System/Security/Cryptography/SHA256CryptoServiceProvider.cs index d39d06ced4d0..cb046dd397b6 100644 --- a/src/System.Security.Cryptography.Csp/src/System/Security/Cryptography/SHA256CryptoServiceProvider.cs +++ b/src/System.Security.Cryptography.Csp/src/System/Security/Cryptography/SHA256CryptoServiceProvider.cs @@ -41,7 +41,7 @@ protected override bool TryHashFinal(Span destination, out int bytesWritte // The Hash and HashSize properties are not overridden since the correct values are returned from base. - protected sealed override void Dispose(bool disposing) + protected override void Dispose(bool disposing) { if (disposing) { diff --git a/src/System.Security.Cryptography.Csp/src/System/Security/Cryptography/SHA384CryptoServiceProvider.cs b/src/System.Security.Cryptography.Csp/src/System/Security/Cryptography/SHA384CryptoServiceProvider.cs index 8bb68a31b84a..8cb2fa02ab58 100644 --- a/src/System.Security.Cryptography.Csp/src/System/Security/Cryptography/SHA384CryptoServiceProvider.cs +++ b/src/System.Security.Cryptography.Csp/src/System/Security/Cryptography/SHA384CryptoServiceProvider.cs @@ -41,7 +41,7 @@ protected override bool TryHashFinal(Span destination, out int bytesWritte // The Hash and HashSize properties are not overridden since the correct values are returned from base. - protected sealed override void Dispose(bool disposing) + protected override void Dispose(bool disposing) { if (disposing) { diff --git a/src/System.Security.Cryptography.Csp/src/System/Security/Cryptography/SHA512CryptoServiceProvider.cs b/src/System.Security.Cryptography.Csp/src/System/Security/Cryptography/SHA512CryptoServiceProvider.cs index eaacf86a0200..220aaf486773 100644 --- a/src/System.Security.Cryptography.Csp/src/System/Security/Cryptography/SHA512CryptoServiceProvider.cs +++ b/src/System.Security.Cryptography.Csp/src/System/Security/Cryptography/SHA512CryptoServiceProvider.cs @@ -41,7 +41,7 @@ protected override bool TryHashFinal(Span destination, out int bytesWritte // The Hash and HashSize properties are not overridden since the correct values are returned from base. - protected sealed override void Dispose(bool disposing) + protected override void Dispose(bool disposing) { if (disposing) { diff --git a/src/System.Security.Cryptography.Primitives/src/System/Security/Cryptography/HashAlgorithm.cs b/src/System.Security.Cryptography.Primitives/src/System/Security/Cryptography/HashAlgorithm.cs index 3c9c4fa2c4a6..8c8daa18c644 100644 --- a/src/System.Security.Cryptography.Primitives/src/System/Security/Cryptography/HashAlgorithm.cs +++ b/src/System.Security.Cryptography.Primitives/src/System/Security/Cryptography/HashAlgorithm.cs @@ -31,7 +31,7 @@ public virtual byte[] Hash if (State != 0) throw new CryptographicUnexpectedOperationException(SR.Cryptography_HashNotYetFinalized); - return (byte[])HashValue.Clone(); + return (byte[])HashValue?.Clone(); } } @@ -66,6 +66,7 @@ public bool TryComputeHash(ReadOnlySpan source, Span destination, ou // but we checked the size earlier. throw new InvalidOperationException(SR.InvalidOperation_IncorrectImplementation); } + HashValue = null; Initialize(); return true; @@ -221,17 +222,19 @@ protected virtual void HashCore(ReadOnlySpan source) protected virtual bool TryHashFinal(Span destination, out int bytesWritten) { - if (destination.Length >= HashSizeValue/8) + int hashSizeInBytes = HashSizeValue / 8; + + if (destination.Length >= hashSizeInBytes) { byte[] final = HashFinal(); - if (final.Length != HashSizeValue/8) + if (final.Length == hashSizeInBytes) { - throw new InvalidOperationException(SR.InvalidOperation_IncorrectImplementation); + new ReadOnlySpan(final).CopyTo(destination); + bytesWritten = final.Length; + return true; } - new ReadOnlySpan(final).CopyTo(destination); - bytesWritten = final.Length; - return true; + throw new InvalidOperationException(SR.InvalidOperation_IncorrectImplementation); } bytesWritten = 0;