diff --git a/eng/Versions.props b/eng/Versions.props index 9a5b8b8fbd11dc..9c8359369bf741 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -128,7 +128,6 @@ 4.5.5 6.0.1 6.0.0 - 4.3.1 5.0.0 5.0.0 5.0.0 diff --git a/src/libraries/Common/src/System/Security/Cryptography/IncrementalHash.netfx.cs b/src/libraries/Common/src/System/Security/Cryptography/IncrementalHash.netfx.cs new file mode 100644 index 00000000000000..b60bac3f6ede6e --- /dev/null +++ b/src/libraries/Common/src/System/Security/Cryptography/IncrementalHash.netfx.cs @@ -0,0 +1,231 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#if !NETFRAMEWORK || NET471_OR_GREATER +#error "This implementation of IncrementalHash should only be used for .NET Framework where it is not available" +#endif + +using System.Diagnostics; + +namespace System.Security.Cryptography +{ + /// + /// Provides support for computing a hash or HMAC value incrementally across several segments. + /// + internal sealed class IncrementalHash : IDisposable + { + private const int NTE_BAD_ALGID = unchecked((int)0x80090008); + + private readonly HashAlgorithmName _algorithmName; + private HashAlgorithm _hash; + private bool _disposed; + private bool _resetPending; + + private IncrementalHash(HashAlgorithmName name, HashAlgorithm hash) + { + Debug.Assert(!string.IsNullOrEmpty(name.Name)); + Debug.Assert(hash != null); + + _algorithmName = name; + _hash = hash; + } + + /// + /// Get the name of the algorithm being performed. + /// + public HashAlgorithmName AlgorithmName + { + get { return _algorithmName; } + } + + /// + /// Append the entire contents of to the data already processed in the hash or HMAC. + /// + /// The data to process. + /// is null. + /// The object has already been disposed. + public void AppendData(byte[] data) + { + if (data == null) + throw new ArgumentNullException(nameof(data)); + + AppendData(data, 0, data.Length); + } + + /// + /// Append bytes of , starting at , + /// to the data already processed in the hash or HMAC. + /// + /// The data to process. + /// The offset into the byte array from which to begin using data. + /// The number of bytes in the array to use as data. + /// is null. + /// + /// is out of range. This parameter requires a non-negative number. + /// + /// + /// is out of range. This parameter requires a non-negative number less than + /// the value of . + /// + /// + /// is greater than + /// . - . + /// + /// The object has already been disposed. + public void AppendData(byte[] data, int offset, int count) + { + if (data == null) + throw new ArgumentNullException(nameof(data)); + if (offset < 0) + throw new ArgumentOutOfRangeException(nameof(offset), SR.ArgumentOutOfRange_NeedNonNegNum); + if (count < 0 || (count > data.Length)) + throw new ArgumentOutOfRangeException(nameof(count)); + if ((data.Length - count) < offset) + throw new ArgumentException(SR.Argument_InvalidOffLen); + if (_disposed) + throw new ObjectDisposedException(nameof(IncrementalHash)); + + Debug.Assert(_hash != null); + + if (_resetPending) + { + _hash.Initialize(); + _resetPending = false; + } + + _hash.TransformBlock(data, offset, count, null, 0); + } + + /// + /// Retrieve the hash or HMAC for the data accumulated from prior calls to + /// , and return to the state the object + /// was in at construction. + /// + /// The computed hash or HMAC. + /// The object has already been disposed. + public byte[] GetHashAndReset() + { + if (_disposed) + throw new ObjectDisposedException(nameof(IncrementalHash)); + + Debug.Assert(_hash != null); + + if (_resetPending) + { + // No point in setting _resetPending to false, we're about to set it to true. + _hash.Initialize(); + } + + _hash.TransformFinalBlock(Array.Empty(), 0, 0); + byte[] hashValue = _hash.Hash; + _resetPending = true; + + return hashValue; + } + + /// + /// Release all resources used by the current instance of the + /// class. + /// + public void Dispose() + { + _disposed = true; + + if (_hash != null) + { + _hash.Dispose(); + _hash = null; + } + } + + /// + /// Create an for the algorithm specified by . + /// + /// The name of the hash algorithm to perform. + /// + /// An instance ready to compute the hash algorithm specified + /// by . + /// + /// + /// . is null, or + /// the empty string. + /// + /// is not a known hash algorithm. + public static IncrementalHash CreateHash(HashAlgorithmName hashAlgorithm) + { + if (string.IsNullOrEmpty(hashAlgorithm.Name)) + throw new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, nameof(hashAlgorithm)); + + return new IncrementalHash(hashAlgorithm, GetHashAlgorithm(hashAlgorithm)); + } + + /// + /// Create an for the Hash-based Message Authentication Code (HMAC) + /// algorithm utilizing the hash algorithm specified by , and a + /// key specified by . + /// + /// The name of the hash algorithm to perform within the HMAC. + /// + /// The secret key for the HMAC. The key can be any length, but a key longer than the output size + /// of the hash algorithm specified by will be hashed (using the + /// algorithm specified by ) to derive a correctly-sized key. Therefore, + /// the recommended size of the secret key is the output size of the hash specified by + /// . + /// + /// + /// An instance ready to compute the hash algorithm specified + /// by . + /// + /// + /// . is null, or + /// the empty string. + /// + /// is not a known hash algorithm. + public static IncrementalHash CreateHMAC(HashAlgorithmName hashAlgorithm, byte[] key) + { + if (key == null) + throw new ArgumentNullException(nameof(key)); + if (string.IsNullOrEmpty(hashAlgorithm.Name)) + throw new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, nameof(hashAlgorithm)); + + return new IncrementalHash(hashAlgorithm, GetHMAC(hashAlgorithm, key)); + } + + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA5351", Justification = "MD5 is used when the user asks for it.")] + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA5350", Justification = "SHA1 is used when the user asks for it.")] + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA5354", Justification = "SHA1 is used when the user asks for it.")] + private static HashAlgorithm GetHashAlgorithm(HashAlgorithmName hashAlgorithm) + { + if (hashAlgorithm == HashAlgorithmName.MD5) + return new MD5CryptoServiceProvider(); + if (hashAlgorithm == HashAlgorithmName.SHA1) + return new SHA1CryptoServiceProvider(); + if (hashAlgorithm == HashAlgorithmName.SHA256) + return new SHA256CryptoServiceProvider(); + if (hashAlgorithm == HashAlgorithmName.SHA384) + return new SHA384CryptoServiceProvider(); + if (hashAlgorithm == HashAlgorithmName.SHA512) + return new SHA512CryptoServiceProvider(); + + throw new CryptographicException(NTE_BAD_ALGID); + } + + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA5351", Justification = "MD5 is used when the user asks for it.")] + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA5350", Justification = "SHA1 is used when the user asks for it.")] + private static HashAlgorithm GetHMAC(HashAlgorithmName hashAlgorithm, byte[] key) + { + if (hashAlgorithm == HashAlgorithmName.MD5) + return new HMACMD5(key); + if (hashAlgorithm == HashAlgorithmName.SHA1) + return new HMACSHA1(key); + if (hashAlgorithm == HashAlgorithmName.SHA256) + return new HMACSHA256(key); + if (hashAlgorithm == HashAlgorithmName.SHA384) + return new HMACSHA384(key); + if (hashAlgorithm == HashAlgorithmName.SHA512) + return new HMACSHA512(key); + + throw new CryptographicException(NTE_BAD_ALGID); + } + } +} diff --git a/src/libraries/Microsoft.Extensions.FileProviders.Physical/src/Microsoft.Extensions.FileProviders.Physical.csproj b/src/libraries/Microsoft.Extensions.FileProviders.Physical/src/Microsoft.Extensions.FileProviders.Physical.csproj index ad62b2a7c571d1..c4bbe1418891c2 100644 --- a/src/libraries/Microsoft.Extensions.FileProviders.Physical/src/Microsoft.Extensions.FileProviders.Physical.csproj +++ b/src/libraries/Microsoft.Extensions.FileProviders.Physical/src/Microsoft.Extensions.FileProviders.Physical.csproj @@ -16,6 +16,9 @@ Link="Common\src\Extensions\NonCapturingTimer\NonCapturingTimer.cs" /> + @@ -24,8 +27,4 @@ - - - - diff --git a/src/libraries/Microsoft.Extensions.FileProviders.Physical/src/Resources/Strings.resx b/src/libraries/Microsoft.Extensions.FileProviders.Physical/src/Resources/Strings.resx index 61a2f55a718489..64c4215b710e34 100644 --- a/src/libraries/Microsoft.Extensions.FileProviders.Physical/src/Resources/Strings.resx +++ b/src/libraries/Microsoft.Extensions.FileProviders.Physical/src/Resources/Strings.resx @@ -117,6 +117,12 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Offset and length were out of bounds for the array or count is greater than the number of elements from index to the end of the source collection. + + + Non-negative number required. + The fileSystemWatcher parameter must be non-null when pollForChanges is false. @@ -126,6 +132,9 @@ Cannot modify {0} once file watcher has been initialized. + + The hash algorithm name cannot be null or empty. + Unexpected type of FileSystemInfo diff --git a/src/libraries/System.Reflection.Metadata/tests/System.Reflection.Metadata.Tests.csproj b/src/libraries/System.Reflection.Metadata/tests/System.Reflection.Metadata.Tests.csproj index 60644e49ba5477..f87afd2009b299 100644 --- a/src/libraries/System.Reflection.Metadata/tests/System.Reflection.Metadata.Tests.csproj +++ b/src/libraries/System.Reflection.Metadata/tests/System.Reflection.Metadata.Tests.csproj @@ -1,4 +1,5 @@ + true false @@ -9,6 +10,7 @@ true $(DefineConstants);TARGET_BROWSER + @@ -24,6 +26,7 @@ Link="Common\Microsoft\Win32\SafeHandles\SafeLibraryHandle.cs" /> + @@ -90,6 +93,7 @@ + @@ -135,16 +139,19 @@ + + - + + diff --git a/src/libraries/System.Reflection.Metadata/tests/TestUtilities/SigningUtilities.cs b/src/libraries/System.Reflection.Metadata/tests/TestUtilities/SigningUtilities.cs index 2b0d573614c59f..4abac3e223eb90 100644 --- a/src/libraries/System.Reflection.Metadata/tests/TestUtilities/SigningUtilities.cs +++ b/src/libraries/System.Reflection.Metadata/tests/TestUtilities/SigningUtilities.cs @@ -29,20 +29,19 @@ public static byte[] CalculateRsaSignature(IEnumerable content, byte[] pri public static byte[] CalculateSha1(IEnumerable content) { - using (var hash = IncrementalHash.CreateHash(HashAlgorithmName.SHA1)) - { - var stream = new MemoryStream(); - - foreach (var blob in content) - { - var segment = blob.GetBytes(); + MemoryStream stream = new(); - stream.Write(segment.Array, segment.Offset, segment.Count); + foreach (Blob blob in content) + { + var segment = blob.GetBytes(); + stream.Write(segment.Array, segment.Offset, segment.Count); + } - hash.AppendData(segment.Array, segment.Offset, segment.Count); - } + stream.Position = 0; - return hash.GetHashAndReset(); + using (SHA1 sha1 = SHA1.Create()) + { + return sha1.ComputeHash(stream); } } diff --git a/src/libraries/System.Security.Cryptography.Cose/src/Resources/Strings.resx b/src/libraries/System.Security.Cryptography.Cose/src/Resources/Strings.resx index c03febddebb117..8a49f05e5e00e0 100644 --- a/src/libraries/System.Security.Cryptography.Cose/src/Resources/Strings.resx +++ b/src/libraries/System.Security.Cryptography.Cose/src/Resources/Strings.resx @@ -123,6 +123,12 @@ The destination is too small to hold the encoded value. + + Offset and length were out of bounds for the array or count is greater than the number of elements from index to the end of the source collection. + + + Non-negative number required. + Content was not included in the message (detached message), provide a content to verify. @@ -156,6 +162,9 @@ Critical Headers must be a CBOR array of at least one element. + + The hash algorithm name cannot be null or empty. + COSE Signature must be an array of three elements. diff --git a/src/libraries/System.Security.Cryptography.Cose/src/System.Security.Cryptography.Cose.csproj b/src/libraries/System.Security.Cryptography.Cose/src/System.Security.Cryptography.Cose.csproj index 23203e5e3e485f..3ed0bec5488ed5 100644 --- a/src/libraries/System.Security.Cryptography.Cose/src/System.Security.Cryptography.Cose.csproj +++ b/src/libraries/System.Security.Cryptography.Cose/src/System.Security.Cryptography.Cose.csproj @@ -1,4 +1,5 @@ + $(NetCoreAppCurrent);$(NetCoreAppPrevious);$(NetCoreAppMinimum);netstandard2.0;$(NetFrameworkMinimum) true @@ -7,9 +8,16 @@ - - - + + + + + @@ -34,8 +42,4 @@ - - - -