2012-10-01 2 views
4

WebAPISSL을 사용하는 자체 호스팅 서비스를 구축하려고하는데 사용할 SSL 인증서를 자체 생성 할 수 있어야합니다. C#에서이 모든 작업을 수행 할 수 있기를 바랍니다. 나는 BouncyCastle으로 놀았습니다.BouncyCastle을 사용하여 루트 인증서를 생성 한 다음 해당 루트 인증서로 서명 한 사이트 인증서를 어떻게 작성합니까?

루트 및 사이트 인증서 인 2 개의 인증서를 생성해야합니다. 그런 다음 올바른 위치에 Windows에 설치해야합니다.

두 번째 인증서 참조를 내 루트 CA로 만드는 방법을 알 수 없습니다. 내가 시도한 모든 것은 나에게 신뢰할 수없는 인증서 오류를 가져옵니다. 어떤 도움을 주시면 감사하겠습니다.

+0

문제가있는 코드를 게시 할 수 있습니까? – newfurniturey

답변

8

이것은 내가하는 일입니다 (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 상점).

+0

이 코드를 함께 넣으려고합니다. BuildCertificateChainBC가 존재하지 않는다고 불평합니다. GenerateDsaKeys도 마찬가지입니다. – user1712714

+0

내 코드가 해당 메소드로 업데이트되었습니다. 누락 된 메서드는 특별한 작업을 수행하지 않습니다. 필요할 경우 RSA 용 DSA를 변경하거나 체인을 만들지 마십시오. BouncyCastle 수업을 통해 몇 가지 결함을 이해해야했습니다. –

+0

@ ser1712714 그게 효과가 있었나요? –

관련 문제