Skip to content

Commit 17ef3d5

Browse files
authored
Add unit tests for CertificatePublicKeyValidator (#511)
Add unit tests for CertificatePublicKeyValidator
1 parent a0b9952 commit 17ef3d5

File tree

2 files changed

+203
-1
lines changed

2 files changed

+203
-1
lines changed
Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
using System.Security.Cryptography;
2+
using System.Security.Cryptography.X509Certificates;
3+
using Shark.Fido2.Core.Validators.AttestationStatementValidators;
4+
using Shark.Fido2.Domain;
5+
using Shark.Fido2.Domain.Enums;
6+
7+
namespace Shark.Fido2.Core.Tests.Validators.AttestationStatementValidators;
8+
9+
[TestFixture]
10+
internal class CertificatePublicKeyValidatorTests
11+
{
12+
private CertificatePublicKeyValidator _sut = null!;
13+
14+
[SetUp]
15+
public void Setup()
16+
{
17+
_sut = new CertificatePublicKeyValidator();
18+
}
19+
20+
[Test]
21+
public void Validate_WhenCertificateIsNull_ThenThrowsArgumentNullException()
22+
{
23+
// Arrange
24+
var credentialPublicKey = new CredentialPublicKey();
25+
26+
// Act & Assert
27+
Assert.Throws<ArgumentNullException>(() => _sut.Validate(null!, credentialPublicKey));
28+
}
29+
30+
[Test]
31+
public void Validate_WhenCredentialPublicKeyIsNull_ThenThrowsArgumentNullException()
32+
{
33+
// Arrange
34+
using var rsa = RSA.Create();
35+
var request = new CertificateRequest("CN=Test", rsa, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
36+
using var certificate = request.CreateSelfSigned(DateTimeOffset.UtcNow, DateTimeOffset.UtcNow.AddDays(1));
37+
38+
// Act & Assert
39+
Assert.Throws<ArgumentNullException>(() => _sut.Validate(certificate, null!));
40+
}
41+
42+
[Test]
43+
public void Validate_WhenRsaPublicKeyMatches_ThenReturnsValidResult()
44+
{
45+
// Arrange
46+
using var rsa = RSA.Create(2048);
47+
var parameters = rsa.ExportParameters(false);
48+
var credentialPublicKey = new CredentialPublicKey
49+
{
50+
KeyType = (int)KeyType.Rsa,
51+
Modulus = parameters.Modulus,
52+
Exponent = parameters.Exponent,
53+
};
54+
55+
var request = new CertificateRequest("CN=Test", rsa, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
56+
using var certificate = request.CreateSelfSigned(DateTimeOffset.UtcNow, DateTimeOffset.UtcNow.AddDays(1));
57+
58+
// Act
59+
var result = _sut.Validate(certificate, credentialPublicKey);
60+
61+
// Assert
62+
Assert.That(result.IsValid, Is.True);
63+
}
64+
65+
[Test]
66+
public void Validate_WhenRsaModulusMismatches_ThenReturnsInvalidResult()
67+
{
68+
// Arrange
69+
using var rsa = RSA.Create(2048);
70+
var parameters = rsa.ExportParameters(false);
71+
var credentialPublicKey = new CredentialPublicKey
72+
{
73+
KeyType = (int)KeyType.Rsa,
74+
Modulus = new byte[parameters.Modulus!.Length], // Wrong modulus
75+
Exponent = parameters.Exponent,
76+
};
77+
78+
var request = new CertificateRequest("CN=Test", rsa, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
79+
using var certificate = request.CreateSelfSigned(DateTimeOffset.UtcNow, DateTimeOffset.UtcNow.AddDays(1));
80+
81+
// Act
82+
var result = _sut.Validate(certificate, credentialPublicKey);
83+
84+
// Assert
85+
Assert.That(result.IsValid, Is.False);
86+
Assert.That(result.Message, Is.EqualTo("Certificate public key is not valid"));
87+
}
88+
89+
[Test]
90+
public void Validate_WhenRsaExponentMismatches_ThenReturnsInvalidResult()
91+
{
92+
// Arrange
93+
using var rsa = RSA.Create(2048);
94+
var parameters = rsa.ExportParameters(false);
95+
var credentialPublicKey = new CredentialPublicKey
96+
{
97+
KeyType = (int)KeyType.Rsa,
98+
Modulus = parameters.Modulus,
99+
Exponent = [0, 0, 0], // Wrong exponent
100+
};
101+
102+
var request = new CertificateRequest("CN=Test", rsa, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
103+
using var certificate = request.CreateSelfSigned(DateTimeOffset.UtcNow, DateTimeOffset.UtcNow.AddDays(1));
104+
105+
// Act
106+
var result = _sut.Validate(certificate, credentialPublicKey);
107+
108+
// Assert
109+
Assert.That(result.IsValid, Is.False);
110+
Assert.That(result.Message, Is.EqualTo("Certificate public key is not valid"));
111+
}
112+
113+
[Test]
114+
public void Validate_WhenEc2PublicKeyMatches_ThenReturnsValidResult()
115+
{
116+
// Arrange
117+
using var ecdsa = ECDsa.Create(ECCurve.NamedCurves.nistP256);
118+
var parameters = ecdsa.ExportParameters(false);
119+
var credentialPublicKey = new CredentialPublicKey
120+
{
121+
KeyType = (int)KeyType.Ec2,
122+
XCoordinate = parameters.Q.X,
123+
YCoordinate = parameters.Q.Y,
124+
};
125+
126+
var request = new CertificateRequest("CN=Test", ecdsa, HashAlgorithmName.SHA256);
127+
using var certificate = request.CreateSelfSigned(DateTimeOffset.UtcNow, DateTimeOffset.UtcNow.AddDays(1));
128+
129+
// Act
130+
var result = _sut.Validate(certificate, credentialPublicKey);
131+
132+
// Assert
133+
Assert.That(result.IsValid, Is.True);
134+
}
135+
136+
[Test]
137+
public void Validate_WhenEc2XMismatches_ThenReturnsInvalidResult()
138+
{
139+
// Arrange
140+
using var ecdsa = ECDsa.Create(ECCurve.NamedCurves.nistP256);
141+
var parameters = ecdsa.ExportParameters(false);
142+
var credentialPublicKey = new CredentialPublicKey
143+
{
144+
KeyType = (int)KeyType.Ec2,
145+
XCoordinate = new byte[parameters.Q.X!.Length], // Wrong X
146+
YCoordinate = parameters.Q.Y,
147+
};
148+
149+
var request = new CertificateRequest("CN=Test", ecdsa, HashAlgorithmName.SHA256);
150+
using var certificate = request.CreateSelfSigned(DateTimeOffset.UtcNow, DateTimeOffset.UtcNow.AddDays(1));
151+
152+
// Act
153+
var result = _sut.Validate(certificate, credentialPublicKey);
154+
155+
// Assert
156+
Assert.That(result.IsValid, Is.False);
157+
Assert.That(result.Message, Is.EqualTo("Certificate public key is not valid"));
158+
}
159+
160+
[Test]
161+
public void Validate_WhenEc2YMismatches_ThenReturnsInvalidResult()
162+
{
163+
// Arrange
164+
using var ecdsa = ECDsa.Create(ECCurve.NamedCurves.nistP256);
165+
var parameters = ecdsa.ExportParameters(false);
166+
var credentialPublicKey = new CredentialPublicKey
167+
{
168+
KeyType = (int)KeyType.Ec2,
169+
XCoordinate = parameters.Q.X,
170+
YCoordinate = new byte[parameters.Q.Y!.Length], // Wrong Y
171+
};
172+
173+
var request = new CertificateRequest("CN=Test", ecdsa, HashAlgorithmName.SHA256);
174+
using var certificate = request.CreateSelfSigned(DateTimeOffset.UtcNow, DateTimeOffset.UtcNow.AddDays(1));
175+
176+
// Act
177+
var result = _sut.Validate(certificate, credentialPublicKey);
178+
179+
// Assert
180+
Assert.That(result.IsValid, Is.False);
181+
Assert.That(result.Message, Is.EqualTo("Certificate public key is not valid"));
182+
}
183+
184+
[Test]
185+
public void Validate_WhenKeyTypeIsUnsupported_ThenThrowsNotSupportedException()
186+
{
187+
// Arrange
188+
using var ecdsa = ECDsa.Create(ECCurve.NamedCurves.nistP256);
189+
var request = new CertificateRequest("CN=Test", ecdsa, HashAlgorithmName.SHA256);
190+
using var certificate = request.CreateSelfSigned(DateTimeOffset.UtcNow, DateTimeOffset.UtcNow.AddDays(1));
191+
192+
var credentialPublicKey = new CredentialPublicKey
193+
{
194+
KeyType = (int)KeyType.Okp,
195+
};
196+
197+
// Act & Assert
198+
Assert.Throws<NotSupportedException>(() => _sut.Validate(certificate, credentialPublicKey));
199+
}
200+
}

tests/Shark.Fido2.Tests.Common/NoneAttestationGenerator.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1-
using System.Formats.Cbor;
1+
using System.Diagnostics.CodeAnalysis;
2+
using System.Formats.Cbor;
23
using Shark.Fido2.Common.Extensions;
34
using Shark.Fido2.Domain;
45

56
namespace Shark.Fido2.Tests.Common;
67

8+
[ExcludeFromCodeCoverage]
79
public static class NoneAttestationGenerator
810
{
911
public static string GenerateAttestationObject(AuthenticatorData sourceAuthenticatorData, byte[] credentialId)

0 commit comments

Comments
 (0)