44using System . Collections . Generic ;
55using System . IO ;
66using System . Runtime . InteropServices ;
7+ using System . Security . Cryptography . Dsa . Tests ;
8+ using System . Security . Cryptography . X509Certificates . Tests . CertificateCreation ;
79using System . Threading ;
810using Microsoft . DotNet . XUnitExtensions ;
911using Test . Cryptography ;
@@ -25,6 +27,155 @@ public CertTests(ITestOutputHelper output)
2527 _log = output ;
2628 }
2729
30+ [ Fact ]
31+ public static void PublicPrivateKey_IndependentLifetimes_ECDsa ( )
32+ {
33+ X509Certificate2 loaded ;
34+
35+ using ( ECDsa ca = ECDsa . Create ( ECCurve . NamedCurves . nistP256 ) )
36+ {
37+ CertificateRequest req = new ( "CN=potatos" , ca , HashAlgorithmName . SHA256 ) ;
38+
39+ using ( X509Certificate2 cert = req . CreateSelfSigned ( DateTimeOffset . Now , DateTimeOffset . Now . AddDays ( 3 ) ) )
40+ {
41+ loaded = new X509Certificate2 ( cert . Export ( X509ContentType . Pkcs12 , "carrots" ) , "carrots" ) ;
42+ }
43+ }
44+
45+ using ( ECDsa verifyKey = loaded . GetECDsaPublicKey ( ) )
46+ {
47+ byte [ ] signature ;
48+ byte [ ] data = RandomNumberGenerator . GetBytes ( 32 ) ;
49+
50+ using ( ECDsa signingKey = loaded . GetECDsaPrivateKey ( ) )
51+ {
52+ loaded . Dispose ( ) ;
53+ signature = signingKey . SignHash ( data ) ;
54+ }
55+
56+ Assert . True ( verifyKey . VerifyHash ( data , signature ) , nameof ( verifyKey . VerifyHash ) ) ;
57+ }
58+ }
59+
60+ [ Fact ]
61+ public static void PublicPrivateKey_IndependentLifetimes_ECDiffieHellman ( )
62+ {
63+ X509Certificate2 loaded ;
64+
65+ using ( ECDsa ca = ECDsa . Create ( ECCurve . NamedCurves . nistP256 ) )
66+ using ( ECDiffieHellman ecdh = ECDiffieHellman . Create ( ECCurve . NamedCurves . nistP256 ) )
67+ {
68+ CertificateRequest issuerRequest = new CertificateRequest (
69+ new X500DistinguishedName ( "CN=root" ) ,
70+ ca ,
71+ HashAlgorithmName . SHA256 ) ;
72+
73+ issuerRequest . CertificateExtensions . Add (
74+ new X509BasicConstraintsExtension ( true , false , 0 , true ) ) ;
75+
76+ CertificateRequest request = new CertificateRequest (
77+ new X500DistinguishedName ( "CN=potato" ) ,
78+ new PublicKey ( ecdh ) ,
79+ HashAlgorithmName . SHA256 ) ;
80+
81+ request . CertificateExtensions . Add (
82+ new X509BasicConstraintsExtension ( false , false , 0 , true ) ) ;
83+ request . CertificateExtensions . Add (
84+ new X509KeyUsageExtension ( X509KeyUsageFlags . KeyAgreement , true ) ) ;
85+
86+ DateTimeOffset notBefore = DateTimeOffset . UtcNow ;
87+ DateTimeOffset notAfter = notBefore . AddDays ( 30 ) ;
88+ byte [ ] serial = [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 ] ;
89+
90+ using ( X509Certificate2 issuer = issuerRequest . CreateSelfSigned ( notBefore , notAfter ) )
91+ using ( X509Certificate2 cert = request . Create ( issuer , notBefore , notAfter , serial ) )
92+ using ( X509Certificate2 certWithKey = cert . CopyWithPrivateKey ( ecdh ) )
93+ {
94+ loaded = new X509Certificate2 ( certWithKey . Export ( X509ContentType . Pkcs12 , "carrots" ) , "carrots" ) ; ;
95+ }
96+ }
97+
98+ using ( ECDiffieHellman partyB = ECDiffieHellman . Create ( ECCurve . NamedCurves . nistP256 ) )
99+ using ( ECDiffieHellman partyAPrivateKey = loaded . GetECDiffieHellmanPrivateKey ( ) )
100+ using ( ECDiffieHellman partyAPublicKey = loaded . GetECDiffieHellmanPublicKey ( ) )
101+ {
102+ loaded . Dispose ( ) ;
103+ byte [ ] derivedB = partyB . DeriveKeyFromHash ( partyAPublicKey . PublicKey , HashAlgorithmName . SHA256 , null , null ) ;
104+ byte [ ] derivedA = partyAPrivateKey . DeriveKeyFromHash ( partyB . PublicKey , HashAlgorithmName . SHA256 , null , null ) ;
105+ Assert . Equal ( derivedB , derivedA ) ;
106+ }
107+ }
108+
109+ [ Fact ]
110+ public static void PublicPrivateKey_IndependentLifetimes_RSA ( )
111+ {
112+ X509Certificate2 loaded ;
113+
114+ using ( RSA ca = RSA . Create ( 2048 ) )
115+ {
116+ CertificateRequest req = new ( "CN=potatos" , ca , HashAlgorithmName . SHA256 , RSASignaturePadding . Pkcs1 ) ;
117+
118+ using ( X509Certificate2 cert = req . CreateSelfSigned ( DateTimeOffset . Now , DateTimeOffset . Now . AddDays ( 3 ) ) )
119+ {
120+ loaded = new X509Certificate2 ( cert . Export ( X509ContentType . Pkcs12 , "carrots" ) , "carrots" ) ;
121+ }
122+ }
123+
124+ using ( RSA verifyKey = loaded . GetRSAPublicKey ( ) )
125+ {
126+ byte [ ] signature ;
127+ byte [ ] data = RandomNumberGenerator . GetBytes ( 32 ) ;
128+
129+ using ( RSA signingKey = loaded . GetRSAPrivateKey ( ) )
130+ {
131+ loaded . Dispose ( ) ;
132+ signature = signingKey . SignHash ( data , HashAlgorithmName . SHA256 , RSASignaturePadding . Pkcs1 ) ;
133+ }
134+
135+ Assert . True ( verifyKey . VerifyHash ( data , signature , HashAlgorithmName . SHA256 , RSASignaturePadding . Pkcs1 ) , nameof ( verifyKey . VerifyHash ) ) ;
136+ }
137+ }
138+
139+ [ Fact ]
140+ [ SkipOnPlatform ( PlatformSupport . MobileAppleCrypto , "DSA is not available" ) ]
141+ public static void PublicPrivateKey_IndependentLifetimes_DSA ( )
142+ {
143+ X509Certificate2 loaded ;
144+
145+ using ( DSA ca = DSA . Create ( ) )
146+ {
147+ ca . ImportParameters ( DSATestData . GetDSA1024Params ( ) ) ;
148+ DSAX509SignatureGenerator gen = new DSAX509SignatureGenerator ( ca ) ;
149+ X500DistinguishedName dn = new X500DistinguishedName ( "CN=potatos" ) ;
150+
151+ CertificateRequest req = new CertificateRequest (
152+ dn ,
153+ gen . PublicKey ,
154+ HashAlgorithmName . SHA1 ) ;
155+
156+ using ( X509Certificate2 cert = req . Create ( dn , gen , DateTimeOffset . Now , DateTimeOffset . Now . AddDays ( 3 ) , new byte [ ] { 1 , 2 , 3 } ) )
157+ using ( X509Certificate2 certWithKey = cert . CopyWithPrivateKey ( ca ) )
158+ {
159+
160+ loaded = new X509Certificate2 ( certWithKey . Export ( X509ContentType . Pkcs12 , "carrots" ) , "carrots" ) ;
161+ }
162+ }
163+
164+ using ( DSA verifyKey = loaded . GetDSAPublicKey ( ) )
165+ {
166+ byte [ ] signature ;
167+ byte [ ] data = RandomNumberGenerator . GetBytes ( 20 ) ;
168+
169+ using ( DSA signingKey = loaded . GetDSAPrivateKey ( ) )
170+ {
171+ loaded . Dispose ( ) ;
172+ signature = signingKey . CreateSignature ( data ) ;
173+ }
174+
175+ Assert . True ( verifyKey . VerifySignature ( data , signature ) , nameof ( verifyKey . VerifySignature ) ) ;
176+ }
177+ }
178+
28179 [ Fact ]
29180 public static void RaceDisposeAndKeyAccess ( )
30181 {
0 commit comments