@@ -22,86 +22,6 @@ namespace Buttplug.Components.WebsocketServer
2222 internal static class CertUtils
2323 {
2424 // Note: Much of this code comes from https://stackoverflow.com/a/22247129
25- private static X509Certificate2 GenerateSelfSignedCertificate ( string subject , X509Certificate2 issuer , AsymmetricCipherKeyPair issuerKeyPair )
26- {
27- const int keyStrength = 2048 ;
28-
29- // Generating Random Numbers
30- var randomGenerator = new CryptoApiRandomGenerator ( ) ;
31- var random = new SecureRandom ( randomGenerator ) ;
32-
33- // The Certificate Generator
34- var certificateGenerator = new X509V3CertificateGenerator ( ) ;
35-
36- // Serial Number
37- certificateGenerator . SetSerialNumber ( BigIntegers . CreateRandomInRange ( BigInteger . One , BigInteger . ValueOf ( long . MaxValue ) , random ) ) ;
38-
39- // Issuer
40- certificateGenerator . SetIssuerDN ( new X509Name ( issuer . Subject ) ) ;
41- certificateGenerator . AddExtension ( X509Extensions . AuthorityKeyIdentifier , false , new AuthorityKeyIdentifier ( SubjectPublicKeyInfoFactory . CreateSubjectPublicKeyInfo ( issuerKeyPair . Public ) ) ) ;
42-
43- // Subject DN
44- certificateGenerator . SetSubjectDN ( new X509Name ( "CN=" + subject ) ) ;
45-
46- // Subject Alternative Name
47- var subjectAlternativeNames = new List < Asn1Encodable > ( )
48- {
49- new GeneralName ( GeneralName . DnsName , Environment . MachineName ) ,
50- new GeneralName ( GeneralName . DnsName , "localhost" ) ,
51- new GeneralName ( GeneralName . IPAddress , "127.0.0.1" ) ,
52- } ;
53-
54- if ( subject != "localhost" && subject != Environment . MachineName )
55- {
56- subjectAlternativeNames . Add ( new GeneralName ( GeneralName . DnsName , subject ) ) ;
57- }
58-
59- certificateGenerator . AddExtension ( X509Extensions . SubjectAlternativeName . Id , false , new DerSequence ( subjectAlternativeNames . ToArray ( ) ) ) ;
60-
61- // Valid For
62- var notBefore = DateTime . UtcNow . Date ;
63- var notAfter = notBefore . AddYears ( 2 ) ;
64- certificateGenerator . SetNotBefore ( notBefore ) ;
65- certificateGenerator . SetNotAfter ( notAfter ) ;
66-
67- // Subject Public Key
68- var keyPairGenerator = new RsaKeyPairGenerator ( ) ;
69- var keyGenerationParameters = new KeyGenerationParameters ( random , keyStrength ) ;
70- keyPairGenerator . Init ( keyGenerationParameters ) ;
71- var subjectKeyPair = keyPairGenerator . GenerateKeyPair ( ) ;
72- certificateGenerator . SetPublicKey ( subjectKeyPair . Public ) ;
73- certificateGenerator . AddExtension ( X509Extensions . SubjectKeyIdentifier . Id , false , new SubjectKeyIdentifier ( SubjectPublicKeyInfoFactory . CreateSubjectPublicKeyInfo ( subjectKeyPair . Public ) ) ) ;
74-
75- // Add basic constraint
76- certificateGenerator . AddExtension ( X509Extensions . BasicConstraints . Id , true , new BasicConstraints ( false ) ) ;
77-
78- certificateGenerator . AddExtension ( X509Extensions . ExtendedKeyUsage . Id , false , new ExtendedKeyUsage ( new [ ] { KeyPurposeID . IdKPServerAuth } ) ) ;
79-
80- // Signature Algorithm
81- const string signatureAlgorithm = "SHA256WithRSA" ;
82- var signatureFactory = new Asn1SignatureFactory ( signatureAlgorithm , issuerKeyPair . Private ) ;
83-
84- // selfsign certificate
85- var certificate = certificateGenerator . Generate ( signatureFactory ) ;
86-
87- // correcponding private key
88- var info = PrivateKeyInfoFactory . CreatePrivateKeyInfo ( subjectKeyPair . Private ) ;
89-
90- // merge into X509Certificate2
91- var x509 = new X509Certificate2 ( certificate . GetEncoded ( ) ) ;
92- var seq = ( Asn1Sequence ) Asn1Object . FromByteArray ( info . ParsePrivateKey ( ) . GetDerEncoded ( ) ) ;
93- if ( seq . Count != 9 )
94- {
95- // throw new PemException("malformed sequence in RSA private key");
96- }
97-
98- var rsa = RsaPrivateKeyStructure . GetInstance ( seq ) ;
99- var rsaparams = new RsaPrivateCrtKeyParameters (
100- rsa . Modulus , rsa . PublicExponent , rsa . PrivateExponent , rsa . Prime1 , rsa . Prime2 , rsa . Exponent1 , rsa . Exponent2 , rsa . Coefficient ) ;
101- x509 . PrivateKey = ToDotNetKey ( rsaparams ) ; // x509.PrivateKey = DotNetUtilities.ToRSA(rsaparams);
102- return x509 ;
103- }
104-
10525 private static X509Certificate2 GenerateSelfSignedCertificate ( string subject )
10626 {
10727 const int keyStrength = 2048 ;
@@ -154,7 +74,7 @@ private static X509Certificate2 GenerateSelfSignedCertificate(string subject)
15474 // Add basic constraint
15575 certificateGenerator . AddExtension ( X509Extensions . BasicConstraints . Id , true , new BasicConstraints ( false ) ) ;
15676
157- certificateGenerator . AddExtension ( X509Extensions . ExtendedKeyUsage . Id , false , new ExtendedKeyUsage ( new [ ] { KeyPurposeID . IdKPServerAuth } ) ) ;
77+ certificateGenerator . AddExtension ( X509Extensions . ExtendedKeyUsage . Id , false , new ExtendedKeyUsage ( KeyPurposeID . IdKPServerAuth ) ) ;
15878
15979 // Signature Algorithm
16080 const string signatureAlgorithm = "SHA256WithRSA" ;
@@ -177,7 +97,15 @@ private static X509Certificate2 GenerateSelfSignedCertificate(string subject)
17797 var rsa = RsaPrivateKeyStructure . GetInstance ( seq ) ;
17898 var rsaparams = new RsaPrivateCrtKeyParameters (
17999 rsa . Modulus , rsa . PublicExponent , rsa . PrivateExponent , rsa . Prime1 , rsa . Prime2 , rsa . Exponent1 , rsa . Exponent2 , rsa . Coefficient ) ;
180- x509 . PrivateKey = ToDotNetKey ( rsaparams ) ; // x509.PrivateKey = DotNetUtilities.ToRSA(rsaparams);
100+ try
101+ {
102+ x509 . PrivateKey = ToDotNetKey ( rsaparams ) ; // x509.PrivateKey = DotNetUtilities.ToRSA(rsaparams);
103+ }
104+ catch ( CryptographicException e )
105+ {
106+ throw new Exception ( $ "Exception on cert generation!\n Subject { subject } \n Hostname { Environment . MachineName } \n SequenceCount { seq . Count } (should be 9?)", e ) ;
107+ }
108+
181109 return x509 ;
182110 }
183111
@@ -205,61 +133,6 @@ private static AsymmetricAlgorithm ToDotNetKey(RsaPrivateCrtKeyParameters privat
205133 return rsaProvider ;
206134 }
207135
208- // ReSharper disable once RedundantAssignment
209- private static X509Certificate2 GenerateCACertificate ( string subjectName , ref AsymmetricCipherKeyPair caKeyPair )
210- {
211- const int keyStrength = 2048 ;
212-
213- // Generating Random Numbers
214- var randomGenerator = new CryptoApiRandomGenerator ( ) ;
215- var random = new SecureRandom ( randomGenerator ) ;
216-
217- // The Certificate Generator
218- var certificateGenerator = new X509V3CertificateGenerator ( ) ;
219-
220- // Subject Public Key
221- var keyGenerationParameters = new KeyGenerationParameters ( random , keyStrength ) ;
222- var keyPairGenerator = new RsaKeyPairGenerator ( ) ;
223- keyPairGenerator . Init ( keyGenerationParameters ) ;
224- caKeyPair = keyPairGenerator . GenerateKeyPair ( ) ;
225-
226- // Serial Number
227- var serialNumber = BigIntegers . CreateRandomInRange ( BigInteger . One , BigInteger . ValueOf ( long . MaxValue ) , random ) ;
228- certificateGenerator . SetSerialNumber ( serialNumber ) ;
229-
230- // Signature Algorithm
231- const string signatureAlgorithm = "SHA256WithRSA" ;
232-
233- // Set the public key
234- certificateGenerator . SetPublicKey ( caKeyPair . Public ) ;
235- certificateGenerator . AddExtension ( X509Extensions . SubjectKeyIdentifier . Id , false , new SubjectKeyIdentifier ( SubjectPublicKeyInfoFactory . CreateSubjectPublicKeyInfo ( caKeyPair . Public ) ) ) ;
236-
237- // Issuer and Subject Name
238- var subjectDN = new X509Name ( subjectName ) ;
239- certificateGenerator . SetSubjectDN ( subjectDN ) ;
240-
241- // Issuer
242- certificateGenerator . SetIssuerDN ( subjectDN ) ;
243- certificateGenerator . AddExtension ( X509Extensions . AuthorityKeyIdentifier , false , new AuthorityKeyIdentifier ( SubjectPublicKeyInfoFactory . CreateSubjectPublicKeyInfo ( caKeyPair . Public ) ) ) ;
244-
245- // Valid For
246- var notBefore = DateTime . UtcNow . Date ;
247- var notAfter = notBefore . AddYears ( 2 ) ;
248- certificateGenerator . SetNotBefore ( notBefore ) ;
249- certificateGenerator . SetNotAfter ( notAfter ) ;
250-
251- // Make this a CA
252- certificateGenerator . AddExtension ( X509Extensions . BasicConstraints . Id , true , new BasicConstraints ( true ) ) ;
253-
254- // selfsign certificate
255- var signatureFactory = new Asn1SignatureFactory ( signatureAlgorithm , caKeyPair . Private ) ;
256- var certificate = certificateGenerator . Generate ( signatureFactory ) ;
257- var x509 = new X509Certificate2 ( certificate . GetEncoded ( ) ) ;
258- return x509 ;
259-
260- // return issuerKeyPair.Private;
261- }
262-
263136 public static X509Certificate2 GetCert ( string app , string hostname = "localhost" )
264137 {
265138 var appPath = Path . Combine ( Environment . GetFolderPath ( Environment . SpecialFolder . ApplicationData ) , app ) ;
@@ -276,17 +149,21 @@ public static X509Certificate2 GetCert(string app, string hostname = "localhost"
276149 }
277150 }
278151
279- if ( ! File . Exists ( certPfx ) )
152+ if ( File . Exists ( certPfx ) )
280153 {
281- var clientCert = GenerateSelfSignedCertificate ( hostname ) ;
282- var p12cert = clientCert . Export ( X509ContentType . Pfx ) ;
283- Directory . CreateDirectory ( appPath ) ;
284- var w = File . OpenWrite ( certPfx ) ;
285- w . Write ( p12cert , 0 , p12cert . Length ) ;
286- w . Close ( ) ;
154+ return new X509Certificate2 ( File . ReadAllBytes ( certPfx ) , ( string ) null ,
155+ X509KeyStorageFlags . Exportable | X509KeyStorageFlags . PersistKeySet ) ;
287156 }
288157
289- return new X509Certificate2 ( File . ReadAllBytes ( certPfx ) , ( string ) null , X509KeyStorageFlags . Exportable | X509KeyStorageFlags . PersistKeySet ) ;
158+ var clientCert = GenerateSelfSignedCertificate ( hostname ) ;
159+ var p12Cert = clientCert . Export ( X509ContentType . Pfx ) ;
160+ Directory . CreateDirectory ( appPath ) ;
161+ var w = File . OpenWrite ( certPfx ) ;
162+ w . Write ( p12Cert , 0 , p12Cert . Length ) ;
163+ w . Close ( ) ;
164+
165+ return new X509Certificate2 ( File . ReadAllBytes ( certPfx ) , ( string ) null ,
166+ X509KeyStorageFlags . Exportable | X509KeyStorageFlags . PersistKeySet ) ;
290167 }
291168 }
292169}
0 commit comments