SSL certificate generation
I am working on C# project where tcp transmition between server and client is made using SSL. I created certificate file with makecert program, but it works only on computer where it was generated (although I have i开发者_如何学Cnstalled .cer file). I am almost sure, that the problem lies in parameters which I put into command, but I checked many combinations and none (despit following) worked
makecert -r -pe -n "CN=This is my certificate" -ss my -sky exchange -sp "Microsoft RSA SChannel Cryptographic Provider" -sy 12 ca.cer
.cer file is used only for ciphering transmition. I don't use PKI. Furthermore using SSL is "dead requirement" - it must be used, just for be used. Any security issues shouldn't be considered.
If anyone should answer me, how to create certificate, that will be able to be used by X509Certificate.CreateFromCertFile method I would be delighted.
Thanks Roger I found your blog and managed to get it working and put a wrapper around it so it's easy to use and I also managed to set the friendly-Name on the certificates
using System;
using System.Collections.Generic;
using System.Security.Cryptography.X509Certificates;
using System.Diagnostics;
public class SSLCertificateCreator
{
public static string RunDosCommand(string Cmd, string Arguments)
{//Executes a Dos command in the current directory and then returns the result
string TestMessageText = "";
string filePath = Environment.CurrentDirectory;
ProcessStartInfo pi = new ProcessStartInfo()
{
FileName = filePath + "\\" + Cmd,
Arguments = Arguments + " ",
RedirectStandardOutput = true,
UseShellExecute = false,
CreateNoWindow = false
};
try
{
using (Process p = Process.Start(pi))
{
p.WaitForExit();
TestMessageText = p.StandardOutput.ReadToEnd();
return TestMessageText;
}
}
catch (Exception Ex)
{
return "ERROR :" +Ex.Message;
}
}
public static bool MakeCACertificate(string RootCertificateName, string FriendlyName)
{//Make a CA certificate but only if we don't already have one and then sets the friendly name
if (FindCertificate("Root", RootCertificateName, OpenFlags.ReadOnly) != null) return false; //We already have this root certificate
string Arguments="-pe -n \"CN=" + RootCertificateName + "\" -ss Root -sr CurrentUser -a sha1 -sky signature -r \"" + RootCertificateName + ".cer\" -m 12";
string Result=RunDosCommand("makecert", Arguments);
X509Certificate2 Cert = FindCertificate("Root", RootCertificateName, OpenFlags.ReadWrite);
if (Cert == null || !Result.ToLower().StartsWith("succeeded")) return false;
Cert.FriendlyName = FriendlyName;
return true;
}
public static bool MakeSignedCertificate(string RootCertificateName, string CertificateName, string FriendlyName)
{//Makes a signed certificate but only if we have the root certificate and then sets the friendly name
if (FindCertificate("Root", RootCertificateName, OpenFlags.ReadOnly) == null) return false; //We must have a valid root-certificate first
if (FindCertificate("my",CertificateName, OpenFlags.ReadOnly)!=null) return false;//Nope we alrady have this signed certificate
string Arguments = "-pe -n \"CN=" + CertificateName + "\" -ss my -sr CurrentUser -a sha1 -sky exchange -eku 1.3.6.1.5.5.7.3.1 -in \"" + RootCertificateName + "\" -is Root -ir CurrentUser -sp \"Microsoft RSA SChannel Cryptographic Provider\" -sy 12 \"" + CertificateName + ".cer\" -m 12";
string Result = RunDosCommand("makecert", Arguments);
X509Certificate2 Cert = FindCertificate("my", CertificateName, OpenFlags.ReadWrite);
if (Cert==null || !Result.ToLower().StartsWith("succeeded")) return false;
Cert.FriendlyName = FriendlyName;
return true;
}
private static X509Certificate2 FindCertificate(string Store, string Name, OpenFlags Mode)
{//Look to see if we can find the certificate store
X509Store store = new X509Store(Store,StoreLocation.CurrentUser);
store.Open(Mode);
foreach (X509Certificate2 Cert in store.Certificates)
{
if (Cert.Subject.ToLower() =="cn="+ Name.ToLower())
return Cert;//Yep found it
}
return null;
}
}
Sample useage
SSLCertificateCreator.MakeCACertificate("DavesRoot","Nice Name"); SSLCertificateCreator.MakeSignedCertificate("DavesRoot", "Daves Signed Certificate5","Nice Name");
makecert.exe needs to be in the Bin/Release or Debug directory for the code to work and this code has only ever been tested on Windows-8
If you control all of the machines that will use these certificates, you can create a CA that's trusted by all of the machines, and then issue certificates based on that.
Here are my batch files. The first one creates the CA certificate:
:// Create a self-signed certificate (-r),
:// with an exportable private key (-pe),
:// using SHA1 (-r), for signing (-sky signature).
:// The private key is written to a file (-sv).
makecert -r -pe -n "CN=My Root Authority" -ss CA ^
-sr CurrentUser -a sha1 -sky signature -cy authority ^
-sv CA.pvk CA.cer
Import the .CER file into the CA certificate store on those machines that must connect to the server (they must trust the CA):
:// Import that certificate into the
:// "Trusted Root Certification Authorities" store.
certutil -user -addstore Root CA.cer
This one creates a server certificate:
:// Create a server certificate, with an exportable private key (-pe),
:// using SHA1 (-r) for key exchange (-sky exchange).
:// It can be used as an SSL server certificate (-eku 1.3.6.1.5.5.7.3.1).
:// The issuing certificate is in a file (-ic), as is the key (-iv).
:// Use a particular crypto provider (-sp, -sy).
makecert -pe -n "CN=server.example.com" -a sha1 ^
-sky exchange -eku 1.3.6.1.5.5.7.3.1
-ic CA.cer -iv CA.pvk ^
-sp "Microsoft RSA SChannel Cryptographic Provider" -sy 12 ^
-sv server.pvk server.cer
pvk2pfx -pvk server.pvk -spc server.cer -pfx server.pfx
Install the .pfx file, and then get the C# server code to use it. This is left as an exercise for the reader.
You need to get a valid certificate. The one generated by makecert command is only for testing and wont work on other systems.
精彩评论