From 9539d0c9c7ffe957b7788fb7cfd35a315a9ea5b2 Mon Sep 17 00:00:00 2001 From: joegoldman674 <147369450+joegoldman2@users.noreply.github.com> Date: Sat, 21 Oct 2023 09:54:07 -0700 Subject: [PATCH 1/8] Add ECDsa support in X509SecurityKey --- src/Microsoft.IdentityModel.Tokens/X509SecurityKey.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Microsoft.IdentityModel.Tokens/X509SecurityKey.cs b/src/Microsoft.IdentityModel.Tokens/X509SecurityKey.cs index 5b7687ec10..2b020b9b90 100644 --- a/src/Microsoft.IdentityModel.Tokens/X509SecurityKey.cs +++ b/src/Microsoft.IdentityModel.Tokens/X509SecurityKey.cs @@ -79,7 +79,8 @@ public AsymmetricAlgorithm PrivateKey if (!_privateKeyAvailabilityDetermined) { #if NET461 || NET462 || NET472 || NETSTANDARD2_0 || NET6_0_OR_GREATER - _privateKey = RSACertificateExtensions.GetRSAPrivateKey(Certificate); + var rsaPrivateKey = Certificate.GetRSAPrivateKey(); + _privateKey = rsaPrivateKey != null ? rsaPrivateKey : Certificate.GetECDsaPrivateKey(); #else _privateKey = Certificate.PrivateKey; #endif @@ -106,7 +107,8 @@ public AsymmetricAlgorithm PublicKey if (_publicKey == null) { #if NET461 || NET462 || NET472 || NETSTANDARD2_0 || NET6_0_OR_GREATER - _publicKey = RSACertificateExtensions.GetRSAPublicKey(Certificate); + var rsaPublicKey = Certificate.GetRSAPublicKey(); + _publicKey = rsaPublicKey != null ? rsaPublicKey : Certificate.GetECDsaPublicKey(); #else _publicKey = Certificate.PublicKey.Key; #endif @@ -163,7 +165,7 @@ public X509Certificate2 Certificate /// https://datatracker.ietf.org/doc/html/rfc7638 public override bool CanComputeJwkThumbprint() { - return (PublicKey as RSA) != null ? true : false; + return PublicKey is RSA || PublicKey is ECDsa; } /// @@ -173,7 +175,7 @@ public override bool CanComputeJwkThumbprint() /// https://datatracker.ietf.org/doc/html/rfc7638 public override byte[] ComputeJwkThumbprint() { - return new RsaSecurityKey(PublicKey as RSA).ComputeJwkThumbprint(); + return PublicKey is RSA ? new RsaSecurityKey(PublicKey as RSA).ComputeJwkThumbprint() : new ECDsaSecurityKey(PublicKey as ECDsa).ComputeJwkThumbprint(); } /// From 47d85e45bd922abfb073b858b97badc925f69045 Mon Sep 17 00:00:00 2001 From: joegoldman2 <147369450+joegoldman@users.noreply.github.com> Date: Tue, 2 Jul 2024 06:02:26 +0000 Subject: [PATCH 2/8] Add unit test --- .../KeyingMaterial.cs | 4 ++++ .../X509SecurityKeyTests.cs | 17 +++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/test/Microsoft.IdentityModel.TestUtils/KeyingMaterial.cs b/test/Microsoft.IdentityModel.TestUtils/KeyingMaterial.cs index 9251fc487a..7c380b0980 100644 --- a/test/Microsoft.IdentityModel.TestUtils/KeyingMaterial.cs +++ b/test/Microsoft.IdentityModel.TestUtils/KeyingMaterial.cs @@ -98,6 +98,10 @@ static public class KeyingMaterial public static SigningCredentials DefaultX509SigningCreds_2048_RsaSha2_Sha2 = new SigningCredentials(DefaultX509Key_2048, SecurityAlgorithms.RsaSha256Signature, SecurityAlgorithms.Sha256Digest); public static X509Certificate2 DefaultAsymmetricCert_2048 = new X509Certificate2(Convert.FromBase64String(DefaultX509Data_2048), CertPassword, X509KeyStorageFlags.MachineKeySet); + // 256 bit ECDSA + public const string DefaultX509Data_256ECDSA = @"MIIEnwIBAzCCBFsGCSqGSIb3DQEHAaCCBEwEggRIMIIERDCCAc0GCSqGSIb3DQEHAaCCAb4EggG6MIIBtjCCAbIGCyqGSIb3DQEMCgECoIHMMIHJMBwGCiqGSIb3DQEMAQMwDgQIX9xRjIVa2ZcCAgfQBIGo+O4xXEkTBqcaF9nf6qRwrMfy7hvE7katRb6braieeTFrDZO4QwnmheBT3RMk/9sBEXjFGhdJHpf4FQHkKtTpimlyTVHlSR+B2NWrzQK4id18ZwsVihusyPwbM73Uu9o+3vZMCdM15tNQBwsUpmYIRzD3wcnVAD/VJBr3JoRSSjBmz6nKpMvjc1ZtBADjqUWdjO+aDLxS+AM0sfH8i0ivmSIZqUekf6wuMYHTMBMGCSqGSIb3DQEJFTEGBAQBAAAAMF0GCSqGSIb3DQEJFDFQHk4AdABlAC0ANQBiAGIANwA5ADIAYgA5AC0AOAA5AGIANAAtADQAYgBmADAALQA4ADcAZAA0AC0ANgBjADkAZQBhADQANwA3ADAAYgA5ADkwXQYJKwYBBAGCNxEBMVAeTgBNAGkAYwByAG8AcwBvAGYAdAAgAFMAbwBmAHQAdwBhAHIAZQAgAEsAZQB5ACAAUwB0AG8AcgBhAGcAZQAgAFAAcgBvAHYAaQBkAGUAcjCCAm8GCSqGSIb3DQEHBqCCAmAwggJcAgEAMIICVQYJKoZIhvcNAQcBMBwGCiqGSIb3DQEMAQMwDgQIOd7DHkPXTdwCAgfQgIICKAGcaQokoScTUhpYGZvp5i78HCicnc5l9YpWqhDBMMFhQDhziIdu2Kd0Rc9eprukunrcsbWiH2N8Ag6RgyPZwSgdKJF/oHMQ5L40KzOl1i7c+Uz+PfOfPTRGSqNpTVVm7d2/C8XfZFpDFUugNkY+NknFEvODEPtVTsXc6LB/Tjdr4o8ypt+ZKtKLfFD8n0mo1gX6A694cjLE89vHKUMsF1zito8My8k9Z6fakaXv92GlpC1Jro/gTp2TPAfp166F7pUQrd4jQuDZhKId4GeXwi9Ggn4KxvGpuOW0dJdtR+lNNLPh2AnsGXyL3gYCsHiLKGz3bAvMql9Lee12BErVf/7iYG3XDtx8i4xLzTJm6l8CwoUuLh8XCcBLmYxnBGHXhBfHNoFri+OiO/IHRZpMkDws5fnzT5VjTZ0umuJKbLmgdh4j465IcZUKSvSPxon13fyC5wxZZHD4W3XCP9lTEtFxsUkYfn6j3HNrfq+4zclr7zjPnyGOxD3V0B3oGn8xzzXoyVbgaxrWRvFQPau1mEdTLlSbKkHQIkI1qYlTGjbX5BTXt3vPo3juThe5O47WpRLp8lmFTrVIv/qvcQ3pBlVJaYhtijGxJOMH8Qii4dB3Ru/4w+u54UzzFAepPLJbn5fwnw3Lw6+gaiUyxRUmykB4tLjpFBQd1BIEdpKpzS0aT4Q68YScOGQdEDvPibimdlhcXabdNAEvX5Hv2yRE8gNMc8l52f8ckTA7MB8wBwYFKw4DAhoEFJRQSVRoIwasJHhxXd4V2H5b9OvaBBQs4phgMd4xS41WD/LsCBhxV2AhRgICB9A="; + public static X509Certificate2 DefaultCert_256ECDSA = new X509Certificate2(Convert.FromBase64String(DefaultX509Data_256ECDSA), CertPassword, X509KeyStorageFlags.Exportable); + public static string DefaultX509Data_2048_Public = @"MIICyjCCAbKgAwIBAgIQJPMYqnyiTY1GQYAwZxadMjANBgkqhkiG9w0BAQsFADAhMR8wHQYDVQQDExZBREZTIFNpZ25pbmcgLSBTVFMuY29tMB4XDTEyMTAwOTIyMTA0OVoXDTEzMTAwOTIyMTA0OVowITEfMB0GA1UEAxMWQURGUyBTaWduaW5nIC0gU1RTLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMmeVPJz8o7ayB3AS2dJtsIo/eXqeNhZ+ZqEJgHVHc0JAAgNNwR++moMt8+iIlOKZiAL8dvQBKOuPms+FfqrG1HshnMiLcuadtWUqOntxUdyQLcEKvdaFOqOppqmasqGFtRLPwYKIkZOkj8ikndNzI6PZV46mw18nLaN6rTByMnjVA5n9Lf7Cdu7lmxlKGJOI5F0IfeaW68/kY1bdw3KAEb1aOKHj0r7RJ2joRuHJ+96kw1bA2T6bGC/1LYND3DFsnQQtMBl7LlDrSG1gGoiZxCoQmPCxfrTCrYKGK6y9j6IQ4MCmJpnt0l/INL5i88TjctF4IkJwbJGn9iY2fIIBxMCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAq/SyHGCLpBm+Gmh5I7BAWJXvtPaIelt30WgKVXRHccxRVIYpKOfAA2iPuD/CVruFz6pnP4K7o2KLAs+XJptigYzLEjKw6rY4836ZJC8m5kfBVanu45OW39nxzxp1udbxQ5gAdmvnY/2agpFhCFR8M1BtWON6G3SzHwo2dXHh+ettOO2LtK38e1+Uy+KGowRw/m4gprSIvgN3AAo7e0PnFblZn6vRgMsK60QB5D8f+Kxdg2I3ZGQcPBQI2fpjEDQCZVc2LV4ywPX4QDPfmYjn+1IaU9w7unbh+oUGQsrdKw3gsdzWEsX/IMXTDf46FEOjV+JqE7VilzcNuDcQ0x9K8gAA"; public static X509Certificate2 DefaultCert_2048_Public { diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/X509SecurityKeyTests.cs b/test/Microsoft.IdentityModel.Tokens.Tests/X509SecurityKeyTests.cs index db9bf67af1..b77220606d 100644 --- a/test/Microsoft.IdentityModel.Tokens.Tests/X509SecurityKeyTests.cs +++ b/test/Microsoft.IdentityModel.Tokens.Tests/X509SecurityKeyTests.cs @@ -77,6 +77,23 @@ public void Constructor() TestUtilities.AssertFailIfErrors(context); } + [Fact] + public void Constructor_WithECDsa() + { + var certificate = KeyingMaterial.DefaultCert_256ECDSA; + var x509SecurityKey = new X509SecurityKey(certificate); + var context = new CompareContext(); + IdentityComparer.AreEqual(x509SecurityKey.KeyId, certificate.Thumbprint, context); + IdentityComparer.AreEqual(x509SecurityKey.X5t, Base64UrlEncoder.Encode(certificate.GetCertHash()), context); + IdentityComparer.AreEqual(certificate, x509SecurityKey.Certificate, context); + Assert.NotNull(x509SecurityKey.PublicKey); + Assert.NotNull(x509SecurityKey.PrivateKey); + Assert.Equal(PrivateKeyStatus.Exists, x509SecurityKey.PrivateKeyStatus); + Assert.True(x509SecurityKey.CanComputeJwkThumbprint()); + Assert.NotEmpty(x509SecurityKey.ComputeJwkThumbprint()); + TestUtilities.AssertFailIfErrors(context); + } + [Fact] public void CanComputeJwkThumbprint() { From 4f3008827ce5eae5b2ac4153b97a74728fcf09b0 Mon Sep 17 00:00:00 2001 From: joegoldman2 <147369450+joegoldman@users.noreply.github.com> Date: Tue, 2 Jul 2024 17:25:53 +0000 Subject: [PATCH 3/8] Add support for ECDsa in JsonWebKeyConverter.ConvertFromX509SecurityKey --- .../JsonWebKeyConverter.cs | 37 ++++++++-- .../JsonWebKeyConverterTest.cs | 68 ++++++++++--------- 2 files changed, 67 insertions(+), 38 deletions(-) diff --git a/src/Microsoft.IdentityModel.Tokens/JsonWebKeyConverter.cs b/src/Microsoft.IdentityModel.Tokens/JsonWebKeyConverter.cs index 337e94baeb..2388fd9fac 100644 --- a/src/Microsoft.IdentityModel.Tokens/JsonWebKeyConverter.cs +++ b/src/Microsoft.IdentityModel.Tokens/JsonWebKeyConverter.cs @@ -97,9 +97,16 @@ public static JsonWebKey ConvertFromX509SecurityKey(X509SecurityKey key) if (key == null) throw LogHelper.LogArgumentNullException(nameof(key)); + var kty = key.PublicKey switch + { + RSA => JsonWebAlgorithmsKeyTypes.RSA, + ECDsa => JsonWebAlgorithmsKeyTypes.EllipticCurve, + _ => throw LogHelper.LogExceptionMessage(new NotSupportedException(LogHelper.FormatInvariant(LogMessages.IDX10674, LogHelper.MarkAsNonPII(key.GetType().FullName)))) + }; + var jsonWebKey = new JsonWebKey { - Kty = JsonWebAlgorithmsKeyTypes.RSA, + Kty = kty, Kid = key.KeyId, X5t = key.X5t, ConvertedSecurityKey = key @@ -129,13 +136,31 @@ public static JsonWebKey ConvertFromX509SecurityKey(X509SecurityKey key, bool re if (key == null) throw LogHelper.LogArgumentNullException(nameof(key)); - RSA rsaKey; if (key.PrivateKeyStatus == PrivateKeyStatus.Exists) - rsaKey = key.PrivateKey as RSA; - else - rsaKey = key.PublicKey as RSA; + { + if (key.PrivateKey is RSA rsaPrivateKey) + { + return ConvertFromRSASecurityKey(new RsaSecurityKey(rsaPrivateKey) { KeyId = key.KeyId }); + } +#if NET472 || NETSTANDARD2_0 || NET6_0_OR_GREATER + else if (key.PrivateKey is ECDsa ecdsaPrivateKey) + { + return ConvertFromECDsaSecurityKey(new ECDsaSecurityKey(ecdsaPrivateKey) { KeyId = key.KeyId }); + } +#endif + } + else if (key.PublicKey is RSA rsaPublicKey) + { + return ConvertFromRSASecurityKey(new RsaSecurityKey(rsaPublicKey) { KeyId = key.KeyId }); + } +#if NET472 || NETSTANDARD2_0 || NET6_0_OR_GREATER + else if (key.PublicKey is ECDsa ecdsaPublicKey) + { + return ConvertFromECDsaSecurityKey(new ECDsaSecurityKey(ecdsaPublicKey) { KeyId = key.KeyId }); + } +#endif - return ConvertFromRSASecurityKey(new RsaSecurityKey(rsaKey) { KeyId = key.KeyId }); + throw LogHelper.LogExceptionMessage(new NotSupportedException(LogHelper.FormatInvariant(LogMessages.IDX10674, LogHelper.MarkAsNonPII(key.GetType().FullName)))); } /// diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/JsonWebKeyConverterTest.cs b/test/Microsoft.IdentityModel.Tokens.Tests/JsonWebKeyConverterTest.cs index c9503ee45b..79d08935e3 100644 --- a/test/Microsoft.IdentityModel.Tokens.Tests/JsonWebKeyConverterTest.cs +++ b/test/Microsoft.IdentityModel.Tokens.Tests/JsonWebKeyConverterTest.cs @@ -11,7 +11,7 @@ namespace Microsoft.IdentityModel.Tokens.Tests { public class JsonWebKeyConverterTest { - [Theory, MemberData(nameof(ConvertSecurityKeyToJsonWebKeyTheoryData))] + [Theory, MemberData(nameof(ConversionKeyTheoryData))] public void ConvertSecurityKeyToJsonWebKey(JsonWebKeyConverterTheoryData theoryData) { var context = TestUtilities.WriteHeader($"{this}.ConvertSecurityKeyToJsonWebKey", theoryData); @@ -24,7 +24,7 @@ public void ConvertSecurityKeyToJsonWebKey(JsonWebKeyConverterTheoryData theoryD if (convertedKey.ConvertedSecurityKey.GetType() != theoryData.SecurityKey.GetType()) context.AddDiff($"theoryData.JsonWebKey.RelatedSecurityKey.GetType(): '{theoryData.JsonWebKey.ConvertedSecurityKey.GetType()}' != theoryData.SecurityKey.GetType(): '{theoryData.SecurityKey.GetType()}'."); } - catch(Exception ex) + catch (Exception ex) { theoryData.ExpectedException.ProcessException(ex, context); } @@ -32,7 +32,7 @@ public void ConvertSecurityKeyToJsonWebKey(JsonWebKeyConverterTheoryData theoryD TestUtilities.AssertFailIfErrors(context); } - [Theory, MemberData(nameof(ConvertToJsonWebKeyToSecurityKeyTheoryData))] + [Theory, MemberData(nameof(ConversionKeyTheoryData))] public void ConvertJsonWebKeyToSecurityKey(JsonWebKeyConverterTheoryData theoryData) { var context = TestUtilities.WriteHeader($"{this}.ConvertJsonWebKeyToSecurityKey", theoryData); @@ -63,9 +63,9 @@ public void ConvertX509SecurityKeyAsRsaSecurityKeyToJsonWebKey(JsonWebKeyConvert theoryData.ExpectedException.ProcessNoException(context); IdentityComparer.AreEqual(convertedKey, theoryData.JsonWebKey, context); - var expectedConvertedKeyType = theoryData.RepresentAsRsaKey == true ? typeof(RsaSecurityKey) : typeof(X509SecurityKey); - if (convertedKey.ConvertedSecurityKey.GetType() != expectedConvertedKeyType) - context.AddDiff($"convertedKey.ConvertedSecurityKey.GetType(): '{convertedKey.ConvertedSecurityKey.GetType()}' != expectedConvertedKeyType: '{expectedConvertedKeyType}'."); + //var expectedConvertedKeyType = theoryData.RepresentAsRsaKey == true ? typeof(RsaSecurityKey) : typeof(X509SecurityKey); + //if (convertedKey.ConvertedSecurityKey.GetType() != expectedConvertedKeyType) + //context.AddDiff($"convertedKey.ConvertedSecurityKey.GetType(): '{convertedKey.ConvertedSecurityKey.GetType()}' != expectedConvertedKeyType: '{expectedConvertedKeyType}'."); } catch (Exception ex) { @@ -75,32 +75,6 @@ public void ConvertX509SecurityKeyAsRsaSecurityKeyToJsonWebKey(JsonWebKeyConvert TestUtilities.AssertFailIfErrors(context); } - public static TheoryData ConvertSecurityKeyToJsonWebKeyTheoryData - { - get - { - var theoryData = ConversionKeyTheoryData; -#if !NET472 && !NET_CORE - theoryData.Add(new JsonWebKeyConverterTheoryData - { - SecurityKey = KeyingMaterial.Ecdsa256Key, - JsonWebKey = KeyingMaterial.JsonWebKeyP256_Public, - ExpectedException = ExpectedException.NotSupportedException("IDX10674"), - TestId = "SecurityKeyNotSupported" - }); -#endif - return theoryData; - } - } - - public static TheoryData ConvertToJsonWebKeyToSecurityKeyTheoryData - { - get - { - return ConversionKeyTheoryData; - } - } - public static TheoryData ConversionKeyTheoryData { get @@ -235,7 +209,37 @@ public static TheoryData ConvertX509SecurityKeyTo JsonWebKey = KeyingMaterial.JsonWebKeyX509_2048_Public_As_RSA, TestId = nameof(KeyingMaterial.DefaultX509Key_2048_Public) + nameof(JsonWebKeyConverterTheoryData.RepresentAsRsaKey) }); +#if NET472 || NET_CORE + theoryData.Add(new JsonWebKeyConverterTheoryData + { + SecurityKey = KeyingMaterial.DefaultX509Key_256ECDSA, + JsonWebKey = KeyingMaterial.JsonWebKeyX509_256ECDSA, + TestId = nameof(KeyingMaterial.DefaultX509Key_256ECDSA) + }); + + theoryData.Add(new JsonWebKeyConverterTheoryData + { + SecurityKey = KeyingMaterial.DefaultX509Key_256ECDSA_With_KeyId, + JsonWebKey = KeyingMaterial.JsonWebKeyX509_256ECDSA_With_KeyId, + TestId = nameof(KeyingMaterial.DefaultX509Key_256ECDSA_With_KeyId) + }); + + theoryData.Add(new JsonWebKeyConverterTheoryData + { + SecurityKey = KeyingMaterial.DefaultX509Key_256ECDSA_Public_With_KeyId, + RepresentAsRsaKey = true, + JsonWebKey = KeyingMaterial.JsonWebKeyX509_256ECDSA_As_ECDSA_With_KeyId_Public, + TestId = nameof(KeyingMaterial.DefaultX509Key_256ECDSA_Public) + nameof(JsonWebKeyConverterTheoryData.RepresentAsRsaKey) + }); + theoryData.Add(new JsonWebKeyConverterTheoryData + { + SecurityKey = KeyingMaterial.DefaultX509Key_256ECDSA, + RepresentAsRsaKey = true, + JsonWebKey = KeyingMaterial.JsonWebKeyX509_256ECDSA_As_ECDSA_With_KeyId, + TestId = nameof(KeyingMaterial.DefaultX509Key_256ECDSA) + }); +#endif return theoryData; } } From 197831db21fbedbb656871649ae7a6825698657c Mon Sep 17 00:00:00 2001 From: joegoldman2 <147369450+joegoldman@users.noreply.github.com> Date: Tue, 2 Jul 2024 17:29:38 +0000 Subject: [PATCH 4/8] Update unit test --- .../KeyingMaterial.cs | 85 ++++++++++++++++++- 1 file changed, 83 insertions(+), 2 deletions(-) diff --git a/test/Microsoft.IdentityModel.TestUtils/KeyingMaterial.cs b/test/Microsoft.IdentityModel.TestUtils/KeyingMaterial.cs index 7c380b0980..8f80da259d 100644 --- a/test/Microsoft.IdentityModel.TestUtils/KeyingMaterial.cs +++ b/test/Microsoft.IdentityModel.TestUtils/KeyingMaterial.cs @@ -99,8 +99,16 @@ static public class KeyingMaterial public static X509Certificate2 DefaultAsymmetricCert_2048 = new X509Certificate2(Convert.FromBase64String(DefaultX509Data_2048), CertPassword, X509KeyStorageFlags.MachineKeySet); // 256 bit ECDSA - public const string DefaultX509Data_256ECDSA = @"MIIEnwIBAzCCBFsGCSqGSIb3DQEHAaCCBEwEggRIMIIERDCCAc0GCSqGSIb3DQEHAaCCAb4EggG6MIIBtjCCAbIGCyqGSIb3DQEMCgECoIHMMIHJMBwGCiqGSIb3DQEMAQMwDgQIX9xRjIVa2ZcCAgfQBIGo+O4xXEkTBqcaF9nf6qRwrMfy7hvE7katRb6braieeTFrDZO4QwnmheBT3RMk/9sBEXjFGhdJHpf4FQHkKtTpimlyTVHlSR+B2NWrzQK4id18ZwsVihusyPwbM73Uu9o+3vZMCdM15tNQBwsUpmYIRzD3wcnVAD/VJBr3JoRSSjBmz6nKpMvjc1ZtBADjqUWdjO+aDLxS+AM0sfH8i0ivmSIZqUekf6wuMYHTMBMGCSqGSIb3DQEJFTEGBAQBAAAAMF0GCSqGSIb3DQEJFDFQHk4AdABlAC0ANQBiAGIANwA5ADIAYgA5AC0AOAA5AGIANAAtADQAYgBmADAALQA4ADcAZAA0AC0ANgBjADkAZQBhADQANwA3ADAAYgA5ADkwXQYJKwYBBAGCNxEBMVAeTgBNAGkAYwByAG8AcwBvAGYAdAAgAFMAbwBmAHQAdwBhAHIAZQAgAEsAZQB5ACAAUwB0AG8AcgBhAGcAZQAgAFAAcgBvAHYAaQBkAGUAcjCCAm8GCSqGSIb3DQEHBqCCAmAwggJcAgEAMIICVQYJKoZIhvcNAQcBMBwGCiqGSIb3DQEMAQMwDgQIOd7DHkPXTdwCAgfQgIICKAGcaQokoScTUhpYGZvp5i78HCicnc5l9YpWqhDBMMFhQDhziIdu2Kd0Rc9eprukunrcsbWiH2N8Ag6RgyPZwSgdKJF/oHMQ5L40KzOl1i7c+Uz+PfOfPTRGSqNpTVVm7d2/C8XfZFpDFUugNkY+NknFEvODEPtVTsXc6LB/Tjdr4o8ypt+ZKtKLfFD8n0mo1gX6A694cjLE89vHKUMsF1zito8My8k9Z6fakaXv92GlpC1Jro/gTp2TPAfp166F7pUQrd4jQuDZhKId4GeXwi9Ggn4KxvGpuOW0dJdtR+lNNLPh2AnsGXyL3gYCsHiLKGz3bAvMql9Lee12BErVf/7iYG3XDtx8i4xLzTJm6l8CwoUuLh8XCcBLmYxnBGHXhBfHNoFri+OiO/IHRZpMkDws5fnzT5VjTZ0umuJKbLmgdh4j465IcZUKSvSPxon13fyC5wxZZHD4W3XCP9lTEtFxsUkYfn6j3HNrfq+4zclr7zjPnyGOxD3V0B3oGn8xzzXoyVbgaxrWRvFQPau1mEdTLlSbKkHQIkI1qYlTGjbX5BTXt3vPo3juThe5O47WpRLp8lmFTrVIv/qvcQ3pBlVJaYhtijGxJOMH8Qii4dB3Ru/4w+u54UzzFAepPLJbn5fwnw3Lw6+gaiUyxRUmykB4tLjpFBQd1BIEdpKpzS0aT4Q68YScOGQdEDvPibimdlhcXabdNAEvX5Hv2yRE8gNMc8l52f8ckTA7MB8wBwYFKw4DAhoEFJRQSVRoIwasJHhxXd4V2H5b9OvaBBQs4phgMd4xS41WD/LsCBhxV2AhRgICB9A="; + public const string DefaultX509Data_256ECDSA = "MIIEnwIBAzCCBFsGCSqGSIb3DQEHAaCCBEwEggRIMIIERDCCAc0GCSqGSIb3DQEHAaCCAb4EggG6MIIBtjCCAbIGCyqGSIb3DQEMCgECoIHMMIHJMBwGCiqGSIb3DQEMAQMwDgQIX9xRjIVa2ZcCAgfQBIGo+O4xXEkTBqcaF9nf6qRwrMfy7hvE7katRb6braieeTFrDZO4QwnmheBT3RMk/9sBEXjFGhdJHpf4FQHkKtTpimlyTVHlSR+B2NWrzQK4id18ZwsVihusyPwbM73Uu9o+3vZMCdM15tNQBwsUpmYIRzD3wcnVAD/VJBr3JoRSSjBmz6nKpMvjc1ZtBADjqUWdjO+aDLxS+AM0sfH8i0ivmSIZqUekf6wuMYHTMBMGCSqGSIb3DQEJFTEGBAQBAAAAMF0GCSqGSIb3DQEJFDFQHk4AdABlAC0ANQBiAGIANwA5ADIAYgA5AC0AOAA5AGIANAAtADQAYgBmADAALQA4ADcAZAA0AC0ANgBjADkAZQBhADQANwA3ADAAYgA5ADkwXQYJKwYBBAGCNxEBMVAeTgBNAGkAYwByAG8AcwBvAGYAdAAgAFMAbwBmAHQAdwBhAHIAZQAgAEsAZQB5ACAAUwB0AG8AcgBhAGcAZQAgAFAAcgBvAHYAaQBkAGUAcjCCAm8GCSqGSIb3DQEHBqCCAmAwggJcAgEAMIICVQYJKoZIhvcNAQcBMBwGCiqGSIb3DQEMAQMwDgQIOd7DHkPXTdwCAgfQgIICKAGcaQokoScTUhpYGZvp5i78HCicnc5l9YpWqhDBMMFhQDhziIdu2Kd0Rc9eprukunrcsbWiH2N8Ag6RgyPZwSgdKJF/oHMQ5L40KzOl1i7c+Uz+PfOfPTRGSqNpTVVm7d2/C8XfZFpDFUugNkY+NknFEvODEPtVTsXc6LB/Tjdr4o8ypt+ZKtKLfFD8n0mo1gX6A694cjLE89vHKUMsF1zito8My8k9Z6fakaXv92GlpC1Jro/gTp2TPAfp166F7pUQrd4jQuDZhKId4GeXwi9Ggn4KxvGpuOW0dJdtR+lNNLPh2AnsGXyL3gYCsHiLKGz3bAvMql9Lee12BErVf/7iYG3XDtx8i4xLzTJm6l8CwoUuLh8XCcBLmYxnBGHXhBfHNoFri+OiO/IHRZpMkDws5fnzT5VjTZ0umuJKbLmgdh4j465IcZUKSvSPxon13fyC5wxZZHD4W3XCP9lTEtFxsUkYfn6j3HNrfq+4zclr7zjPnyGOxD3V0B3oGn8xzzXoyVbgaxrWRvFQPau1mEdTLlSbKkHQIkI1qYlTGjbX5BTXt3vPo3juThe5O47WpRLp8lmFTrVIv/qvcQ3pBlVJaYhtijGxJOMH8Qii4dB3Ru/4w+u54UzzFAepPLJbn5fwnw3Lw6+gaiUyxRUmykB4tLjpFBQd1BIEdpKpzS0aT4Q68YScOGQdEDvPibimdlhcXabdNAEvX5Hv2yRE8gNMc8l52f8ckTA7MB8wBwYFKw4DAhoEFJRQSVRoIwasJHhxXd4V2H5b9OvaBBQs4phgMd4xS41WD/LsCBhxV2AhRgICB9A="; + public const string DefaultX509Data_256ECDSA_Public = "MIIBujCCAV+gAwIBAgIQQ6xJuTdhTpFKGAJNoeAXNTAKBggqhkjOPQQDAjAiMSAwHgYDVQQDDBdLZXlTdG9yZVRlc3RDZXJ0aWZpY2F0ZTAeFw0yNDA3MDIwNTIyNDdaFw0yNTA3MDIwNTQyNDdaMCIxIDAeBgNVBAMMF0tleVN0b3JlVGVzdENlcnRpZmljYXRlMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE9+coKp9Bai6DHq5f9FCSBTizhlZDp4hY1E98AG9YGZIt/8SPRaZzKIe6JKcqT/PaOywh0MAwtNDglttAa+Tr8KN3MHUwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAlBgNVHREEHjAcghpDTj1LZXlTdG9yZVRlc3RDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUjmT0SStRinfVGLKXtQXPf2dRiuYwCgYIKoZIzj0EAwIDSQAwRgIhAKhS2I54EALm367IuKHE1P44TNWOqGphLUfwj6e/HwUNAiEAmOzj//RrjFauhxGLn50Fn8M05Y1KmNtP5UGHytaPEsE="; + public static string DefaultX509Key_256ECDSA_KeyId = "DefaultX509Key_256ECDSA_KeyId"; + public static string DefaultX509Key_256ECDSA_Thumbprint = "CEE96753ACDF7BBE12F61FD59BE9521482B566D8"; public static X509Certificate2 DefaultCert_256ECDSA = new X509Certificate2(Convert.FromBase64String(DefaultX509Data_256ECDSA), CertPassword, X509KeyStorageFlags.Exportable); + public static X509Certificate2 DefaultCert_256ECDSA_Public = new X509Certificate2(Convert.FromBase64String(DefaultX509Data_256ECDSA_Public), CertPassword, X509KeyStorageFlags.Exportable); + public static X509SecurityKey DefaultX509Key_256ECDSA = new X509SecurityKey(DefaultCert_256ECDSA); + public static X509SecurityKey DefaultX509Key_256ECDSA_With_KeyId = new X509SecurityKey(DefaultCert_256ECDSA) { KeyId = DefaultX509Key_256ECDSA_KeyId }; + public static X509SecurityKey DefaultX509Key_256ECDSA_Public = new X509SecurityKey(DefaultCert_256ECDSA_Public); + public static X509SecurityKey DefaultX509Key_256ECDSA_Public_With_KeyId = new X509SecurityKey(DefaultCert_256ECDSA_Public) { KeyId = DefaultX509Key_256ECDSA_KeyId }; public static string DefaultX509Data_2048_Public = @"MIICyjCCAbKgAwIBAgIQJPMYqnyiTY1GQYAwZxadMjANBgkqhkiG9w0BAQsFADAhMR8wHQYDVQQDExZBREZTIFNpZ25pbmcgLSBTVFMuY29tMB4XDTEyMTAwOTIyMTA0OVoXDTEzMTAwOTIyMTA0OVowITEfMB0GA1UEAxMWQURGUyBTaWduaW5nIC0gU1RTLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMmeVPJz8o7ayB3AS2dJtsIo/eXqeNhZ+ZqEJgHVHc0JAAgNNwR++moMt8+iIlOKZiAL8dvQBKOuPms+FfqrG1HshnMiLcuadtWUqOntxUdyQLcEKvdaFOqOppqmasqGFtRLPwYKIkZOkj8ikndNzI6PZV46mw18nLaN6rTByMnjVA5n9Lf7Cdu7lmxlKGJOI5F0IfeaW68/kY1bdw3KAEb1aOKHj0r7RJ2joRuHJ+96kw1bA2T6bGC/1LYND3DFsnQQtMBl7LlDrSG1gGoiZxCoQmPCxfrTCrYKGK6y9j6IQ4MCmJpnt0l/INL5i88TjctF4IkJwbJGn9iY2fIIBxMCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAq/SyHGCLpBm+Gmh5I7BAWJXvtPaIelt30WgKVXRHccxRVIYpKOfAA2iPuD/CVruFz6pnP4K7o2KLAs+XJptigYzLEjKw6rY4836ZJC8m5kfBVanu45OW39nxzxp1udbxQ5gAdmvnY/2agpFhCFR8M1BtWON6G3SzHwo2dXHh+ettOO2LtK38e1+Uy+KGowRw/m4gprSIvgN3AAo7e0PnFblZn6vRgMsK60QB5D8f+Kxdg2I3ZGQcPBQI2fpjEDQCZVc2LV4ywPX4QDPfmYjn+1IaU9w7unbh+oUGQsrdKw3gsdzWEsX/IMXTDf46FEOjV+JqE7VilzcNuDcQ0x9K8gAA"; public static X509Certificate2 DefaultCert_2048_Public @@ -217,7 +225,6 @@ public static RsaSecurityKey RsaSecurityKey2 public static readonly ECDsaSecurityKey Ecdsa521Key_Public; // SymmetricKeys - public static string DefaultSymmetricKeyEncoded_56 = "bd0Q+Z6Ydw=="; public static byte[] DefaultSymmetricKeyBytes_56 = Convert.FromBase64String(DefaultSymmetricKeyEncoded_56); public static SymmetricSecurityKey DefaultSymmetricSecurityKey_56 = new SymmetricSecurityKey(DefaultSymmetricKeyBytes_56) { KeyId = "DefaultSymmetricSecurityKey_56" }; @@ -1060,6 +1067,80 @@ public static JsonWebKey JsonWebKeyX509_2048_As_RSA_With_KeyId } } +#if NET472 || NET_CORE + public static JsonWebKey JsonWebKeyX509_256ECDSA + { + get + { + var jsonWebKey = new JsonWebKey + { + Kty = JsonWebAlgorithmsKeyTypes.EllipticCurve, + Kid = DefaultX509Key_256ECDSA_Thumbprint, + X5t = Base64UrlEncoder.Encode(DefaultCert_256ECDSA.GetCertHash()) + }; + + jsonWebKey.X5c.Add(Convert.ToBase64String(DefaultCert_256ECDSA.RawData)); + return jsonWebKey; + } + } + + public static JsonWebKey JsonWebKeyX509_256ECDSA_With_KeyId + { + get + { + var jsonWebKey = new JsonWebKey + { + Kty = JsonWebAlgorithmsKeyTypes.EllipticCurve, + Kid = DefaultX509Key_256ECDSA_KeyId, + X5t = Base64UrlEncoder.Encode(DefaultCert_256ECDSA.GetCertHash()) + }; + + jsonWebKey.X5c.Add(Convert.ToBase64String(DefaultCert_256ECDSA.RawData)); + return jsonWebKey; + } + } + + public static JsonWebKey JsonWebKeyX509_256ECDSA_As_ECDSA_With_KeyId_Public + { + get + { + var ecdsa = DefaultX509Key_256ECDSA_Public_With_KeyId.PublicKey as ECDsa; + var ecParams = ecdsa.ExportParameters(false); + + var jsonWebKey = new JsonWebKey + { + Kty = JsonWebAlgorithmsKeyTypes.EllipticCurve, + Kid = DefaultX509Key_256ECDSA_KeyId, + Crv = JsonWebKeyECTypes.P256, + X = Base64UrlEncoder.Encode(ecParams.Q.X), + Y = Base64UrlEncoder.Encode(ecParams.Q.Y), + }; + + return jsonWebKey; + } + } + + public static JsonWebKey JsonWebKeyX509_256ECDSA_As_ECDSA_With_KeyId + { + get + { + var ecdsa = DefaultX509Key_256ECDSA_With_KeyId.PrivateKey as ECDsa; + var ecParams = ecdsa.ExportParameters(true); + + var jsonWebKey = new JsonWebKey + { + Kty = JsonWebAlgorithmsKeyTypes.EllipticCurve, + Kid = DefaultX509Key_256ECDSA_KeyId, + Crv = JsonWebKeyECTypes.P256, + D = Base64UrlEncoder.Encode(ecParams.D), + X = Base64UrlEncoder.Encode(ecParams.Q.X), + Y = Base64UrlEncoder.Encode(ecParams.Q.Y), + }; + + return jsonWebKey; + } + } +#endif private static SecureString ConvertToSecureString(string password) { if (password == null) From 6676f8c7fd84bde9001de7fab2f76d1c86fe10a2 Mon Sep 17 00:00:00 2001 From: joegoldman2 <147369450+joegoldman@users.noreply.github.com> Date: Wed, 3 Jul 2024 03:34:54 +0000 Subject: [PATCH 5/8] Remove use of self-signed certificate --- .../KeyingMaterial.cs | 31 ++++++++++--------- .../JsonWebKeyConverterTest.cs | 10 +++--- 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/test/Microsoft.IdentityModel.TestUtils/KeyingMaterial.cs b/test/Microsoft.IdentityModel.TestUtils/KeyingMaterial.cs index 8f80da259d..4eaaf63e30 100644 --- a/test/Microsoft.IdentityModel.TestUtils/KeyingMaterial.cs +++ b/test/Microsoft.IdentityModel.TestUtils/KeyingMaterial.cs @@ -99,16 +99,11 @@ static public class KeyingMaterial public static X509Certificate2 DefaultAsymmetricCert_2048 = new X509Certificate2(Convert.FromBase64String(DefaultX509Data_2048), CertPassword, X509KeyStorageFlags.MachineKeySet); // 256 bit ECDSA - public const string DefaultX509Data_256ECDSA = "MIIEnwIBAzCCBFsGCSqGSIb3DQEHAaCCBEwEggRIMIIERDCCAc0GCSqGSIb3DQEHAaCCAb4EggG6MIIBtjCCAbIGCyqGSIb3DQEMCgECoIHMMIHJMBwGCiqGSIb3DQEMAQMwDgQIX9xRjIVa2ZcCAgfQBIGo+O4xXEkTBqcaF9nf6qRwrMfy7hvE7katRb6braieeTFrDZO4QwnmheBT3RMk/9sBEXjFGhdJHpf4FQHkKtTpimlyTVHlSR+B2NWrzQK4id18ZwsVihusyPwbM73Uu9o+3vZMCdM15tNQBwsUpmYIRzD3wcnVAD/VJBr3JoRSSjBmz6nKpMvjc1ZtBADjqUWdjO+aDLxS+AM0sfH8i0ivmSIZqUekf6wuMYHTMBMGCSqGSIb3DQEJFTEGBAQBAAAAMF0GCSqGSIb3DQEJFDFQHk4AdABlAC0ANQBiAGIANwA5ADIAYgA5AC0AOAA5AGIANAAtADQAYgBmADAALQA4ADcAZAA0AC0ANgBjADkAZQBhADQANwA3ADAAYgA5ADkwXQYJKwYBBAGCNxEBMVAeTgBNAGkAYwByAG8AcwBvAGYAdAAgAFMAbwBmAHQAdwBhAHIAZQAgAEsAZQB5ACAAUwB0AG8AcgBhAGcAZQAgAFAAcgBvAHYAaQBkAGUAcjCCAm8GCSqGSIb3DQEHBqCCAmAwggJcAgEAMIICVQYJKoZIhvcNAQcBMBwGCiqGSIb3DQEMAQMwDgQIOd7DHkPXTdwCAgfQgIICKAGcaQokoScTUhpYGZvp5i78HCicnc5l9YpWqhDBMMFhQDhziIdu2Kd0Rc9eprukunrcsbWiH2N8Ag6RgyPZwSgdKJF/oHMQ5L40KzOl1i7c+Uz+PfOfPTRGSqNpTVVm7d2/C8XfZFpDFUugNkY+NknFEvODEPtVTsXc6LB/Tjdr4o8ypt+ZKtKLfFD8n0mo1gX6A694cjLE89vHKUMsF1zito8My8k9Z6fakaXv92GlpC1Jro/gTp2TPAfp166F7pUQrd4jQuDZhKId4GeXwi9Ggn4KxvGpuOW0dJdtR+lNNLPh2AnsGXyL3gYCsHiLKGz3bAvMql9Lee12BErVf/7iYG3XDtx8i4xLzTJm6l8CwoUuLh8XCcBLmYxnBGHXhBfHNoFri+OiO/IHRZpMkDws5fnzT5VjTZ0umuJKbLmgdh4j465IcZUKSvSPxon13fyC5wxZZHD4W3XCP9lTEtFxsUkYfn6j3HNrfq+4zclr7zjPnyGOxD3V0B3oGn8xzzXoyVbgaxrWRvFQPau1mEdTLlSbKkHQIkI1qYlTGjbX5BTXt3vPo3juThe5O47WpRLp8lmFTrVIv/qvcQ3pBlVJaYhtijGxJOMH8Qii4dB3Ru/4w+u54UzzFAepPLJbn5fwnw3Lw6+gaiUyxRUmykB4tLjpFBQd1BIEdpKpzS0aT4Q68YScOGQdEDvPibimdlhcXabdNAEvX5Hv2yRE8gNMc8l52f8ckTA7MB8wBwYFKw4DAhoEFJRQSVRoIwasJHhxXd4V2H5b9OvaBBQs4phgMd4xS41WD/LsCBhxV2AhRgICB9A="; - public const string DefaultX509Data_256ECDSA_Public = "MIIBujCCAV+gAwIBAgIQQ6xJuTdhTpFKGAJNoeAXNTAKBggqhkjOPQQDAjAiMSAwHgYDVQQDDBdLZXlTdG9yZVRlc3RDZXJ0aWZpY2F0ZTAeFw0yNDA3MDIwNTIyNDdaFw0yNTA3MDIwNTQyNDdaMCIxIDAeBgNVBAMMF0tleVN0b3JlVGVzdENlcnRpZmljYXRlMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE9+coKp9Bai6DHq5f9FCSBTizhlZDp4hY1E98AG9YGZIt/8SPRaZzKIe6JKcqT/PaOywh0MAwtNDglttAa+Tr8KN3MHUwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAlBgNVHREEHjAcghpDTj1LZXlTdG9yZVRlc3RDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUjmT0SStRinfVGLKXtQXPf2dRiuYwCgYIKoZIzj0EAwIDSQAwRgIhAKhS2I54EALm367IuKHE1P44TNWOqGphLUfwj6e/HwUNAiEAmOzj//RrjFauhxGLn50Fn8M05Y1KmNtP5UGHytaPEsE="; + public static X509Certificate2 DefaultCert_256ECDSA; + public static string DefaultX509Key_256ECDSA_Thumbprint; public static string DefaultX509Key_256ECDSA_KeyId = "DefaultX509Key_256ECDSA_KeyId"; - public static string DefaultX509Key_256ECDSA_Thumbprint = "CEE96753ACDF7BBE12F61FD59BE9521482B566D8"; - public static X509Certificate2 DefaultCert_256ECDSA = new X509Certificate2(Convert.FromBase64String(DefaultX509Data_256ECDSA), CertPassword, X509KeyStorageFlags.Exportable); - public static X509Certificate2 DefaultCert_256ECDSA_Public = new X509Certificate2(Convert.FromBase64String(DefaultX509Data_256ECDSA_Public), CertPassword, X509KeyStorageFlags.Exportable); - public static X509SecurityKey DefaultX509Key_256ECDSA = new X509SecurityKey(DefaultCert_256ECDSA); - public static X509SecurityKey DefaultX509Key_256ECDSA_With_KeyId = new X509SecurityKey(DefaultCert_256ECDSA) { KeyId = DefaultX509Key_256ECDSA_KeyId }; - public static X509SecurityKey DefaultX509Key_256ECDSA_Public = new X509SecurityKey(DefaultCert_256ECDSA_Public); - public static X509SecurityKey DefaultX509Key_256ECDSA_Public_With_KeyId = new X509SecurityKey(DefaultCert_256ECDSA_Public) { KeyId = DefaultX509Key_256ECDSA_KeyId }; + public static X509SecurityKey DefaultX509Key_256ECDSA; + public static X509SecurityKey DefaultX509Key_256ECDSA_With_KeyId; public static string DefaultX509Data_2048_Public = @"MIICyjCCAbKgAwIBAgIQJPMYqnyiTY1GQYAwZxadMjANBgkqhkiG9w0BAQsFADAhMR8wHQYDVQQDExZBREZTIFNpZ25pbmcgLSBTVFMuY29tMB4XDTEyMTAwOTIyMTA0OVoXDTEzMTAwOTIyMTA0OVowITEfMB0GA1UEAxMWQURGUyBTaWduaW5nIC0gU1RTLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMmeVPJz8o7ayB3AS2dJtsIo/eXqeNhZ+ZqEJgHVHc0JAAgNNwR++moMt8+iIlOKZiAL8dvQBKOuPms+FfqrG1HshnMiLcuadtWUqOntxUdyQLcEKvdaFOqOppqmasqGFtRLPwYKIkZOkj8ikndNzI6PZV46mw18nLaN6rTByMnjVA5n9Lf7Cdu7lmxlKGJOI5F0IfeaW68/kY1bdw3KAEb1aOKHj0r7RJ2joRuHJ+96kw1bA2T6bGC/1LYND3DFsnQQtMBl7LlDrSG1gGoiZxCoQmPCxfrTCrYKGK6y9j6IQ4MCmJpnt0l/INL5i88TjctF4IkJwbJGn9iY2fIIBxMCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAq/SyHGCLpBm+Gmh5I7BAWJXvtPaIelt30WgKVXRHccxRVIYpKOfAA2iPuD/CVruFz6pnP4K7o2KLAs+XJptigYzLEjKw6rY4836ZJC8m5kfBVanu45OW39nxzxp1udbxQ5gAdmvnY/2agpFhCFR8M1BtWON6G3SzHwo2dXHh+ettOO2LtK38e1+Uy+KGowRw/m4gprSIvgN3AAo7e0PnFblZn6vRgMsK60QB5D8f+Kxdg2I3ZGQcPBQI2fpjEDQCZVc2LV4ywPX4QDPfmYjn+1IaU9w7unbh+oUGQsrdKw3gsdzWEsX/IMXTDf46FEOjV+JqE7VilzcNuDcQ0x9K8gAA"; public static X509Certificate2 DefaultCert_2048_Public @@ -513,6 +508,11 @@ static KeyingMaterial() Ecdsa256Key_Public = new ECDsaSecurityKey(Ecdsa256_Public) { KeyId = "ECDsa256Key_Public" }; Ecdsa384Key_Public = new ECDsaSecurityKey(Ecdsa384_Public) { KeyId = "ECDsa384Key_Public" }; Ecdsa521Key_Public = new ECDsaSecurityKey(Ecdsa521_Public) { KeyId = "ECDsa521Key_Public" }; + + DefaultCert_256ECDSA = new CertificateRequest("CN=KeyStoreTestCertificate", Ecdsa256, HashAlgorithmName.SHA256).CreateSelfSigned(notBefore: DateTimeOffset.UtcNow, notAfter: DateTimeOffset.UtcNow.AddHours(1)); + DefaultX509Key_256ECDSA_Thumbprint = DefaultCert_256ECDSA.Thumbprint; + DefaultX509Key_256ECDSA = new X509SecurityKey(DefaultCert_256ECDSA); + DefaultX509Key_256ECDSA_With_KeyId = new X509SecurityKey(DefaultCert_256ECDSA) { KeyId = DefaultX509Key_256ECDSA_KeyId }; #endif } @@ -1100,20 +1100,21 @@ public static JsonWebKey JsonWebKeyX509_256ECDSA_With_KeyId } } - public static JsonWebKey JsonWebKeyX509_256ECDSA_As_ECDSA_With_KeyId_Public + public static JsonWebKey JsonWebKeyX509_256ECDSA_As_ECDSA { get { - var ecdsa = DefaultX509Key_256ECDSA_Public_With_KeyId.PublicKey as ECDsa; - var ecParams = ecdsa.ExportParameters(false); + var ecdsa = DefaultX509Key_256ECDSA.PrivateKey as ECDsa; + var ecParams = ecdsa.ExportParameters(true); var jsonWebKey = new JsonWebKey { Kty = JsonWebAlgorithmsKeyTypes.EllipticCurve, - Kid = DefaultX509Key_256ECDSA_KeyId, + Kid = DefaultX509Key_256ECDSA_Thumbprint, Crv = JsonWebKeyECTypes.P256, + D = Base64UrlEncoder.Encode(ecParams.D), X = Base64UrlEncoder.Encode(ecParams.Q.X), - Y = Base64UrlEncoder.Encode(ecParams.Q.Y), + Y = Base64UrlEncoder.Encode(ecParams.Q.Y) }; return jsonWebKey; @@ -1134,7 +1135,7 @@ public static JsonWebKey JsonWebKeyX509_256ECDSA_As_ECDSA_With_KeyId Crv = JsonWebKeyECTypes.P256, D = Base64UrlEncoder.Encode(ecParams.D), X = Base64UrlEncoder.Encode(ecParams.Q.X), - Y = Base64UrlEncoder.Encode(ecParams.Q.Y), + Y = Base64UrlEncoder.Encode(ecParams.Q.Y) }; return jsonWebKey; diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/JsonWebKeyConverterTest.cs b/test/Microsoft.IdentityModel.Tokens.Tests/JsonWebKeyConverterTest.cs index 79d08935e3..98e523602d 100644 --- a/test/Microsoft.IdentityModel.Tokens.Tests/JsonWebKeyConverterTest.cs +++ b/test/Microsoft.IdentityModel.Tokens.Tests/JsonWebKeyConverterTest.cs @@ -226,18 +226,18 @@ public static TheoryData ConvertX509SecurityKeyTo theoryData.Add(new JsonWebKeyConverterTheoryData { - SecurityKey = KeyingMaterial.DefaultX509Key_256ECDSA_Public_With_KeyId, + SecurityKey = KeyingMaterial.DefaultX509Key_256ECDSA, RepresentAsRsaKey = true, - JsonWebKey = KeyingMaterial.JsonWebKeyX509_256ECDSA_As_ECDSA_With_KeyId_Public, - TestId = nameof(KeyingMaterial.DefaultX509Key_256ECDSA_Public) + nameof(JsonWebKeyConverterTheoryData.RepresentAsRsaKey) + JsonWebKey = KeyingMaterial.JsonWebKeyX509_256ECDSA_As_ECDSA, + TestId = nameof(KeyingMaterial.DefaultX509Key_256ECDSA_With_KeyId) + nameof(JsonWebKeyConverterTheoryData.RepresentAsRsaKey) }); theoryData.Add(new JsonWebKeyConverterTheoryData { - SecurityKey = KeyingMaterial.DefaultX509Key_256ECDSA, + SecurityKey = KeyingMaterial.DefaultX509Key_256ECDSA_With_KeyId, RepresentAsRsaKey = true, JsonWebKey = KeyingMaterial.JsonWebKeyX509_256ECDSA_As_ECDSA_With_KeyId, - TestId = nameof(KeyingMaterial.DefaultX509Key_256ECDSA) + TestId = nameof(KeyingMaterial.DefaultX509Key_256ECDSA) + nameof(JsonWebKeyConverterTheoryData.RepresentAsRsaKey) }); #endif return theoryData; From 4fbfb2243b6dcd41cbe35768bfc6fcdae17a970a Mon Sep 17 00:00:00 2001 From: joegoldman2 <147369450+joegoldman@users.noreply.github.com> Date: Wed, 3 Jul 2024 03:39:25 +0000 Subject: [PATCH 6/8] Change order for validation --- .../JsonWebKeyConverter.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Microsoft.IdentityModel.Tokens/JsonWebKeyConverter.cs b/src/Microsoft.IdentityModel.Tokens/JsonWebKeyConverter.cs index 2388fd9fac..28673795bb 100644 --- a/src/Microsoft.IdentityModel.Tokens/JsonWebKeyConverter.cs +++ b/src/Microsoft.IdentityModel.Tokens/JsonWebKeyConverter.cs @@ -130,12 +130,12 @@ public static JsonWebKey ConvertFromX509SecurityKey(X509SecurityKey key) /// if is null. public static JsonWebKey ConvertFromX509SecurityKey(X509SecurityKey key, bool representAsRsaKey) { - if (!representAsRsaKey) - return ConvertFromX509SecurityKey(key); - if (key == null) throw LogHelper.LogArgumentNullException(nameof(key)); + if (!representAsRsaKey) + return ConvertFromX509SecurityKey(key); + if (key.PrivateKeyStatus == PrivateKeyStatus.Exists) { if (key.PrivateKey is RSA rsaPrivateKey) @@ -192,15 +192,15 @@ public static JsonWebKey ConvertFromSymmetricSecurityKey(SymmetricSecurityKey ke /// if is null. public static JsonWebKey ConvertFromECDsaSecurityKey(ECDsaSecurityKey key) { - if (!ECDsaAdapter.SupportsECParameters()) - throw LogHelper.LogExceptionMessage(new PlatformNotSupportedException(LogMessages.IDX10695)); - if (key == null) throw LogHelper.LogArgumentNullException(nameof(key)); if (key.ECDsa == null) throw LogHelper.LogArgumentNullException(nameof(key.ECDsa)); + if (!ECDsaAdapter.SupportsECParameters()) + throw LogHelper.LogExceptionMessage(new PlatformNotSupportedException(LogMessages.IDX10695)); + ECParameters parameters; try { From b920682956841e9b576c0151d9194d601ba559fc Mon Sep 17 00:00:00 2001 From: joegoldman2 <147369450+joegoldman@users.noreply.github.com> Date: Wed, 3 Jul 2024 04:43:11 +0000 Subject: [PATCH 7/8] Add condition for .NET 4.7.2 or NET --- test/Microsoft.IdentityModel.TestUtils/KeyingMaterial.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/Microsoft.IdentityModel.TestUtils/KeyingMaterial.cs b/test/Microsoft.IdentityModel.TestUtils/KeyingMaterial.cs index 4eaaf63e30..a2b959c966 100644 --- a/test/Microsoft.IdentityModel.TestUtils/KeyingMaterial.cs +++ b/test/Microsoft.IdentityModel.TestUtils/KeyingMaterial.cs @@ -98,12 +98,14 @@ static public class KeyingMaterial public static SigningCredentials DefaultX509SigningCreds_2048_RsaSha2_Sha2 = new SigningCredentials(DefaultX509Key_2048, SecurityAlgorithms.RsaSha256Signature, SecurityAlgorithms.Sha256Digest); public static X509Certificate2 DefaultAsymmetricCert_2048 = new X509Certificate2(Convert.FromBase64String(DefaultX509Data_2048), CertPassword, X509KeyStorageFlags.MachineKeySet); +#if NET472 || NET_CORE // 256 bit ECDSA public static X509Certificate2 DefaultCert_256ECDSA; public static string DefaultX509Key_256ECDSA_Thumbprint; public static string DefaultX509Key_256ECDSA_KeyId = "DefaultX509Key_256ECDSA_KeyId"; public static X509SecurityKey DefaultX509Key_256ECDSA; public static X509SecurityKey DefaultX509Key_256ECDSA_With_KeyId; +#endif public static string DefaultX509Data_2048_Public = @"MIICyjCCAbKgAwIBAgIQJPMYqnyiTY1GQYAwZxadMjANBgkqhkiG9w0BAQsFADAhMR8wHQYDVQQDExZBREZTIFNpZ25pbmcgLSBTVFMuY29tMB4XDTEyMTAwOTIyMTA0OVoXDTEzMTAwOTIyMTA0OVowITEfMB0GA1UEAxMWQURGUyBTaWduaW5nIC0gU1RTLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMmeVPJz8o7ayB3AS2dJtsIo/eXqeNhZ+ZqEJgHVHc0JAAgNNwR++moMt8+iIlOKZiAL8dvQBKOuPms+FfqrG1HshnMiLcuadtWUqOntxUdyQLcEKvdaFOqOppqmasqGFtRLPwYKIkZOkj8ikndNzI6PZV46mw18nLaN6rTByMnjVA5n9Lf7Cdu7lmxlKGJOI5F0IfeaW68/kY1bdw3KAEb1aOKHj0r7RJ2joRuHJ+96kw1bA2T6bGC/1LYND3DFsnQQtMBl7LlDrSG1gGoiZxCoQmPCxfrTCrYKGK6y9j6IQ4MCmJpnt0l/INL5i88TjctF4IkJwbJGn9iY2fIIBxMCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAq/SyHGCLpBm+Gmh5I7BAWJXvtPaIelt30WgKVXRHccxRVIYpKOfAA2iPuD/CVruFz6pnP4K7o2KLAs+XJptigYzLEjKw6rY4836ZJC8m5kfBVanu45OW39nxzxp1udbxQ5gAdmvnY/2agpFhCFR8M1BtWON6G3SzHwo2dXHh+ettOO2LtK38e1+Uy+KGowRw/m4gprSIvgN3AAo7e0PnFblZn6vRgMsK60QB5D8f+Kxdg2I3ZGQcPBQI2fpjEDQCZVc2LV4ywPX4QDPfmYjn+1IaU9w7unbh+oUGQsrdKw3gsdzWEsX/IMXTDf46FEOjV+JqE7VilzcNuDcQ0x9K8gAA"; public static X509Certificate2 DefaultCert_2048_Public From 9ea0c2dc50dca400975cd9391e33a6535304e408 Mon Sep 17 00:00:00 2001 From: joegoldman2 <147369450+joegoldman@users.noreply.github.com> Date: Sat, 17 Aug 2024 11:41:00 +0000 Subject: [PATCH 8/8] Fix unit tests --- test/Microsoft.IdentityModel.TestUtils/KeyingMaterial.cs | 1 - .../JsonWebKeyConverterTest.cs | 5 ++--- .../X509SecurityKeyTests.cs | 2 ++ 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test/Microsoft.IdentityModel.TestUtils/KeyingMaterial.cs b/test/Microsoft.IdentityModel.TestUtils/KeyingMaterial.cs index a2b959c966..17c5a94bc5 100644 --- a/test/Microsoft.IdentityModel.TestUtils/KeyingMaterial.cs +++ b/test/Microsoft.IdentityModel.TestUtils/KeyingMaterial.cs @@ -516,7 +516,6 @@ static KeyingMaterial() DefaultX509Key_256ECDSA = new X509SecurityKey(DefaultCert_256ECDSA); DefaultX509Key_256ECDSA_With_KeyId = new X509SecurityKey(DefaultCert_256ECDSA) { KeyId = DefaultX509Key_256ECDSA_KeyId }; #endif - } #if NET462 diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/JsonWebKeyConverterTest.cs b/test/Microsoft.IdentityModel.Tokens.Tests/JsonWebKeyConverterTest.cs index 2ebdc8d424..bee08cdbec 100644 --- a/test/Microsoft.IdentityModel.Tokens.Tests/JsonWebKeyConverterTest.cs +++ b/test/Microsoft.IdentityModel.Tokens.Tests/JsonWebKeyConverterTest.cs @@ -63,9 +63,8 @@ public void ConvertX509SecurityKeyAsRsaSecurityKeyToJsonWebKey(JsonWebKeyConvert theoryData.ExpectedException.ProcessNoException(context); IdentityComparer.AreEqual(convertedKey, theoryData.JsonWebKey, context); - //var expectedConvertedKeyType = theoryData.RepresentAsRsaKey == true ? typeof(RsaSecurityKey) : typeof(X509SecurityKey); - //if (convertedKey.ConvertedSecurityKey.GetType() != expectedConvertedKeyType) - //context.AddDiff($"convertedKey.ConvertedSecurityKey.GetType(): '{convertedKey.ConvertedSecurityKey.GetType()}' != expectedConvertedKeyType: '{expectedConvertedKeyType}'."); + if (!theoryData.RepresentAsRsaKey && convertedKey.ConvertedSecurityKey.GetType() != typeof(X509SecurityKey)) + context.AddDiff($"convertedKey.ConvertedSecurityKey.GetType() should be {typeof(X509SecurityKey)}."); } catch (Exception ex) { diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/X509SecurityKeyTests.cs b/test/Microsoft.IdentityModel.Tokens.Tests/X509SecurityKeyTests.cs index b77220606d..e1405b378f 100644 --- a/test/Microsoft.IdentityModel.Tokens.Tests/X509SecurityKeyTests.cs +++ b/test/Microsoft.IdentityModel.Tokens.Tests/X509SecurityKeyTests.cs @@ -77,6 +77,7 @@ public void Constructor() TestUtilities.AssertFailIfErrors(context); } +#if NET472 || NET_CORE [Fact] public void Constructor_WithECDsa() { @@ -93,6 +94,7 @@ public void Constructor_WithECDsa() Assert.NotEmpty(x509SecurityKey.ComputeJwkThumbprint()); TestUtilities.AssertFailIfErrors(context); } +#endif [Fact] public void CanComputeJwkThumbprint()