Exporting or Saving CX509PrivateKey

2019-07-20 08:55发布

Is it possible somehow to save or export CX509PrivateKey. The idea is that I create a CSR sent to CA get a Certificate and then... somehow I have to get the private key but no idea how, unfortunately nothing found on google.

My piece of code:

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();

1条回答
不美不萌又怎样
2楼-- · 2019-07-20 09:26

Actually I have soled this task in this way (here is a bit more code, so you can understand what I was trying to do).

Here all the job is done.

/*
    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;
}

The private key is in the CARequest.

/*
    using Org.BouncyCastle.Crypto;
*/

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

The private key is saved in the memory until the moment we need it to save to the PFX file and it is generated at the moment we create the certificate request. So here the certificate request generating method.

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
        };
}
查看更多
登录 后发表回答