我怎么可以创建在C#DSA密钥对自签名证书的PKCS12 P12文件? [英] How can I create a PKCS12 p12 file with selfsigned certificate for DSA keypair in C#?

查看:821
本文介绍了我怎么可以创建在C#DSA密钥对自签名证书的PKCS12 P12文件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要生成我自己的DSA密钥对,并使用C#将其存储为私钥和证书捆绑在.p12文件。

I need to generate my own DSA keypair and store it as a bundle of private key and certificate in .p12 file using C#.

这问题

如何做我C#创建一个PKCS12 .p12文件?

似乎非常相似,但它并不能帮助我,不幸的是,因为有一些显著差异(RSA VS DSA等。)

seems to be very similar, but it does not help me, unfortunately, because there are some significant differences (RSA vs DSA, etc.)

我试图用System.Security.Cryptography.DSACryptoServiceProvider生成密钥对,然后用充气城堡生成X509证书:

I am trying to generate the keypair using System.Security.Cryptography.DSACryptoServiceProvider and then to generate a X509 certificate using Bouncy Castle:

using (DSACryptoServiceProvider csp = new DSACryptoServiceProvider(1024))
{
       privKeyDSA = csp.ExportParameters(true);
       pubKeyDSA = csp.ExportParameters(false);
       var keypair = DotNetUtilities.GetDsaKeyPair(privKeyDSA);

       var gen = new X509V3CertificateGenerator();

       var CN = new X509Name("CN=" + "TEST");
       var SN = BigInteger.ProbablePrime(120, new Random());

       gen.SetSerialNumber(SN);
       gen.SetSubjectDN(CN);
       gen.SetIssuerDN(CN);
       gen.SetNotAfter(DateTime.MaxValue);
       gen.SetNotBefore(DateTime.Now.Subtract(new TimeSpan(7, 0, 0, 0)));
       gen.SetSignatureAlgorithm("sha1WithDSA");
       gen.SetPublicKey(DotNetUtilities.GetDsaPublicKey(pubKeyDSA));
       var newCert = gen.Generate(keypair.Private);


       certificateDSA = new X509Certificate2(DotNetUtilities.ToX509Certificate((Org.BouncyCastle.X509.X509Certificate)newCert));

       certificateDSA.PrivateKey = csp;
       StringBuilder builder = new StringBuilder();

        builder.AppendLine("-----BEGIN CERTIFICATE-----");
        builder.AppendLine(Convert.ToBase64String(certificateDSA.Export(X509ContentType.Cert), Base64FormattingOptions.InsertLineBreaks));
        builder.AppendLine("-----END CERTIFICATE-----");

        string result = builder.ToString();
        byte[] pkcsData = certificateDSA.Export(X509ContentType.Pfx, "changeit");
}



不过,该行 certificateDSA.PrivateKey = CSP; 抛出一个 CryptographicUnexpectedOperationException 与消息:,该证书不符合指定的值的公共密钥

我真的不明白发生了什么。我究竟做错了什么?谢谢!

I really do not understand what is happening. What am I doing wrong? Thanks!

推荐答案

了浓厚的兴趣这个,这里是我的小调查。当您设置certificateDSA的PrivateKey,.NET代码的功能大致是这样的:

Got interested by this and here is my little investigation. When you set PrivateKey of certificateDSA, .NET code does roughly this:

byte[] numArray1 = ((ICspAsymmetricAlgorithm) certificateDSA.PublicKey.Key).ExportCspBlob(false);
byte[] numArray2 = csp.ExportCspBlob(false);
// And then those two blobs are compared byte by byte



这些斑点是不同的起点在420位(他们有444的长度)。所以,什么是错的CSP参数。这并不容易比较原始字节,所以让我们把它们转换成可读的XML用:

Those blobs are different starting at position 420 (they have length of 444). So something is wrong in csp parameters. It's not easy to compare raw bytes, so let's convert them to readable xml with:

var xml1 = certificateDSA.PublicKey.Key.ToXmlString(false);
var xml2 = csp.ToXmlString(false);



我们将得到的是这样的:

What we will get is this:

<DSAKeyValue> <!--this is parameters of cert public key-->
    <P>2arEQPD3/tKm7pJF1y4gN0/4WzSGfkgFwdmtmoUf/gHoXpdBetRH/5j98qo4k1ybePxM4om4y6n9vhxijocMw5LaeQPceGyNOEScWXXrNKAcUsK74klQmiPOoI2qI1zU5v2HrilKmkOELH81U8/Qmmjmg7ouOdOHqlZAxW9Sv8M=</P>
    <Q>lzRdUtp56eZHIgxRemvdHciGIfc=</Q>
    <G>Z/2T+jXvv0ZLswbuMd9DxrHldakJxZ8JNGRf1QzN09B2VO9WYAzUy0S+J8hbYQjP/jzWbmL5LaK57v+MUOmOHzFwNqfVMe9OUglUfF3nN990ur9hp6csu8+vCEQt3EoI8Wmh/b2yqhtKRN6U494vf33WKo1NCNQapB+iWVQ/egQ=</G>
    <Y>ykcPXFIxWvYDDbbY05oD3hD6LsM5rk76FakUY8YiCo8ZwWbMIlQw+v5nOYS9vpQaZAzUqxx9OXIGSTUGItruTARkDqZ0nGKL0r94Zhog1Y0wU2AVKJh8Vjq/dLFyDDGZZsxBZtmI8TDyKGJbZqvzGbdGLhoRxRFmNi1fVsADv+U=</Y>
</DSAKeyValue>

<DSAKeyValue> <!-- this is paramteres of original DSACryptoServiceProvider-->
    <P>2arEQPD3/tKm7pJF1y4gN0/4WzSGfkgFwdmtmoUf/gHoXpdBetRH/5j98qo4k1ybePxM4om4y6n9vhxijocMw5LaeQPceGyNOEScWXXrNKAcUsK74klQmiPOoI2qI1zU5v2HrilKmkOELH81U8/Qmmjmg7ouOdOHqlZAxW9Sv8M=</P>
    <Q>lzRdUtp56eZHIgxRemvdHciGIfc=</Q>
    <G>Z/2T+jXvv0ZLswbuMd9DxrHldakJxZ8JNGRf1QzN09B2VO9WYAzUy0S+J8hbYQjP/jzWbmL5LaK57v+MUOmOHzFwNqfVMe9OUglUfF3nN990ur9hp6csu8+vCEQt3EoI8Wmh/b2yqhtKRN6U494vf33WKo1NCNQapB+iWVQ/egQ=</G>
    <Y>ykcPXFIxWvYDDbbY05oD3hD6LsM5rk76FakUY8YiCo8ZwWbMIlQw+v5nOYS9vpQaZAzUqxx9OXIGSTUGItruTARkDqZ0nGKL0r94Zhog1Y0wU2AVKJh8Vjq/dLFyDDGZZsxBZtmI8TDyKGJbZqvzGbdGLhoRxRFmNi1fVsADv+U=</Y>
    <Seed>1hiZoCQFivF9xDZdQEGue65oObA=</Seed>
    <PgenCounter>Og==</PgenCounter>
</DSAKeyValue>

您看到原来DSACryptoServiceProvider包括种子和PgenCounter,一边用充气城堡,证书的公钥生成证书后不包含它们。这些参数是可选的(在某种意义上该公钥可能不包含的话),但如果它们存在,它们应存在于两侧(私人和公共)。我们怎样才能解决这个?下面是代码:

You see that original DSACryptoServiceProvider includes Seed and PgenCounter, while after generating certificate with Bouncy Castle, certificate's public key does not contain them. Those parameters are optional (in a sense that public key may not contain then), but if they are present, they should be present on both sides (private and public). How can we workaround this? Here is the code:

using (DSACryptoServiceProvider csp = new DSACryptoServiceProvider(1024)) {
            var parameters = csp.ExportParameters(true);                
            var keypair = DotNetUtilities.GetDsaKeyPair(parameters);
            var gen = new X509V3CertificateGenerator();
            var CN = new X509Name("CN=" + "TEST");
            var SN = BigInteger.ProbablePrime(120, new Random());
            gen.SetSerialNumber(SN);
            gen.SetSubjectDN(CN);
            gen.SetIssuerDN(CN);
            gen.SetNotAfter(DateTime.Now.AddDays(1));
            gen.SetNotBefore(DateTime.Now.Subtract(new TimeSpan(7, 0, 0, 0)));
            gen.SetSignatureAlgorithm("sha1WithDSA");
            gen.SetPublicKey(keypair.Public);
            var newCert = gen.Generate(keypair.Private);

            var certificateDSA = new X509Certificate2(DotNetUtilities.ToX509Certificate(newCert));
            // added block
            parameters.Seed = new byte[20];
            unchecked {
                parameters.Counter = (int) 0xFFFFFFFF;
            }
            csp.ImportParameters(parameters);
            // end of added block
            certificateDSA.PrivateKey = csp;
            StringBuilder builder = new StringBuilder();

            builder.AppendLine("-----BEGIN CERTIFICATE-----");
            builder.AppendLine(Convert.ToBase64String(certificateDSA.Export(X509ContentType.Pkcs12), Base64FormattingOptions.InsertLineBreaks));
            builder.AppendLine("-----END CERTIFICATE-----");

            string result = builder.ToString();                
        }

我们在这里做什么是产生一切后,但分配的私钥证书之前,我们从DSACryptoServiceProvider参数删除种子和计数器。此代码不会引发错误并完成罚款。也许有这个解决办法一些注意事项,但尽管如此,它可能是进一步的调查问题是有用的,即使它不能完全修复它。

What we do here is after generating everything, but before assigning private key to certificate, we "removing" seed and counter from DSACryptoServiceProvider parameters. This code does not throw errors and completes fine. Maybe there are some caveats in this workaround, but nevertheless it might be useful to futher investigating the issue, even if it not fixes it completely.

这篇关于我怎么可以创建在C#DSA密钥对自签名证书的PKCS12 P12文件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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