未验证 提交 42cef019 编写于 作者: A Alexander Köplinger 提交者: GitHub

Implement CryptoConfig.CreateFromName() for wasm (#51750)

Hardcodes the mapping for the SHA* hashes supported on WebAssembly from https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.cryptoconfig?view=net-5.0#remarks

Fixes https://github.com/dotnet/runtime/issues/44996
上级 5f8f7977
...@@ -101,13 +101,17 @@ public partial class CryptoConfig ...@@ -101,13 +101,17 @@ public partial class CryptoConfig
{ {
public CryptoConfig() { } public CryptoConfig() { }
public static bool AllowOnlyFipsAlgorithms { get { throw null; } } public static bool AllowOnlyFipsAlgorithms { get { throw null; } }
[System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")]
public static void AddAlgorithm(System.Type algorithm, params string[] names) { } public static void AddAlgorithm(System.Type algorithm, params string[] names) { }
[System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")]
public static void AddOID(string oid, params string[] names) { } public static void AddOID(string oid, params string[] names) { }
[System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The default algorithm implementations might be removed, use strong type references like 'RSA.Create()' instead.")] [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The default algorithm implementations might be removed, use strong type references like 'RSA.Create()' instead.")]
public static object? CreateFromName(string name) { throw null; } public static object? CreateFromName(string name) { throw null; }
[System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The default algorithm implementations might be removed, use strong type references like 'RSA.Create()' instead.")] [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The default algorithm implementations might be removed, use strong type references like 'RSA.Create()' instead.")]
public static object? CreateFromName(string name, params object?[]? args) { throw null; } public static object? CreateFromName(string name, params object?[]? args) { throw null; }
[System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")]
public static byte[] EncodeOID(string str) { throw null; } public static byte[] EncodeOID(string str) { throw null; }
[System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")]
public static string? MapNameToOID(string name) { throw null; } public static string? MapNameToOID(string name) { throw null; }
} }
[System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")]
......
T:System.Security.Cryptography.CryptoConfig
T:System.Security.Cryptography.RandomNumberGenerator T:System.Security.Cryptography.RandomNumberGenerator
T:System.Security.Cryptography.IncrementalHash T:System.Security.Cryptography.IncrementalHash
T:System.Security.Cryptography.SHA1 T:System.Security.Cryptography.SHA1
......
...@@ -675,6 +675,7 @@ ...@@ -675,6 +675,7 @@
<Compile Include="Internal\Cryptography\RandomNumberGeneratorImplementation.cs" /> <Compile Include="Internal\Cryptography\RandomNumberGeneratorImplementation.cs" />
<Compile Include="Internal\Cryptography\RandomNumberGeneratorImplementation.Browser.cs" /> <Compile Include="Internal\Cryptography\RandomNumberGeneratorImplementation.Browser.cs" />
<Compile Include="Internal\Cryptography\SHAHashProvider.Browser.cs" /> <Compile Include="Internal\Cryptography\SHAHashProvider.Browser.cs" />
<Compile Include="System\Security\Cryptography\CryptoConfig.Browser.cs" />
<Compile Include="System\Security\Cryptography\RandomNumberGenerator.cs" /> <Compile Include="System\Security\Cryptography\RandomNumberGenerator.cs" />
<Compile Include="System\Security\Cryptography\IncrementalHash.cs" /> <Compile Include="System\Security\Cryptography\IncrementalHash.cs" />
<Compile Include="System\Security\Cryptography\SHA1.cs" /> <Compile Include="System\Security\Cryptography\SHA1.cs" />
......
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Reflection;
using System.Runtime.Versioning;
namespace System.Security.Cryptography
{
public partial class CryptoConfig
{
[UnsupportedOSPlatform("browser")]
public static void AddAlgorithm(Type algorithm, params string[] names) => throw new PlatformNotSupportedException(SR.SystemSecurityCryptographyAlgorithms_PlatformNotSupported);
[UnsupportedOSPlatform("browser")]
public static void AddOID(string oid, params string[] names) => throw new PlatformNotSupportedException(SR.SystemSecurityCryptographyAlgorithms_PlatformNotSupported);
[UnsupportedOSPlatform("browser")]
public static string? MapNameToOID(string name) => throw new PlatformNotSupportedException(SR.SystemSecurityCryptographyAlgorithms_PlatformNotSupported);
[UnsupportedOSPlatform("browser")]
public static byte[] EncodeOID(string str) => throw new PlatformNotSupportedException(SR.SystemSecurityCryptographyAlgorithms_PlatformNotSupported);
[RequiresUnreferencedCode("The default algorithm implementations might be removed, use strong type references like 'RSA.Create()' instead.")]
public static object? CreateFromName(string name, params object?[]? args)
{
if (name == null)
throw new ArgumentNullException(nameof(name));
switch (name)
{
// hardcode mapping for SHA* algorithm names from https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.cryptoconfig?view=net-5.0#remarks
case "SHA":
case "SHA1":
case "System.Security.Cryptography.SHA1":
return new SHA1Managed();
case "SHA256":
case "SHA-256":
case "System.Security.Cryptography.SHA256":
return new SHA256Managed();
case "SHA384":
case "SHA-384":
case "System.Security.Cryptography.SHA384":
return new SHA384Managed();
case "SHA512":
case "SHA-512":
case "System.Security.Cryptography.SHA512":
return new SHA512Managed();
}
return null;
}
[RequiresUnreferencedCode(CreateFromNameUnreferencedCodeMessage)]
public static object? CreateFromName(string name)
{
return CreateFromName(name, null);
}
}
}
...@@ -6,5 +6,8 @@ namespace System.Security.Cryptography ...@@ -6,5 +6,8 @@ namespace System.Security.Cryptography
public partial class CryptoConfig public partial class CryptoConfig
{ {
internal const string CreateFromNameUnreferencedCodeMessage = "The default algorithm implementations might be removed, use strong type references like 'RSA.Create()' instead."; internal const string CreateFromNameUnreferencedCodeMessage = "The default algorithm implementations might be removed, use strong type references like 'RSA.Create()' instead.";
// .NET Core does not support AllowOnlyFipsAlgorithms
public static bool AllowOnlyFipsAlgorithms => false;
} }
} }
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Globalization; using System.Globalization;
using System.Reflection; using System.Reflection;
using System.Runtime.Versioning;
namespace System.Security.Cryptography namespace System.Security.Cryptography
{ {
...@@ -37,9 +38,6 @@ public partial class CryptoConfig ...@@ -37,9 +38,6 @@ public partial class CryptoConfig
private static readonly ConcurrentDictionary<string, Type> appNameHT = new ConcurrentDictionary<string, Type>(StringComparer.OrdinalIgnoreCase); private static readonly ConcurrentDictionary<string, Type> appNameHT = new ConcurrentDictionary<string, Type>(StringComparer.OrdinalIgnoreCase);
private static readonly ConcurrentDictionary<string, string> appOidHT = new ConcurrentDictionary<string, string>(StringComparer.OrdinalIgnoreCase); private static readonly ConcurrentDictionary<string, string> appOidHT = new ConcurrentDictionary<string, string>(StringComparer.OrdinalIgnoreCase);
// .NET Core does not support AllowOnlyFipsAlgorithms
public static bool AllowOnlyFipsAlgorithms => false;
private static Dictionary<string, string> DefaultOidHT private static Dictionary<string, string> DefaultOidHT
{ {
get get
...@@ -294,6 +292,7 @@ public partial class CryptoConfig ...@@ -294,6 +292,7 @@ public partial class CryptoConfig
} }
} }
[UnsupportedOSPlatform("browser")]
public static void AddAlgorithm(Type algorithm, params string[] names) public static void AddAlgorithm(Type algorithm, params string[] names)
{ {
if (algorithm == null) if (algorithm == null)
...@@ -450,6 +449,7 @@ public static void AddAlgorithm(Type algorithm, params string[] names) ...@@ -450,6 +449,7 @@ public static void AddAlgorithm(Type algorithm, params string[] names)
return CreateFromName(name, null); return CreateFromName(name, null);
} }
[UnsupportedOSPlatform("browser")]
public static void AddOID(string oid, params string[] names) public static void AddOID(string oid, params string[] names)
{ {
if (oid == null) if (oid == null)
...@@ -477,6 +477,7 @@ public static void AddOID(string oid, params string[] names) ...@@ -477,6 +477,7 @@ public static void AddOID(string oid, params string[] names)
} }
} }
[UnsupportedOSPlatform("browser")]
public static string? MapNameToOID(string name) public static string? MapNameToOID(string name)
{ {
if (name == null) if (name == null)
...@@ -497,6 +498,7 @@ public static void AddOID(string oid, params string[] names) ...@@ -497,6 +498,7 @@ public static void AddOID(string oid, params string[] names)
return oidName; return oidName;
} }
[UnsupportedOSPlatform("browser")]
public static byte[] EncodeOID(string str) public static byte[] EncodeOID(string str)
{ {
if (str == null) if (str == null)
......
...@@ -9,7 +9,6 @@ ...@@ -9,7 +9,6 @@
namespace System.Security.Cryptography.CryptoConfigTests namespace System.Security.Cryptography.CryptoConfigTests
{ {
[SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public static class CryptoConfigTests public static class CryptoConfigTests
{ {
[Fact] [Fact]
...@@ -19,6 +18,7 @@ public static void AllowOnlyFipsAlgorithms() ...@@ -19,6 +18,7 @@ public static void AllowOnlyFipsAlgorithms()
} }
[Fact] [Fact]
[SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public static void AddOID_MapNameToOID_ReturnsMapped() public static void AddOID_MapNameToOID_ReturnsMapped()
{ {
CryptoConfig.AddOID("1.3.14.3.2.28", "SHAFancy"); CryptoConfig.AddOID("1.3.14.3.2.28", "SHAFancy");
...@@ -26,12 +26,14 @@ public static void AddOID_MapNameToOID_ReturnsMapped() ...@@ -26,12 +26,14 @@ public static void AddOID_MapNameToOID_ReturnsMapped()
} }
[Fact] [Fact]
[SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public static void AddOID_EmptyString_Throws() public static void AddOID_EmptyString_Throws()
{ {
AssertExtensions.Throws<ArgumentException>(null, () => CryptoConfig.AddOID(string.Empty, string.Empty)); AssertExtensions.Throws<ArgumentException>(null, () => CryptoConfig.AddOID(string.Empty, string.Empty));
} }
[Fact] [Fact]
[SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public static void AddOID_EmptyNamesArray() public static void AddOID_EmptyNamesArray()
{ {
CryptoConfig.AddOID("1.3.14.3.2.28", new string[0]); CryptoConfig.AddOID("1.3.14.3.2.28", new string[0]);
...@@ -39,18 +41,21 @@ public static void AddOID_EmptyNamesArray() ...@@ -39,18 +41,21 @@ public static void AddOID_EmptyNamesArray()
} }
[Fact] [Fact]
[SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public static void AddOID_NullOid_Throws() public static void AddOID_NullOid_Throws()
{ {
AssertExtensions.Throws<ArgumentNullException>("oid", () => CryptoConfig.AddOID(null, string.Empty)); AssertExtensions.Throws<ArgumentNullException>("oid", () => CryptoConfig.AddOID(null, string.Empty));
} }
[Fact] [Fact]
[SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public static void AddOID_NullNames_Throws() public static void AddOID_NullNames_Throws()
{ {
AssertExtensions.Throws<ArgumentNullException>("names", () => CryptoConfig.AddOID(string.Empty, null)); AssertExtensions.Throws<ArgumentNullException>("names", () => CryptoConfig.AddOID(string.Empty, null));
} }
[Fact] [Fact]
[SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public static void AddAlgorithm_CreateFromName_ReturnsMapped() public static void AddAlgorithm_CreateFromName_ReturnsMapped()
{ {
CryptoConfig.AddAlgorithm(typeof(AesCryptoServiceProvider), "AESFancy"); CryptoConfig.AddAlgorithm(typeof(AesCryptoServiceProvider), "AESFancy");
...@@ -58,6 +63,7 @@ public static void AddAlgorithm_CreateFromName_ReturnsMapped() ...@@ -58,6 +63,7 @@ public static void AddAlgorithm_CreateFromName_ReturnsMapped()
} }
[Fact] [Fact]
[SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public static void AddAlgorithm_NonVisibleType() public static void AddAlgorithm_NonVisibleType()
{ {
AssertExtensions.Throws<ArgumentException>("algorithm", () => CryptoConfig.AddAlgorithm(typeof(AESFancy), "AESFancy")); AssertExtensions.Throws<ArgumentException>("algorithm", () => CryptoConfig.AddAlgorithm(typeof(AESFancy), "AESFancy"));
...@@ -68,12 +74,14 @@ private class AESFancy ...@@ -68,12 +74,14 @@ private class AESFancy
} }
[Fact] [Fact]
[SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public static void AddAlgorithm_EmptyString_Throws() public static void AddAlgorithm_EmptyString_Throws()
{ {
AssertExtensions.Throws<ArgumentException>(null, () => CryptoConfig.AddAlgorithm(typeof(CryptoConfigTests), string.Empty)); AssertExtensions.Throws<ArgumentException>(null, () => CryptoConfig.AddAlgorithm(typeof(CryptoConfigTests), string.Empty));
} }
[Fact] [Fact]
[SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public static void AddAlgorithm_EmptyNamesArray() public static void AddAlgorithm_EmptyNamesArray()
{ {
CryptoConfig.AddAlgorithm(typeof(AesCryptoServiceProvider), new string[0]); CryptoConfig.AddAlgorithm(typeof(AesCryptoServiceProvider), new string[0]);
...@@ -81,18 +89,21 @@ public static void AddAlgorithm_EmptyNamesArray() ...@@ -81,18 +89,21 @@ public static void AddAlgorithm_EmptyNamesArray()
} }
[Fact] [Fact]
[SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public static void AddAlgorithm_NullAlgorithm_Throws() public static void AddAlgorithm_NullAlgorithm_Throws()
{ {
AssertExtensions.Throws<ArgumentNullException>("algorithm", () => CryptoConfig.AddAlgorithm(null, string.Empty)); AssertExtensions.Throws<ArgumentNullException>("algorithm", () => CryptoConfig.AddAlgorithm(null, string.Empty));
} }
[Fact] [Fact]
[SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public static void AddAlgorithm_NullNames_Throws() public static void AddAlgorithm_NullNames_Throws()
{ {
AssertExtensions.Throws<ArgumentNullException>("names", () => CryptoConfig.AddAlgorithm(typeof(CryptoConfigTests), null)); AssertExtensions.Throws<ArgumentNullException>("names", () => CryptoConfig.AddAlgorithm(typeof(CryptoConfigTests), null));
} }
[Fact] [Fact]
[SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public static void StaticCreateMethods() public static void StaticCreateMethods()
{ {
// Ensure static create methods exist and don't throw // Ensure static create methods exist and don't throw
...@@ -120,6 +131,7 @@ private static void VerifyStaticCreateResult(object obj, Type expectedType) ...@@ -120,6 +131,7 @@ private static void VerifyStaticCreateResult(object obj, Type expectedType)
} }
[Fact] [Fact]
[SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public static void MapNameToOID() public static void MapNameToOID()
{ {
Assert.Throws<ArgumentNullException>(() => CryptoConfig.MapNameToOID(null)); Assert.Throws<ArgumentNullException>(() => CryptoConfig.MapNameToOID(null));
...@@ -137,6 +149,7 @@ public static void MapNameToOID() ...@@ -137,6 +149,7 @@ public static void MapNameToOID()
} }
[Fact] [Fact]
[SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public static void CreateFromName_validation() public static void CreateFromName_validation()
{ {
Assert.Throws<ArgumentNullException>(() => CryptoConfig.CreateFromName(null)); Assert.Throws<ArgumentNullException>(() => CryptoConfig.CreateFromName(null));
...@@ -149,6 +162,24 @@ public static void CreateFromName_validation() ...@@ -149,6 +162,24 @@ public static void CreateFromName_validation()
public static IEnumerable<object[]> AllValidNames public static IEnumerable<object[]> AllValidNames
{ {
get get
{
if (PlatformDetection.IsBrowser)
{
// Hash functions
yield return new object[] { "SHA", typeof(SHA1Managed).FullName, true };
yield return new object[] { "SHA1", typeof(SHA1Managed).FullName, true };
yield return new object[] { "System.Security.Cryptography.SHA1", typeof(SHA1Managed).FullName, true };
yield return new object[] { "SHA256", typeof(SHA256Managed).FullName, true };
yield return new object[] { "SHA-256", typeof(SHA256Managed).FullName, true };
yield return new object[] { "System.Security.Cryptography.SHA256", typeof(SHA256Managed).FullName, true };
yield return new object[] { "SHA384", typeof(SHA384Managed).FullName, true };
yield return new object[] { "SHA-384", typeof(SHA384Managed).FullName, true };
yield return new object[] { "System.Security.Cryptography.SHA384", typeof(SHA384Managed).FullName, true };
yield return new object[] { "SHA512", typeof(SHA512Managed).FullName, true };
yield return new object[] { "SHA-512", typeof(SHA512Managed).FullName, true };
yield return new object[] { "System.Security.Cryptography.SHA512", typeof(SHA512Managed).FullName, true };
}
else
{ {
// Random number generator // Random number generator
yield return new object[] { "RandomNumberGenerator", "System.Security.Cryptography.RNGCryptoServiceProvider", true }; yield return new object[] { "RandomNumberGenerator", "System.Security.Cryptography.RNGCryptoServiceProvider", true };
...@@ -251,6 +282,7 @@ public static IEnumerable<object[]> AllValidNames ...@@ -251,6 +282,7 @@ public static IEnumerable<object[]> AllValidNames
yield return new object[] { "1.3.6.1.4.1.311.88.2.2", "System.Security.Cryptography.Pkcs.Pkcs9DocumentDescription", true }; yield return new object[] { "1.3.6.1.4.1.311.88.2.2", "System.Security.Cryptography.Pkcs.Pkcs9DocumentDescription", true };
} }
} }
}
[Theory, MemberData(nameof(AllValidNames))] [Theory, MemberData(nameof(AllValidNames))]
public static void CreateFromName_AllValidNames(string name, string typeName, bool supportsUnixMac) public static void CreateFromName_AllValidNames(string name, string typeName, bool supportsUnixMac)
...@@ -290,6 +322,7 @@ public static void CreateFromName_AllValidNames(string name, string typeName, bo ...@@ -290,6 +322,7 @@ public static void CreateFromName_AllValidNames(string name, string typeName, bo
} }
[Fact] [Fact]
[SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public static void CreateFromName_CtorArguments() public static void CreateFromName_CtorArguments()
{ {
string className = typeof(ClassWithCtorArguments).FullName + ", System.Security.Cryptography.Algorithms.Tests"; string className = typeof(ClassWithCtorArguments).FullName + ", System.Security.Cryptography.Algorithms.Tests";
...@@ -307,6 +340,7 @@ public static void CreateFromName_CtorArguments() ...@@ -307,6 +340,7 @@ public static void CreateFromName_CtorArguments()
} }
[Fact] [Fact]
[SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public static void EncodeOID_Validation() public static void EncodeOID_Validation()
{ {
Assert.Throws<ArgumentNullException>(() => CryptoConfig.EncodeOID(null)); Assert.Throws<ArgumentNullException>(() => CryptoConfig.EncodeOID(null));
...@@ -317,6 +351,7 @@ public static void EncodeOID_Validation() ...@@ -317,6 +351,7 @@ public static void EncodeOID_Validation()
} }
[Fact] [Fact]
[SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public static void EncodeOID_Compat() public static void EncodeOID_Compat()
{ {
string actual = CryptoConfig.EncodeOID("-1.2.-3").ByteArrayToHex(); string actual = CryptoConfig.EncodeOID("-1.2.-3").ByteArrayToHex();
...@@ -324,6 +359,7 @@ public static void EncodeOID_Compat() ...@@ -324,6 +359,7 @@ public static void EncodeOID_Compat()
} }
[Fact] [Fact]
[SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public static void EncodeOID_Length_Boundary() public static void EncodeOID_Length_Boundary()
{ {
string valueToRepeat = "1.1"; string valueToRepeat = "1.1";
...@@ -341,6 +377,7 @@ public static void EncodeOID_Length_Boundary() ...@@ -341,6 +377,7 @@ public static void EncodeOID_Length_Boundary()
} }
[Theory] [Theory]
[SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
[InlineData(0x4000, "0603818028")] [InlineData(0x4000, "0603818028")]
[InlineData(0x200000, "060481808028")] [InlineData(0x200000, "060481808028")]
[InlineData(0x10000000, "06058180808028")] [InlineData(0x10000000, "06058180808028")]
...@@ -356,6 +393,7 @@ public static void EncodeOID_Value_Boundary_And_Compat(uint elementValue, string ...@@ -356,6 +393,7 @@ public static void EncodeOID_Value_Boundary_And_Compat(uint elementValue, string
} }
[Theory] [Theory]
[SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
[InlineData("SHA1", "1.3.14.3.2.26", "06052B0E03021A")] [InlineData("SHA1", "1.3.14.3.2.26", "06052B0E03021A")]
[InlineData("DES", "1.3.14.3.2.7", "06052B0E030207")] [InlineData("DES", "1.3.14.3.2.7", "06052B0E030207")]
[InlineData("MD5", "1.2.840.113549.2.5", "06082A864886F70D0205")] [InlineData("MD5", "1.2.840.113549.2.5", "06082A864886F70D0205")]
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册