fx509Certificate错误:证书公钥与存储的密钥集不匹配

时间:2016-11-17 19:27:20

标签: ssl-certificate rsa x509certificate bouncycastle x509certificate2

我需要一些严肃的证书上帝干预。我使用BouncyCastle csharp生成CA和SSL自签名证书。以下是生成证书的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;


//Downloaded using nuget, source: http://www.bouncycastle.org/csharp/
//Library is open-source.

namespace CertificateToolLibrary
{
    using System;
    using System.Security.Cryptography;
    using System.Security.Cryptography.X509Certificates;
    using Org.BouncyCastle.Asn1;
    using Org.BouncyCastle.Asn1.X9;
    using Org.BouncyCastle.Asn1.Pkcs;
    using Org.BouncyCastle.Asn1.X509;
    using Org.BouncyCastle.Crypto;
    using Org.BouncyCastle.Crypto.Generators;
    using Org.BouncyCastle.Crypto.Parameters;
    using Org.BouncyCastle.Crypto.Prng;
    using Org.BouncyCastle.Math;
    using Org.BouncyCastle.OpenSsl;
    using Org.BouncyCastle.Pkcs;
    using Org.BouncyCastle.Security;
    using Org.BouncyCastle.Utilities;
    using Org.BouncyCastle.X509.Extension;
    using Org.BouncyCastle.X509;

    public class X509Certificate2Builder
    {
        public string SubjectName
        { set { _subjectName = value; }
            get { return _subjectName; }
        }

        public string SubjectAlternativeName
        { set { _subjectAlternativeName = value; }
            get { return _subjectAlternativeName; }
        }

        public string IssuerName
        { set { _issuerName = value; }
            get { return _issuerName; }
        }

        public AsymmetricAlgorithm IssuerPrivateKey
        { set { _issuerPrivateKey = value; } 
          get { return _issuerPrivateKey; }
        }

        public X509Certificate2 Issuer
        {
            set
            {
                _issuer = value;
                _issuerName = value.IssuerName.Name;
                if (value.HasPrivateKey)
                    _issuerPrivateKey = value.PrivateKey;
            }
            get { return _issuer; }
        }

        public int? KeyStrength
        { set { _keyStrength = value ?? 2048; }
            get { return _keyStrength; }
        }

        public DateTime? NotBefore
        { set { _notBefore = value; }
            get { return _notBefore; }
        }

        public DateTime? NotAfter
        { set { _notAfter = value; }
            get { return _notAfter; }
        }

        public bool Intermediate
        { set { _intermediate = value; }
            get { return _intermediate; }
        }

        private string _subjectName;
        private string _subjectAlternativeName;
        private X509Certificate2 _issuer;
        private string _issuerName;
        private AsymmetricAlgorithm _issuerPrivateKey;
        private int _keyStrength = 2048;
        private DateTime? _notBefore;
        private DateTime? _notAfter;
        private bool _intermediate = true;

        private const string KEY_CONTAINER_NAME = "cf16236d-0e91-4cb7-9670-6cdbafe54c11";

        public X509Certificate2 BuildCACert(ref AsymmetricKeyParameter CaPrivateKey)
        {
            const int keyStrength = 2048;

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

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

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

            // Signature Algorithm
            certificateGenerator.SetSignatureAlgorithm("SHA512withRSA");

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

            // Valid For
            certificateGenerator.SetNotBefore(_notBefore ?? DateTime.UtcNow.Date.AddDays(-1));
            certificateGenerator.SetNotAfter(_notAfter ?? DateTime.UtcNow.Date.AddYears(5));


            //Turn Basic Constraints off to remove the error on scout for mozilla_pkix_error_ca_cert_used_as_end entity error:
            //https://bugzilla.mozilla.org/show_bug.cgi?id=1034124

            // Basic Constraints - certificate is allowed to be used as intermediate.
            certificateGenerator.AddExtension(X509Extensions.BasicConstraints, true, new BasicConstraints(_intermediate));

            //Key Usage(s)
            certificateGenerator.AddExtension(X509Extensions.KeyUsage, true, new KeyUsage(KeyUsage.CrlSign | KeyUsage.KeyCertSign));

            // Subject Public Key
            AsymmetricCipherKeyPair subjectKeyPair;
            KeyGenerationParameters keyGenerationParameters = new KeyGenerationParameters(random, keyStrength);
            RsaKeyPairGenerator 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(issuerKeyPair.Private, random);
            X509Certificate2 x509 = new System.Security.Cryptography.X509Certificates.X509Certificate2(certificate.GetEncoded());

            CaPrivateKey = issuerKeyPair.Private;

            return x509;

        }

        public X509Certificate2 BuildSelfSignedCert(AsymmetricKeyParameter issuerPrivKey)
        {
            const int keyStrength = 2048;

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

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

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

            // Signature Algorithm
            certificateGenerator.SetSignatureAlgorithm("SHA512withRSA");

            // Issuer and Subject Name
            certificateGenerator.SetIssuerDN(new X509Name(_issuerName ?? _subjectName));
            certificateGenerator.SetSubjectDN(new X509Name(_subjectName));


            //Subject Alternative Name
            if (!(String.IsNullOrEmpty(_subjectAlternativeName)))
            {
                //IP Addresss
                GeneralNames dnsAltName = new GeneralNames(new GeneralName[] { new GeneralName(GeneralName.IPAddress, _subjectAlternativeName), new GeneralName(GeneralName.DnsName, _subjectAlternativeName) });

                //certificateGenerator.AddExtension(X509Extensions.SubjectAlternativeName, false, subjectAltName);
                certificateGenerator.AddExtension(X509Extensions.SubjectAlternativeName, false, dnsAltName);

            }

            // Valid For
            certificateGenerator.SetNotBefore(_notBefore ?? DateTime.UtcNow.Date.AddDays(-1));
            certificateGenerator.SetNotAfter(_notAfter ?? DateTime.UtcNow.Date.AddYears(5));


            // Basic Constraints - SSL certificate not allowed to be used as intermediate.
            certificateGenerator.AddExtension(X509Extensions.BasicConstraints, false, new BasicConstraints(false));

            // Authority Key Identifier
            var authorityKeyIdentifier = new AuthorityKeyIdentifierStructure(DotNetUtilities.FromX509Certificate(_issuer));
            certificateGenerator.AddExtension(X509Extensions.AuthorityKeyIdentifier.Id, false, authorityKeyIdentifier);

            //Key Usage(s)
            certificateGenerator.AddExtension(X509Extensions.KeyUsage, true, new KeyUsage(KeyUsage.DigitalSignature | KeyUsage.NonRepudiation | KeyUsage.KeyEncipherment | KeyUsage.DataEncipherment));

            //Extended Key Usage(s)
            var usages = new[] { KeyPurposeID.IdKPClientAuth, KeyPurposeID.IdKPServerAuth };
            certificateGenerator.AddExtension(X509Extensions.ExtendedKeyUsage.Id, false, new ExtendedKeyUsage(usages));

            // 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(issuerPrivKey, random);

            // corresponding 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 = ToDotNetKey(rsaparams);

            return x509;

        }

        public static AsymmetricAlgorithm ToDotNetKey(RsaPrivateCrtKeyParameters privateKey)
        {
            var cspParams = new CspParameters
            {
                ProviderName = "Microsoft Enhanced RSA and AES Cryptographic Provider",
                ProviderType = 24,
                KeyContainerName = KEY_CONTAINER_NAME,
                KeyNumber = (int)KeyNumber.Signature,
                Flags = CspProviderFlags.UseMachineKeyStore
            };

            RSACryptoServiceProvider rsaProvider = new RSACryptoServiceProvider(cspParams);

            RSAParameters parameters = new RSAParameters
            {
                Modulus = privateKey.Modulus.ToByteArrayUnsigned(),
                P = privateKey.P.ToByteArrayUnsigned(),
                Q = privateKey.Q.ToByteArrayUnsigned(),
                DP = privateKey.DP.ToByteArrayUnsigned(),
                DQ = privateKey.DQ.ToByteArrayUnsigned(),
                InverseQ = privateKey.QInv.ToByteArrayUnsigned(),
                D = privateKey.Exponent.ToByteArrayUnsigned(),
                Exponent = privateKey.PublicExponent.ToByteArrayUnsigned()
            };

            rsaProvider.ImportParameters(parameters);

            return rsaProvider;
        }
    }
}

然后,调用代码:

AsymmetricKeyParameter myCAprivateKey = null;

//CA Certificate Actions
ca2 = new X509Certificate2Builder { SubjectName = "CN=Test Certificate Authority" }.BuildCACert(ref myCAprivateKey);

X509Store castore = new X509Store(StoreName.Root, StoreLocation.LocalMachine);
castore.Open(OpenFlags.ReadWrite | OpenFlags.MaxAllowed);

castore.Add(ca2);
castore.Close();

//build out the file name.
string localCAFile = txtPFXExport.Text + "\\TestCertificateAuthority.cer";

//export  CA cert to desktop.
TestCertificateCreationUtility.Program.ExportCertificateToFileSystem(ca2, localCAFile, false, txtPFXPass.Text);

//SSL Certificate Actions
var cert2 = new X509Certificate2Builder { SubjectName = "CN=" + txtCNAME.Text, SubjectAlternativeName = txtSAN.Text, Issuer = ca2, Intermediate = true }.BuildSelfSignedCert(myCAprivateKey);

//build out the file name.
string localPFXFile = txtPFXExport.Text + "\\" + txtCNAME.Text + ".pfx";

然而,当我运行certutil -v -store MY时,我得到了:

================ Certificate 0 ================
X509 Certificate:
Version: 3
Serial Number: 6b1ccf343b18c7e7
Signature Algorithm:
    Algorithm ObjectId: 1.2.840.113549.1.1.13 sha512RSA
    Algorithm Parameters:
    05 00
Issuer:
    CN=Test Certificate Authority
  Name Hash(sha1): e63af6f08c0a4f2e190c7bc1a406ac57e167b460
  Name Hash(md5): a2f27838878e6ae3df34ed2d9b970a2d

 NotBefore: 11/15/2016 7:00 PM
 NotAfter: 11/16/2021 7:00 PM

Subject:
    CN=10.13.206.99
  Name Hash(sha1): ee5776f520e749311a56a44a5b7b15d9ffb5e678
  Name Hash(md5): 187b17b18c208ad942b23763d5feacd7

Public Key Algorithm:
    Algorithm ObjectId: 1.2.840.113549.1.1.1 RSA
    Algorithm Parameters:
    05 00
Public Key Length: 2048 bits
Public Key: UnusedBits = 0
    0000  30 82 01 0a 02 82 01 01  00 ae 12 4d 4d 4a d8 e9
    0010  f8 77 9b 2e 29 1f 94 04  d1 8c 59 2b 62 05 1a 9c
    0020  0c 2a f7 62 28 ce bd 0d  44 35 18 01 8e 43 56 7b
    0030  82 6f 81 79 65 fa 7b c6  1b a4 f2 21 c3 bb 14 cb
    0040  79 90 5a 4e b2 fc 37 91  3d cb fe c1 a4 13 df 02
    0050  2e f4 da 01 6a bd d2 59  eb af 18 3d 02 36 a6 d4
    0060  9d 2a 41 72 d4 da f3 65  9c 78 f0 2a 63 df 38 a7
    0070  4d cd 7a 78 67 cb 37 87  52 55 8d 68 4b 5a 7a eb
    0080  32 b4 d3 de f4 67 9a 34  8a db 85 b5 bd 55 9f 99
    0090  72 53 d3 92 85 aa b6 16  87 83 e0 59 11 64 e1 79
    00a0  d9 03 a0 07 bd 1e cd 40  68 ec d2 06 ce 6f 88 31
    00b0  34 c9 a5 34 90 fa 0c bd  50 7f fd 67 df 92 69 f5
    00c0  f2 62 0c c2 f6 2a 94 62  dd 97 db 01 71 2b aa 78
    00d0  3f a7 94 ba 70 e0 d3 cb  d8 ae f3 87 8b c1 35 5e
    00e0  e7 1d b8 00 fc 34 db 75  f0 ad b6 67 ac 6f 81 f7
    00f0  6a 63 3c d3 1b f7 18 5d  83 ad 58 c1 79 2f 4a 56
    0100  3e e6 3a a4 a3 94 0c 37  a5 02 03 01 00 01
Certificate Extensions: 4
    2.5.29.19: Flags = 0, Length = 2
    Basic Constraints
        Subject Type=End Entity
        Path Length Constraint=None

    2.5.29.35: Flags = 0, Length = 4e
    Authority Key Identifier
        KeyID=a5 25 a6 c6 bf 95 07 31 0f 85 cf cc b6 0a da 16 92 f0 85 47
        Certificate Issuer:
             Directory Address:
                  CN=Test Certificate Authority
        Certificate SerialNumber=11 c6 33 31 b9 42 f1 7d

    2.5.29.15: Flags = 1(Critical), Length = 4
    Key Usage
        Digital Signature, Non-Repudiation, Key Encipherment, Data Encipherment (f0)

    2.5.29.37: Flags = 0, Length = 16
    Enhanced Key Usage
        Client Authentication (1.3.6.1.5.5.7.3.2)
        Server Authentication (1.3.6.1.5.5.7.3.1)

Signature Algorithm:
    Algorithm ObjectId: 1.2.840.113549.1.1.13 sha512RSA
    Algorithm Parameters:
    05 00
Signature: UnusedBits=0
    0000  e4 0a d2 00 0f 95 6b 8e  b8 bd da ff 7d 54 5c b4
    0010  d0 13 39 de 53 35 91 dd  eb c5 0c 9f 1b 65 01 eb
    0020  68 ad 0e b9 cc 4f 11 64  f0 30 49 95 30 5f de 4a
    0030  d7 ec c6 22 db 33 c4 7e  50 d7 fc 79 1d 8c 9c 40
    0040  18 9d 3b 7d 68 3d c1 51  ad e3 30 99 62 cf 5a 7a
    0050  c3 fb 98 06 40 0f 2f 38  60 dd 6e 22 d5 9c df 94
    0060  71 c3 a7 c9 80 1d 68 a0  59 e2 89 a6 c2 b5 9a 69
    0070  c4 0a 27 d3 80 a5 77 9e  15 c6 da 79 c1 99 7a c4
    0080  e7 b8 77 b6 db f8 1d c7  b9 7c 80 de 66 ac e7 38
    0090  09 24 0a c5 f9 95 cd 01  0f 23 3d 2c 8f 07 5f 8e
    00a0  de e2 50 2e 54 44 72 76  f6 1f 64 d2 bf 47 39 98
    00b0  08 79 87 7b f0 c3 c0 bb  69 1d f3 97 1f ab 70 d1
    00c0  d7 5b ee 18 08 fc e6 a2  92 73 28 65 98 6e 45 36
    00d0  59 8d 37 78 83 e8 80 6b  66 cc ae 49 14 2c 28 11
    00e0  29 b3 b3 22 81 b7 27 d7  33 84 d7 75 8c 4d 90 c4
    00f0  11 5b c2 11 9b f6 f1 5d  d3 6a 04 e1 65 4e 49 69
Non-root Certificate
Key Id Hash(rfc-sha1): cd a7 52 88 42 30 3b f8 9d bf 05 cd 05 52 f8 fa 22 36 8f 48
Key Id Hash(sha1): 2a 62 63 b4 80 89 57 d0 bb a1 ac 34 1e 06 f0 45 7f 92 61 07
Key Id Hash(md5): 595eb604a64cea82117caae36148fbfd
Key Id Hash(sha256): 0df22d23712b109af3cce45abe23ea6f666e756dad3c2b6dbffad05946fefcbf
Cert Hash(md5): dd 7e 1a 00 10 30 67 c7 b9 1e 5f ea b0 09 c3 6e
Cert Hash(sha1): 87 d4 8c 1d 52 44 10 d9 ff 71 9f c8 31 80 20 34 d6 82 03 94
Cert Hash(sha256): 81ab6f802ed270f184d2e96fbd0e34953a228c5185f0812574b3373048882edf
Signature Hash: f4b1c5cba4228969ccdccd237078ace1e249673edcf2465cd399a0a14bf64ee47ebf4a9feb062c504b95772eebcab9a89eeeced558f42788876add2ce0b5531c

  CERT_MD5_HASH_PROP_ID(4):
    dd 7e 1a 00 10 30 67 c7 b9 1e 5f ea b0 09 c3 6e

  CERT_SHA1_HASH_PROP_ID(3):
    87 d4 8c 1d 52 44 10 d9 ff 71 9f c8 31 80 20 34 d6 82 03 94

  CERT_KEY_PROV_INFO_PROP_ID(2):
    Key Container = {6E928910-36B1-4C1A-8B72-CF33D5C85C98}
  Unique container name: 5619e9cf0e097e0aa54f3dcfec6a06c7_521b1f9c-0dde-4e20-b00f-1cf68cd6e71b
    Provider = Microsoft Enhanced RSA and AES Cryptographic Provider
    ProviderType = 18
  Flags = 20 (32)
    CRYPT_MACHINE_KEYSET -- 20 (32)
    KeySpec = 2 -- AT_SIGNATURE

  CERT_KEY_IDENTIFIER_PROP_ID(20):
    2a 62 63 b4 80 89 57 d0 bb a1 ac 34 1e 06 f0 45 7f 92 61 07

  Provider = Microsoft Enhanced RSA and AES Cryptographic Provider
  ProviderType = 18
  Unique container name: 5619e9cf0e097e0aa54f3dcfec6a06c7_521b1f9c-0dde-4e20-b00f-1cf68cd6e71b
  RSA
  PP_KEYSTORAGE = 1
    CRYPT_SEC_DESCR -- 1
  KP_PERMISSIONS = 3f (63)
    CRYPT_ENCRYPT -- 1
    CRYPT_DECRYPT -- 2
    CRYPT_EXPORT -- 4
    CRYPT_READ -- 8
    CRYPT_WRITE -- 10 (16)
    CRYPT_MAC -- 20 (32)

  D:AI(A;ID;GAGR;;;S-1-5-21-3932969098-2735528041-405945392-1012)(A;ID;GR;;;WD)(A;ID;GAGR;;;BA)

    Allow Full Control  TEST\Test
    Allow Read  Everyone
    Allow Full Control  BUILTIN\Administrators


Certificate Public Key:
Version: 3
Public Key Algorithm:
    Algorithm ObjectId: 1.2.840.113549.1.1.1 RSA
    Algorithm Parameters:
    05 00
Public Key Length: 2048 bits
Public Key: UnusedBits = 0
    0000  30 82 01 0a 02 82 01 01  00 ae 12 4d 4d 4a d8 e9
    0010  f8 77 9b 2e 29 1f 94 04  d1 8c 59 2b 62 05 1a 9c
    0020  0c 2a f7 62 28 ce bd 0d  44 35 18 01 8e 43 56 7b
    0030  82 6f 81 79 65 fa 7b c6  1b a4 f2 21 c3 bb 14 cb
    0040  79 90 5a 4e b2 fc 37 91  3d cb fe c1 a4 13 df 02
    0050  2e f4 da 01 6a bd d2 59  eb af 18 3d 02 36 a6 d4
    0060  9d 2a 41 72 d4 da f3 65  9c 78 f0 2a 63 df 38 a7
    0070  4d cd 7a 78 67 cb 37 87  52 55 8d 68 4b 5a 7a eb
    0080  32 b4 d3 de f4 67 9a 34  8a db 85 b5 bd 55 9f 99
    0090  72 53 d3 92 85 aa b6 16  87 83 e0 59 11 64 e1 79
    00a0  d9 03 a0 07 bd 1e cd 40  68 ec d2 06 ce 6f 88 31
    00b0  34 c9 a5 34 90 fa 0c bd  50 7f fd 67 df 92 69 f5
    00c0  f2 62 0c c2 f6 2a 94 62  dd 97 db 01 71 2b aa 78
    00d0  3f a7 94 ba 70 e0 d3 cb  d8 ae f3 87 8b c1 35 5e
    00e0  e7 1d b8 00 fc 34 db 75  f0 ad b6 67 ac 6f 81 f7
    00f0  6a 63 3c d3 1b f7 18 5d  83 ad 58 c1 79 2f 4a 56
    0100  3e e6 3a a4 a3 94 0c 37  a5 02 03 01 00 01
Key Id Hash(rfc-sha1): cd a7 52 88 42 30 3b f8 9d bf 05 cd 05 52 f8 fa 22 36 8f 48
Key Id Hash(sha1): 2a 62 63 b4 80 89 57 d0 bb a1 ac 34 1e 06 f0 45 7f 92 61 07

Container Public Key:
Public Key Algorithm:
    Algorithm ObjectId: 1.2.840.113549.1.1.1 RSA
    Algorithm Parameters: NULL
Public Key Length: 1024 bits
Public Key: UnusedBits = 0
    0000  30 81 89 02 81 81 00 a2  66 92 2b 96 67 60 b5 2d
    0010  c9 34 ed ec 1f 51 d2 24  98 59 de f4 3c 47 bd 84
    0020  a3 49 5d d9 a6 a7 33 86  b8 36 d7 02 f5 c0 e9 65
    0030  84 b8 7b 65 76 3c f9 b7  74 9a 16 3d 6f 5f 23 0d
    0040  fe 67 b7 47 a2 ab 4c e3  0b ee 17 19 e1 21 8a 8a
    0050  6a df 65 2b 9d 8c 50 cf  ac 0d af 0f d4 64 b5 58
    0060  4b a5 63 ea 6f 90 84 a9  92 ac 2e fe 0f cc e4 46
    0070  e1 de b6 e6 3d ce 5a 72  af 28 39 23 65 35 42 01
    0080  5f ce 90 9f 52 1a 79 02  03 01 00 01
Key Id Hash(rfc-sha1): 1a 77 b0 aa 49 b1 fe d0 93 d6 dc e2 64 ed 34 62 0c 09 da da
Key Id Hash(sha1): 9e 60 9d fc b2 f1 ef 16 d2 7e 5a bc de 51 e1 ab 63 24 eb 67

ERROR: Certificate public key does NOT match stored keyset
Signature test FAILED
CertUtil: -store command completed successfully.

该验证的关键部分是: 错误:证书公钥与存储的密钥集不匹配

签名测试失败

有谁知道为什么会失败?我只是想让它通过。我真的在我的智慧结束就好像你google" 错误:证书公钥与存储的密钥集不匹配"或" 签名测试失败"关于这个问题的程序化解决方案的信息非常少。

任何帮助都非常感谢。谢谢。

1 个答案:

答案 0 :(得分:0)

好的,找到了答案。此代码使用BouncyCastle 1.8.1 csharp库生成CA证书和自签名证书。

调用代码:

using System;
using System.IO;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using CertificateToolLibrary;
using System.Net.Sockets;
using System.Security.Principal;
using System.Security.Cryptography;
using Microsoft.Win32;
using System.Security.AccessControl;
using SecureString = System.Security.SecureString;
using System.Security.Cryptography.X509Certificates;
using System.Configuration;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Security;                        
X509Certificate2 ca2 = null;

                    AsymmetricKeyParameter myCAprivateKey = null;
                    AsymmetricKeyParameter myCApubKey = null;


                    //CA Certificate Actions
                    ca2 = new X509Certificate2Builder { SubjectName = "Test-Certificate-Authority" }.BuildCACert(ref myCApubKey, ref myCAprivateKey);

                    X509Store castore = new X509Store(StoreName.Root, StoreLocation.LocalMachine);
                    castore.Open(OpenFlags.ReadWrite | OpenFlags.MaxAllowed);

                    castore.Add(ca2);
                    castore.Close();

                    //build out the file name.
                    string localCAFile = txtPFXExport.Text + "\\TestCertificateAuthority.cer";

                    //export  CA cert to desktop.
                    TestCertificateCreationUtility.Program.ExportCertificateToFileSystem(ca2, localCAFile, false, "password");

                    //SSL Certificate Actions
                    var cert2 = new X509Certificate2Builder { SubjectName = txtCNAME.Text, SubjectAlternativeName = txtSAN.Text, Issuer = ca2 }.BuildSelfSignedCert(ca2, myCApubKey, myCAprivateKey);

                    //build out the file name.
                    string localPFXFile = txtPFXExport.Text + "\\" + txtCNAME.Text + ".pfx";

                    //export SSL cert to desktop.
                    bool status = TestCertificateCreationUtility.Program.ExportCertificateToFileSystem(cert2, localPFXFile, true, "password");

图书馆代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;


//Downloaded using nuget, source: http://www.bouncycastle.org/csharp/
//Library is open-source.

namespace CertificateToolLibrary
{
using System;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.X9;
using Org.BouncyCastle.Asn1.Pkcs;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Crypto.Prng;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.X509.Extension;
using Org.BouncyCastle.X509;
using Org.BouncyCastle.Crypto.Operators;

public class X509Certificate2Builder
{
    public string SubjectName
    { set { _subjectName = value; }
        get { return _subjectName; }
    }

    public string SubjectAlternativeName
    { set { _subjectAlternativeName = value; }
        get { return _subjectAlternativeName; }
    }

    public string IssuerName
    { set { _issuerName = value; }
        get { return _issuerName; }
    }

    public AsymmetricAlgorithm IssuerPrivateKey
    { set { _issuerPrivateKey = value; } 
      get { return _issuerPrivateKey; }
    }

    public X509Certificate2 Issuer
    {
        set
        {
            _issuer = value;
            _issuerName = value.IssuerName.Name;
            if (value.HasPrivateKey)
                _issuerPrivateKey = value.PrivateKey;
        }
        get { return _issuer; }
    }

    public int? KeyStrength
    { set { _keyStrength = value ?? 2048; }
        get { return _keyStrength; }
    }

    public DateTime? NotBefore
    { set { _notBefore = value; }
        get { return _notBefore; }
    }

    public DateTime? NotAfter
    { set { _notAfter = value; }
        get { return _notAfter; }
    }

    public bool Intermediate
    { set { _intermediate = value; }
        get { return _intermediate; }
    }

    private string _subjectName;
    private string _subjectAlternativeName;
    private X509Certificate2 _issuer;
    private string _issuerName;
    private AsymmetricAlgorithm _issuerPrivateKey;
    private int _keyStrength = 2048;
    private DateTime? _notBefore;
    private DateTime? _notAfter;
    private bool _intermediate = true;

    private const string KEY_CONTAINER_NAME = "cf16236d-0e91-4cb7-9670-6cdbafe54c11";

    public X509Certificate2 BuildCACert(ref AsymmetricKeyParameter CaPubKey, ref AsymmetricKeyParameter CaPrivateKey)
    {
        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
        certificateGenerator.SetSignatureAlgorithm("SHA512withRSA");

        // Issuer and Subject Name
        X509Name subjectDN = new X509Name("CN=" + _subjectName);
        X509Name issuerDN = subjectDN;
        certificateGenerator.SetIssuerDN(issuerDN);
        certificateGenerator.SetSubjectDN(subjectDN);

        // Valid For
        certificateGenerator.SetNotBefore(_notBefore ?? DateTime.UtcNow.Date.AddDays(-1));
        certificateGenerator.SetNotAfter(_notAfter ?? DateTime.UtcNow.Date.AddYears(5));

        //Turn Basic Constraints off to remove the error on scout for mozilla_pkix_error_ca_cert_used_as_end entity error:
        //https://bugzilla.mozilla.org/show_bug.cgi?id=1034124

        // Basic Constraints - certificate is allowed to be used as intermediate.
        certificateGenerator.AddExtension(X509Extensions.BasicConstraints, true, new BasicConstraints(_intermediate));

        //Key Usage(s)
        certificateGenerator.AddExtension(X509Extensions.KeyUsage, true, new KeyUsage(KeyUsage.KeyCertSign));

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

        certificateGenerator.SetPublicKey(subjectKeyPair.Public);

        // Subject Key Identifier
        certificateGenerator.AddExtension(X509Extensions.SubjectKeyIdentifier, false, new SubjectKeyIdentifierStructure(subjectKeyPair.Public));

        // Generating the Certificate
        AsymmetricCipherKeyPair issuerKeyPair = subjectKeyPair;
        ISignatureFactory signatureFactory = new Asn1SignatureFactory("SHA512WITHRSA", issuerKeyPair.Private, random);

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

        // selfsign certificate
        Org.BouncyCastle.X509.X509Certificate certificate = certificateGenerator.Generate(signatureFactory);
        X509Certificate2 x509 = new X509Certificate2(certificate.GetEncoded(), string.Empty, X509KeyStorageFlags.Exportable);


        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 = ToDotNetKey(rsaparams);

        CaPubKey = issuerKeyPair.Public;
        CaPrivateKey = issuerKeyPair.Private;


        return x509;

    }

    public X509Certificate2 BuildSelfSignedCert(X509Certificate2 ca ,AsymmetricKeyParameter issuerPubKey, AsymmetricKeyParameter issuerPrivKey)
    {
        const int keyStrength = 2048;

        // Generating Random Numbers
        var randomGenerator = new CryptoApiRandomGenerator();
        var random = new SecureRandom(randomGenerator);
        ISignatureFactory signatureFactory = new Asn1SignatureFactory("SHA512WITHRSA", issuerPrivKey, random);

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

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

        // Signature Algorithm
        certificateGenerator.SetSignatureAlgorithm("SHA512withRSA");

        // Issuer and Subject Name
        certificateGenerator.SetIssuerDN(new X509Name(_issuerName));
        certificateGenerator.SetSubjectDN(new X509Name("CN=" + _subjectName));

        //Subject Alternative Name
        if (!(String.IsNullOrEmpty(_subjectAlternativeName)))
        {
            //IP Addresss
            GeneralNames dnsAltName = new GeneralNames(new GeneralName[] { 
                new GeneralName(GeneralName.IPAddress, _subjectName), 
                new GeneralName(GeneralName.DnsName, _subjectName),
                new GeneralName(GeneralName.IPAddress, _subjectAlternativeName), 
                new GeneralName(GeneralName.DnsName, _subjectAlternativeName),
            });

            //certificateGenerator.AddExtension(X509Extensions.SubjectAlternativeName, false, subjectAltName);
            certificateGenerator.AddExtension(X509Extensions.SubjectAlternativeName, false, dnsAltName);
        }

        // Valid For
        certificateGenerator.SetNotBefore(_notBefore ?? DateTime.UtcNow.Date.AddDays(-1));
        certificateGenerator.SetNotAfter(_notAfter ?? DateTime.UtcNow.Date.AddYears(5));

        //Key Usage(s)
        certificateGenerator.AddExtension(X509Extensions.KeyUsage, true, new KeyUsage(KeyUsage.DigitalSignature | KeyUsage.NonRepudiation | KeyUsage.KeyEncipherment | KeyUsage.DataEncipherment));

        //Extended Key Usage(s)
        var usages = new[] { KeyPurposeID.IdKPClientAuth, KeyPurposeID.IdKPServerAuth };
        certificateGenerator.AddExtension(X509Extensions.ExtendedKeyUsage.Id, false, new ExtendedKeyUsage(usages));

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

        // Authority Key Identifier
        certificateGenerator.AddExtension(X509Extensions.AuthorityKeyIdentifier, false, new AuthorityKeyIdentifierStructure(issuerPubKey));

        // Subject Key Identifier
        certificateGenerator.AddExtension(X509Extensions.SubjectKeyIdentifier, false, new SubjectKeyIdentifierStructure(subjectKeyPair.Public));

        // selfsign certificate
        Org.BouncyCastle.X509.X509Certificate certificate = certificateGenerator.Generate(signatureFactory);

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

        // merge into X509Certificate2
        X509Certificate2 x509 = new System.Security.Cryptography.X509Certificates.X509Certificate2(certificate.GetEncoded(), string.Empty, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet);

        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 = ToDotNetKey(rsaparams);

        return x509;

    }

    /// <summary>
    /// Converts a Bouncy Castle key object into a .NET key object
    /// </summary>
    /// <param name="privateKey">A bouncy castle key object</param>
    /// <returns>A .NET key object</returns>
    public static AsymmetricAlgorithm ToDotNetKey(RsaPrivateCrtKeyParameters privateKey)
    {
        var cspParams = new CspParameters
        {
            ProviderName = "Microsoft Strong Cryptographic Provider",
            ProviderType = 1,
            KeyContainerName = Guid.NewGuid().ToString(),
            KeyNumber = (int)KeyNumber.Exchange,
            Flags = CspProviderFlags.UseMachineKeyStore
        };

        RSACryptoServiceProvider rsaProvider = new RSACryptoServiceProvider(cspParams);
        RSAParameters parameters = new RSAParameters
        {
            Modulus = privateKey.Modulus.ToByteArrayUnsigned(),
            P = privateKey.P.ToByteArrayUnsigned(),
            Q = privateKey.Q.ToByteArrayUnsigned(),
            DP = privateKey.DP.ToByteArrayUnsigned(),
            DQ = privateKey.DQ.ToByteArrayUnsigned(),
            InverseQ = privateKey.QInv.ToByteArrayUnsigned(),
            D = privateKey.Exponent.ToByteArrayUnsigned(),
            Exponent = privateKey.PublicExponent.ToByteArrayUnsigned()
        };

        rsaProvider.ImportParameters(parameters);
        rsaProvider.PersistKeyInCsp = true;

        return rsaProvider;
    }

    /// <summary>
    /// Converts a .NET key object into a Bouncy Castle key object
    /// </summary>
    /// <param name="privateKey">A .NET key object</param>
    /// <param name="isPrivate">True if the key is private, false if it is public</param>
    /// <returns>A Bouncy Castle key object</returns>
    public static RsaKeyParameters ToBouncyCastleKey(AsymmetricAlgorithm dotNetKey, bool isPrivate)
    {
        RSACryptoServiceProvider prov = dotNetKey as RSACryptoServiceProvider;
        RSAParameters parameters = prov.ExportParameters(isPrivate);

        if (isPrivate)
        {
            return new RsaPrivateCrtKeyParameters(
                new BigInteger(1, parameters.Modulus),
                new BigInteger(1, parameters.Exponent),
                new BigInteger(1, parameters.D),
                new BigInteger(1, parameters.P),
                new BigInteger(1, parameters.Q),
                new BigInteger(1, parameters.DP),
                new BigInteger(1, parameters.DQ),
                new BigInteger(1, parameters.InverseQ)
                );
        }
        else
        {
            return new RsaKeyParameters(
                false,
                new BigInteger(1, parameters.Modulus),
                new BigInteger(1, parameters.Exponent)
                );
        }
    }
}

}