We currently use self-signed server certificates in our Windows-to-WCF application. The certificates are created with the following commands in a batch file:
makecert -sv CERTNAME.pvk -n "CN=SUBJECTNAME" CERTNAME.cer -sky exchange cert2spc CERTNAME.cer CERTNAME.spc pvk2pfx -pvk CERTNAME.pvk -spc CERTNAME.spc -pfx CERTNAME.pfx
I have been tasked with replacing the batch file with code and it's proving to be tricky.
After googling I found that I needed to do this via PInvoke calls to CertCreateSelfSignCertificate and CertStrToName in crypt32.dll.
I found an open source project that I could use as a reference:
http://www.mentalis.org/soft/projects/sectools/
I immitate the procedure, load the handle into an isnatnce of X509Certificate2 and then export the file to .pfx format and save on disk. I then (as a test) attempt to load the file back into an X509Certificate2 instance (the same way we did when using the batch file generated certificates).
The certificate generation appears to work but there are several issues:
Firstly, the issuer name in the code-generated certificate is the same as the subject name (whereas the issuer name in the certificate batch-file-generated certificate is "CN=Root Agency"). When you export view the batch-file generated certificateto .cer file, you can see the Root Authority in the path. The code-generated certificate when exported to .cer has no Root Agency.
Secondly, the password in the code-generated certificate is NULL whereas the password in the batch-file-generated certificate is "". Therefore, the batch-file-generated certificate has to be loaded using the call:
X509Certificate2 certificate = new X509Certificate2(fullPath, string.Empty);
whereares the code-generated certificate has to be loaded using the call:
X509Certificate2 certificate = new X509Certificate2(fullPath);
Thirdly, the certificate doesn't actually work. Any WCF service call fails. An error is enetered into the server WCF logs:
System.ComponentModel.Win32Exception: The credentials supplied to the package were not recognized
at System.IdentityModel.SspiWrapper.AcquireCredentialsHandle(String package, CredentialUse intent, SecureCredential scc)
at System.ServiceModel.Security.TlsSspiNegotiation.AcquireServerCredentials()
at System.ServiceModel.Security.TlsSspiNegotiation..ctor(String destination, Boolean isServer, SchProtocols protocolFlags, X509Certificate2 serverCertificate, X509Certificate2 clientCertificate, Boolean clientCertRequired)
at System.ServiceModel.Security.TlsnegoTokenAuthenticator.CreateSspiState(Byte[] incomingBlob, String incomingValueTypeUri)
at System.ServiceModel.Security.SspiNegotiationTokenAuthenticator.ProcessRequestSecurityToken(Message request, RequestSecurityToken requestSecurityToken, SspiNegotiationTokenAuthenticatorState& negotiationState)
at System.ServiceModel.Security.NegotiationTokenAuthenticator1.ProcessRequestCore(Message request)
at System.ServiceModel.Security.NegotiationTokenAuthenticator
1.NegotiationHost.NegotiationSyncInvoker.Invoke(Object instance, Object[] inputs, Object[]& outputs)
So my question is are: Does anyone know what the error means and if it is anything to do with the fact that there is no root authority?
NOTE: There are 3 questions about CertCreateSelfSignCertificate on this site but what I would like to know is not covered:
http://stackoverflow.com/search?q=CertCreateSelfSignCertificate