WASM: Add SHA* hash functions (#40486)
authorAlexander Köplinger <alex.koeplinger@outlook.com>
Wed, 2 Sep 2020 21:23:26 +0000 (23:23 +0200)
committerGitHub <noreply@github.com>
Wed, 2 Sep 2020 21:23:26 +0000 (23:23 +0200)
This ports the managed SHA* hash functions from https://github.com/microsoft/referencesource so we can use them on Browser/WASM where we don't have OpenSSL.

Enables the System.Security.Cryptography.Algorithms tests for these classes: `Tests run: 271, Errors: 0, Failures: 0, Skipped: 1. Time: 11.857137s`

Resolves https://github.com/dotnet/runtime/issues/40076

85 files changed:
src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/AesCipherTests.cs
src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/AesContractTests.cs
src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/AesCornerTests.cs
src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/AesModeTests.cs
src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/DecryptorReusability.cs
src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DES/DESCipherTests.cs
src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DES/DESContractTests.cs
src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DES/DesTests.cs
src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSAImportExport.cs
src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSAKeyFileTests.cs
src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSAKeyGeneration.cs
src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSAKeyPemTests.cs
src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSASignVerify.cs
src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSASignatureFormatTests.cs
src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSASignatureFormatter.cs
src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSAXml.cs
src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DsaFamilySignatureFormatTests.cs
src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/EC/ECKeyFileTests.cs
src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/EC/ECKeyPemTests.cs
src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDhKeyFileTests.cs
src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanKeyPemTests.cs
src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanTests.cs
src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaImportExport.cs
src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaKeyFileTests.cs
src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaKeyPemTests.cs
src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaSignatureFormatTests.cs
src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaTests.cs
src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaTests.netcoreapp.cs
src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaTestsBase.cs
src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaXml.cs
src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RC2/RC2CipherTests.cs
src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RC2/RC2ContractTests.cs
src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RC2/RC2Tests.cs
src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/EncryptDecrypt.cs
src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/EncryptDecrypt.netcoreapp.cs
src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/ImportExport.cs
src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/KeyGeneration.cs
src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSAKeyExchangeFormatter.cs
src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSAKeyFileTests.cs
src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSAKeyPemTests.cs
src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSASignatureFormatter.cs
src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSAXml.cs
src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/SignVerify.cs
src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/TripleDES/TripleDESCipherTests.cs
src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/TripleDES/TripleDESContractTests.cs
src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/TripleDES/TripleDESReusabilityTests.cs
src/libraries/System.Security.Cryptography.Algorithms/src/ExcludeApiList.PNSE.Browser.txt
src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/HashProviderDispenser.Browser.cs [new file with mode: 0644]
src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/SHAHashProvider.Browser.cs [new file with mode: 0644]
src/libraries/System.Security.Cryptography.Algorithms/src/System.Security.Cryptography.Algorithms.csproj
src/libraries/System.Security.Cryptography.Algorithms/tests/AesCcmTests.cs
src/libraries/System.Security.Cryptography.Algorithms/tests/AesGcmTests.cs
src/libraries/System.Security.Cryptography.Algorithms/tests/AesManagedTests.cs
src/libraries/System.Security.Cryptography.Algorithms/tests/AesTests.cs
src/libraries/System.Security.Cryptography.Algorithms/tests/AssemblyInfo.cs [deleted file]
src/libraries/System.Security.Cryptography.Algorithms/tests/AsymmetricSignatureFormatterTests.cs
src/libraries/System.Security.Cryptography.Algorithms/tests/BlockSizeValueTests.cs
src/libraries/System.Security.Cryptography.Algorithms/tests/CryptoConfigTests.cs
src/libraries/System.Security.Cryptography.Algorithms/tests/DSACreateTests.cs
src/libraries/System.Security.Cryptography.Algorithms/tests/DSATests.cs
src/libraries/System.Security.Cryptography.Algorithms/tests/ECDiffieHellmanPublicKeyTests.cs
src/libraries/System.Security.Cryptography.Algorithms/tests/ECDsaTests.cs
src/libraries/System.Security.Cryptography.Algorithms/tests/HKDFTests.cs
src/libraries/System.Security.Cryptography.Algorithms/tests/HmacMD5Tests.cs
src/libraries/System.Security.Cryptography.Algorithms/tests/HmacSha1Tests.cs
src/libraries/System.Security.Cryptography.Algorithms/tests/HmacSha256Tests.cs
src/libraries/System.Security.Cryptography.Algorithms/tests/HmacSha384Tests.cs
src/libraries/System.Security.Cryptography.Algorithms/tests/HmacSha512Tests.cs
src/libraries/System.Security.Cryptography.Algorithms/tests/HmacTests.cs
src/libraries/System.Security.Cryptography.Algorithms/tests/IncrementalHashTests.cs
src/libraries/System.Security.Cryptography.Algorithms/tests/InvalidUsageTests.cs
src/libraries/System.Security.Cryptography.Algorithms/tests/MD5Tests.cs
src/libraries/System.Security.Cryptography.Algorithms/tests/PKCS1MaskGenerationMethodTest.cs
src/libraries/System.Security.Cryptography.Algorithms/tests/PaddingModeTests.cs
src/libraries/System.Security.Cryptography.Algorithms/tests/RSACreateTests.cs
src/libraries/System.Security.Cryptography.Algorithms/tests/RSATests.cs
src/libraries/System.Security.Cryptography.Algorithms/tests/RandomNumberGeneratorTests.cs
src/libraries/System.Security.Cryptography.Algorithms/tests/ReusabilityTests.cs
src/libraries/System.Security.Cryptography.Algorithms/tests/Rfc2202HmacTests.cs
src/libraries/System.Security.Cryptography.Algorithms/tests/Rfc2898Tests.cs
src/libraries/System.Security.Cryptography.Algorithms/tests/Rfc4231HmacTests.cs
src/libraries/System.Security.Cryptography.Algorithms/tests/RijndaelTests.cs
src/libraries/System.Security.Cryptography.Algorithms/tests/SignatureDescriptionTests.cs
src/libraries/System.Security.Cryptography.Algorithms/tests/System.Security.Cryptography.Algorithms.Tests.csproj
src/libraries/System.Security.Cryptography.Algorithms/tests/TripleDesTests.cs

index 67a44f8..896c3f8 100644 (file)
@@ -11,6 +11,7 @@ namespace System.Security.Cryptography.Encryption.Aes.Tests
 {
     using Aes = System.Security.Cryptography.Aes;
 
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public partial class AesCipherTests
     {
         [Fact]
index 8e430d4..49d7665 100644 (file)
@@ -7,6 +7,7 @@ namespace System.Security.Cryptography.Encryption.Aes.Tests
 {
     using Aes = System.Security.Cryptography.Aes;
 
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public class AesContractTests
     {
         [Fact]
index ffbbac7..f98b8a9 100644 (file)
@@ -12,6 +12,7 @@ namespace System.Security.Cryptography.Encryption.Aes.Tests
 {
     using Aes = System.Security.Cryptography.Aes;
 
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public static class AesCornerTests
     {
         [Fact]
index e52bf61..f36e0f0 100644 (file)
@@ -7,6 +7,7 @@ namespace System.Security.Cryptography.Encryption.Aes.Tests
 {
     using Aes = System.Security.Cryptography.Aes;
 
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public class AesModeTests
     {
         [Fact]
index 8daa947..76d1bc5 100644 (file)
@@ -7,6 +7,7 @@ namespace System.Security.Cryptography.Encryption.Aes.Tests
 {
     using Aes = System.Security.Cryptography.Aes;
 
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public static class DecryptorReusabilty
     {
         // See https://github.com/dotnet/runtime/issues/21354 for details
index bb13c39..de5e564 100644 (file)
@@ -9,6 +9,7 @@ using Xunit;
 
 namespace System.Security.Cryptography.Encryption.Des.Tests
 {
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public static class DesCipherTests
     {
         // These are the expected output of many decryptions. Changing these values requires re-generating test input.
index 4fe0e86..16ce108 100644 (file)
@@ -10,6 +10,7 @@ using Xunit;
 
 namespace System.Security.Cryptography.Encryption.Des.Tests
 {
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public static class DesContractTests
     {
         // cfb not available on windows 7
index 1600d13..b906485 100644 (file)
@@ -7,6 +7,7 @@ using Xunit;
 
 namespace System.Security.Cryptography.Encryption.Des.Tests
 {
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public static partial class DesTests
     {
         private static readonly byte[] KnownWeakKey = "e0e0e0e0f1f1f1f1".HexToByteArray();
index d797d5a..3e2a708 100644 (file)
@@ -5,6 +5,7 @@ using Xunit;
 
 namespace System.Security.Cryptography.Dsa.Tests
 {
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public partial class DSAImportExport
     {
         public static bool SupportsFips186_3 => DSAFactory.SupportsFips186_3;
index 97ff898..e3b5500 100644 (file)
@@ -7,6 +7,7 @@ using Xunit;
 
 namespace System.Security.Cryptography.Dsa.Tests
 {
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public static class DSAKeyFileTests
     {
         public static bool SupportsFips186_3 => DSAFactory.SupportsFips186_3;
index 8749c02..0d6f244 100644 (file)
@@ -5,6 +5,7 @@ using Xunit;
 
 namespace System.Security.Cryptography.Dsa.Tests
 {
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public partial class DSAKeyGeneration
     {
         public static bool SupportsKeyGeneration => DSAFactory.SupportsKeyGeneration;
index 53edb82..199135a 100644 (file)
@@ -7,6 +7,7 @@ using Xunit;
 
 namespace System.Security.Cryptography.Dsa.Tests
 {
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public static class DSAKeyPemTests
     {
         private const string AmbiguousExceptionMarker = "multiple keys";
index 10c2fd5..5db9c9e 100644 (file)
@@ -7,6 +7,7 @@ using Xunit;
 
 namespace System.Security.Cryptography.Dsa.Tests
 {
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public sealed class DSASignVerify_Array : DSASignVerify
     {
         public override byte[] SignData(DSA dsa, byte[] data, HashAlgorithmName hashAlgorithm) =>
@@ -53,6 +54,7 @@ namespace System.Security.Cryptography.Dsa.Tests
         }
     }
 
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public sealed class DSASignVerify_Stream : DSASignVerify
     {
         public override byte[] SignData(DSA dsa, byte[] data, HashAlgorithmName hashAlgorithm) =>
@@ -74,6 +76,7 @@ namespace System.Security.Cryptography.Dsa.Tests
     }
 
 #if NETCOREAPP
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public sealed class DSASignVerify_Span : DSASignVerify
     {
         public override byte[] SignData(DSA dsa, byte[] data, HashAlgorithmName hashAlgorithm) =>
@@ -106,6 +109,7 @@ namespace System.Security.Cryptography.Dsa.Tests
         }
     }
 #endif
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public abstract partial class DSASignVerify
     {
         public abstract byte[] SignData(DSA dsa, byte[] data, HashAlgorithmName hashAlgorithm);
index 601a743..6b9eab6 100644 (file)
@@ -8,6 +8,7 @@ using Xunit;
 
 namespace System.Security.Cryptography.Dsa.Tests
 {
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public abstract class DSASignatureFormatTests : DsaFamilySignatureFormatTests
     {
         protected override bool SupportsSha2 => DSAFactory.SupportsFips186_3;
index ccfba94..867e87c 100644 (file)
@@ -6,6 +6,7 @@ using Xunit;
 
 namespace System.Security.Cryptography.Dsa.Tests
 {
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public partial class DSASignatureFormatterTests : AsymmetricSignatureFormatterTests
     {
         [Fact]
index 438856b..1a742d3 100644 (file)
@@ -7,6 +7,7 @@ using Xunit;
 
 namespace System.Security.Cryptography.Dsa.Tests
 {
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public static class DSAXml
     {
         [Fact]
index e14ed38..d55b5a7 100644 (file)
@@ -8,6 +8,7 @@ using Xunit;
 
 namespace System.Security.Cryptography.Algorithms.Tests
 {
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public abstract class DsaFamilySignatureFormatTests
     {
         protected readonly struct KeyDescription
index 62fc99a..1c3a0c2 100644 (file)
@@ -7,6 +7,7 @@ using Xunit;
 
 namespace System.Security.Cryptography.Tests
 {
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public abstract partial class ECKeyFileTests<T> where T : AsymmetricAlgorithm
     {
         protected abstract T CreateKey();
index 79d9986..1593a5d 100644 (file)
@@ -7,6 +7,7 @@ using Xunit;
 
 namespace System.Security.Cryptography.Tests
 {
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public abstract class ECKeyPemTests<TAlg> where TAlg : AsymmetricAlgorithm
     {
         private const string AmbiguousExceptionMarker = "multiple keys";
index b46c546..6067f33 100644 (file)
@@ -2,9 +2,11 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 
 using System.Security.Cryptography.Tests;
+using Xunit;
 
 namespace System.Security.Cryptography.EcDiffieHellman.Tests
 {
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public class ECDhKeyFileTests : ECKeyFileTests<ECDiffieHellman>
     {
         protected override ECDiffieHellman CreateKey()
index da1ecb5..78bc9a3 100644 (file)
@@ -2,9 +2,11 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 
 using System.Security.Cryptography.Tests;
+using Xunit;
 
 namespace System.Security.Cryptography.EcDsa.Tests
 {
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public sealed class ECDiffieHellmanKeyPemTests : ECKeyPemTests<ECDiffieHellman>
     {
         protected override ECDiffieHellman CreateKey() => ECDiffieHellman.Create();
index 98cc21c..d826b73 100644 (file)
@@ -9,6 +9,7 @@ using Test.Cryptography;
 
 namespace System.Security.Cryptography.EcDiffieHellman.Tests
 {
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public partial class ECDiffieHellmanTests : EccTestBase
     {
         private static List<object[]> s_everyKeysize;
index 0efb211..d6bc256 100644 (file)
@@ -7,6 +7,7 @@ using Test.Cryptography;
 
 namespace System.Security.Cryptography.EcDsa.Tests
 {
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public class ECDsaImportExportTests : ECDsaTestsBase
     {
 #if NETCOREAPP
index 598ee14..61419f5 100644 (file)
@@ -2,9 +2,11 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 
 using System.Security.Cryptography.Tests;
+using Xunit;
 
 namespace System.Security.Cryptography.EcDsa.Tests
 {
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public class ECDsaKeyFileTests : ECKeyFileTests<ECDsa>
     {
         protected override ECDsa CreateKey()
index 8ab0314..a4e4e25 100644 (file)
@@ -2,9 +2,11 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 
 using System.Security.Cryptography.Tests;
+using Xunit;
 
 namespace System.Security.Cryptography.EcDsa.Tests
 {
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public sealed class ECDsaKeyPemTests : ECKeyPemTests<ECDsa>
     {
         protected override ECDsa CreateKey() => ECDsa.Create();
index 5d44d03..e298877 100644 (file)
@@ -9,6 +9,7 @@ using Xunit;
 
 namespace System.Security.Cryptography.EcDsa.Tests
 {
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public abstract class ECDsaSignatureFormatTests : DsaFamilySignatureFormatTests
     {
         protected override bool SupportsSha2 => true;
index 4017294..530027e 100644 (file)
@@ -11,6 +11,7 @@ using Xunit;
 
 namespace System.Security.Cryptography.EcDsa.Tests
 {
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public sealed class ECDsaTests_Array : ECDsaTests
     {
         protected override bool VerifyData(ECDsa ecdsa, byte[] data, int offset, int count, byte[] signature, HashAlgorithmName hashAlgorithm) =>
@@ -86,6 +87,7 @@ namespace System.Security.Cryptography.EcDsa.Tests
         }
     }
 
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public sealed class ECDsaTests_Stream : ECDsaTests
     {
         protected override bool VerifyData(ECDsa ecdsa, byte[] data, int offset, int count, byte[] signature, HashAlgorithmName hashAlgorithm)
@@ -123,6 +125,7 @@ namespace System.Security.Cryptography.EcDsa.Tests
         }
     }
 
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public abstract partial class ECDsaTests : ECDsaTestsBase
     {
         protected bool VerifyData(ECDsa ecdsa, byte[] data, byte[] signature, HashAlgorithmName hashAlgorithm) =>
index 1b10799..391bfae 100644 (file)
@@ -6,6 +6,7 @@ using Xunit;
 
 namespace System.Security.Cryptography.EcDsa.Tests
 {
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public sealed class ECDsaTests_Span : ECDsaTests
     {
         protected override bool VerifyData(ECDsa ecdsa, byte[] data, int offset, int count, byte[] signature, HashAlgorithmName hashAlgorithm) =>
index 649d58a..af03c8c 100644 (file)
@@ -12,6 +12,7 @@ namespace System.Security.Cryptography.EcDsa.Tests
     /// <summary>
     /// Input and helper methods for ECDsa
     /// </summary>
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public abstract class ECDsaTestsBase : EccTestBase
     {
 #if NETCOREAPP
index ac4ad57..dc8ab6a 100644 (file)
@@ -5,6 +5,7 @@ using Xunit;
 
 namespace System.Security.Cryptography.EcDsa.Tests
 {
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public partial class ECDsaXml : ECDsaTestsBase
     {
         [Fact]
index 02e8992..d52160c 100644 (file)
@@ -10,6 +10,7 @@ namespace System.Security.Cryptography.Encryption.RC2.Tests
 {
     using RC2 = System.Security.Cryptography.RC2;
 
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public static class RC2CipherTests
     {
         // These are the expected output of many decryptions. Changing these values requires re-generating test input.
index 0555074..bbf9b7f 100644 (file)
@@ -12,6 +12,7 @@ namespace System.Security.Cryptography.Encryption.RC2.Tests
 {
     using RC2 = System.Security.Cryptography.RC2;
 
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public static class RC2ContractTests
     {
         [Theory]
index 5d1ecd9..98573f6 100644 (file)
@@ -7,6 +7,7 @@ namespace System.Security.Cryptography.Encryption.RC2.Tests
 {
     using RC2 = System.Security.Cryptography.RC2;
 
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public static partial class RC2Tests
     {
         [Fact]
index 891fbae..5cb0d64 100644 (file)
@@ -24,6 +24,7 @@ namespace System.Security.Cryptography.Rsa.Tests
         }
     }
 
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public abstract class EncryptDecrypt
     {
         public static bool SupportsSha2Oaep => RSAFactory.SupportsSha2Oaep;
index e9489c3..cf5a46e 100644 (file)
@@ -6,6 +6,7 @@ using Xunit;
 
 namespace System.Security.Cryptography.Rsa.Tests
 {
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public sealed class EncryptDecrypt_Span : EncryptDecrypt
     {
         protected override byte[] Encrypt(RSA rsa, byte[] data, RSAEncryptionPadding padding) =>
index 3e04ba6..7f2b093 100644 (file)
@@ -7,6 +7,7 @@ using Xunit;
 
 namespace System.Security.Cryptography.Rsa.Tests
 {
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public partial class ImportExport
     {
         public static bool Supports16384 { get; } = TestRsa16384();
index d47ad3b..b222861 100644 (file)
@@ -7,6 +7,7 @@ using Xunit;
 
 namespace System.Security.Cryptography.Rsa.Tests
 {
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public static class RSAKeyFileTests
     {
         public static bool Supports384BitPrivateKey { get; } = RSAFactory.Supports384PrivateKey;
index 35d0820..c76ab44 100644 (file)
@@ -7,6 +7,7 @@ using Xunit;
 
 namespace System.Security.Cryptography.Rsa.Tests
 {
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public static class RSAKeyPemTests
     {
         private const string AmbiguousExceptionMarker = "multiple keys";
index 6965efd..d93f794 100644 (file)
@@ -7,6 +7,7 @@ using Xunit;
 
 namespace System.Security.Cryptography.Rsa.Tests
 {
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public partial class RSASignatureFormatterTests : AsymmetricSignatureFormatterTests
     {
         [Fact]
index 7fe1079..4af160a 100644 (file)
@@ -7,6 +7,7 @@ using Xunit;
 
 namespace System.Security.Cryptography.Rsa.Tests
 {
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public static class RSAXml
     {
         [Fact]
index 61b15e2..afeddd9 100644 (file)
@@ -9,6 +9,7 @@ using Xunit;
 
 namespace System.Security.Cryptography.Rsa.Tests
 {
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public sealed class SignVerify_Array : SignVerify
     {
         protected override byte[] SignData(RSA rsa, byte[] data, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding) =>
@@ -37,6 +38,7 @@ namespace System.Security.Cryptography.Rsa.Tests
         }
     }
 
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public abstract class SignVerify
     {
         public static bool SupportsPss => RSAFactory.SupportsPss;
index 41513f0..4e34ea9 100644 (file)
@@ -1,2 +1,11 @@
 T:System.Security.Cryptography.RandomNumberGenerator
-T:System.Security.Cryptography.RandomNumberGeneratorImplementation
\ No newline at end of file
+T:System.Security.Cryptography.IncrementalHash
+T:System.Security.Cryptography.MD5
+T:System.Security.Cryptography.SHA1
+T:System.Security.Cryptography.SHA256
+T:System.Security.Cryptography.SHA384
+T:System.Security.Cryptography.SHA512
+T:System.Security.Cryptography.SHA1Managed
+T:System.Security.Cryptography.SHA256Managed
+T:System.Security.Cryptography.SHA384Managed
+T:System.Security.Cryptography.SHA512Managed
\ No newline at end of file
diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/HashProviderDispenser.Browser.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/HashProviderDispenser.Browser.cs
new file mode 100644 (file)
index 0000000..17d2292
--- /dev/null
@@ -0,0 +1,42 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System.Security.Cryptography;
+using Microsoft.Win32.SafeHandles;
+
+namespace Internal.Cryptography
+{
+    internal static partial class HashProviderDispenser
+    {
+        public static HashProvider CreateHashProvider(string hashAlgorithmId)
+        {
+            switch (hashAlgorithmId)
+            {
+                case HashAlgorithmNames.SHA1:
+                case HashAlgorithmNames.SHA256:
+                case HashAlgorithmNames.SHA384:
+                case HashAlgorithmNames.SHA512:
+                    return new SHAHashProvider(hashAlgorithmId);
+            }
+            throw new CryptographicException(SR.Format(SR.Cryptography_UnknownHashAlgorithm, hashAlgorithmId));
+        }
+
+        public static class OneShotHashProvider
+        {
+            public static int HashData(string hashAlgorithmId, ReadOnlySpan<byte> source, Span<byte> destination)
+            {
+                HashProvider provider = HashProviderDispenser.CreateHashProvider(hashAlgorithmId);
+                provider.AppendHashData(source);
+                return provider.FinalizeHashAndReset(destination);
+            }
+        }
+
+        public static unsafe HashProvider CreateMacProvider(string hashAlgorithmId, ReadOnlySpan<byte> key)
+        {
+            throw new PlatformNotSupportedException(SR.SystemSecurityCryptographyAlgorithms_PlatformNotSupported);
+        }
+    }
+}
diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/SHAHashProvider.Browser.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/SHAHashProvider.Browser.cs
new file mode 100644 (file)
index 0000000..9fd4ab1
--- /dev/null
@@ -0,0 +1,1210 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.IO;
+using System.Diagnostics;
+using System.Security.Cryptography;
+
+namespace Internal.Cryptography
+{
+    internal sealed class SHAHashProvider : HashProvider
+    {
+        private int hashSizeInBytes;
+        private SHAManagedImplementationBase impl;
+        private MemoryStream buffer;
+
+        public SHAHashProvider(string hashAlgorithmId)
+        {
+            switch (hashAlgorithmId)
+            {
+                case HashAlgorithmNames.SHA1:
+                    impl = new SHA1ManagedImplementation();
+                    hashSizeInBytes = 20;
+                    break;
+                case HashAlgorithmNames.SHA256:
+                    impl = new SHA256ManagedImplementation();
+                    hashSizeInBytes = 32;
+                    break;
+                case HashAlgorithmNames.SHA384:
+                    impl = new SHA384ManagedImplementation();
+                    hashSizeInBytes = 48;
+                    break;
+                case HashAlgorithmNames.SHA512:
+                    impl = new SHA512ManagedImplementation();
+                    hashSizeInBytes = 64;
+                    break;
+                default:
+                    throw new CryptographicException(SR.Format(SR.Cryptography_UnknownHashAlgorithm, hashAlgorithmId));
+            }
+        }
+
+        public override void AppendHashData(ReadOnlySpan<byte> data)
+        {
+            if (buffer == null)
+            {
+                buffer = new MemoryStream(1000);
+            }
+
+            buffer.Write(data);
+        }
+
+        public override int FinalizeHashAndReset(Span<byte> destination)
+        {
+            GetCurrentHash(destination);
+            buffer = null;
+
+            return hashSizeInBytes;
+        }
+
+        public override int GetCurrentHash(Span<byte> destination)
+        {
+            Debug.Assert(destination.Length >= hashSizeInBytes);
+
+            impl.Initialize();
+            if (buffer != null)
+            {
+                impl.HashCore(buffer.GetBuffer(), 0, (int)buffer.Length);
+            }
+            impl.HashFinal().CopyTo(destination);
+
+            return hashSizeInBytes;
+        }
+
+        public override int HashSizeInBytes => hashSizeInBytes;
+
+        public override void Dispose(bool disposing)
+        {
+        }
+
+        private abstract class SHAManagedImplementationBase
+        {
+            public abstract void Initialize();
+            public abstract void HashCore(byte[] partIn, int ibStart, int cbSize);
+            public abstract byte[] HashFinal();
+        }
+
+        // ported from https://github.com/microsoft/referencesource/blob/a48449cb48a9a693903668a71449ac719b76867c/mscorlib/system/security/cryptography/sha1managed.cs
+        private class SHA1ManagedImplementation : SHAManagedImplementationBase
+        {
+            private byte[] _buffer;
+            private long _count; // Number of bytes in the hashed message
+            private uint[] _stateSHA1;
+            private uint[] _expandedBuffer;
+
+            public SHA1ManagedImplementation()
+            {
+                _stateSHA1 = new uint[5];
+                _buffer = new byte[64];
+                _expandedBuffer = new uint[80];
+
+                InitializeState();
+            }
+
+            public override void Initialize()
+            {
+                InitializeState();
+
+                // Zeroize potentially sensitive information.
+                Array.Clear(_buffer, 0, _buffer.Length);
+                Array.Clear(_expandedBuffer, 0, _expandedBuffer.Length);
+            }
+
+            private void InitializeState()
+            {
+                _count = 0;
+
+                _stateSHA1[0] = 0x67452301;
+                _stateSHA1[1] = 0xefcdab89;
+                _stateSHA1[2] = 0x98badcfe;
+                _stateSHA1[3] = 0x10325476;
+                _stateSHA1[4] = 0xc3d2e1f0;
+            }
+
+            /* Copyright (C) RSA Data Security, Inc. created 1993.  This is an
+            unpublished work protected as such under copyright law.  This work
+            contains proprietary, confidential, and trade secret information of
+            RSA Data Security, Inc.  Use, disclosure or reproduction without the
+            express written authorization of RSA Data Security, Inc. is
+            prohibited.
+            */
+
+            /* SHA block update operation. Continues an SHA message-digest
+            operation, processing another message block, and updating the
+            context.
+            */
+            public override unsafe void HashCore(byte[] partIn, int ibStart, int cbSize)
+            {
+                int bufferLen;
+                int partInLen = cbSize;
+                int partInBase = ibStart;
+
+                /* Compute length of buffer */
+                bufferLen = (int)(_count & 0x3f);
+
+                /* Update number of bytes */
+                _count += partInLen;
+
+                fixed (uint* stateSHA1 = _stateSHA1)
+                {
+                    fixed (byte* buffer = _buffer)
+                    {
+                        fixed (uint* expandedBuffer = _expandedBuffer)
+                        {
+                            if ((bufferLen > 0) && (bufferLen + partInLen >= 64))
+                            {
+                                Buffer.BlockCopy(partIn, partInBase, _buffer, bufferLen, 64 - bufferLen);
+                                partInBase += (64 - bufferLen);
+                                partInLen -= (64 - bufferLen);
+                                SHATransform(expandedBuffer, stateSHA1, buffer);
+                                bufferLen = 0;
+                            }
+
+                            /* Copy input to temporary buffer and hash */
+                            while (partInLen >= 64)
+                            {
+                                Buffer.BlockCopy(partIn, partInBase, _buffer, 0, 64);
+                                partInBase += 64;
+                                partInLen -= 64;
+                                SHATransform(expandedBuffer, stateSHA1, buffer);
+                            }
+
+                            if (partInLen > 0)
+                            {
+                                Buffer.BlockCopy(partIn, partInBase, _buffer, bufferLen, partInLen);
+                            }
+                        }
+                    }
+                }
+            }
+
+            /* SHA finalization. Ends an SHA message-digest operation, writing
+            the message digest.
+                */
+            public override byte[] HashFinal()
+            {
+                byte[] pad;
+                int padLen;
+                long bitCount;
+                byte[] hash = new byte[20];
+
+                /* Compute padding: 80 00 00 ... 00 00 <bit count>
+                */
+
+                padLen = 64 - (int)(_count & 0x3f);
+                if (padLen <= 8)
+                    padLen += 64;
+
+                pad = new byte[padLen];
+                pad[0] = 0x80;
+
+                //  Convert count to bit count
+                bitCount = _count * 8;
+
+                pad[padLen - 8] = (byte)((bitCount >> 56) & 0xff);
+                pad[padLen - 7] = (byte)((bitCount >> 48) & 0xff);
+                pad[padLen - 6] = (byte)((bitCount >> 40) & 0xff);
+                pad[padLen - 5] = (byte)((bitCount >> 32) & 0xff);
+                pad[padLen - 4] = (byte)((bitCount >> 24) & 0xff);
+                pad[padLen - 3] = (byte)((bitCount >> 16) & 0xff);
+                pad[padLen - 2] = (byte)((bitCount >> 8) & 0xff);
+                pad[padLen - 1] = (byte)((bitCount >> 0) & 0xff);
+
+                /* Digest padding */
+                HashCore(pad, 0, pad.Length);
+
+                /* Store digest */
+                SHAUtils.DWORDToBigEndian(hash, _stateSHA1, 5);
+
+                return hash;
+            }
+
+            private unsafe void SHATransform(uint* expandedBuffer, uint* state, byte* block)
+            {
+                uint a = state[0];
+                uint b = state[1];
+                uint c = state[2];
+                uint d = state[3];
+                uint e = state[4];
+
+                int i;
+
+                SHAUtils.DWORDFromBigEndian(expandedBuffer, 16, block);
+                SHAExpand(expandedBuffer);
+
+                /* Round 1 */
+                for (i = 0; i < 20; i += 5)
+                {
+                    { (e) += (((((a)) << (5)) | (((a)) >> (32 - (5)))) + ((d) ^ ((b) & ((c) ^ (d)))) + (expandedBuffer[i]) + 0x5a827999); (b) = ((((b)) << (30)) | (((b)) >> (32 - (30)))); }
+                    { (d) += (((((e)) << (5)) | (((e)) >> (32 - (5)))) + ((c) ^ ((a) & ((b) ^ (c)))) + (expandedBuffer[i + 1]) + 0x5a827999); (a) = ((((a)) << (30)) | (((a)) >> (32 - (30)))); }
+                    { (c) += (((((d)) << (5)) | (((d)) >> (32 - (5)))) + ((b) ^ ((e) & ((a) ^ (b)))) + (expandedBuffer[i + 2]) + 0x5a827999); (e) = ((((e)) << (30)) | (((e)) >> (32 - (30)))); }; ;
+                    { (b) += (((((c)) << (5)) | (((c)) >> (32 - (5)))) + ((a) ^ ((d) & ((e) ^ (a)))) + (expandedBuffer[i + 3]) + 0x5a827999); (d) = ((((d)) << (30)) | (((d)) >> (32 - (30)))); }; ;
+                    { (a) += (((((b)) << (5)) | (((b)) >> (32 - (5)))) + ((e) ^ ((c) & ((d) ^ (e)))) + (expandedBuffer[i + 4]) + 0x5a827999); (c) = ((((c)) << (30)) | (((c)) >> (32 - (30)))); }; ;
+                }
+
+                /* Round 2 */
+                for (; i < 40; i += 5)
+                {
+                    { (e) += (((((a)) << (5)) | (((a)) >> (32 - (5)))) + ((b) ^ (c) ^ (d)) + (expandedBuffer[i]) + 0x6ed9eba1); (b) = ((((b)) << (30)) | (((b)) >> (32 - (30)))); }; ;
+                    { (d) += (((((e)) << (5)) | (((e)) >> (32 - (5)))) + ((a) ^ (b) ^ (c)) + (expandedBuffer[i + 1]) + 0x6ed9eba1); (a) = ((((a)) << (30)) | (((a)) >> (32 - (30)))); }; ;
+                    { (c) += (((((d)) << (5)) | (((d)) >> (32 - (5)))) + ((e) ^ (a) ^ (b)) + (expandedBuffer[i + 2]) + 0x6ed9eba1); (e) = ((((e)) << (30)) | (((e)) >> (32 - (30)))); }; ;
+                    { (b) += (((((c)) << (5)) | (((c)) >> (32 - (5)))) + ((d) ^ (e) ^ (a)) + (expandedBuffer[i + 3]) + 0x6ed9eba1); (d) = ((((d)) << (30)) | (((d)) >> (32 - (30)))); }; ;
+                    { (a) += (((((b)) << (5)) | (((b)) >> (32 - (5)))) + ((c) ^ (d) ^ (e)) + (expandedBuffer[i + 4]) + 0x6ed9eba1); (c) = ((((c)) << (30)) | (((c)) >> (32 - (30)))); }; ;
+                }
+
+                /* Round 3 */
+                for (; i < 60; i += 5)
+                {
+                    { (e) += (((((a)) << (5)) | (((a)) >> (32 - (5)))) + (((b) & (c)) | ((d) & ((b) | (c)))) + (expandedBuffer[i]) + 0x8f1bbcdc); (b) = ((((b)) << (30)) | (((b)) >> (32 - (30)))); }; ;
+                    { (d) += (((((e)) << (5)) | (((e)) >> (32 - (5)))) + (((a) & (b)) | ((c) & ((a) | (b)))) + (expandedBuffer[i + 1]) + 0x8f1bbcdc); (a) = ((((a)) << (30)) | (((a)) >> (32 - (30)))); }; ;
+                    { (c) += (((((d)) << (5)) | (((d)) >> (32 - (5)))) + (((e) & (a)) | ((b) & ((e) | (a)))) + (expandedBuffer[i + 2]) + 0x8f1bbcdc); (e) = ((((e)) << (30)) | (((e)) >> (32 - (30)))); }; ;
+                    { (b) += (((((c)) << (5)) | (((c)) >> (32 - (5)))) + (((d) & (e)) | ((a) & ((d) | (e)))) + (expandedBuffer[i + 3]) + 0x8f1bbcdc); (d) = ((((d)) << (30)) | (((d)) >> (32 - (30)))); }; ;
+                    { (a) += (((((b)) << (5)) | (((b)) >> (32 - (5)))) + (((c) & (d)) | ((e) & ((c) | (d)))) + (expandedBuffer[i + 4]) + 0x8f1bbcdc); (c) = ((((c)) << (30)) | (((c)) >> (32 - (30)))); }; ;
+                }
+
+                /* Round 4 */
+                for (; i < 80; i += 5)
+                {
+                    { (e) += (((((a)) << (5)) | (((a)) >> (32 - (5)))) + ((b) ^ (c) ^ (d)) + (expandedBuffer[i]) + 0xca62c1d6); (b) = ((((b)) << (30)) | (((b)) >> (32 - (30)))); }; ;
+                    { (d) += (((((e)) << (5)) | (((e)) >> (32 - (5)))) + ((a) ^ (b) ^ (c)) + (expandedBuffer[i + 1]) + 0xca62c1d6); (a) = ((((a)) << (30)) | (((a)) >> (32 - (30)))); }; ;
+                    { (c) += (((((d)) << (5)) | (((d)) >> (32 - (5)))) + ((e) ^ (a) ^ (b)) + (expandedBuffer[i + 2]) + 0xca62c1d6); (e) = ((((e)) << (30)) | (((e)) >> (32 - (30)))); }; ;
+                    { (b) += (((((c)) << (5)) | (((c)) >> (32 - (5)))) + ((d) ^ (e) ^ (a)) + (expandedBuffer[i + 3]) + 0xca62c1d6); (d) = ((((d)) << (30)) | (((d)) >> (32 - (30)))); }; ;
+                    { (a) += (((((b)) << (5)) | (((b)) >> (32 - (5)))) + ((c) ^ (d) ^ (e)) + (expandedBuffer[i + 4]) + 0xca62c1d6); (c) = ((((c)) << (30)) | (((c)) >> (32 - (30)))); }; ;
+                }
+
+                state[0] += a;
+                state[1] += b;
+                state[2] += c;
+                state[3] += d;
+                state[4] += e;
+            }
+
+            /* Expands x[0..15] into x[16..79], according to the recurrence
+            x[i] = x[i-3] ^ x[i-8] ^ x[i-14] ^ x[i-16].
+            */
+            private unsafe void SHAExpand(uint* x)
+            {
+                int i;
+                uint tmp;
+
+                for (i = 16; i < 80; i++)
+                {
+                    tmp = (x[i - 3] ^ x[i - 8] ^ x[i - 14] ^ x[i - 16]);
+                    x[i] = ((tmp << 1) | (tmp >> 31));
+                }
+            }
+        }
+
+        // ported from https://github.com/microsoft/referencesource/blob/a48449cb48a9a693903668a71449ac719b76867c/mscorlib/system/security/cryptography/sha256managed.cs
+        private class SHA256ManagedImplementation : SHAManagedImplementationBase
+        {
+            private byte[] _buffer;
+            private long _count; // Number of bytes in the hashed message
+            private uint[] _stateSHA256;
+            private uint[] _W;
+
+            public SHA256ManagedImplementation()
+            {
+                _stateSHA256 = new uint[8];
+                _buffer = new byte[64];
+                _W = new uint[64];
+
+                InitializeState();
+            }
+
+            public override void Initialize()
+            {
+                InitializeState();
+
+                // Zeroize potentially sensitive information.
+                Array.Clear(_buffer, 0, _buffer.Length);
+                Array.Clear(_W, 0, _W.Length);
+            }
+
+            private void InitializeState()
+            {
+                _count = 0;
+
+                _stateSHA256[0] = 0x6a09e667;
+                _stateSHA256[1] = 0xbb67ae85;
+                _stateSHA256[2] = 0x3c6ef372;
+                _stateSHA256[3] = 0xa54ff53a;
+                _stateSHA256[4] = 0x510e527f;
+                _stateSHA256[5] = 0x9b05688c;
+                _stateSHA256[6] = 0x1f83d9ab;
+                _stateSHA256[7] = 0x5be0cd19;
+            }
+
+            /* SHA256 block update operation. Continues an SHA message-digest
+            operation, processing another message block, and updating the
+            context.
+            */
+            public override unsafe void HashCore(byte[] partIn, int ibStart, int cbSize)
+            {
+                int bufferLen;
+                int partInLen = cbSize;
+                int partInBase = ibStart;
+
+                /* Compute length of buffer */
+                bufferLen = (int)(_count & 0x3f);
+
+                /* Update number of bytes */
+                _count += partInLen;
+
+                fixed (uint* stateSHA256 = _stateSHA256)
+                {
+                    fixed (byte* buffer = _buffer)
+                    {
+                        fixed (uint* expandedBuffer = _W)
+                        {
+                            if ((bufferLen > 0) && (bufferLen + partInLen >= 64))
+                            {
+                                Buffer.BlockCopy(partIn, partInBase, _buffer, bufferLen, 64 - bufferLen);
+                                partInBase += (64 - bufferLen);
+                                partInLen -= (64 - bufferLen);
+                                SHATransform(expandedBuffer, stateSHA256, buffer);
+                                bufferLen = 0;
+                            }
+
+                            /* Copy input to temporary buffer and hash */
+                            while (partInLen >= 64)
+                            {
+                                Buffer.BlockCopy(partIn, partInBase, _buffer, 0, 64);
+                                partInBase += 64;
+                                partInLen -= 64;
+                                SHATransform(expandedBuffer, stateSHA256, buffer);
+                            }
+
+                            if (partInLen > 0)
+                            {
+                                Buffer.BlockCopy(partIn, partInBase, _buffer, bufferLen, partInLen);
+                            }
+                        }
+                    }
+                }
+            }
+
+            /* SHA256 finalization. Ends an SHA256 message-digest operation, writing
+            the message digest.
+            */
+            public override byte[] HashFinal()
+            {
+                byte[] pad;
+                int padLen;
+                long bitCount;
+                byte[] hash = new byte[32]; // HashSizeValue = 256
+
+                /* Compute padding: 80 00 00 ... 00 00 <bit count>
+                */
+
+                padLen = 64 - (int)(_count & 0x3f);
+                if (padLen <= 8)
+                    padLen += 64;
+
+                pad = new byte[padLen];
+                pad[0] = 0x80;
+
+                //  Convert count to bit count
+                bitCount = _count * 8;
+
+                pad[padLen - 8] = (byte)((bitCount >> 56) & 0xff);
+                pad[padLen - 7] = (byte)((bitCount >> 48) & 0xff);
+                pad[padLen - 6] = (byte)((bitCount >> 40) & 0xff);
+                pad[padLen - 5] = (byte)((bitCount >> 32) & 0xff);
+                pad[padLen - 4] = (byte)((bitCount >> 24) & 0xff);
+                pad[padLen - 3] = (byte)((bitCount >> 16) & 0xff);
+                pad[padLen - 2] = (byte)((bitCount >> 8) & 0xff);
+                pad[padLen - 1] = (byte)((bitCount >> 0) & 0xff);
+
+                /* Digest padding */
+                HashCore(pad, 0, pad.Length);
+
+                /* Store digest */
+                SHAUtils.DWORDToBigEndian(hash, _stateSHA256, 8);
+
+                return hash;
+            }
+
+            private static readonly uint[] _K = {
+                0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
+                0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
+                0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
+                0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
+                0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
+                0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
+                0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
+                0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
+                0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
+                0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
+                0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
+                0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
+                0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
+                0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
+                0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
+                0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
+            };
+
+            private static unsafe void SHATransform(uint* expandedBuffer, uint* state, byte* block)
+            {
+                uint a, b, c, d, e, f, h, g;
+                uint aa, bb, cc, dd, ee, ff, hh, gg;
+                uint T1;
+
+                a = state[0];
+                b = state[1];
+                c = state[2];
+                d = state[3];
+                e = state[4];
+                f = state[5];
+                g = state[6];
+                h = state[7];
+
+                // fill in the first 16 bytes of W.
+                SHAUtils.DWORDFromBigEndian(expandedBuffer, 16, block);
+                SHA256Expand(expandedBuffer);
+
+                /* Apply the SHA256 compression function */
+                // We are trying to be smart here and avoid as many copies as we can
+                // The perf gain with this method over the straightforward modify and shift
+                // forward is >= 20%, so it's worth the pain
+                for (int j = 0; j < 64;)
+                {
+                    T1 = h + Sigma_1(e) + Ch(e, f, g) + _K[j] + expandedBuffer[j];
+                    ee = d + T1;
+                    aa = T1 + Sigma_0(a) + Maj(a, b, c);
+                    j++;
+
+                    T1 = g + Sigma_1(ee) + Ch(ee, e, f) + _K[j] + expandedBuffer[j];
+                    ff = c + T1;
+                    bb = T1 + Sigma_0(aa) + Maj(aa, a, b);
+                    j++;
+
+                    T1 = f + Sigma_1(ff) + Ch(ff, ee, e) + _K[j] + expandedBuffer[j];
+                    gg = b + T1;
+                    cc = T1 + Sigma_0(bb) + Maj(bb, aa, a);
+                    j++;
+
+                    T1 = e + Sigma_1(gg) + Ch(gg, ff, ee) + _K[j] + expandedBuffer[j];
+                    hh = a + T1;
+                    dd = T1 + Sigma_0(cc) + Maj(cc, bb, aa);
+                    j++;
+
+                    T1 = ee + Sigma_1(hh) + Ch(hh, gg, ff) + _K[j] + expandedBuffer[j];
+                    h = aa + T1;
+                    d = T1 + Sigma_0(dd) + Maj(dd, cc, bb);
+                    j++;
+
+                    T1 = ff + Sigma_1(h) + Ch(h, hh, gg) + _K[j] + expandedBuffer[j];
+                    g = bb + T1;
+                    c = T1 + Sigma_0(d) + Maj(d, dd, cc);
+                    j++;
+
+                    T1 = gg + Sigma_1(g) + Ch(g, h, hh) + _K[j] + expandedBuffer[j];
+                    f = cc + T1;
+                    b = T1 + Sigma_0(c) + Maj(c, d, dd);
+                    j++;
+
+                    T1 = hh + Sigma_1(f) + Ch(f, g, h) + _K[j] + expandedBuffer[j];
+                    e = dd + T1;
+                    a = T1 + Sigma_0(b) + Maj(b, c, d);
+                    j++;
+                }
+
+                state[0] += a;
+                state[1] += b;
+                state[2] += c;
+                state[3] += d;
+                state[4] += e;
+                state[5] += f;
+                state[6] += g;
+                state[7] += h;
+            }
+
+            private static uint RotateRight(uint x, int n)
+            {
+                return (((x) >> (n)) | ((x) << (32 - (n))));
+            }
+
+            private static uint Ch(uint x, uint y, uint z)
+            {
+                return ((x & y) ^ ((x ^ 0xffffffff) & z));
+            }
+
+            private static uint Maj(uint x, uint y, uint z)
+            {
+                return ((x & y) ^ (x & z) ^ (y & z));
+            }
+
+            private static uint sigma_0(uint x)
+            {
+                return (RotateRight(x, 7) ^ RotateRight(x, 18) ^ (x >> 3));
+            }
+
+            private static uint sigma_1(uint x)
+            {
+                return (RotateRight(x, 17) ^ RotateRight(x, 19) ^ (x >> 10));
+            }
+
+            private static uint Sigma_0(uint x)
+            {
+                return (RotateRight(x, 2) ^ RotateRight(x, 13) ^ RotateRight(x, 22));
+            }
+
+            private static uint Sigma_1(uint x)
+            {
+                return (RotateRight(x, 6) ^ RotateRight(x, 11) ^ RotateRight(x, 25));
+            }
+
+            /* This function creates W_16,...,W_63 according to the formula
+            W_j <- sigma_1(W_{j-2}) + W_{j-7} + sigma_0(W_{j-15}) + W_{j-16};
+            */
+            private static unsafe void SHA256Expand(uint* x)
+            {
+                for (int i = 16; i < 64; i++)
+                {
+                    x[i] = sigma_1(x[i - 2]) + x[i - 7] + sigma_0(x[i - 15]) + x[i - 16];
+                }
+            }
+        }
+
+        // ported from https://github.com/microsoft/referencesource/blob/a48449cb48a9a693903668a71449ac719b76867c/mscorlib/system/security/cryptography/sha384managed.cs
+        private class SHA384ManagedImplementation : SHAManagedImplementationBase
+        {
+            private byte[] _buffer;
+            private ulong _count; // Number of bytes in the hashed message
+            private ulong[] _stateSHA384;
+            private ulong[] _W;
+
+            public SHA384ManagedImplementation()
+            {
+                _stateSHA384 = new ulong[8];
+                _buffer = new byte[128];
+                _W = new ulong[80];
+
+                InitializeState();
+            }
+
+            public override void Initialize()
+            {
+                InitializeState();
+
+                // Zeroize potentially sensitive information.
+                Array.Clear(_buffer, 0, _buffer.Length);
+                Array.Clear(_W, 0, _W.Length);
+            }
+
+            private void InitializeState()
+            {
+                _count = 0;
+
+                _stateSHA384[0] = 0xcbbb9d5dc1059ed8;
+                _stateSHA384[1] = 0x629a292a367cd507;
+                _stateSHA384[2] = 0x9159015a3070dd17;
+                _stateSHA384[3] = 0x152fecd8f70e5939;
+                _stateSHA384[4] = 0x67332667ffc00b31;
+                _stateSHA384[5] = 0x8eb44a8768581511;
+                _stateSHA384[6] = 0xdb0c2e0d64f98fa7;
+                _stateSHA384[7] = 0x47b5481dbefa4fa4;
+            }
+
+            /* SHA384 block update operation. Continues an SHA message-digest
+            operation, processing another message block, and updating the
+            context.
+            */
+            public override unsafe void HashCore(byte[] partIn, int ibStart, int cbSize)
+            {
+                int bufferLen;
+                int partInLen = cbSize;
+                int partInBase = ibStart;
+
+                /* Compute length of buffer */
+                bufferLen = (int)(_count & 0x7f);
+
+                /* Update number of bytes */
+                _count += (ulong)partInLen;
+
+                fixed (ulong* stateSHA384 = _stateSHA384)
+                {
+                    fixed (byte* buffer = _buffer)
+                    {
+                        fixed (ulong* expandedBuffer = _W)
+                        {
+                            if ((bufferLen > 0) && (bufferLen + partInLen >= 128))
+                            {
+                                Buffer.BlockCopy(partIn, partInBase, _buffer, bufferLen, 128 - bufferLen);
+                                partInBase += (128 - bufferLen);
+                                partInLen -= (128 - bufferLen);
+                                SHATransform(expandedBuffer, stateSHA384, buffer);
+                                bufferLen = 0;
+                            }
+
+                            /* Copy input to temporary buffer and hash */
+                            while (partInLen >= 128)
+                            {
+                                Buffer.BlockCopy(partIn, partInBase, _buffer, 0, 128);
+                                partInBase += 128;
+                                partInLen -= 128;
+                                SHATransform(expandedBuffer, stateSHA384, buffer);
+                            }
+
+                            if (partInLen > 0)
+                            {
+                                Buffer.BlockCopy(partIn, partInBase, _buffer, bufferLen, partInLen);
+                            }
+                        }
+                    }
+                }
+            }
+
+            /* SHA384 finalization. Ends an SHA384 message-digest operation, writing
+            the message digest.
+            */
+            public override byte[] HashFinal()
+            {
+                byte[] pad;
+                int padLen;
+                ulong bitCount;
+                byte[] hash = new byte[48]; // HashSizeValue = 384
+
+                /* Compute padding: 80 00 00 ... 00 00 <bit count>
+                */
+
+                padLen = 128 - (int)(_count & 0x7f);
+                if (padLen <= 16)
+                    padLen += 128;
+
+                pad = new byte[padLen];
+                pad[0] = 0x80;
+
+                //  Convert count to bit count
+                bitCount = _count * 8;
+
+                // bitCount is at most 8 * 128 = 1024. Its representation as a 128-bit number has all bits set to zero
+                // except eventually the 11 lower bits
+
+                //pad[padLen-16] = (byte) ((bitCount >> 120) & 0xff);
+                //pad[padLen-15] = (byte) ((bitCount >> 112) & 0xff);
+                //pad[padLen-14] = (byte) ((bitCount >> 104) & 0xff);
+                //pad[padLen-13] = (byte) ((bitCount >> 96) & 0xff);
+                //pad[padLen-12] = (byte) ((bitCount >> 88) & 0xff);
+                //pad[padLen-11] = (byte) ((bitCount >> 80) & 0xff);
+                //pad[padLen-10] = (byte) ((bitCount >> 72) & 0xff);
+                //pad[padLen-9] = (byte) ((bitCount >> 64) & 0xff);
+                pad[padLen - 8] = (byte)((bitCount >> 56) & 0xff);
+                pad[padLen - 7] = (byte)((bitCount >> 48) & 0xff);
+                pad[padLen - 6] = (byte)((bitCount >> 40) & 0xff);
+                pad[padLen - 5] = (byte)((bitCount >> 32) & 0xff);
+                pad[padLen - 4] = (byte)((bitCount >> 24) & 0xff);
+                pad[padLen - 3] = (byte)((bitCount >> 16) & 0xff);
+                pad[padLen - 2] = (byte)((bitCount >> 8) & 0xff);
+                pad[padLen - 1] = (byte)((bitCount >> 0) & 0xff);
+
+                /* Digest padding */
+                HashCore(pad, 0, pad.Length);
+
+                /* Store digest */
+                SHAUtils.QuadWordToBigEndian(hash, _stateSHA384, 6);
+
+                return hash;
+            }
+
+            private static readonly ulong[] _K = {
+                0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc,
+                0x3956c25bf348b538, 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118,
+                0xd807aa98a3030242, 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2,
+                0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235, 0xc19bf174cf692694,
+                0xe49b69c19ef14ad2, 0xefbe4786384f25e3, 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65,
+                0x2de92c6f592b0275, 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5,
+                0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f, 0xbf597fc7beef0ee4,
+                0xc6e00bf33da88fc2, 0xd5a79147930aa725, 0x06ca6351e003826f, 0x142929670a0e6e70,
+                0x27b70a8546d22ffc, 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df,
+                0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, 0x92722c851482353b,
+                0xa2bfe8a14cf10364, 0xa81a664bbc423001, 0xc24b8b70d0f89791, 0xc76c51a30654be30,
+                0xd192e819d6ef5218, 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8,
+                0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8,
+                0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3,
+                0x748f82ee5defb2fc, 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec,
+                0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, 0xc67178f2e372532b,
+                0xca273eceea26619c, 0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178,
+                0x06f067aa72176fba, 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b,
+                0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c,
+                0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817,
+            };
+
+            private static unsafe void SHATransform(ulong* expandedBuffer, ulong* state, byte* block)
+            {
+                ulong a, b, c, d, e, f, g, h;
+                ulong aa, bb, cc, dd, ee, ff, hh, gg;
+                ulong T1;
+
+                a = state[0];
+                b = state[1];
+                c = state[2];
+                d = state[3];
+                e = state[4];
+                f = state[5];
+                g = state[6];
+                h = state[7];
+
+                // fill in the first 16 blocks of W.
+                SHAUtils.QuadWordFromBigEndian(expandedBuffer, 16, block);
+                SHA384Expand(expandedBuffer);
+
+                /* Apply the SHA384 compression function */
+                // We are trying to be smart here and avoid as many copies as we can
+                // The perf gain with this method over the straightforward modify and shift
+                // forward is >= 20%, so it's worth the pain
+                for (int j = 0; j < 80;)
+                {
+                    T1 = h + Sigma_1(e) + Ch(e, f, g) + _K[j] + expandedBuffer[j];
+                    ee = d + T1;
+                    aa = T1 + Sigma_0(a) + Maj(a, b, c);
+                    j++;
+
+                    T1 = g + Sigma_1(ee) + Ch(ee, e, f) + _K[j] + expandedBuffer[j];
+                    ff = c + T1;
+                    bb = T1 + Sigma_0(aa) + Maj(aa, a, b);
+                    j++;
+
+                    T1 = f + Sigma_1(ff) + Ch(ff, ee, e) + _K[j] + expandedBuffer[j];
+                    gg = b + T1;
+                    cc = T1 + Sigma_0(bb) + Maj(bb, aa, a);
+                    j++;
+
+                    T1 = e + Sigma_1(gg) + Ch(gg, ff, ee) + _K[j] + expandedBuffer[j];
+                    hh = a + T1;
+                    dd = T1 + Sigma_0(cc) + Maj(cc, bb, aa);
+                    j++;
+
+                    T1 = ee + Sigma_1(hh) + Ch(hh, gg, ff) + _K[j] + expandedBuffer[j];
+                    h = aa + T1;
+                    d = T1 + Sigma_0(dd) + Maj(dd, cc, bb);
+                    j++;
+
+                    T1 = ff + Sigma_1(h) + Ch(h, hh, gg) + _K[j] + expandedBuffer[j];
+                    g = bb + T1;
+                    c = T1 + Sigma_0(d) + Maj(d, dd, cc);
+                    j++;
+
+                    T1 = gg + Sigma_1(g) + Ch(g, h, hh) + _K[j] + expandedBuffer[j];
+                    f = cc + T1;
+                    b = T1 + Sigma_0(c) + Maj(c, d, dd);
+                    j++;
+
+                    T1 = hh + Sigma_1(f) + Ch(f, g, h) + _K[j] + expandedBuffer[j];
+                    e = dd + T1;
+                    a = T1 + Sigma_0(b) + Maj(b, c, d);
+                    j++;
+                }
+
+                state[0] += a;
+                state[1] += b;
+                state[2] += c;
+                state[3] += d;
+                state[4] += e;
+                state[5] += f;
+                state[6] += g;
+                state[7] += h;
+            }
+
+            private static ulong RotateRight(ulong x, int n)
+            {
+                return (((x) >> (n)) | ((x) << (64 - (n))));
+            }
+
+            private static ulong Ch(ulong x, ulong y, ulong z)
+            {
+                return ((x & y) ^ ((x ^ 0xffffffffffffffff) & z));
+            }
+
+            private static ulong Maj(ulong x, ulong y, ulong z)
+            {
+                return ((x & y) ^ (x & z) ^ (y & z));
+            }
+
+            private static ulong Sigma_0(ulong x)
+            {
+                return (RotateRight(x, 28) ^ RotateRight(x, 34) ^ RotateRight(x, 39));
+            }
+
+            private static ulong Sigma_1(ulong x)
+            {
+                return (RotateRight(x, 14) ^ RotateRight(x, 18) ^ RotateRight(x, 41));
+            }
+
+            private static ulong sigma_0(ulong x)
+            {
+                return (RotateRight(x, 1) ^ RotateRight(x, 8) ^ (x >> 7));
+            }
+
+            private static ulong sigma_1(ulong x)
+            {
+                return (RotateRight(x, 19) ^ RotateRight(x, 61) ^ (x >> 6));
+            }
+
+            /* This function creates W_16,...,W_79 according to the formula
+            W_j <- sigma_1(W_{j-2}) + W_{j-7} + sigma_0(W_{j-15}) + W_{j-16};
+            */
+            private static unsafe void SHA384Expand(ulong* x)
+            {
+                for (int i = 16; i < 80; i++)
+                {
+                    x[i] = sigma_1(x[i - 2]) + x[i - 7] + sigma_0(x[i - 15]) + x[i - 16];
+                }
+            }
+        }
+
+        // ported from https://github.com/microsoft/referencesource/blob/a48449cb48a9a693903668a71449ac719b76867c/mscorlib/system/security/cryptography/sha512managed.cs
+        private class SHA512ManagedImplementation : SHAManagedImplementationBase
+        {
+            private byte[] _buffer;
+            private ulong _count; // Number of bytes in the hashed message
+            private ulong[] _stateSHA512;
+            private ulong[] _W;
+
+            public SHA512ManagedImplementation()
+            {
+                _stateSHA512 = new ulong[8];
+                _buffer = new byte[128];
+                _W = new ulong[80];
+
+                InitializeState();
+            }
+
+            public override void Initialize()
+            {
+                InitializeState();
+
+                // Zeroize potentially sensitive information.
+                Array.Clear(_buffer, 0, _buffer.Length);
+                Array.Clear(_W, 0, _W.Length);
+            }
+
+            private void InitializeState()
+            {
+                _count = 0;
+
+                _stateSHA512[0] = 0x6a09e667f3bcc908;
+                _stateSHA512[1] = 0xbb67ae8584caa73b;
+                _stateSHA512[2] = 0x3c6ef372fe94f82b;
+                _stateSHA512[3] = 0xa54ff53a5f1d36f1;
+                _stateSHA512[4] = 0x510e527fade682d1;
+                _stateSHA512[5] = 0x9b05688c2b3e6c1f;
+                _stateSHA512[6] = 0x1f83d9abfb41bd6b;
+                _stateSHA512[7] = 0x5be0cd19137e2179;
+            }
+
+            /* SHA512 block update operation. Continues an SHA message-digest
+            operation, processing another message block, and updating the
+            context.
+            */
+            public override unsafe void HashCore(byte[] partIn, int ibStart, int cbSize)
+            {
+                int bufferLen;
+                int partInLen = cbSize;
+                int partInBase = ibStart;
+
+                /* Compute length of buffer */
+                bufferLen = (int)(_count & 0x7f);
+
+                /* Update number of bytes */
+                _count += (ulong)partInLen;
+
+                fixed (ulong* stateSHA512 = _stateSHA512)
+                {
+                    fixed (byte* buffer = _buffer)
+                    {
+                        fixed (ulong* expandedBuffer = _W)
+                        {
+                            if ((bufferLen > 0) && (bufferLen + partInLen >= 128))
+                            {
+                                Buffer.BlockCopy(partIn, partInBase, _buffer, bufferLen, 128 - bufferLen);
+                                partInBase += (128 - bufferLen);
+                                partInLen -= (128 - bufferLen);
+                                SHATransform(expandedBuffer, stateSHA512, buffer);
+                                bufferLen = 0;
+                            }
+
+                            /* Copy input to temporary buffer and hash */
+                            while (partInLen >= 128)
+                            {
+                                Buffer.BlockCopy(partIn, partInBase, _buffer, 0, 128);
+                                partInBase += 128;
+                                partInLen -= 128;
+                                SHATransform(expandedBuffer, stateSHA512, buffer);
+                            }
+
+                            if (partInLen > 0)
+                            {
+                                Buffer.BlockCopy(partIn, partInBase, _buffer, bufferLen, partInLen);
+                            }
+                        }
+                    }
+                }
+            }
+
+            /* SHA512 finalization. Ends an SHA512 message-digest operation, writing
+            the message digest.
+            */
+            public override byte[] HashFinal()
+            {
+                byte[] pad;
+                int padLen;
+                ulong bitCount;
+                byte[] hash = new byte[64]; // HashSizeValue = 512
+
+                /* Compute padding: 80 00 00 ... 00 00 <bit count>
+                */
+
+                padLen = 128 - (int)(_count & 0x7f);
+                if (padLen <= 16)
+                    padLen += 128;
+
+                pad = new byte[padLen];
+                pad[0] = 0x80;
+
+                //  Convert count to bit count
+                bitCount = _count * 8;
+
+                // If we ever have UInt128 for bitCount, then these need to be uncommented.
+                // Note that C# only looks at the low 6 bits of the shift value for ulongs,
+                // so >>0 and >>64 are equal!
+
+                //pad[padLen-16] = (byte) ((bitCount >> 120) & 0xff);
+                //pad[padLen-15] = (byte) ((bitCount >> 112) & 0xff);
+                //pad[padLen-14] = (byte) ((bitCount >> 104) & 0xff);
+                //pad[padLen-13] = (byte) ((bitCount >> 96) & 0xff);
+                //pad[padLen-12] = (byte) ((bitCount >> 88) & 0xff);
+                //pad[padLen-11] = (byte) ((bitCount >> 80) & 0xff);
+                //pad[padLen-10] = (byte) ((bitCount >> 72) & 0xff);
+                //pad[padLen-9] = (byte) ((bitCount >> 64) & 0xff);
+                pad[padLen - 8] = (byte)((bitCount >> 56) & 0xff);
+                pad[padLen - 7] = (byte)((bitCount >> 48) & 0xff);
+                pad[padLen - 6] = (byte)((bitCount >> 40) & 0xff);
+                pad[padLen - 5] = (byte)((bitCount >> 32) & 0xff);
+                pad[padLen - 4] = (byte)((bitCount >> 24) & 0xff);
+                pad[padLen - 3] = (byte)((bitCount >> 16) & 0xff);
+                pad[padLen - 2] = (byte)((bitCount >> 8) & 0xff);
+                pad[padLen - 1] = (byte)((bitCount >> 0) & 0xff);
+
+                /* Digest padding */
+                HashCore(pad, 0, pad.Length);
+
+                /* Store digest */
+                SHAUtils.QuadWordToBigEndian(hash, _stateSHA512, 8);
+
+                return hash;
+            }
+
+            private static readonly ulong[] _K = {
+                0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc,
+                0x3956c25bf348b538, 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118,
+                0xd807aa98a3030242, 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2,
+                0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235, 0xc19bf174cf692694,
+                0xe49b69c19ef14ad2, 0xefbe4786384f25e3, 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65,
+                0x2de92c6f592b0275, 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5,
+                0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f, 0xbf597fc7beef0ee4,
+                0xc6e00bf33da88fc2, 0xd5a79147930aa725, 0x06ca6351e003826f, 0x142929670a0e6e70,
+                0x27b70a8546d22ffc, 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df,
+                0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, 0x92722c851482353b,
+                0xa2bfe8a14cf10364, 0xa81a664bbc423001, 0xc24b8b70d0f89791, 0xc76c51a30654be30,
+                0xd192e819d6ef5218, 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8,
+                0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8,
+                0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3,
+                0x748f82ee5defb2fc, 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec,
+                0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, 0xc67178f2e372532b,
+                0xca273eceea26619c, 0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178,
+                0x06f067aa72176fba, 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b,
+                0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c,
+                0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817,
+            };
+
+            private static unsafe void SHATransform(ulong* expandedBuffer, ulong* state, byte* block)
+            {
+                ulong a, b, c, d, e, f, g, h;
+                ulong aa, bb, cc, dd, ee, ff, hh, gg;
+                ulong T1;
+
+                a = state[0];
+                b = state[1];
+                c = state[2];
+                d = state[3];
+                e = state[4];
+                f = state[5];
+                g = state[6];
+                h = state[7];
+
+                // fill in the first 16 blocks of W.
+                SHAUtils.QuadWordFromBigEndian(expandedBuffer, 16, block);
+                SHA512Expand(expandedBuffer);
+
+                /* Apply the SHA512 compression function */
+                // We are trying to be smart here and avoid as many copies as we can
+                // The perf gain with this method over the straightforward modify and shift
+                // forward is >= 20%, so it's worth the pain
+                for (int j = 0; j < 80;)
+                {
+                    T1 = h + Sigma_1(e) + Ch(e, f, g) + _K[j] + expandedBuffer[j];
+                    ee = d + T1;
+                    aa = T1 + Sigma_0(a) + Maj(a, b, c);
+                    j++;
+
+                    T1 = g + Sigma_1(ee) + Ch(ee, e, f) + _K[j] + expandedBuffer[j];
+                    ff = c + T1;
+                    bb = T1 + Sigma_0(aa) + Maj(aa, a, b);
+                    j++;
+
+                    T1 = f + Sigma_1(ff) + Ch(ff, ee, e) + _K[j] + expandedBuffer[j];
+                    gg = b + T1;
+                    cc = T1 + Sigma_0(bb) + Maj(bb, aa, a);
+                    j++;
+
+                    T1 = e + Sigma_1(gg) + Ch(gg, ff, ee) + _K[j] + expandedBuffer[j];
+                    hh = a + T1;
+                    dd = T1 + Sigma_0(cc) + Maj(cc, bb, aa);
+                    j++;
+
+                    T1 = ee + Sigma_1(hh) + Ch(hh, gg, ff) + _K[j] + expandedBuffer[j];
+                    h = aa + T1;
+                    d = T1 + Sigma_0(dd) + Maj(dd, cc, bb);
+                    j++;
+
+                    T1 = ff + Sigma_1(h) + Ch(h, hh, gg) + _K[j] + expandedBuffer[j];
+                    g = bb + T1;
+                    c = T1 + Sigma_0(d) + Maj(d, dd, cc);
+                    j++;
+
+                    T1 = gg + Sigma_1(g) + Ch(g, h, hh) + _K[j] + expandedBuffer[j];
+                    f = cc + T1;
+                    b = T1 + Sigma_0(c) + Maj(c, d, dd);
+                    j++;
+
+                    T1 = hh + Sigma_1(f) + Ch(f, g, h) + _K[j] + expandedBuffer[j];
+                    e = dd + T1;
+                    a = T1 + Sigma_0(b) + Maj(b, c, d);
+                    j++;
+                }
+
+                state[0] += a;
+                state[1] += b;
+                state[2] += c;
+                state[3] += d;
+                state[4] += e;
+                state[5] += f;
+                state[6] += g;
+                state[7] += h;
+            }
+
+            private static ulong RotateRight(ulong x, int n)
+            {
+                return (((x) >> (n)) | ((x) << (64 - (n))));
+            }
+
+            private static ulong Ch(ulong x, ulong y, ulong z)
+            {
+                return ((x & y) ^ ((x ^ 0xffffffffffffffff) & z));
+            }
+
+            private static ulong Maj(ulong x, ulong y, ulong z)
+            {
+                return ((x & y) ^ (x & z) ^ (y & z));
+            }
+
+            private static ulong Sigma_0(ulong x)
+            {
+                return (RotateRight(x, 28) ^ RotateRight(x, 34) ^ RotateRight(x, 39));
+            }
+
+            private static ulong Sigma_1(ulong x)
+            {
+                return (RotateRight(x, 14) ^ RotateRight(x, 18) ^ RotateRight(x, 41));
+            }
+
+            private static ulong sigma_0(ulong x)
+            {
+                return (RotateRight(x, 1) ^ RotateRight(x, 8) ^ (x >> 7));
+            }
+
+            private static ulong sigma_1(ulong x)
+            {
+                return (RotateRight(x, 19) ^ RotateRight(x, 61) ^ (x >> 6));
+            }
+
+            /* This function creates W_16,...,W_79 according to the formula
+            W_j <- sigma_1(W_{j-2}) + W_{j-7} + sigma_0(W_{j-15}) + W_{j-16};
+            */
+            private static unsafe void SHA512Expand(ulong* x)
+            {
+                for (int i = 16; i < 80; i++)
+                {
+                    x[i] = sigma_1(x[i - 2]) + x[i - 7] + sigma_0(x[i - 15]) + x[i - 16];
+                }
+            }
+        }
+
+        // ported from https://github.com/microsoft/referencesource/blob/a48449cb48a9a693903668a71449ac719b76867c/mscorlib/system/security/cryptography/utils.cs
+        private class SHAUtils
+        {
+            // digits == number of DWORDs
+            public static unsafe void DWORDFromBigEndian(uint* x, int digits, byte* block)
+            {
+                int i;
+                int j;
+
+                for (i = 0, j = 0; i < digits; i++, j += 4)
+                    x[i] = (uint)((block[j] << 24) | (block[j + 1] << 16) | (block[j + 2] << 8) | block[j + 3]);
+            }
+
+            // encodes x (DWORD) into block (unsigned char), most significant byte first.
+            // digits == number of DWORDs
+            public static void DWORDToBigEndian(byte[] block, uint[] x, int digits)
+            {
+                int i;
+                int j;
+
+                for (i = 0, j = 0; i < digits; i++, j += 4)
+                {
+                    block[j] = (byte)((x[i] >> 24) & 0xff);
+                    block[j + 1] = (byte)((x[i] >> 16) & 0xff);
+                    block[j + 2] = (byte)((x[i] >> 8) & 0xff);
+                    block[j + 3] = (byte)(x[i] & 0xff);
+                }
+            }
+
+            // digits == number of QWORDs
+            public static unsafe void QuadWordFromBigEndian(ulong* x, int digits, byte* block)
+            {
+                int i;
+                int j;
+
+                for (i = 0, j = 0; i < digits; i++, j += 8)
+                    x[i] = (
+                            (((ulong)block[j]) << 56) | (((ulong)block[j + 1]) << 48) |
+                            (((ulong)block[j + 2]) << 40) | (((ulong)block[j + 3]) << 32) |
+                            (((ulong)block[j + 4]) << 24) | (((ulong)block[j + 5]) << 16) |
+                            (((ulong)block[j + 6]) << 8) | ((ulong)block[j + 7])
+                            );
+            }
+
+            // encodes x (DWORD) into block (unsigned char), most significant byte first.
+            // digits = number of QWORDS
+            public static void QuadWordToBigEndian(byte[] block, ulong[] x, int digits)
+            {
+                int i;
+                int j;
+
+                for (i = 0, j = 0; i < digits; i++, j += 8)
+                {
+                    block[j] = (byte)((x[i] >> 56) & 0xff);
+                    block[j + 1] = (byte)((x[i] >> 48) & 0xff);
+                    block[j + 2] = (byte)((x[i] >> 40) & 0xff);
+                    block[j + 3] = (byte)((x[i] >> 32) & 0xff);
+                    block[j + 4] = (byte)((x[i] >> 24) & 0xff);
+                    block[j + 5] = (byte)((x[i] >> 16) & 0xff);
+                    block[j + 6] = (byte)((x[i] >> 8) & 0xff);
+                    block[j + 7] = (byte)(x[i] & 0xff);
+                }
+            }
+        }
+    }
+}
index 80fa4fb..5fa0818 100644 (file)
     <Compile Include="System\Security\Cryptography\AesGcm.Unix.cs" />
   </ItemGroup>
   <ItemGroup Condition=" '$(TargetsBrowser)' == 'true'">
-    <Compile Include="System\Security\Cryptography\RandomNumberGenerator.cs" />
-    <Compile Include="Internal\Cryptography\RandomNumberGeneratorImplementation.cs" />
-    <Compile Include="Internal\Cryptography\RandomNumberGeneratorImplementation.Browser.cs" />
+    <Compile Include="$(CommonPath)Internal\Cryptography\HashProvider.cs"
+             Link="Internal\Cryptography\HashProvider.cs" />
     <Compile Include="$(CommonPath)Interop\Unix\System.Native\Interop.GetRandomBytes.cs"
              Link="Common\Interop\Unix\System.Native\Interop.GetRandomBytes.cs" />
     <Compile Include="$(CommonPath)Interop\Unix\Interop.Libraries.cs"
              Link="Common\Interop\Unix\Interop.Libraries.cs" />
+    <Compile Include="Internal\Cryptography\HashAlgorithmNames.cs" />
+    <Compile Include="Internal\Cryptography\HashProviderDispenser.Browser.cs" />
+    <Compile Include="Internal\Cryptography\HMACCommon.cs" />
+    <Compile Include="Internal\Cryptography\RandomNumberGeneratorImplementation.cs" />
+    <Compile Include="Internal\Cryptography\RandomNumberGeneratorImplementation.Browser.cs" />
+    <Compile Include="Internal\Cryptography\SHAHashProvider.Browser.cs" />
+    <Compile Include="System\Security\Cryptography\RandomNumberGenerator.cs" />
+    <Compile Include="System\Security\Cryptography\IncrementalHash.cs" />
+    <Compile Include="System\Security\Cryptography\MD5.cs" />
+    <Compile Include="System\Security\Cryptography\SHA1.cs" />
+    <Compile Include="System\Security\Cryptography\SHA1Managed.cs" />
+    <Compile Include="System\Security\Cryptography\SHA256.cs" />
+    <Compile Include="System\Security\Cryptography\SHA256Managed.cs" />
+    <Compile Include="System\Security\Cryptography\SHA384.cs" />
+    <Compile Include="System\Security\Cryptography\SHA384Managed.cs" />
+    <Compile Include="System\Security\Cryptography\SHA512.cs" />
+    <Compile Include="System\Security\Cryptography\SHA512Managed.cs" />
   </ItemGroup>
   <ItemGroup>
     <Reference Include="System.Collections" />
index 359cdae..f6ecad1 100644 (file)
@@ -8,6 +8,7 @@ using Xunit;
 
 namespace System.Security.Cryptography.Algorithms.Tests
 {
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public class AesCcmTests : AesAEADTests
     {
         [Theory]
index 1a7b596..3cde0f3 100644 (file)
@@ -8,6 +8,7 @@ using Xunit;
 
 namespace System.Security.Cryptography.Algorithms.Tests
 {
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public class AesGcmTests : AesAEADTests
     {
         [Theory]
index ca9f92c..681f9ed 100644 (file)
@@ -11,6 +11,7 @@ namespace System.Security.Cryptography.Encryption.Aes.Tests
     /// <summary>
     /// Since AesManaged wraps Aes, we only test minimally here.
     /// </summary>
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public class AesManagedTests
     {
         [Fact]
index 92d712a..516bcf7 100644 (file)
@@ -5,6 +5,7 @@ using Xunit;
 
 namespace System.Security.Cryptography.Algorithms.Tests
 {
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public partial class AesTests
     {
         [Fact]
diff --git a/src/libraries/System.Security.Cryptography.Algorithms/tests/AssemblyInfo.cs b/src/libraries/System.Security.Cryptography.Algorithms/tests/AssemblyInfo.cs
deleted file mode 100644 (file)
index 3a74f33..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System;
-using Xunit;
-
-[assembly: ActiveIssue("https://github.com/dotnet/runtime/issues/37669", TestPlatforms.Browser)]
index 27013d8..655735d 100644 (file)
@@ -8,6 +8,7 @@ namespace System.Security.Cryptography.Tests
     /// <summary>
     /// Helper methods for DSASignatureFormatterTests and RSASignatureFormatterTests
     /// </summary>
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public partial class AsymmetricSignatureFormatterTests
     {
         protected static void InvalidFormatterArguments(AsymmetricSignatureFormatter formatter)
index 6afe499..0faa251 100644 (file)
@@ -6,6 +6,7 @@ using Xunit;
 
 namespace System.Security.Cryptography.Hashing.Algorithms.Tests
 {
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public class BlockSizeValueTests
     {
         [Fact]
index 74d475b..630aac6 100644 (file)
@@ -9,6 +9,7 @@ using Xunit;
 
 namespace System.Security.Cryptography.CryptoConfigTests
 {
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public static class CryptoConfigTests
     {
         [Fact]
index e9b5559..0ed0f5c 100644 (file)
@@ -6,6 +6,7 @@ using Xunit;
 
 namespace System.Security.Cryptography.Algorithms.Tests
 {
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public static class DSACreateTests
     {
         public static bool SupportsKeyGeneration => DSAFactory.SupportsKeyGeneration;
index 2d35887..57270d6 100644 (file)
@@ -8,6 +8,7 @@ using Xunit;
 
 namespace System.Security.Cryptography.Algorithms.Tests
 {
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public class DSATests
     {
         public static bool SupportsKeyGeneration => DSAFactory.SupportsKeyGeneration;
index a5bd21b..d6ef4ab 100644 (file)
@@ -5,6 +5,7 @@ using Xunit;
 
 namespace System.Security.Cryptography.EcDiffieHellman.Tests
 {
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public class ECDiffieHellmanPublicKeyTests
     {
         private class TestDerived : ECDiffieHellmanPublicKey
index 7ec18b7..cd74668 100644 (file)
@@ -8,6 +8,7 @@ using Xunit;
 
 namespace System.Security.Cryptography.Algorithms.Tests
 {
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public class ECDsaTests
     {
         [Fact]
index 88ad4e7..cf69960 100644 (file)
@@ -9,6 +9,7 @@ using Xunit;
 
 namespace System.Security.Cryptography.Algorithms.Tests
 {
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public abstract class HKDFTests
     {
         protected abstract byte[] Extract(HashAlgorithmName hash, int prkLength, byte[] ikm, byte[] salt);
index b51aaeb..77052ef 100644 (file)
@@ -6,6 +6,7 @@ using Xunit;
 
 namespace System.Security.Cryptography.Hashing.Algorithms.Tests
 {
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public class HmacMD5Tests : Rfc2202HmacTests
     {
         private static readonly byte[][] s_testKeys2202 =
index 81bfecc..12542b9 100644 (file)
@@ -6,6 +6,7 @@ using Xunit;
 
 namespace System.Security.Cryptography.Hashing.Algorithms.Tests
 {
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public class HmacSha1Tests : Rfc2202HmacTests
     {
         private static readonly byte[][] s_testKeys2202 =
index 9de8cdc..1024972 100644 (file)
@@ -5,6 +5,7 @@ using Xunit;
 
 namespace System.Security.Cryptography.Hashing.Algorithms.Tests
 {
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public class HmacSha256Tests : Rfc4231HmacTests
     {
         protected override HMAC Create()
index de33f4e..2bd880c 100644 (file)
@@ -5,6 +5,7 @@ using Xunit;
 
 namespace System.Security.Cryptography.Hashing.Algorithms.Tests
 {
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public class HmacSha384Tests : Rfc4231HmacTests
     {
         protected override HMAC Create()
index 720950c..7b5ee6d 100644 (file)
@@ -5,6 +5,7 @@ using Xunit;
 
 namespace System.Security.Cryptography.Hashing.Algorithms.Tests
 {
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public class HmacSha512Tests : Rfc4231HmacTests
     {
         protected override HMAC Create()
index 16a1b88..700bf7d 100644 (file)
@@ -7,6 +7,7 @@ using Xunit;
 
 namespace System.Security.Cryptography.Hashing.Algorithms.Tests
 {
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public abstract class HmacTests
     {
         // RFC2202 defines the test vectors for HMACMD5 and HMACSHA1
index 4b876c3..379fda2 100644 (file)
@@ -15,14 +15,16 @@ namespace System.Security.Cryptography.Algorithms.Tests
 
         public static IEnumerable<object[]> GetHashAlgorithms()
         {
-            return new[]
+            if (PlatformDetection.IsNotBrowser)
             {
-                new object[] { MD5.Create(), HashAlgorithmName.MD5 },
-                new object[] { SHA1.Create(), HashAlgorithmName.SHA1 },
-                new object[] { SHA256.Create(), HashAlgorithmName.SHA256 },
-                new object[] { SHA384.Create(), HashAlgorithmName.SHA384 },
-                new object[] { SHA512.Create(), HashAlgorithmName.SHA512 },
-            };
+                // MD5 is not supported on Browser
+                yield return new object[] { MD5.Create(), HashAlgorithmName.MD5 };
+            }
+
+            yield return new object[] { SHA1.Create(), HashAlgorithmName.SHA1 };
+            yield return new object[] { SHA256.Create(), HashAlgorithmName.SHA256 };
+            yield return new object[] { SHA384.Create(), HashAlgorithmName.SHA384 };
+            yield return new object[] { SHA512.Create(), HashAlgorithmName.SHA512 };
         }
 
         public static IEnumerable<object[]> GetHMACs()
@@ -43,10 +45,14 @@ namespace System.Security.Cryptography.Algorithms.Tests
             AssertExtensions.Throws<ArgumentException>("hashAlgorithm", () => IncrementalHash.CreateHash(new HashAlgorithmName(null)));
             AssertExtensions.Throws<ArgumentException>("hashAlgorithm", () => IncrementalHash.CreateHash(new HashAlgorithmName("")));
 
-            AssertExtensions.Throws<ArgumentException>("hashAlgorithm", () => IncrementalHash.CreateHMAC(new HashAlgorithmName(null), new byte[1]));
-            AssertExtensions.Throws<ArgumentException>("hashAlgorithm", () => IncrementalHash.CreateHMAC(new HashAlgorithmName(""), new byte[1]));
+            if (PlatformDetection.IsNotBrowser)
+            {
+                // HMAC is not supported on Browser
+                AssertExtensions.Throws<ArgumentException>("hashAlgorithm", () => IncrementalHash.CreateHMAC(new HashAlgorithmName(null), new byte[1]));
+                AssertExtensions.Throws<ArgumentException>("hashAlgorithm", () => IncrementalHash.CreateHMAC(new HashAlgorithmName(""), new byte[1]));
 
-            AssertExtensions.Throws<ArgumentNullException>("key", () => IncrementalHash.CreateHMAC(HashAlgorithmName.SHA512, null));
+                AssertExtensions.Throws<ArgumentNullException>("key", () => IncrementalHash.CreateHMAC(HashAlgorithmName.SHA512, null));
+            }
 
             using (IncrementalHash incrementalHash = IncrementalHash.CreateHash(HashAlgorithmName.SHA512))
             {
@@ -75,6 +81,7 @@ namespace System.Security.Cryptography.Algorithms.Tests
         }
 
         [Theory]
+        [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
         [MemberData(nameof(GetHMACs))]
         public static void VerifyIncrementalHMAC(HMAC referenceAlgorithm, HashAlgorithmName hashAlgorithm)
         {
@@ -88,6 +95,7 @@ namespace System.Security.Cryptography.Algorithms.Tests
         }
 
         [Theory]
+        [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
         [MemberData(nameof(GetHMACs))]
         public static void VerifyIncrementalHMAC_SpanKey(HMAC referenceAlgorithm, HashAlgorithmName hashAlgorithm)
         {
@@ -154,6 +162,7 @@ namespace System.Security.Cryptography.Algorithms.Tests
         }
 
         [Theory]
+        [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
         [MemberData(nameof(GetHMACs))]
         public static void VerifyEmptyHMAC(HMAC referenceAlgorithm, HashAlgorithmName hashAlgorithm)
         {
@@ -189,6 +198,7 @@ namespace System.Security.Cryptography.Algorithms.Tests
         }
 
         [Theory]
+        [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
         [MemberData(nameof(GetHMACs))]
         public static void VerifyTrivialHMAC(HMAC referenceAlgorithm, HashAlgorithmName hashAlgorithm)
         {
@@ -219,6 +229,7 @@ namespace System.Security.Cryptography.Algorithms.Tests
         }
 
         [Fact]
+        [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
         public static void AppendDataAfterHMACClose()
         {
             using (IncrementalHash hash = IncrementalHash.CreateHMAC(HashAlgorithmName.SHA256, s_hmacKey))
@@ -245,6 +256,7 @@ namespace System.Security.Cryptography.Algorithms.Tests
         }
 
         [Fact]
+        [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
         public static void GetHMACTwice()
         {
             using (IncrementalHash hash = IncrementalHash.CreateHMAC(HashAlgorithmName.SHA256, s_hmacKey))
@@ -268,6 +280,7 @@ namespace System.Security.Cryptography.Algorithms.Tests
         }
 
         [Fact]
+        [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
         public static void ModifyAfterHMACDispose()
         {
             using (IncrementalHash hash = IncrementalHash.CreateHMAC(HashAlgorithmName.SHA256, s_hmacKey))
@@ -286,6 +299,7 @@ namespace System.Security.Cryptography.Algorithms.Tests
         }
 
         [Fact]
+        [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
         public static void UnknownHmacAlgorithm()
         {
             Assert.ThrowsAny<CryptographicException>(
@@ -304,6 +318,7 @@ namespace System.Security.Cryptography.Algorithms.Tests
         }
 
         [Theory]
+        [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
         [MemberData(nameof(GetHMACs))]
         public static void VerifyIncrementalHMAC_Span(HMAC referenceAlgorithm, HashAlgorithmName hashAlgorithm)
         {
@@ -380,6 +395,7 @@ namespace System.Security.Cryptography.Algorithms.Tests
         }
 
         [Theory]
+        [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
         [MemberData(nameof(GetHMACs))]
         public static void VerifyEmptyHMAC_Span(HMAC referenceAlgorithm, HashAlgorithmName hashAlgorithm)
         {
@@ -417,6 +433,7 @@ namespace System.Security.Cryptography.Algorithms.Tests
         }
 
         [Theory]
+        [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
         [MemberData(nameof(GetHMACs))]
         public static void VerifyTrivialHMAC_Span(HMAC referenceAlgorithm, HashAlgorithmName hashAlgorithm)
         {
@@ -457,6 +474,7 @@ namespace System.Security.Cryptography.Algorithms.Tests
         }
 
         [Theory]
+        [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
         [MemberData(nameof(GetHMACs))]
         public static void Dispose_HMAC_ThrowsException(HMAC referenceAlgorithm, HashAlgorithmName hashAlgorithm)
         {
@@ -493,6 +511,7 @@ namespace System.Security.Cryptography.Algorithms.Tests
         }
 
         [Theory]
+        [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
         [MemberData(nameof(GetHMACs))]
         public static void VerifyGetCurrentHash_HMAC(HMAC referenceAlgorithm, HashAlgorithmName hashAlgorithm)
         {
@@ -506,6 +525,7 @@ namespace System.Security.Cryptography.Algorithms.Tests
         }
 
         [Theory]
+        [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
         [MemberData(nameof(GetHMACs))]
         public static void VerifyBounds_GetCurrentHash_HMAC(HMAC referenceAlgorithm, HashAlgorithmName hashAlgorithm)
         {
@@ -526,6 +546,7 @@ namespace System.Security.Cryptography.Algorithms.Tests
         }
 
         [Theory]
+        [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
         [MemberData(nameof(GetHMACs))]
         public static void VerifyBounds_GetHashAndReset_HMAC(HMAC referenceAlgorithm, HashAlgorithmName hashAlgorithm)
         {
index fa27002..2517780 100644 (file)
@@ -9,6 +9,7 @@ namespace System.Security.Cryptography.Hashing.Algorithms.Tests
     public class InvalidUsageTests
     {
         [Fact]
+        [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
         public void InvalidHashCoreArgumentsFromDerivedType()
         {
             using (var hmac = new DerivedHMACSHA1())
index 54dfb5d..b1b6cff 100644 (file)
@@ -5,6 +5,7 @@ using Xunit;
 
 namespace System.Security.Cryptography.Hashing.Algorithms.Tests
 {
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public class MD5Tests : HashAlgorithmTest
     {
         protected override HashAlgorithm Create()
index 08f9a03..77d5991 100644 (file)
@@ -29,6 +29,7 @@ using Xunit;
 
 namespace System.Security.Cryptography.Algorithms.Tests
 {
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public class PKCS1MaskGenerationMethodTest
     {
         [Fact]
index 3de2ef9..d6fcdfb 100644 (file)
@@ -10,6 +10,7 @@ using Xunit;
 
 namespace System.Security.Cryptography.Tests
 {
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public static class PaddingModeTests
     {
         [Theory]
index edbee10..ce0f8de 100644 (file)
@@ -6,6 +6,7 @@ using Xunit;
 
 namespace System.Security.Cryptography.Algorithms.Tests
 {
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public static class RSACreateTests
     {
         // macOS has the highest smallest key value, 1024.
index 303e3ee..e80c5d1 100644 (file)
@@ -7,6 +7,7 @@ using Xunit;
 
 namespace System.Security.Cryptography.Algorithms.Tests
 {
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public class RSATests
     {
         [Fact]
index 2a4a32d..4ea43c2 100644 (file)
@@ -55,7 +55,7 @@ namespace System.Security.Cryptography.RNG.Tests
             }
         }
 
-        [Fact]
+        [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
         public static void ConcurrentAccess()
         {
             const int ParallelTasks = 3;
index f183775..e31a170 100644 (file)
@@ -6,6 +6,7 @@ using Xunit;
 
 namespace System.Security.Cryptography.Hashing.Algorithms.Tests
 {
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public class ReusabilityTests
     {
         [Theory]
index 4bf95ee..22f14a2 100644 (file)
@@ -2,9 +2,11 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 
 using Test.Cryptography;
+using Xunit;
 
 namespace System.Security.Cryptography.Hashing.Algorithms.Tests
 {
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public abstract class Rfc2202HmacTests : HmacTests
     {
         private static readonly byte[][] s_testData2202 =
index 3a13bd7..8090be7 100644 (file)
@@ -9,6 +9,7 @@ using Xunit;
 
 namespace System.Security.Cryptography.DeriveBytesTests
 {
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public class Rfc2898Tests
     {
         // 8 bytes is the minimum accepted value, by using it we've already assured that the minimum is acceptable.
index 16f570a..ae32e54 100644 (file)
@@ -2,9 +2,11 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 
 using Test.Cryptography;
+using Xunit;
 
 namespace System.Security.Cryptography.Hashing.Algorithms.Tests
 {
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public abstract class Rfc4231HmacTests : HmacTests
     {
         private static readonly byte[][] s_testKeys4231 =
index f054568..f2c922f 100644 (file)
@@ -13,6 +13,7 @@ namespace System.Security.Cryptography.Encryption.Rijndael.Tests
     /// Since RijndaelImplementation (from Rijndael.Create()) and RijndaelManaged classes wrap Aes,
     /// we only test minimally here.
     /// </summary>
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public class RijndaelTests
     {
         [Fact]
index 2618451..5f1bc43 100644 (file)
@@ -8,6 +8,7 @@ using Xunit;
 
 namespace System.Security.Cryptography.Algorithms.Tests
 {
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public class SignatureDescriptionTests
     {
         [Fact]
index 37aaf30..90171a9 100644 (file)
@@ -1,6 +1,6 @@
 <Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
-    <TargetFrameworks>$(NetCoreAppCurrent)-Windows_NT;$(NetCoreAppCurrent)-Unix</TargetFrameworks>
+    <TargetFrameworks>$(NetCoreAppCurrent)-Windows_NT;$(NetCoreAppCurrent)-Unix;$(NetCoreAppCurrent)-Browser</TargetFrameworks>
   </PropertyGroup>
   <ItemGroup>
     <Compile Include="$(CommonTestPath)System\IO\PositionValueStream.cs"
@@ -67,7 +67,6 @@
              Link="CommonTest\System\Security\Cryptography\AlgorithmImplementations\TripleDES\TripleDESFactory.cs" />
     <Compile Include="$(CommonTestPath)System\Security\Cryptography\AlgorithmImplementations\TripleDES\TripleDESReusabilityTests.cs"
              Link="CommonTest\System\Security\Cryptography\AlgorithmImplementations\TripleDES\TripleDESReusabilityTests.cs" />
-    <Compile Include="AssemblyInfo.cs" />
     <Compile Include="AesProvider.cs" />
     <Compile Include="AesTests.cs" />
     <Compile Include="DefaultECDsaProvider.cs" />
   <ItemGroup Condition="'$(TargetsWindows)' == 'true'">
     <Compile Include="DefaultECDiffieHellmanProvider.Windows.cs" />
   </ItemGroup>
-  <ItemGroup Condition="'$(TargetsUnix)' == 'true'">
+  <ItemGroup Condition="'$(TargetsUnix)' == 'true' or '$(TargetsBrowser)' == 'true'">
     <Compile Include="DefaultECDsaProvider.Unix.cs" />
     <Compile Include="$(CommonPath)Interop\Unix\Interop.Libraries.cs"
              Link="Common\Interop\Unix\Interop.Libraries.cs" />
   </ItemGroup>
-  <ItemGroup Condition="'$(TargetsUnix)' == 'true'">
+  <ItemGroup Condition="'$(TargetsUnix)' == 'true' or '$(TargetsBrowser)' == 'true'">
     <Compile Include="DefaultECDiffieHellmanProvider.Unix.cs" />
   </ItemGroup>
   <ItemGroup>
index 92be6e8..0400cfc 100644 (file)
@@ -9,7 +9,7 @@ using Xunit;
 
 namespace System.Security.Cryptography.Encryption.TripleDes.Tests
 {
-
+    [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
     public static partial class TripleDesTests
     {
         [Fact]