2010-09-22 10 views
34

हम सी # और BouncyCastle लाइब्रेरी का उपयोग करके प्रोग्रामेटिक रूप से X509 प्रमाण पत्र (निजी कुंजी सहित) उत्पन्न करने का प्रयास कर रहे हैं। हमने this sample by Felix Kollmann से कुछ कोड का उपयोग करने का प्रयास किया है लेकिन प्रमाणपत्र का निजी कुंजी हिस्सा शून्य लौटाता है। संहिता और इकाई परीक्षण के रूप में नीचे हैं:क्या प्रोग्रामिंग रूप से केवल सी # का उपयोग कर X509 प्रमाणपत्र उत्पन्न करना संभव है?

using System; 
using System.Collections; 
using Org.BouncyCastle.Asn1; 
using Org.BouncyCastle.Asn1.X509; 
using Org.BouncyCastle.Crypto; 
using Org.BouncyCastle.Crypto.Generators; 
using Org.BouncyCastle.Crypto.Prng; 
using Org.BouncyCastle.Math; 
using Org.BouncyCastle.Security; 
using Org.BouncyCastle.X509; 

namespace MyApp 
{ 
    public class CertificateGenerator 
    { 
     /// <summary> 
     /// 
     /// </summary> 
     /// <remarks>Based on <see cref="http://www.fkollmann.de/v2/post/Creating-certificates-using-BouncyCastle.aspx"/></remarks> 
     /// <param name="subjectName"></param> 
     /// <returns></returns> 
     public static byte[] GenerateCertificate(string subjectName) 
     { 
      var kpgen = new RsaKeyPairGenerator(); 

      kpgen.Init(new KeyGenerationParameters(new SecureRandom(new CryptoApiRandomGenerator()), 1024)); 

      var kp = kpgen.GenerateKeyPair(); 

      var gen = new X509V3CertificateGenerator(); 

      var certName = new X509Name("CN=" + subjectName); 
      var serialNo = BigInteger.ProbablePrime(120, new Random()); 

      gen.SetSerialNumber(serialNo); 
      gen.SetSubjectDN(certName); 
      gen.SetIssuerDN(certName); 
      gen.SetNotAfter(DateTime.Now.AddYears(100)); 
      gen.SetNotBefore(DateTime.Now.Subtract(new TimeSpan(7, 0, 0, 0))); 
      gen.SetSignatureAlgorithm("MD5WithRSA"); 
      gen.SetPublicKey(kp.Public); 

      gen.AddExtension(
       X509Extensions.AuthorityKeyIdentifier.Id, 
       false, 
       new AuthorityKeyIdentifier(
        SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(kp.Public), 
        new GeneralNames(new GeneralName(certName)), 
        serialNo)); 

      gen.AddExtension(
       X509Extensions.ExtendedKeyUsage.Id, 
       false, 
       new ExtendedKeyUsage(new ArrayList() { new DerObjectIdentifier("1.3.6.1.5.5.7.3.1") })); 

      var newCert = gen.Generate(kp.Private); 
      return DotNetUtilities.ToX509Certificate(newCert).Export(System.Security.Cryptography.X509Certificates.X509ContentType.Pkcs12, "password"); 
     } 
    } 
} 

यूनिट टेस्ट:

using System.Security.Cryptography; 
using System.Security.Cryptography.X509Certificates; 
using Microsoft.VisualStudio.TestTools.UnitTesting; 

namespace MyApp 
{ 
    [TestClass] 
    public class CertificateGeneratorTests 
    { 
     [TestMethod] 
     public void GenerateCertificate_Test_ValidCertificate() 
     { 
      // Arrange 
      string subjectName = "test"; 

      // Act 
      byte[] actual = CertificateGenerator.GenerateCertificate(subjectName); 

      // Assert 
      var cert = new X509Certificate2(actual, "password"); 
      Assert.AreEqual("CN=" + subjectName, cert.Subject); 
      Assert.IsInstanceOfType(cert.PrivateKey, typeof(RSACryptoServiceProvider)); 
     } 
    } 
} 

उत्तर

27

बस, स्पष्ट एक X.509 प्रमाणपत्र निजी कुंजी शामिल नहीं करता है। प्रमाणपत्र शब्द कभी-कभी प्रमाण पत्र और निजी कुंजी के संयोजन का प्रतिनिधित्व करने के लिए दुरुपयोग किया जाता है, लेकिन वे दो अलग-अलग इकाइयां हैं। सर्टिफिकेट्स का उपयोग करने का पूरा बिंदु निजी कुंजी भेजने के बिना उन्हें कम से कम खुले तौर पर भेजना है, जिसे गुप्त रखा जाना चाहिए। एक X509Certificate2 ऑब्जेक्ट में इसके साथ एक निजी कुंजी हो सकती है (इसकी PrivateKey संपत्ति के माध्यम से), लेकिन यह इस वर्ग के डिज़ाइन के हिस्से के रूप में केवल एक सुविधा है।

आपके पहले बाउंसीकास्टल कोड उदाहरण में, newCert वास्तव में केवल प्रमाणपत्र है और DotNetUtilities.ToX509Certificate(newCert) केवल प्रमाणपत्र से बनाया गया है।

ध्यान में रखते हुए कि पीकेसीएस # 12 प्रारूप को एक निजी कुंजी की उपस्थिति की आवश्यकता है, मुझे आश्चर्य है कि निम्नलिखित भाग भी काम करता है (मानते हुए कि आप इसे ऐसे प्रमाणपत्र पर बुला रहे हैं जो संभवतः निजी कुंजी नहीं जान सकता) :

.Export(System.Security.Cryptography.X509Certificates.X509ContentType.Pkcs12, 
    "password"); 

(gen.Generate(kp.Private) प्रमाण पत्र निजी कुंजी का उपयोग कर संकेत है, लेकिन प्रमाण पत्र है, जो कोई मतलब नहीं होगा में निजी कुंजी डाल नहीं है।)

आप अपने विधि दोनों वापस जाने के लिए चाहते हैं सर्टिफिकेट और निजी कुंजी जो आप कर सकते हैं:

  • वापसी एक X509Certificate2 वस्तु जिसमें आप PrivateKey संपत्ति
  • बिल्ड एक PKCS # 12 की दुकान प्रारंभ और उसके byte[] सामग्री देता है (जैसे कि यह एक फ़ाइल था) है। Step 3 in the link you've sent (mirror) बताता है कि पीकेसीएस # 12 स्टोर कैसे बनाया जाए।

X.50 9 प्रमाण पत्र के लिए byte[] (डीईआर) संरचना को वापस करने में निजी कुंजी नहीं होगी।

यदि आपकी मुख्य चिंता (आपके परीक्षण मामले के अनुसार) यह जांचना है कि प्रमाण पत्र आरएसए कुंजी-जोड़ी से बनाया गया था, तो आप इसकी सार्वजनिक कुंजी के प्रकार की जांच कर सकते हैं।

+0

+1, बहुत अच्छा विवरण। क्या आपने पीकेसीएस # 12 स्पेक देखा है? यह * ब्रूटल * है! मुझे लगता है कि पीकेसीएस # 12 के साथ कुछ भी संभव है; आपको निजी कुंजी रखने की आवश्यकता नहीं है। आम तौर पर, पीकेसीएस # 12 का उपयोग निजी कुंजी और संबंधित प्रमाणपत्र रखने के लिए किया जाता है, लेकिन अन्य संभावनाएं भी होती हैं। –

+4

चरण 3 के लिए प्रदान किया गया लिंक नीचे प्रतीत होता है। शुक्र है कि archive.org में अभी भी सामग्री है: http://web.archive.org/web/20100504192226/http://www.fkollmann.de/v2/post/Creating-certificates-using-BouncyCastle।एएसपीएक्स – Kyle

+0

@ जेनॉक्स, मेरा जवाब संपादित करने और इसे बदलने के लिए स्वतंत्र महसूस करें, इससे आपको कुछ बिंदु भी मिलेंगे। – Bruno

6

मुझे पता है यह एक पुरानी पोस्ट है, लेकिन मैं इन उत्कृष्ट लेख जो प्रक्रिया से गुजरना पाया:

Using Bouncy Castle from .NET

+1

का उपयोग करके सीए हस्ताक्षरित प्रमाणपत्र बनाएं, मेटा आपका मित्र है: https://meta.stackexchange.com/questions/8231/are-answers-that-just- कंटेनर-अन्य-वास्तव में-अच्छे-उत्तर – MatthewMartin

+1

लिंक के लिए सुरक्षा चेतावनी प्राप्त करना .. –

+1

मैंने लिंक अपडेट किया है। – haymansfield

संबंधित मुद्दे