2015-05-04 3 views
1

Возможно ли каким-либо образом сохранить или экспортировать CX509PrivateKey. Идея в том, что я создаю CSR, отправленную в CA, получить сертификат, а затем ... как-то я должен получить закрытый ключ, но не знаю, как, к сожалению, ничего не найдено в google.Экспорт или сохранение CX509PrivateKey

Мой кусок кода:

var objPrivateKey = new CX509PrivateKey(); 
objPrivateKey.Length = int.Parse(ConfigurationManager.AppSettings["objPrivateKeyLength"]); 
objPrivateKey.KeySpec = X509KeySpec.XCN_AT_SIGNATURE; 
objPrivateKey.KeyUsage = X509PrivateKeyUsageFlags.XCN_NCRYPT_ALLOW_ALL_USAGES; 
objPrivateKey.MachineContext = false; 
objPrivateKey.ExportPolicy = X509PrivateKeyExportFlags.XCN_NCRYPT_ALLOW_EXPORT_FLAG; 
objPrivateKey.CspInformations = objCSPs; 
objPrivateKey.Create(); 
+0

Я отредактировал ваше название. Пожалуйста, смотрите: «Если вопросы включают« теги »в их названиях?] (Http://meta.stackexchange.com/questions/19190/), где консенсус« нет, они не должны ». Также см. [Help/tagging]. –

+0

@JohnSaunders Я не уверен, что это полный консенсус, хотя (см. [Этот вопрос тоже] (http://meta.stackoverflow.com/a/292281/372643)). В то время как C# здесь не особенно полезен, полезно иметь представление об окружающей среде в заголовке (например, .Net или Java), а не просто имя класса, которое может принадлежать обоим (что имеет место для 'X509Certificate'). – Bruno

+0

@Bruno: извините, не согласен. [tag: .net] полезен в тегах, может быть (я добавил его там), но действительно ли вы утверждаете, что каждый вопрос о .NET должен содержать слово «.NET» в заголовке? См. Также http://stackoverflow.com/help/tagging, особенно раздел «Должен ли я использовать теги в заголовках?» –

ответ

3

На самом деле я подошвой эту задачу таким образом (здесь немного больше кода, так что вы можете понять, что я пытался сделать).

Здесь вся работа выполнена.

/* 
    using CERTADMINLib; 
    using CERTCLILib; 
    using CertSevAPI.Core.Models; 
    using CertSrvAPI.Core; 
    using CertSrvAPI.Core.Models; 
    using Org.BouncyCastle.Asn1; 
    using Org.BouncyCastle.Asn1.Pkcs; 
    using Org.BouncyCastle.Asn1.X509; 
    using Org.BouncyCastle.Crypto; 
    using Org.BouncyCastle.Crypto.Generators; 
    using Org.BouncyCastle.Crypto.Prng; 
    using Org.BouncyCastle.Pkcs; 
    using Org.BouncyCastle.Security; 
    using System; 
*/ 

var caService = new CAService(); 

// Create a certificate request. 
// The private key is here. 
var caRequest = caService.CertRequest(subjectDN); 

// Submit the certificate request and get the response. 
var caResponse = caService.SendCertRequest(caRequest.Request); 

// If certificated is not issued return null. 
if (!caService.IsIssued(caResponse.Disposition)) 
{ 
    return null; 
} 

// Download the P7B file from CA. 
var p7b = new WebClient().DownloadData(
    _appSettings.CERT_SRV + "/CertSrv/CertNew.p7b?ReqID=" + caResponse.CertRequest.GetRequestId() + "&Enc=bin"); 

try 
{ 
    var certCollection = new X509Certificate2Collection(); 

    // Import the downloaded file. 
    certCollection.Import(p7b); 

    // Create a PKCS store. 
    var pfx = new Pkcs12Store(); 

    // Insert root CA certificate into the PKCS store. 
    pfx.SetCertificateEntry("rootCert", 
     new X509CertificateEntry(DotNetUtilities.FromX509Certificate(certCollection[0]))); 

    // Get the second certificate from the downloaded file. 
    // That one is the generated certificate for our request. 
    var certificateEntry = new X509CertificateEntry[1]; 
    certificateEntry[0] = new X509CertificateEntry(DotNetUtilities.FromX509Certificate(certCollection[1])); 

    // Insert our certificate with the private key 
    // under the same alias so then we know that this private key 
    // is for our certificate. 
    pfx.SetKeyEntry("taxkey", new AsymmetricKeyEntry(caRequest.PrivateKey), certificateEntry); 

    var memoryStream = new MemoryStream(); 

    // Stream PFX store using the desired password 
    // for our file. 
    pfx.Save(memoryStream, password.ToCharArray(), new SecureRandom()); 

    var pfxBytes = memoryStream.GetBuffer(); 
    pfxBytes = Pkcs12Utilities.ConvertToDefiniteLength(pfxBytes, password.ToCharArray()); 

    // Here you can save the pfxBytes to a file, if you want. 
    // Actually I needed it to give as a response in MVC application. 
    return File(pfxBytes, System.Net.Mime.MediaTypeNames.Application.Octet, "NewCert.pfx"); 
} 
catch (Exception ex) 
{ 
    // If there is an error remove private key from 
    // the memory. 
    caRequest.PrivateKey = null; 
    caRequest.Request = null; 

    ErrorSignal.FromCurrentContext().Raise(ex); 

    if (showError != null && showError.ToLower() == "true") 
    { 
     throw ex; 
    } 

    return null; 
} 

Закрытый ключ находится в CARequest.

/* 
    using Org.BouncyCastle.Crypto; 
*/ 

public class CARequestModel 
{ 
    public AsymmetricKeyParameter PrivateKey { get; set; } 
    public string Request { get; set; } 
} 

Секретный ключ сохраняется в памяти до момента, мы должны его сохранить в файл PFX и генерируется в данный момент мы создаем запрос на сертификат. Итак, здесь метод генерации запроса сертификата.

public CARequestModel CertRequest(string subjectDN) 
{ 
    var name = new X509Name(subjectDN); 
    var rsaKeyPairGenerator = new RsaKeyPairGenerator(); 

    rsaKeyPairGenerator.Init(
     new KeyGenerationParameters(new SecureRandom(
       new CryptoApiRandomGenerator()), _appSettings.PRIVATE_KEY_LENGHT)); 

    // Generate key pair. 
    var keyPair = rsaKeyPairGenerator.GenerateKeyPair(); 

    // Get the private key. 
    var privateKey = keyPair.Private; 

    // Get the public key. 
    var publicKey = keyPair.Public; 

    // Set the key usage scope. 
    var keyUsage = new KeyUsage(KeyUsage.DigitalSignature); 
    var extensionsGenerator = new X509ExtensionsGenerator(); 

    extensionsGenerator.AddExtension(X509Extensions.KeyUsage, true, keyUsage); 

    var attribute = new AttributeX509(
     PkcsObjectIdentifiers.Pkcs9AtExtensionRequest, new DerSet(extensionsGenerator.Generate())); 

    // Create the certificate request 
    var csr = new Pkcs10CertificationRequest("SHA1WITHRSA", name, publicKey, new DerSet(attribute), privateKey); 

    // Get it as DER, because then I have to submit it to the MS CA server. 
    var csrBytes = csr.GetDerEncoded(); 

    // Return the Request and private key 
    return 
     new CARequestModel 
     { 
      Request = Convert.ToBase64String(csrBytes), 
      PrivateKey = privateKey 
     }; 
} 
Смежные вопросы