如何使证书中的私钥不可导出 C# [英] How to make priv key in certificate not exportable C#

查看:30
本文介绍了如何使证书中的私钥不可导出 C#的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以在下面你会找到我的代码,它创建了一个带有私钥的自签名证书.它存储在用户存储中.现在当我使用 mmc 工具时,我可以从证书中导出私钥吗?我认为这是您在创建证书时必须明确添加的标志?

So below you'll find my code that creates a self signed certificate with the private key in there. It's stored in the user store. Now when I use the mmc tool I can just export the private key from the certificate? I thought that was a flag you had to explicitly add when you create the cert?

所以我想知道的是,如何更改此代码以便私钥不再可通过 mmc 导出.

So what I wanna know is, how do I change this code so that the private key is no longer exportable through mmc.

代码:

public static X509Certificate2 GenerateSelfSignedCertificateNoCA(string subjectName, string issuerName)
{
        const int keyStrength = 2048;

        // Generating Random Numbers
        CryptoApiRandomGenerator randomGenerator = new CryptoApiRandomGenerator();
        SecureRandom random = new SecureRandom(randomGenerator);

        // The Certificate Generator
        X509V3CertificateGenerator certificateGenerator = new X509V3CertificateGenerator();

        // Serial Number
        BigInteger serialNumber = BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(Int64.MaxValue), random);
        certificateGenerator.SetSerialNumber(serialNumber);

        // Signature Algorithm
        const string signatureAlgorithm = "SHA256WithRSA";
        certificateGenerator.SetSignatureAlgorithm(signatureAlgorithm);

        // Issuer and Subject Name
        X509Name subjectDN = new X509Name(subjectName);
        X509Name issuerDN = new X509Name(issuerName);
        certificateGenerator.SetIssuerDN(issuerDN);
        certificateGenerator.SetSubjectDN(subjectDN);

        // Valid For
        DateTime notBefore = DateTime.UtcNow.Date;
        DateTime notAfter = notBefore.AddYears(2);

        certificateGenerator.SetNotBefore(notBefore);
        certificateGenerator.SetNotAfter(notAfter);

        // Subject Public Key
        AsymmetricCipherKeyPair subjectKeyPair;
        var keyGenerationParameters = new KeyGenerationParameters(random, keyStrength);
        var keyPairGenerator = new RsaKeyPairGenerator();
        keyPairGenerator.Init(keyGenerationParameters);
        subjectKeyPair = keyPairGenerator.GenerateKeyPair();

        certificateGenerator.SetPublicKey(subjectKeyPair.Public);

        // Generating the Certificate
        AsymmetricCipherKeyPair issuerKeyPair = subjectKeyPair;

        // selfsign certificate
        Org.BouncyCastle.X509.X509Certificate certificate = certificateGenerator.Generate(subjectKeyPair.Private, random);

        // correcponding private key
        PrivateKeyInfo info = PrivateKeyInfoFactory.CreatePrivateKeyInfo(subjectKeyPair.Private);

        // merge into X509Certificate2
        X509Certificate2 x509 = new System.Security.Cryptography.X509Certificates.X509Certificate2(certificate.GetEncoded());


        Asn1Sequence seq = (Asn1Sequence)Asn1Object.FromByteArray(info.PrivateKey.GetDerEncoded());
        if (seq.Count != 9)
        {
            //throw new PemException("malformed sequence in RSA private key");
        }

        RsaPrivateKeyStructure rsa = new RsaPrivateKeyStructure(seq);
        RsaPrivateCrtKeyParameters rsaparams = new RsaPrivateCrtKeyParameters(
            rsa.Modulus, rsa.PublicExponent, rsa.PrivateExponent, rsa.Prime1, rsa.Prime2, rsa.Exponent1, rsa.Exponent2, rsa.Coefficient);

        x509.PrivateKey = DotNetUtilities.ToRSA(rsaparams);
        // Console.Write("Private key: " + x509.PrivateKey);
        return x509;

}

推荐答案

DotNetUtilities.ToRSA 将始终将私钥设置为可导出.为了防止这种情况,有一种替代方法可以将您的 BouncyCastle 密钥转换为 .NET X509Certificate2 所采用的 从这里

DotNetUtilities.ToRSA will always set the private key to Exportable. To prevent this, there is an alternate way to convert your BouncyCastle key to a .NET X509Certificate2 as taken from here

    public X509Certificate2 GenerateSelfSignedCertificateNoCA(string subjectName, string issuerName)
    {
        const int keyStrength = 2048;

        // Generating Random Numbers
        CryptoApiRandomGenerator randomGenerator = new CryptoApiRandomGenerator();
        SecureRandom random = new SecureRandom(randomGenerator);

        // The Certificate Generator
        X509V3CertificateGenerator certificateGenerator = new X509V3CertificateGenerator();

        // Serial Number
        BigInteger serialNumber = BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(Int64.MaxValue), random);
        certificateGenerator.SetSerialNumber(serialNumber);

        // Signature Algorithm
        const string signatureAlgorithm = "SHA256WithRSA";
        certificateGenerator.SetSignatureAlgorithm(signatureAlgorithm);

        // Issuer and Subject Name
        X509Name subjectDN = new X509Name(subjectName);
        X509Name issuerDN = new X509Name(issuerName);
        certificateGenerator.SetIssuerDN(issuerDN);
        certificateGenerator.SetSubjectDN(subjectDN);

        // Valid For
        DateTime notBefore = DateTime.UtcNow.Date;
        DateTime notAfter = notBefore.AddYears(2);

        certificateGenerator.SetNotBefore(notBefore);
        certificateGenerator.SetNotAfter(notAfter);

        // Subject Public Key
        AsymmetricCipherKeyPair subjectKeyPair;
        var keyGenerationParameters = new KeyGenerationParameters(random, keyStrength);
        var keyPairGenerator = new RsaKeyPairGenerator();
        keyPairGenerator.Init(keyGenerationParameters);
        subjectKeyPair = keyPairGenerator.GenerateKeyPair();

        certificateGenerator.SetPublicKey(subjectKeyPair.Public);

        // Generating the Certificate
        AsymmetricCipherKeyPair issuerKeyPair = subjectKeyPair;

        // selfsign certificate
        Org.BouncyCastle.X509.X509Certificate certificate = certificateGenerator.Generate(subjectKeyPair.Private, random);

        //import into store
        var certificateEntry = new X509CertificateEntry(certificate);
        string friendlyName = certificate.SubjectDN.ToString();
        var store = new Pkcs12Store();
        store.SetCertificateEntry(friendlyName, certificateEntry);
        store.SetKeyEntry(friendlyName, new AsymmetricKeyEntry(subjectKeyPair.Private), new[] {certificateEntry});

        //save to memorystream
        var password = "password";
        var stream = new MemoryStream();
        store.Save(stream, password.ToCharArray(), random);

        // convert into X509Certificate2
        X509Certificate2 x509 = new System.Security.Cryptography.X509Certificates.X509Certificate2(stream.ToArray(), password, X509KeyStorageFlags.UserKeySet);

        return x509;
    }

私钥现在被标记为 Exportable=false.

The private key is now marked as Exportable=false.

这篇关于如何使证书中的私钥不可导出 C#的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆