Reputation: 440
I'm having a hard time understanding why my simple C# SSL Server code is failing. When I try to 'Authenticate as Server' using a .p12 file I load from the file system, I get an error.
Here's my code:
IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, 2045);
Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
server.Bind(localEndPoint);
while (true)
{
server.Listen(10);
Socket client = server.Accept();
Stream clientStream = new NetworkStream(client, true);
var clientTlsStream = new SslStream(clientStream, false);
var p12Cert =
new X509Certificate2(
@"C:\Repos\ITEL-Trunk\Code\Applications\Server\bin\Debug\Configuration\Certificate_tool_signed_with_ca.p12",
"Passw0rd");
clientTlsStream.AuthenticateAsServer(p12Cert);
var cr = clientTlsStream.CanRead;
}
And here's the exception detail:
System.ComponentModel.Win32Exception was unhandled
HResult=-2147467259
Message=The credentials supplied to the package were not recognized
Source=System
ErrorCode=-2147467259
NativeErrorCode=-2146893043
The X509Certificate2 object indicates that 'Has Private Key = true' and I've tried running as Admininstrator without luck. Other SO questions that I've seen for this revolve around CAPI permissions, but since I'm loading straight from the file system I was not able to apply those answers.
Upvotes: 3
Views: 7060
Reputation: 440
I was able to trace this problem back to the way the p12 file was being generated. The .p12 was being created by a Bouncy-Castle based C# utility which was not packaging the certificate and private key correctly. I had to change the Certificate Generator so it properly packages both the Certificate and the CA certificate used to sign it.
After I made the changes to the certificate generator the "credentials supplied to the package were not recognized" exception went away.
Here is the P12 packager code that seems to work:
// Create the PKCS12 store
Pkcs12Store store = new Pkcs12Store();
// Add a Certificate entry
string certCn = cert.SubjectDN.GetValues(X509Name.CN).OfType<string>().Single();
X509CertificateEntry certEntry = new X509CertificateEntry(cert);
store.SetCertificateEntry(certCn, certEntry); // use DN as the Alias.
// Add a key entry & cert chain (if applicable)
AsymmetricKeyEntry keyEntry = new AsymmetricKeyEntry(kp.Private);
X509CertificateEntry[] certChain;
if (_issuerCert != null)
{
X509CertificateEntry issuerCertEntry = new X509CertificateEntry(_issuerCert);
certChain = new X509CertificateEntry[] { certEntry, issuerCertEntry};
}
else
{
certChain = new X509CertificateEntry[] { certEntry };
}
store.SetKeyEntry(certCn, keyEntry, certChain); // Set the friendly name along with the generated certs key and its chain
// Write the p12 file to disk
FileInfo p12File = new FileInfo(pathToP12File);
Directory.CreateDirectory(p12File.DirectoryName);
using (FileStream filestream = new FileStream(pathToP12File, FileMode.Create, FileAccess.ReadWrite))
{
store.Save(filestream, password.ToCharArray(), new SecureRandom());
}
Upvotes: 4