by Zachary [zmccain at asmr dot com] posted on 2004/09/22 |
|
The Basics
---------------------------------------
1) Created a class to communicate with a remote raw SSL socket. We initiate communication using a PFX file which contains both public and private key :
objCert = Certificate.CreateFromPfxFile(pfxcertpath,"conus");
2) Class tested succesfully when incorporated into a console application but failed on 2 of 3 computers when used in a .Net WebService.
----------------------------------------
The Specifics
----------------------------------------
1)Exception:
Couldnt Acquire Crypto Service Provider context. Occuring when socket does its first Send.
2)Stack Trace:
StackTrace "
at Org.Mentalis.Security.Cryptography.CAPIProvider.CreateInternalHandle(Int32& handle, String container)\r\n
at Org.Mentalis.Security.Cryptography.CAPIProvider.get_Handle()\r\n
at Org.Mentalis.Security.Certificates.Certificate.get_PublicKey()\r\n
at Org.Mentalis.Security.Ssl.Shared.ClientHandshakeLayer.ProcessServerHelloDone(HandshakeMessage message)\r\n
at Org.Mentalis.Security.Ssl.Shared.ClientHandshakeLayer.ProcessMessage(HandshakeMessage message)\r\n
at Org.Mentalis.Security.Ssl.Shared.HandshakeLayer.ProcessMessages(RecordMessage message)\r\n
at Org.Mentalis.Security.Ssl.Shared.RecordLayer.ProcessBytes(Byte[] buffer, Int32 offset, Int32 size)\r\n
at Org.Mentalis.Security.Ssl.Shared.SocketController.OnReceive(IAsyncResult ar)" string
3)Steps Taken
Being that this error occurs only within a .Net WebService environment (remember our multiple console applications work fine) and that 1 of the 3 WebService environments tested on had no problem when using the class, we assumed there was an issue with the IUSER account context. We changed the IUSER group to admin but still experienced the error. Going on our initial assumption we then decided that in the event that the error was caused by some permission needed by IUSER in order to access the PFX file (we are guessing here) , we used the Mentalis library to create strings of our PFX file and hardcoded these into our application...
we created the string by calling the CreateFromBase64 string function on our original certificate object.
objCert=Certificate.CreateFromBase64String(sCert);
This worked fine on the console apps and the webserver running the webservice that had previously worked with our socket class.
However, it continued to fail with the same error on the other 2 webservers we were testing on (again the console apps on these 2 webservers both worked).
But, there was a difference in the error thrown this time. Instead of throwing the 'Crypto Service Provider' error it threw a 'if a certificate is specified it must have a private key' exception. We find this odd in that if a private key was absent this would not have worked on our 1 webserver which up to this point has had no problems using the secure socket ; also the hasPrivateKey property of the Certificate object returns true when instantiated from the base64 string. But for fullness of testing we decided to export the private string to XML
...
deerscert.PrivateKey.ToXmlString(false)
...
and then reconstitute it from string...
...
ObjCert.PrivateKey.FromXmlString("<RSAKeyValue><Modu ..... AKeyValue>");
...
This worked fine on all console apps and on the 'Golden' WebServer. However it again failed on the WebService running on the problematic servers, but with an error message this time of 'Could Not Acquire Private Key'!
Now we know the private key is there and proper as we just had 4 applications use the XML encoding of that key properly.
So....that is where we are now. Ive read these forums and Ive seen several people mention similiar problems but no real solution that I wish to bank on. Any help would be greatly appreciated.
Thanks
|