我在嘗試構建一個自我託管的服務,使用WebAPI
和SSL
,我需要能夠自行生成SSL證書才能使用。我希望能夠從C#
這樣做。我一直在玩BouncyCastle
。如何使用BouncyCastle生成根證書,然後生成由該根證書籤名的站點證書?
我需要生成2個證書,一個根和一個站點證書。然後,我需要將它們安裝在Windows中正確的位置。
我無法弄清楚如何使我的第二個證書引用我的根ca.我試過的一切都讓我感到不可信的證書錯誤。任何幫助,將不勝感激。
我在嘗試構建一個自我託管的服務,使用WebAPI
和SSL
,我需要能夠自行生成SSL證書才能使用。我希望能夠從C#
這樣做。我一直在玩BouncyCastle
。如何使用BouncyCastle生成根證書,然後生成由該根證書籤名的站點證書?
我需要生成2個證書,一個根和一個站點證書。然後,我需要將它們安裝在Windows中正確的位置。
我無法弄清楚如何使我的第二個證書引用我的根ca.我試過的一切都讓我感到不可信的證書錯誤。任何幫助,將不勝感激。
這就是我所做的(我正在使用DSA,但如果您使用RSA,只需更改密鑰生成)。
public void IssueClientFromCA()
{
// get CA
string caCn = "MyCA CommonName";
Stream caCertFile = File.OpenRead(string.Format(@"{0}\{1}", _certificatesDir, "MyCAFile.pfx"));
char[] caPass = "passwordForThePfx".ToCharArray();
Pkcs12Store store = new Pkcs12StoreBuilder().Build();
store.Load(caCertFile, caPass);
var caCert = store.GetCertificate(caCn).Certificate;
var caPrivKey = store.GetKey(caCn).Key;
var clientCert = CertIssuer.GenerateDsaCertificateAsPkcs12(
"My Client FriendlyName",
"My Client SubjectName",
"GT",
new DateTime(2011,9,19),
new DateTime(2014,9,18),
"PFXPASS",
caCert,
caPrivKey);
var saveAS = string.Format(@"{0}\{1}", _certificatesDir, "clientCertFile.pfx");
File.WriteAllBytes(saveAS, clientCert);
}
public static byte[] GenerateDsaCertificateAsPkcs12(
string friendlyName,
string subjectName,
string country,
DateTime validStartDate,
DateTime validEndDate,
string password,
Org.BouncyCastle.X509.X509Certificate caCert,
AsymmetricKeyParameter caPrivateKey)
{
var keys = GenerateDsaKeys();
#region build certificate
var certGen = new X509V3CertificateGenerator();
// build name attributes
var nameOids = new ArrayList();
nameOids.Add(Org.BouncyCastle.Asn1.X509.X509Name.CN);
nameOids.Add(X509Name.O);
nameOids.Add(X509Name.C);
var nameValues = new ArrayList();
nameValues.Add(friendlyName);
nameValues.Add(subjectName);
nameValues.Add(country);
var subjectDN = new X509Name(nameOids, nameValues);
// certificate fields
certGen.SetSerialNumber(BigInteger.ValueOf(1));
certGen.SetIssuerDN(caCert.SubjectDN);
certGen.SetNotBefore(validStartDate);
certGen.SetNotAfter(validEndDate);
certGen.SetSubjectDN(subjectDN);
certGen.SetPublicKey(keys.Public);
certGen.SetSignatureAlgorithm("SHA1withDSA");
// extended information
certGen.AddExtension(X509Extensions.AuthorityKeyIdentifier, false, new AuthorityKeyIdentifierStructure(caCert.GetPublicKey()));
certGen.AddExtension(X509Extensions.SubjectKeyIdentifier, false, new SubjectKeyIdentifierStructure(keys.Public));
#endregion
// generate x509 certificate
var cert = certGen.Generate(caPrivateKey);
//ert.Verify(caCert.GetPublicKey());
var chain = new Dictionary<string, Org.BouncyCastle.X509.X509Certificate>();
//chain.Add("CertiFirmas CA", caCert);
var caCn = caCert.SubjectDN.GetValues(X509Name.CN)[0].ToString();
chain.Add(caCn, caCert);
// store the file
return GeneratePkcs12(keys, cert, friendlyName, password, chain);
}
private static byte[] GeneratePkcs12(AsymmetricCipherKeyPair keys, Org.BouncyCastle.X509.X509Certificate cert, string friendlyName, string password,
Dictionary<string, Org.BouncyCastle.X509.X509Certificate> chain)
{
var chainCerts = new List<X509CertificateEntry>();
// Create the PKCS12 store
Pkcs12Store store = new Pkcs12StoreBuilder().Build();
// Add a Certificate entry
X509CertificateEntry certEntry = new X509CertificateEntry(cert);
store.SetCertificateEntry(friendlyName, certEntry); // use DN as the Alias.
//chainCerts.Add(certEntry);
// Add chain entries
var additionalCertsAsBytes = new List<byte[]>();
if (chain != null && chain.Count > 0)
{
foreach (var additionalCert in chain)
{
additionalCertsAsBytes.Add(additionalCert.Value.GetEncoded());
}
}
if (chain != null && chain.Count > 0)
{
var addicionalCertsAsX09Chain = BuildCertificateChainBC(cert.GetEncoded(), additionalCertsAsBytes);
foreach (var addCertAsX09 in addicionalCertsAsX09Chain)
{
chainCerts.Add(new X509CertificateEntry(addCertAsX09));
}
}
// Add a key entry
AsymmetricKeyEntry keyEntry = new AsymmetricKeyEntry(keys.Private);
// no chain
store.SetKeyEntry(friendlyName, keyEntry, new X509CertificateEntry[] { certEntry });
using (var memoryStream = new MemoryStream())
{
store.Save(memoryStream, password.ToCharArray(), new SecureRandom());
return memoryStream.ToArray();
}
}
缺少一些方法:
static IEnumerable<Org.BouncyCastle.X509.X509Certificate> BuildCertificateChainBC(byte[] primary, IEnumerable<byte[]> additional)
{
X509CertificateParser parser = new X509CertificateParser();
PkixCertPathBuilder builder = new PkixCertPathBuilder();
// Separate root from itermediate
var intermediateCerts = new List<Org.BouncyCastle.X509.X509Certificate>();
HashSet rootCerts = new HashSet();
foreach (byte[] cert in additional)
{
var x509Cert = parser.ReadCertificate(cert);
// Separate root and subordinate certificates
if (x509Cert.IssuerDN.Equivalent(x509Cert.SubjectDN))
rootCerts.Add(new TrustAnchor(x509Cert, null));
else
intermediateCerts.Add(x509Cert);
}
// Create chain for this certificate
X509CertStoreSelector holder = new X509CertStoreSelector();
holder.Certificate = parser.ReadCertificate(primary);
// WITHOUT THIS LINE BUILDER CANNOT BEGIN BUILDING THE CHAIN
intermediateCerts.Add(holder.Certificate);
PkixBuilderParameters builderParams = new PkixBuilderParameters(rootCerts, holder);
builderParams.IsRevocationEnabled = false;
X509CollectionStoreParameters intermediateStoreParameters =
new X509CollectionStoreParameters(intermediateCerts);
builderParams.AddStore(X509StoreFactory.Create(
"Certificate/Collection", intermediateStoreParameters));
PkixCertPathBuilderResult result = builder.Build(builderParams);
return result.CertPath.Certificates.Cast<Org.BouncyCastle.X509.X509Certificate>();
}
private static AsymmetricCipherKeyPair GenerateDsaKeys()
{
DSACryptoServiceProvider DSA = new DSACryptoServiceProvider();
var dsaParams = DSA.ExportParameters(true);
AsymmetricCipherKeyPair keys = DotNetUtilities.GetDsaKeyPair(dsaParams);
return keys;
}
另外:你必須安裝你的CA證書到客戶機的可信的CA存儲,以及客戶端證書(也可能是在個人或ThirdParty商店)。
我試圖把這段代碼放在一起。它抱怨BuildCertificateChainBC不存在。 GenerateDsaKeys也是如此。 – user1712714
用該方法更新我的代碼。缺少的方法不會做任何特殊的事情,如果需要,可以更改它們:更改RSA的DSA或不創建鏈。我必須用BouncyCastle課程玩很多東西來理解一些故障。 –
@ ser1712714是否爲您工作? –
你可以發佈你有問題的代碼嗎? – newfurniturey