2727 * http://opcfoundation.org/License/MIT/1.00/
2828 * ======================================================================*/
2929
30- using Opc . Ua . Gds ;
3130using Opc . Ua . Security . Certificates ;
3231using System ;
3332using System . Drawing ;
@@ -50,6 +49,7 @@ public ApplicationCertificateControl()
5049 private ServerPushConfigurationClient m_server ;
5150 private RegisteredApplication m_application ;
5251 private X509Certificate2 m_certificate ;
52+ private bool m_temporaryCertificateCreated ;
5353 private string m_certificatePassword ;
5454
5555 public async Task Initialize (
@@ -64,6 +64,7 @@ public async Task Initialize(
6464 m_server = server ;
6565 m_application = application ;
6666 m_certificate = null ;
67+ m_temporaryCertificateCreated = false ;
6768 m_certificatePassword = null ;
6869
6970 CertificateRequestTimer . Enabled = false ;
@@ -236,10 +237,31 @@ private async Task RequestNewCertificatePullMode(object sender, EventArgs e)
236237 SubjectName = Utils . ReplaceDCLocalhost ( m_application . CertificateSubjectName )
237238 } ;
238239 m_certificate = await id . Find ( true ) ;
240+ //test if private key is available & exportable, else create new temporary certificate for csr
239241 if ( m_certificate != null &&
240242 m_certificate . HasPrivateKey )
241243 {
242- m_certificate = await id . LoadPrivateKey ( m_certificatePassword ) ;
244+ try
245+ {
246+ //this line fails with a CryptographicException if export of private key is not allowed
247+ _ = m_certificate . GetRSAPrivateKey ( ) . ExportParameters ( true ) ;
248+ //proceed with a CSR using the exportable private key
249+ m_certificate = await id . LoadPrivateKey ( m_certificatePassword ) ;
250+ }
251+ catch
252+ {
253+ //create temporary cert to generate csr from
254+ m_certificate = CertificateFactory . CreateCertificate (
255+ X509Utils . GetApplicationUriFromCertificate ( m_certificate ) ,
256+ m_application . ApplicationName ,
257+ Utils . ReplaceDCLocalhost ( m_application . CertificateSubjectName ) ,
258+ m_application . GetDomainNames ( m_certificate ) )
259+ . SetNotBefore ( DateTime . Today . AddDays ( - 1 ) )
260+ . SetNotAfter ( DateTime . Today . AddDays ( 14 ) )
261+ . SetRSAKeySize ( ( ushort ) ( m_certificate . GetRSAPublicKey ( ) ? . KeySize ?? 0 ) )
262+ . CreateForRSA ( ) ;
263+ m_temporaryCertificateCreated = true ;
264+ }
243265 }
244266 }
245267
@@ -347,7 +369,7 @@ private async void CertificateRequestTimer_Tick(object sender, EventArgs e)
347369 if ( oldCertificate != null && oldCertificate . HasPrivateKey )
348370 {
349371 oldCertificate = await cid . LoadPrivateKey ( string . Empty ) ;
350- newCert = CertificateFactory . CreateCertificateWithPrivateKey ( newCert , oldCertificate ) ;
372+ newCert = CertificateFactory . CreateCertificateWithPrivateKey ( newCert , m_temporaryCertificateCreated ? m_certificate : oldCertificate ) ;
351373 await store . Delete ( oldCertificate . Thumbprint ) ;
352374 }
353375 else
@@ -361,6 +383,12 @@ private async void CertificateRequestTimer_Tick(object sender, EventArgs e)
361383 newCert = CertificateFactory . Load ( newCert , true ) ;
362384 }
363385 await store . Add ( newCert ) ;
386+ if ( m_temporaryCertificateCreated )
387+ {
388+ m_certificate . Dispose ( ) ;
389+ m_certificate = null ;
390+ m_temporaryCertificateCreated = false ;
391+ }
364392 }
365393 }
366394 else
0 commit comments