Skip to content

Commit 0a2bc2f

Browse files
authored
Condition S.S.Cryptography tests on SHA1 signature support
1 parent c504512 commit 0a2bc2f

File tree

18 files changed

+171
-79
lines changed

18 files changed

+171
-79
lines changed

src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSAFactory.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ public interface IRSAProvider
1111
bool SupportsLargeExponent { get; }
1212
bool SupportsSha2Oaep { get; }
1313
bool SupportsPss { get; }
14+
bool SupportsSha1Signatures { get; }
1415
}
1516

1617
public static partial class RSAFactory
@@ -39,5 +40,7 @@ public static RSA Create(RSAParameters rsaParameters)
3940
public static bool SupportsSha2Oaep => s_provider.SupportsSha2Oaep;
4041

4142
public static bool SupportsPss => s_provider.SupportsPss;
43+
44+
public static bool SupportsSha1Signatures => s_provider.SupportsSha1Signatures;
4245
}
4346
}

src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSASignatureFormatter.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ namespace System.Security.Cryptography.Rsa.Tests
1010
[SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
1111
public partial class RSASignatureFormatterTests : AsymmetricSignatureFormatterTests
1212
{
13-
[Fact]
13+
[ConditionalFact(typeof(RSAFactory), nameof(RSAFactory.SupportsSha1Signatures))]
1414
public static void VerifySignature_SHA1()
1515
{
1616
using (RSA rsa = RSAFactory.Create())
@@ -66,7 +66,7 @@ public static void InvalidHashAlgorithm()
6666
}
6767
}
6868

69-
[Fact]
69+
[ConditionalFact(typeof(RSAFactory), nameof(RSAFactory.SupportsSha1Signatures))]
7070
public static void VerifyKnownSignature()
7171
{
7272
byte[] hash = "012d161304fa0c6321221516415813022320620c".HexToByteArray();

src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/SignVerify.cs

Lines changed: 42 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using System.Collections.Generic;
55
using System.IO;
6+
using Microsoft.DotNet.XUnitExtensions;
67
using Test.Cryptography;
78
using Test.IO.Streams;
89
using Xunit;
@@ -26,14 +27,14 @@ public void NullArray_Throws()
2627
{
2728
using (RSA rsa = RSAFactory.Create())
2829
{
29-
AssertExtensions.Throws<ArgumentNullException>("data", () => SignData(rsa, null, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1));
30-
AssertExtensions.Throws<ArgumentNullException>("hash", () => SignHash(rsa, null, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1));
30+
AssertExtensions.Throws<ArgumentNullException>("data", () => SignData(rsa, null, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1));
31+
AssertExtensions.Throws<ArgumentNullException>("hash", () => SignHash(rsa, null, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1));
3132

32-
AssertExtensions.Throws<ArgumentNullException>("data", () => VerifyData(rsa, null, new byte[1], HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1));
33-
AssertExtensions.Throws<ArgumentNullException>("hash", () => VerifyHash(rsa, null, new byte[1], HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1));
33+
AssertExtensions.Throws<ArgumentNullException>("data", () => VerifyData(rsa, null, new byte[1], HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1));
34+
AssertExtensions.Throws<ArgumentNullException>("hash", () => VerifyHash(rsa, null, new byte[1], HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1));
3435

35-
AssertExtensions.Throws<ArgumentNullException>("signature", () => VerifyData(rsa, new byte[1], null, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1));
36-
AssertExtensions.Throws<ArgumentNullException>("signature", () => VerifyHash(rsa, new byte[1], null, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1));
36+
AssertExtensions.Throws<ArgumentNullException>("signature", () => VerifyData(rsa, new byte[1], null, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1));
37+
AssertExtensions.Throws<ArgumentNullException>("signature", () => VerifyHash(rsa, new byte[1], null, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1));
3738
}
3839
}
3940
}
@@ -72,10 +73,10 @@ public void NullPadding_Throws()
7273
{
7374
using (RSA rsa = RSAFactory.Create())
7475
{
75-
AssertExtensions.Throws<ArgumentNullException>("padding", () => SignData(rsa, new byte[1], HashAlgorithmName.SHA1, null));
76-
AssertExtensions.Throws<ArgumentNullException>("padding", () => SignHash(rsa, new byte[1], HashAlgorithmName.SHA1, null));
77-
AssertExtensions.Throws<ArgumentNullException>("padding", () => VerifyData(rsa, new byte[1], new byte[1], HashAlgorithmName.SHA1, null));
78-
AssertExtensions.Throws<ArgumentNullException>("padding", () => VerifyHash(rsa, new byte[1], new byte[1], HashAlgorithmName.SHA1, null));
76+
AssertExtensions.Throws<ArgumentNullException>("padding", () => SignData(rsa, new byte[1], HashAlgorithmName.SHA256, null));
77+
AssertExtensions.Throws<ArgumentNullException>("padding", () => SignHash(rsa, new byte[1], HashAlgorithmName.SHA256, null));
78+
AssertExtensions.Throws<ArgumentNullException>("padding", () => VerifyData(rsa, new byte[1], new byte[1], HashAlgorithmName.SHA256, null));
79+
AssertExtensions.Throws<ArgumentNullException>("padding", () => VerifyHash(rsa, new byte[1], new byte[1], HashAlgorithmName.SHA256, null));
7980
}
8081
}
8182

@@ -87,7 +88,7 @@ public void UseAfterDispose(bool importKey)
8788
RSA rsa = importKey ? RSAFactory.Create(TestData.RSA2048Params) : RSAFactory.Create(1024);
8889
byte[] data = TestData.HelloBytes;
8990
byte[] sig;
90-
HashAlgorithmName alg = HashAlgorithmName.SHA1;
91+
HashAlgorithmName alg = HashAlgorithmName.SHA256;
9192
RSASignaturePadding padding = RSASignaturePadding.Pkcs1;
9293

9394
using (rsa)
@@ -115,12 +116,12 @@ public void InvalidKeySize_DoesNotInvalidateKey()
115116
{
116117
using (RSA rsa = RSAFactory.Create())
117118
{
118-
byte[] signature = SignData(rsa, TestData.HelloBytes, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1);
119+
byte[] signature = SignData(rsa, TestData.HelloBytes, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
119120

120121
// A 2049-bit key is hard to describe, none of the providers support it.
121122
Assert.ThrowsAny<CryptographicException>(() => rsa.KeySize = 2049);
122123

123-
Assert.True(VerifyData(rsa, TestData.HelloBytes, signature, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1));
124+
Assert.True(VerifyData(rsa, TestData.HelloBytes, signature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1));
124125
}
125126
}
126127

@@ -143,11 +144,11 @@ public void SignEmptyHash()
143144
using (RSA rsa = RSAFactory.Create())
144145
{
145146
Assert.ThrowsAny<CryptographicException>(
146-
() => SignHash(rsa, Array.Empty<byte>(), HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1));
147+
() => SignHash(rsa, Array.Empty<byte>(), HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1));
147148
}
148149
}
149150

150-
[Fact]
151+
[ConditionalFact(typeof(RSAFactory), nameof(RSAFactory.SupportsSha1Signatures))]
151152
public void ExpectedSignature_SHA1_384()
152153
{
153154
byte[] expectedSignature =
@@ -178,7 +179,7 @@ public void ExpectedSignature_SHA1_384()
178179
}
179180
}
180181

181-
[Fact]
182+
[ConditionalFact(typeof(RSAFactory), nameof(RSAFactory.SupportsSha1Signatures))]
182183
public void ExpectedSignature_SHA1_1032()
183184
{
184185
byte[] expectedSignature =
@@ -205,7 +206,7 @@ public void ExpectedSignature_SHA1_1032()
205206
ExpectSignature(expectedSignature, TestData.HelloBytes, "SHA1", TestData.RSA1032Parameters);
206207
}
207208

208-
[Fact]
209+
[ConditionalFact(typeof(RSAFactory), nameof(RSAFactory.SupportsSha1Signatures))]
209210
public void ExpectedSignature_SHA1_2048()
210211
{
211212
byte[] expectedSignature = new byte[]
@@ -350,7 +351,7 @@ public void ExpectSignature_SHA256_1024_Stream()
350351
Assert.Equal(expectedSignature, signature);
351352
}
352353

353-
[Fact]
354+
[ConditionalFact(typeof(RSAFactory), nameof(RSAFactory.SupportsSha1Signatures))]
354355
public void VerifySignature_SHA1_384()
355356
{
356357
byte[] signature =
@@ -366,7 +367,7 @@ public void VerifySignature_SHA1_384()
366367
VerifySignature(signature, TestData.HelloBytes, "SHA1", TestData.RSA384Parameters);
367368
}
368369

369-
[Fact]
370+
[ConditionalFact(typeof(RSAFactory), nameof(RSAFactory.SupportsSha1Signatures))]
370371
public void VerifySignature_SHA1_1032()
371372
{
372373
byte[] signature =
@@ -393,7 +394,7 @@ public void VerifySignature_SHA1_1032()
393394
VerifySignature(signature, TestData.HelloBytes, "SHA1", TestData.RSA1032Parameters);
394395
}
395396

396-
[Fact]
397+
[ConditionalFact(typeof(RSAFactory), nameof(RSAFactory.SupportsSha1Signatures))]
397398
public void VerifySignature_SHA1_2048()
398399
{
399400
byte[] signature = new byte[]
@@ -516,8 +517,12 @@ public static IEnumerable<object[]> RoundTripTheories
516517
{
517518
foreach (RSAParameters rsaParameters in new[] { TestData.RSA1024Params, TestData.RSA2048Params })
518519
{
520+
if (RSAFactory.SupportsSha1Signatures)
521+
{
522+
yield return new object[] { nameof(HashAlgorithmName.SHA1), rsaParameters };
523+
}
524+
519525
yield return new object[] { nameof(HashAlgorithmName.MD5), rsaParameters };
520-
yield return new object[] { nameof(HashAlgorithmName.SHA1), rsaParameters };
521526
yield return new object[] { nameof(HashAlgorithmName.SHA256), rsaParameters };
522527
}
523528

@@ -532,8 +537,8 @@ public void NegativeVerify_WrongAlgorithm()
532537
using (RSA rsa = RSAFactory.Create())
533538
{
534539
rsa.ImportParameters(TestData.RSA2048Params);
535-
byte[] signature = SignData(rsa, TestData.HelloBytes, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1);
536-
bool signatureMatched = VerifyData(rsa, TestData.HelloBytes, signature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
540+
byte[] signature = SignData(rsa, TestData.HelloBytes, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
541+
bool signatureMatched = VerifyData(rsa, TestData.HelloBytes, signature, HashAlgorithmName.SHA384, RSASignaturePadding.Pkcs1);
537542

538543
Assert.False(signatureMatched);
539544
}
@@ -545,12 +550,12 @@ public void NegativeVerify_WrongSignature()
545550
using (RSA rsa = RSAFactory.Create())
546551
{
547552
rsa.ImportParameters(TestData.RSA2048Params);
548-
byte[] signature = SignData(rsa, TestData.HelloBytes, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1);
553+
byte[] signature = SignData(rsa, TestData.HelloBytes, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
549554

550555
// Invalidate the signature.
551556
signature[0] = unchecked((byte)~signature[0]);
552557

553-
bool signatureMatched = VerifyData(rsa, TestData.HelloBytes, signature, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1);
558+
bool signatureMatched = VerifyData(rsa, TestData.HelloBytes, signature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
554559
Assert.False(signatureMatched);
555560
}
556561
}
@@ -561,8 +566,8 @@ public void NegativeVerify_TamperedData()
561566
using (RSA rsa = RSAFactory.Create())
562567
{
563568
rsa.ImportParameters(TestData.RSA2048Params);
564-
byte[] signature = SignData(rsa, TestData.HelloBytes, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1);
565-
bool signatureMatched = VerifyData(rsa, Array.Empty<byte>(), signature, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1);
569+
byte[] signature = SignData(rsa, TestData.HelloBytes, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
570+
bool signatureMatched = VerifyData(rsa, Array.Empty<byte>(), signature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
566571
Assert.False(signatureMatched);
567572
}
568573
}
@@ -575,13 +580,13 @@ public void NegativeVerify_BadKeysize()
575580
using (RSA rsa = RSAFactory.Create())
576581
{
577582
rsa.ImportParameters(TestData.RSA2048Params);
578-
signature = SignData(rsa, TestData.HelloBytes, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1);
583+
signature = SignData(rsa, TestData.HelloBytes, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
579584
}
580585

581586
using (RSA rsa = RSAFactory.Create())
582587
{
583588
rsa.ImportParameters(TestData.RSA1024Params);
584-
bool signatureMatched = VerifyData(rsa, TestData.HelloBytes, signature, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1);
589+
bool signatureMatched = VerifyData(rsa, TestData.HelloBytes, signature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
585590

586591
Assert.False(signatureMatched);
587592
}
@@ -610,7 +615,7 @@ public void PkcsSignHash_MismatchedHashSize()
610615
}
611616
}
612617

613-
[Fact]
618+
[ConditionalFact(typeof(RSAFactory), nameof(RSAFactory.SupportsSha1Signatures))]
614619
public void ExpectedHashSignature_SHA1_2048()
615620
{
616621
byte[] expectedHashSignature = new byte[]
@@ -741,7 +746,7 @@ public void ExpectedHashSignature_SHA256_2048()
741746
ExpectHashSignature(expectedHashSignature, dataHash, "SHA256", TestData.RSA2048Params);
742747
}
743748

744-
[Fact]
749+
[ConditionalFact(typeof(RSAFactory), nameof(RSAFactory.SupportsSha1Signatures))]
745750
public void VerifyHashSignature_SHA1_2048()
746751
{
747752
byte[] hashSignature = new byte[]
@@ -872,14 +877,19 @@ public void VerifyHashSignature_SHA256_2048()
872877
VerifyHashSignature(hashSignature, dataHash, "SHA256", TestData.RSA2048Params);
873878
}
874879

875-
[Theory]
880+
[ConditionalTheory]
876881
[InlineData("SHA256")]
877882
[InlineData("SHA384")]
878883
[InlineData("SHA512")]
879884
[InlineData("MD5")]
880885
[InlineData("SHA1")]
881886
public void PssRoundtrip(string hashAlgorithmName)
882887
{
888+
if (!RSAFactory.SupportsSha1Signatures && hashAlgorithmName == "SHA1")
889+
{
890+
throw new SkipTestException("Platform does not support RSA with SHA1 signatures.");
891+
}
892+
883893
RSAParameters privateParameters = TestData.RSA2048Params;
884894
RSAParameters publicParameters = new RSAParameters
885895
{

src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/SignVerify.netcoreapp.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ public static void VerifyDefaultSpanHash()
5656
byte[] signature = new byte[2048 / 8];
5757

5858
Assert.False(
59-
rsa.VerifyHash(ReadOnlySpan<byte>.Empty, signature, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1));
59+
rsa.VerifyHash(ReadOnlySpan<byte>.Empty, signature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1));
6060

6161
if (RSAFactory.SupportsPss)
6262
{
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
namespace System.Security.Cryptography.Tests
5+
{
6+
internal static class SignatureSupport
7+
{
8+
internal static bool CanProduceSha1Signature(AsymmetricAlgorithm algorithm)
9+
{
10+
// We expect all non-Linux platforms to support SHA1 signatures, currently.
11+
if (!OperatingSystem.IsLinux())
12+
{
13+
return true;
14+
}
15+
16+
switch (algorithm)
17+
{
18+
case ECDsa ecdsa:
19+
try
20+
{
21+
ecdsa.SignData(Array.Empty<byte>(), HashAlgorithmName.SHA1);
22+
return true;
23+
}
24+
catch (CryptographicException)
25+
{
26+
return false;
27+
}
28+
finally
29+
{
30+
algorithm.Dispose();
31+
}
32+
case RSA rsa:
33+
try
34+
{
35+
rsa.SignData(Array.Empty<byte>(), HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1);
36+
return true;
37+
}
38+
catch (CryptographicException)
39+
{
40+
return false;
41+
}
42+
finally
43+
{
44+
algorithm.Dispose();
45+
}
46+
default:
47+
throw new NotSupportedException($"Algorithm type {algorithm.GetType()} is not supported.");
48+
}
49+
}
50+
}
51+
}

src/libraries/System.Security.Cryptography.Cng/tests/RSACngProvider.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ public bool Supports384PrivateKey
3434
public bool SupportsSha2Oaep => true;
3535

3636
public bool SupportsPss => true;
37+
38+
public bool SupportsSha1Signatures => true;
3739
}
3840

3941
public partial class RSAFactory

src/libraries/System.Security.Cryptography.Cng/tests/System.Security.Cryptography.Cng.Tests.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
<Compile Include="TestData.cs" />
1616
</ItemGroup>
1717
<ItemGroup Condition="'$(TargetPlatformIdentifier)' == 'windows'">
18+
<Compile Include="$(CommonTestPath)System\Security\Cryptography\SignatureSupport.cs"
19+
Link="CommonTest\System\Security\Cryptography\SignatureSupport.cs" />
1820
<Compile Include="$(CommonTestPath)System\Security\Cryptography\AlgorithmImplementations\AES\AesCipherTests.Data.cs"
1921
Link="CommonTest\AlgorithmImplementations\AES\AesCipherTests.Data.cs" />
2022
<Compile Include="$(CommonTestPath)System\Security\Cryptography\AlgorithmImplementations\AES\AesCornerTests.cs"

src/libraries/System.Security.Cryptography.Csp/tests/RSACryptoServiceProviderBackCompat.cs

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -156,24 +156,26 @@ public static void VerifyLegacySignVerifyHash(bool useLegacySign, bool useLegacy
156156

157157
public static IEnumerable<object[]> AlgorithmIdentifiers()
158158
{
159-
return new[]
159+
yield return new object[] { "MD5", MD5.Create() };
160+
yield return new object[] { "MD5", typeof(MD5) };
161+
yield return new object[] { "MD5", "1.2.840.113549.2.5" };
162+
163+
if (RSAFactory.SupportsSha1Signatures)
160164
{
161-
new object[] { "MD5", MD5.Create() },
162-
new object[] { "MD5", typeof(MD5) },
163-
new object[] { "MD5", "1.2.840.113549.2.5" },
164-
new object[] { "SHA1", SHA1.Create() },
165-
new object[] { "SHA1", typeof(SHA1) },
166-
new object[] { "SHA1", "1.3.14.3.2.26" },
167-
new object[] { "SHA256", SHA256.Create() },
168-
new object[] { "SHA256", typeof(SHA256) },
169-
new object[] { "SHA256", "2.16.840.1.101.3.4.2.1" },
170-
new object[] { "SHA384", SHA384.Create() },
171-
new object[] { "SHA384", typeof(SHA384) },
172-
new object[] { "SHA384", "2.16.840.1.101.3.4.2.2" },
173-
new object[] { "SHA512", SHA512.Create() },
174-
new object[] { "SHA512", typeof(SHA512) },
175-
new object[] { "SHA512", "2.16.840.1.101.3.4.2.3" },
176-
};
165+
yield return new object[] { "SHA1", SHA1.Create() };
166+
yield return new object[] { "SHA1", typeof(SHA1) };
167+
yield return new object[] { "SHA1", "1.3.14.3.2.26" };
168+
}
169+
170+
yield return new object[] { "SHA256", SHA256.Create() };
171+
yield return new object[] { "SHA256", typeof(SHA256) };
172+
yield return new object[] { "SHA256", "2.16.840.1.101.3.4.2.1" };
173+
yield return new object[] { "SHA384", SHA384.Create() };
174+
yield return new object[] { "SHA384", typeof(SHA384) };
175+
yield return new object[] { "SHA384", "2.16.840.1.101.3.4.2.2" };
176+
yield return new object[] { "SHA512", SHA512.Create() };
177+
yield return new object[] { "SHA512", typeof(SHA512) };
178+
yield return new object[] { "SHA512", "2.16.840.1.101.3.4.2.3" };
177179
}
178180
}
179181
}

0 commit comments

Comments
 (0)