diff --git a/src/System.Security.Cryptography.X509Certificates/ref/System.Security.Cryptography.X509Certificates.cs b/src/System.Security.Cryptography.X509Certificates/ref/System.Security.Cryptography.X509Certificates.cs index 7676b7338db2..3f20423435c1 100644 --- a/src/System.Security.Cryptography.X509Certificates/ref/System.Security.Cryptography.X509Certificates.cs +++ b/src/System.Security.Cryptography.X509Certificates/ref/System.Security.Cryptography.X509Certificates.cs @@ -21,10 +21,10 @@ namespace System.Security.Cryptography.X509Certificates public sealed partial class CertificateRequest { public CertificateRequest(System.Security.Cryptography.X509Certificates.X500DistinguishedName subjectName, System.Security.Cryptography.ECDsa key, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) { } - public CertificateRequest(System.Security.Cryptography.X509Certificates.X500DistinguishedName subjectName, System.Security.Cryptography.RSA key, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) { } + public CertificateRequest(System.Security.Cryptography.X509Certificates.X500DistinguishedName subjectName, System.Security.Cryptography.RSA key, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding) { } public CertificateRequest(System.Security.Cryptography.X509Certificates.X500DistinguishedName subjectName, System.Security.Cryptography.X509Certificates.PublicKey publicKey, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) { } public CertificateRequest(string subjectName, System.Security.Cryptography.ECDsa key, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) { } - public CertificateRequest(string subjectName, System.Security.Cryptography.RSA key, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) { } + public CertificateRequest(string subjectName, System.Security.Cryptography.RSA key, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding) { } public System.Collections.ObjectModel.Collection CertificateExtensions { get { throw null; } } public System.Security.Cryptography.HashAlgorithmName HashAlgorithm { get { throw null; } } public System.Security.Cryptography.X509Certificates.PublicKey PublicKey { get { throw null; } } diff --git a/src/System.Security.Cryptography.X509Certificates/src/Resources/Strings.resx b/src/System.Security.Cryptography.X509Certificates/src/Resources/Strings.resx index 0fbed8111585..46ffbcff7e22 100644 --- a/src/System.Security.Cryptography.X509Certificates/src/Resources/Strings.resx +++ b/src/System.Security.Cryptography.X509Certificates/src/Resources/Strings.resx @@ -106,6 +106,9 @@ The certificate already has an associated private key. + + The issuer certificate public key algorithm ({0}) does not match the value for this certificate request ({1}), use the X509SignatureGenerator overload. + The provided notBefore value is later than the notAfter value. @@ -121,6 +124,9 @@ This method cannot be used since no signing key was provided via a constructor, use an overload accepting an X509SignatureGenerator instead. + + The issuer certificate uses an RSA key but no RSASignaturePadding was provided to a constructor. If one cannot be provided, use the X509SignatureGenerator overload. + Object contains only the public half of a key pair. A private key must also be provided. diff --git a/src/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/CertificateRequest.cs b/src/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/CertificateRequest.cs index a53edac40b19..05d7e403b2e6 100644 --- a/src/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/CertificateRequest.cs +++ b/src/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/CertificateRequest.cs @@ -17,6 +17,7 @@ public sealed class CertificateRequest { private readonly AsymmetricAlgorithm _key; private readonly X509SignatureGenerator _generator; + private readonly RSASignaturePadding _rsaPadding; /// /// The X.500 Distinguished Name to use as the Subject in a created certificate or certificate request. @@ -112,8 +113,11 @@ public CertificateRequest(X500DistinguishedName subjectName, ECDsa key, HashAlgo /// /// The hash algorithm to use when signing the certificate or certificate request. /// + /// + /// The RSA signature padding to apply if self-signing or being signed with an . + /// /// - public CertificateRequest(string subjectName, RSA key, HashAlgorithmName hashAlgorithm) + public CertificateRequest(string subjectName, RSA key, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding) { if (subjectName == null) throw new ArgumentNullException(nameof(subjectName)); @@ -121,11 +125,14 @@ public CertificateRequest(string subjectName, RSA key, HashAlgorithmName hashAlg throw new ArgumentNullException(nameof(key)); if (string.IsNullOrEmpty(hashAlgorithm.Name)) throw new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, nameof(hashAlgorithm)); + if (padding == null) + throw new ArgumentNullException(nameof(padding)); SubjectName = new X500DistinguishedName(subjectName); _key = key; - _generator = X509SignatureGenerator.CreateForRSA(key, RSASignaturePadding.Pkcs1); + _generator = X509SignatureGenerator.CreateForRSA(key, padding); + _rsaPadding = padding; PublicKey = _generator.PublicKey; HashAlgorithm = hashAlgorithm; } @@ -143,7 +150,14 @@ public CertificateRequest(string subjectName, RSA key, HashAlgorithmName hashAlg /// /// The hash algorithm to use when signing the certificate or certificate request. /// - public CertificateRequest(X500DistinguishedName subjectName, RSA key, HashAlgorithmName hashAlgorithm) + /// + /// The RSA signature padding to apply if self-signing or being signed with an . + /// + public CertificateRequest( + X500DistinguishedName subjectName, + RSA key, + HashAlgorithmName hashAlgorithm, + RSASignaturePadding padding) { if (subjectName == null) throw new ArgumentNullException(nameof(subjectName)); @@ -151,11 +165,14 @@ public CertificateRequest(X500DistinguishedName subjectName, RSA key, HashAlgori throw new ArgumentNullException(nameof(key)); if (string.IsNullOrEmpty(hashAlgorithm.Name)) throw new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, nameof(hashAlgorithm)); + if (padding == null) + throw new ArgumentNullException(nameof(padding)); SubjectName = subjectName; _key = key; - _generator = X509SignatureGenerator.CreateForRSA(key, RSASignaturePadding.Pkcs1); + _generator = X509SignatureGenerator.CreateForRSA(key, padding); + _rsaPadding = padding; PublicKey = _generator.PublicKey; HashAlgorithm = hashAlgorithm; } @@ -354,6 +371,13 @@ public X509Certificate2 CreateSelfSigned(DateTimeOffset notBefore, DateTimeOffse /// represents a date and time before . /// /// is null or has length 0. + /// + /// has a different key algorithm than the requested certificate. + /// + /// + /// is an RSA certificate and this object was created via a constructor + /// which does not accept a value. + /// public X509Certificate2 Create( X509Certificate2 issuerCertificate, DateTimeOffset notBefore, @@ -365,6 +389,16 @@ public X509Certificate2 Create( if (!issuerCertificate.HasPrivateKey) throw new ArgumentException(SR.Cryptography_CertReq_IssuerRequiresPrivateKey, nameof(issuerCertificate)); + if (issuerCertificate.PublicKey.Oid.Value != PublicKey.Oid.Value) + { + throw new ArgumentException( + SR.Format( + SR.Cryptography_CertReq_AlgorithmMustMatch, + issuerCertificate.PublicKey.Oid.Value, + PublicKey.Oid.Value), + nameof(issuerCertificate)); + } + AsymmetricAlgorithm key = null; string keyAlgorithm = issuerCertificate.GetKeyAlgorithm(); X509SignatureGenerator generator; @@ -374,9 +408,14 @@ public X509Certificate2 Create( switch (keyAlgorithm) { case Oids.RsaRsa: + if (_rsaPadding == null) + { + throw new InvalidOperationException(SR.Cryptography_CertReq_RSAPaddingRequired); + } + RSA rsa = issuerCertificate.GetRSAPrivateKey(); key = rsa; - generator = X509SignatureGenerator.CreateForRSA(rsa, RSASignaturePadding.Pkcs1); + generator = X509SignatureGenerator.CreateForRSA(rsa, _rsaPadding); break; case Oids.Ecc: ECDsa ecdsa = issuerCertificate.GetECDsaPrivateKey(); diff --git a/src/System.Security.Cryptography.X509Certificates/tests/CertificateCreation/CertificateRequestApiTests.cs b/src/System.Security.Cryptography.X509Certificates/tests/CertificateCreation/CertificateRequestApiTests.cs index 066f991cf9e2..8967724ed1fe 100644 --- a/src/System.Security.Cryptography.X509Certificates/tests/CertificateCreation/CertificateRequestApiTests.cs +++ b/src/System.Security.Cryptography.X509Certificates/tests/CertificateCreation/CertificateRequestApiTests.cs @@ -42,7 +42,7 @@ public static void SelfSign_ArgumentValidation() { rsa.ImportParameters(TestData.RsaBigExponentParams); - CertificateRequest request = new CertificateRequest("CN=Test", rsa, HashAlgorithmName.SHA256); + var request = new CertificateRequest("CN=Test", rsa, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); Assert.Throws( null, @@ -54,8 +54,13 @@ public static void SelfSign_ArgumentValidation() public static void Sign_ArgumentValidation() { using (X509Certificate2 testRoot = new X509Certificate2(TestData.PfxData, TestData.PfxDataPassword)) + using (RSA publicKey = testRoot.GetRSAPublicKey()) { - CertificateRequest request = new CertificateRequest("CN=Test", testRoot.GetRSAPublicKey(), HashAlgorithmName.SHA256); + var request = new CertificateRequest( + "CN=Test", + publicKey, + HashAlgorithmName.SHA256, + RSASignaturePadding.Pkcs1); Assert.Throws( "generator", @@ -74,5 +79,155 @@ public static void Sign_ArgumentValidation() () => request.Create(testRoot, DateTimeOffset.MinValue, DateTimeOffset.MaxValue, Array.Empty())); } } + + [Fact] + public static void CtorValidation_ECDSA_string() + { + string subjectName = null; + ECDsa key = null; + HashAlgorithmName hashAlgorithm = default(HashAlgorithmName); + + Assert.Throws( + "subjectName", + () => new CertificateRequest(subjectName, key, hashAlgorithm)); + + subjectName = ""; + + Assert.Throws( + "key", + () => new CertificateRequest(subjectName, key, hashAlgorithm)); + + key = ECDsa.Create(EccTestData.Secp384r1Data.KeyParameters); + + using (key) + { + Assert.Throws( + "hashAlgorithm", + () => new CertificateRequest(subjectName, key, hashAlgorithm)); + } + } + + [Fact] + public static void CtorValidation_ECDSA_X500DN() + { + X500DistinguishedName subjectName = null; + ECDsa key = null; + HashAlgorithmName hashAlgorithm = default(HashAlgorithmName); + + Assert.Throws( + "subjectName", + () => new CertificateRequest(subjectName, key, hashAlgorithm)); + + subjectName = new X500DistinguishedName(""); + + Assert.Throws( + "key", + () => new CertificateRequest(subjectName, key, hashAlgorithm)); + + key = ECDsa.Create(EccTestData.Secp384r1Data.KeyParameters); + + using (key) + { + Assert.Throws( + "hashAlgorithm", + () => new CertificateRequest(subjectName, key, hashAlgorithm)); + } + } + + [Fact] + public static void CtorValidation_RSA_string() + { + string subjectName = null; + RSA key = null; + HashAlgorithmName hashAlgorithm = default(HashAlgorithmName); + RSASignaturePadding padding = null; + + Assert.Throws( + "subjectName", + () => new CertificateRequest(subjectName, key, hashAlgorithm, padding)); + + subjectName = ""; + + Assert.Throws( + "key", + () => new CertificateRequest(subjectName, key, hashAlgorithm, padding)); + + key = RSA.Create(TestData.RsaBigExponentParams); + + using (key) + { + Assert.Throws( + "hashAlgorithm", + () => new CertificateRequest(subjectName, key, hashAlgorithm, padding)); + + hashAlgorithm = HashAlgorithmName.SHA256; + + Assert.Throws( + "padding", + () => new CertificateRequest(subjectName, key, hashAlgorithm, padding)); + } + } + + [Fact] + public static void CtorValidation_RSA_X500DN() + { + X500DistinguishedName subjectName = null; + RSA key = null; + HashAlgorithmName hashAlgorithm = default(HashAlgorithmName); + RSASignaturePadding padding = null; + + Assert.Throws( + "subjectName", + () => new CertificateRequest(subjectName, key, hashAlgorithm, padding)); + + subjectName = new X500DistinguishedName(""); + + Assert.Throws( + "key", + () => new CertificateRequest(subjectName, key, hashAlgorithm, padding)); + + key = RSA.Create(TestData.RsaBigExponentParams); + + using (key) + { + Assert.Throws( + "hashAlgorithm", + () => new CertificateRequest(subjectName, key, hashAlgorithm, padding)); + + hashAlgorithm = HashAlgorithmName.SHA256; + + Assert.Throws( + "padding", + () => new CertificateRequest(subjectName, key, hashAlgorithm, padding)); + } + } + + [Fact] + public static void CtorValidation_PublicKey_X500DN() + { + X500DistinguishedName subjectName = null; + PublicKey publicKey = null; + HashAlgorithmName hashAlgorithm = default(HashAlgorithmName); + + Assert.Throws( + "subjectName", + () => new CertificateRequest(subjectName, publicKey, hashAlgorithm)); + + subjectName = new X500DistinguishedName(""); + + Assert.Throws( + "publicKey", + () => new CertificateRequest(subjectName, publicKey, hashAlgorithm)); + + using (ECDsa ecdsa = ECDsa.Create(EccTestData.Secp384r1Data.KeyParameters)) + { + X509SignatureGenerator generator = X509SignatureGenerator.CreateForECDsa(ecdsa); + publicKey = generator.PublicKey; + } + + Assert.Throws( + "hashAlgorithm", + () => new CertificateRequest(subjectName, publicKey, hashAlgorithm)); + } } } diff --git a/src/System.Security.Cryptography.X509Certificates/tests/CertificateCreation/CertificateRequestChainTests.cs b/src/System.Security.Cryptography.X509Certificates/tests/CertificateCreation/CertificateRequestChainTests.cs index 13cb5716746b..d058814fc575 100644 --- a/src/System.Security.Cryptography.X509Certificates/tests/CertificateCreation/CertificateRequestChainTests.cs +++ b/src/System.Security.Cryptography.X509Certificates/tests/CertificateCreation/CertificateRequestChainTests.cs @@ -70,7 +70,7 @@ private static CertificateRequest OpenCertRequest( RSA rsa = key as RSA; if (rsa != null) - return new CertificateRequest(dn, rsa, hashAlgorithm); + return new CertificateRequest(dn, rsa, hashAlgorithm, RSASignaturePadding.Pkcs1); ECDsa ecdsa = key as ECDsa; @@ -81,6 +81,22 @@ private static CertificateRequest OpenCertRequest( $"Had no handler for key of type {key?.GetType().FullName ?? "null"}"); } + private static X509SignatureGenerator OpenGenerator(AsymmetricAlgorithm key) + { + RSA rsa = key as RSA; + + if (rsa != null) + return X509SignatureGenerator.CreateForRSA(rsa, RSASignaturePadding.Pkcs1); + + ECDsa ecdsa = key as ECDsa; + + if (ecdsa != null) + return X509SignatureGenerator.CreateForECDsa(ecdsa); + + throw new InvalidOperationException( + $"Had no handler for key of type {key?.GetType().FullName ?? "null"}"); + } + private static CertificateRequest CreateChainRequest( string dn, AsymmetricAlgorithm key, @@ -219,6 +235,9 @@ private static void CreateAndTestChain( leafRequest.CertificateExtensions.Add( new X509EnhancedKeyUsageExtension(new OidCollection { new Oid("1.3.6.1.5.5.7.3.1") }, false)); + X509SignatureGenerator rootGenerator = OpenGenerator(rootPrivKey); + X509SignatureGenerator intermed2Generator = OpenGenerator(intermed2PrivKey); + X509Certificate2 rootCertWithKey = null; X509Certificate2 intermed1CertWithKey = null; X509Certificate2 intermed2CertWithKey = null; @@ -248,8 +267,11 @@ private static void CreateAndTestChain( rng.GetBytes(leafSerial, 2, leafSerial.Length - 2); } - X509Certificate2 intermed1Tmp = intermed1Request.Create(rootCertWithKey, now, intermedEnd, intermed1Serial); - X509Certificate2 intermed2Tmp = intermed2Request.Create(rootCertWithKey, now, intermedEnd, intermed1Serial); + X509Certificate2 intermed1Tmp = + intermed1Request.Create(rootCertWithKey.SubjectName, rootGenerator, now, intermedEnd, intermed1Serial); + + X509Certificate2 intermed2Tmp = + intermed2Request.Create(rootCertWithKey.SubjectName, rootGenerator, now, intermedEnd, intermed1Serial); intermed1CertWithKey = CloneWithPrivateKey(intermed1Tmp, intermed1PrivKey); intermed2CertWithKey = CloneWithPrivateKey(intermed2Tmp, intermed2PrivKey); @@ -257,7 +279,8 @@ private static void CreateAndTestChain( intermed1Tmp.Dispose(); intermed2Tmp.Dispose(); - leafCert = leafRequest.Create(intermed2CertWithKey, now, leafEnd, leafSerial); + leafCert = leafRequest.Create( + intermed2CertWithKey.SubjectName, intermed2Generator, now, leafEnd, leafSerial); using (X509Chain chain = new X509Chain()) { diff --git a/src/System.Security.Cryptography.X509Certificates/tests/CertificateCreation/CertificateRequestUsageTests.cs b/src/System.Security.Cryptography.X509Certificates/tests/CertificateCreation/CertificateRequestUsageTests.cs index f9cfe0d5f158..fdad5b274b82 100644 --- a/src/System.Security.Cryptography.X509Certificates/tests/CertificateCreation/CertificateRequestUsageTests.cs +++ b/src/System.Security.Cryptography.X509Certificates/tests/CertificateCreation/CertificateRequestUsageTests.cs @@ -28,7 +28,8 @@ public static void ReproduceBigExponentCsr() CertificateRequest request = new CertificateRequest( "CN=localhost, OU=.NET Framework (CoreFX), O=Microsoft Corporation, L=Redmond, S=Washington, C=US", rsa, - HashAlgorithmName.SHA256); + HashAlgorithmName.SHA256, + RSASignaturePadding.Pkcs1); request.CertificateExtensions.Add(sanExtension); @@ -69,7 +70,7 @@ public static void ReproduceBigExponentCert() { rsa.ImportParameters(TestData.RsaBigExponentParams); - CertificateRequest request = new CertificateRequest(subject, rsa, HashAlgorithmName.SHA256); + var request = new CertificateRequest(subject, rsa, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); request.CertificateExtensions.Add(skidExtension); request.CertificateExtensions.Add(akidExtension); request.CertificateExtensions.Add(basicConstraints); @@ -122,7 +123,7 @@ public static void SimpleSelfSign_RSA() using (RSA rsa = RSA.Create()) { SimpleSelfSign( - new CertificateRequest("CN=localhost", rsa, HashAlgorithmName.SHA256), + new CertificateRequest("CN=localhost", rsa, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1), "1.2.840.113549.1.1.1"); } } @@ -185,7 +186,8 @@ public static void SelfSign_RSA_UseCertKeys() CertificateRequest request = new CertificateRequest( "CN=localhost, OU=.NET Framework (CoreFX), O=Microsoft Corporation, L=Redmond, S=Washington, C=US", rsa, - HashAlgorithmName.SHA256); + HashAlgorithmName.SHA256, + RSASignaturePadding.Pkcs1); DateTimeOffset now = DateTimeOffset.UtcNow; cert = request.CreateSelfSigned(now, now.AddDays(90)); @@ -356,7 +358,8 @@ public static void UniqueExtensions() CertificateRequest request = new CertificateRequest( "CN=Double Extension Test", rsa, - HashAlgorithmName.SHA256); + HashAlgorithmName.SHA256, + RSASignaturePadding.Pkcs1); request.CertificateExtensions.Add( new X509BasicConstraintsExtension(true, false, 0, true)); @@ -444,6 +447,168 @@ public static void InvalidSignatureAlgorithmEncoding(string caseName, string sig } } + [Fact] + public static void ECDSA_Signing_RSA() + { + using (RSA rsa = RSA.Create()) + using (ECDsa ecdsa = ECDsa.Create()) + { + var request = new CertificateRequest( + new X500DistinguishedName("CN=Test"), + ecdsa, + HashAlgorithmName.SHA256); + + request.CertificateExtensions.Add( + new X509BasicConstraintsExtension(true, false, 0, true)); + + DateTimeOffset now = DateTimeOffset.UtcNow; + + using (X509Certificate2 cert = request.CreateSelfSigned(now, now.AddDays(1))) + { + X509SignatureGenerator generator = + X509SignatureGenerator.CreateForRSA(rsa, RSASignaturePadding.Pkcs1); + + request = new CertificateRequest( + new X500DistinguishedName("CN=Leaf"), + rsa, + HashAlgorithmName.SHA256, + RSASignaturePadding.Pkcs1); + + byte[] serialNumber = { 1, 1, 2, 3, 5, 8, 13 }; + + Assert.Throws( + () => request.Create(cert, now, now.AddHours(3), serialNumber)); + + + // Passes with the generator + using (request.Create(cert.SubjectName, generator, now, now.AddHours(3), serialNumber)) + { + } + } + } + } + + [Fact] + public static void ECDSA_Signing_RSAPublicKey() + { + using (RSA rsa = RSA.Create()) + using (ECDsa ecdsa = ECDsa.Create()) + { + var request = new CertificateRequest( + new X500DistinguishedName("CN=Test"), + ecdsa, + HashAlgorithmName.SHA256); + + request.CertificateExtensions.Add( + new X509BasicConstraintsExtension(true, false, 0, true)); + + DateTimeOffset now = DateTimeOffset.UtcNow; + + using (X509Certificate2 cert = request.CreateSelfSigned(now, now.AddDays(1))) + { + X509SignatureGenerator rsaGenerator = + X509SignatureGenerator.CreateForRSA(rsa, RSASignaturePadding.Pkcs1); + + request = new CertificateRequest( + new X500DistinguishedName("CN=Leaf"), + rsaGenerator.PublicKey, + HashAlgorithmName.SHA256); + + byte[] serialNumber = { 1, 1, 2, 3, 5, 8, 13 }; + + Assert.Throws( + () => request.Create(cert, now, now.AddHours(3), serialNumber)); + + X509SignatureGenerator ecdsaGenerator = + X509SignatureGenerator.CreateForECDsa(ecdsa); + + // Passes with the generator + using (request.Create(cert.SubjectName, ecdsaGenerator, now, now.AddHours(3), serialNumber)) + { + } + } + } + } + + [Fact] + public static void RSA_Signing_ECDSA() + { + using (RSA rsa = RSA.Create()) + using (ECDsa ecdsa = ECDsa.Create()) + { + var request = new CertificateRequest( + new X500DistinguishedName("CN=Test"), + rsa, + HashAlgorithmName.SHA256, + RSASignaturePadding.Pkcs1); + + request.CertificateExtensions.Add( + new X509BasicConstraintsExtension(true, false, 0, true)); + + DateTimeOffset now = DateTimeOffset.UtcNow; + + using (X509Certificate2 cert = request.CreateSelfSigned(now, now.AddDays(1))) + { + request = new CertificateRequest( + new X500DistinguishedName("CN=Leaf"), + ecdsa, + HashAlgorithmName.SHA256); + + byte[] serialNumber = { 1, 1, 2, 3, 5, 8, 13 }; + + Assert.Throws( + () => request.Create(cert, now, now.AddHours(3), serialNumber)); + + X509SignatureGenerator generator = + X509SignatureGenerator.CreateForRSA(rsa, RSASignaturePadding.Pkcs1); + + // Passes with the generator + using (request.Create(cert.SubjectName, generator, now, now.AddHours(3), serialNumber)) + { + } + } + } + } + + [Fact] + public static void RSACertificateNoPaddingMode() + { + using (RSA rsa = RSA.Create()) + { + var request = new CertificateRequest( + new X500DistinguishedName("CN=Test"), + rsa, + HashAlgorithmName.SHA256, + RSASignaturePadding.Pkcs1); + + request.CertificateExtensions.Add( + new X509BasicConstraintsExtension(true, false, 0, true)); + + DateTimeOffset now = DateTimeOffset.UtcNow; + + using (X509Certificate2 cert = request.CreateSelfSigned(now, now.AddDays(1))) + { + request = new CertificateRequest( + new X500DistinguishedName("CN=Leaf"), + cert.PublicKey, + HashAlgorithmName.SHA256); + + byte[] serialNumber = { 1, 1, 2, 3, 5, 8, 13 }; + + Assert.Throws( + () => request.Create(cert, now, now.AddHours(3), serialNumber)); + + X509SignatureGenerator generator = + X509SignatureGenerator.CreateForRSA(rsa, RSASignaturePadding.Pkcs1); + + // Passes with the generator + using (request.Create(cert.SubjectName, generator, now, now.AddHours(3), serialNumber)) + { + } + } + } + } + private class InvalidSignatureGenerator : X509SignatureGenerator { private readonly byte[] _signatureAlgBytes; diff --git a/src/System.Security.Cryptography.X509Certificates/tests/CertificateCreation/PrivateKeyAssociationTests.cs b/src/System.Security.Cryptography.X509Certificates/tests/CertificateCreation/PrivateKeyAssociationTests.cs index be4591692e56..d4a6f38e475e 100644 --- a/src/System.Security.Cryptography.X509Certificates/tests/CertificateCreation/PrivateKeyAssociationTests.cs +++ b/src/System.Security.Cryptography.X509Certificates/tests/CertificateCreation/PrivateKeyAssociationTests.cs @@ -106,7 +106,8 @@ public static void AssociatePersistedKey_CAPIviaCNG_RSA(int provType, KeyNumber CertificateRequest request = new CertificateRequest( $"CN={KeyName}-{provType}-{keyNumber}", rsaCsp, - hashAlgorithm); + hashAlgorithm, + RSASignaturePadding.Pkcs1); DateTimeOffset now = DateTimeOffset.UtcNow; @@ -121,7 +122,8 @@ public static void AssociatePersistedKey_CAPIviaCNG_RSA(int provType, KeyNumber request = new CertificateRequest( $"CN={KeyName}-{provType}-{keyNumber}-again", rsa, - hashAlgorithm); + hashAlgorithm, + RSASignaturePadding.Pkcs1); X509Certificate2 cert2 = request.Create( request.SubjectName, @@ -189,7 +191,8 @@ public static void AssociatePersistedKey_CNG_RSA() CertificateRequest request = new CertificateRequest( $"CN={KeyName}", rsaCng, - HashAlgorithmName.SHA256); + HashAlgorithmName.SHA256, + RSASignaturePadding.Pkcs1); DateTimeOffset now = DateTimeOffset.UtcNow; @@ -228,7 +231,8 @@ public static void ThirdPartyProvider_RSA() CertificateRequest request = new CertificateRequest( $"CN={nameof(ThirdPartyProvider_RSA)}", rsaOther, - hashAlgorithm); + hashAlgorithm, + RSASignaturePadding.Pkcs1); byte[] signature; byte[] data = request.SubjectName.RawData;