It is much the same as the method DC++ uses. The only reference is BouncyCastle v1.5 (http://www.bouncycastle.org/csharp/).
The next step for an implementation would be to load the certificate with System.Security.Cryptography.X509Certificates.X509Certificate2.
Code: Select all
using System;
using System.IO;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.X509;
namespace CryptoCertGeneration
{
class Program
{
static void Main(string[] args)
{
string userCID = "BMWBDHYZB2BYYEONDYJ4WCLQMQS7H4ZZSCOHEW2";
string certPath = @"C:\Certificates\";
// Steps
// 1. Generate the RSA Key Pair.
// 2. Set the X.509 certificate members.
// 3. Generate the X.509 certificate.
// 4. Write the X.509 certificate to file.
// 5. Write the RSA Private Key to file.
X509Certificate x509;
const string CERT_FILE_NAME = "my.crt";
const string KEY_FILE_NAME = "my.key";
const int CERTIFICATE_LIFESPAN_DAYS = 10;
const int KEY_LENGTH = 2048;
// 1. Generate the RSA Key Pair.
SecureRandom secureRandom = new SecureRandom();
BigInteger publicExponent = BigInteger.ValueOf(0x10001L); // 0x10001 = RSA_F4 from OpenSSL's rsa.h
RsaKeyGenerationParameters rsaKeyGenParams = new RsaKeyGenerationParameters(publicExponent, secureRandom, KEY_LENGTH, 80); // Not sure what certainty = 80 means :S
RsaKeyPairGenerator rsaKeyPairGen = new RsaKeyPairGenerator();
rsaKeyPairGen.Init(rsaKeyGenParams);
AsymmetricCipherKeyPair keyPair = rsaKeyPairGen.GenerateKeyPair();
// 2. Set the X.509 certificate members.
X509V1CertificateGenerator xGen = new X509V1CertificateGenerator();
BigInteger serialNum = BigInteger.One; // Should generate something random here, at least 64-bits e.g. DateTime.Now.Ticks or System.Random
X509Name xName = new X509Name(string.Format("CN={0}", userCID)); // Set the name to the user's client Id
xGen.SetSerialNumber(serialNum);
xGen.SetIssuerDN(xName);
xGen.SetNotBefore(DateTime.Now);
xGen.SetNotAfter(DateTime.Now.AddDays(CERTIFICATE_LIFESPAN_DAYS));
xGen.SetSubjectDN(xName);
xGen.SetPublicKey(keyPair.Public);
xGen.SetSignatureAlgorithm("SHA1withRSA");
// 3. Generate the X.509 certificate.
x509 = xGen.Generate(keyPair.Private);
// 4. Write the X.509 certificate to file.
StreamWriter sWriter;
PemWriter pWriter;
sWriter = new StreamWriter(new FileStream(Path.Combine(certPath, CERT_FILE_NAME), FileMode.Create));
pWriter = new PemWriter(sWriter);
pWriter.WriteObject(x509);
sWriter.Flush();
sWriter.Close();
// 5. Write the RSA Private Key to file.
sWriter = new StreamWriter(new FileStream(Path.Combine(certPath, KEY_FILE_NAME), FileMode.Create));
pWriter = new PemWriter(sWriter);
pWriter.WriteObject(keyPair);
sWriter.Flush();
sWriter.Close();
}
}
}