使用特定私钥生成证书

时间:2017-01-24 14:30:05

标签: c# encryption x509certificate bouncycastle x509certificate2

我正在使用充气城堡,我想生成一个特定的私钥而不是生成的随机密钥。

我想提供自己的私钥,但代码会不断生成随机密钥。有没有办法指定在充气城堡中使用的确切私钥?

我的代码如下。当我检查生成的证书的公钥时,我总是得到不同的值。我需要我指定的值。

主要

 var cb = new X509CertBuilder(suppliers, "CN=MandarinAS, OU=Scheme42, O=MandarinAS, C=GB",
                    CertStrength.Bits1024);


                   var cert = cb.MakeCertificate(pwd, "CN=Mandarin, OU=CustomerId, OU=Scheme42, O=OrgX, C=GB", 1,keypair);

                    File.WriteAllBytes("Cert.pfx", cert.Export(X509ContentType.Pkcs12, pwd));


                File.WriteAllBytes("Cert.cer", cert.Export(X509ContentType.Cert, pwd));
    var store = new X509Store(storeLocation);
                store.Open(OpenFlags.ReadOnly);

                var myCertificate = new X509Certificate2("Cert.pfx", "password");
                if (myCertificate.PrivateKey !

= null)
            {
                store.Close();

            }
//here i debug and compare the public key values myCertificate is always changing

X509CertBuilder.cs

public class X509CertBuilder
    {
        private const string SignatureAlgorithm = "SHA1WithRSA";
        private readonly int _strength;
        private readonly CryptoApiRandomGenerator _randomGenerator = new CryptoApiRandomGenerator();
        private readonly X509V3CertificateGenerator _certificateGenerator = new X509V3CertificateGenerator();
        private readonly SecureRandom _random;
        private readonly X509Name _issuer;
        private readonly GeneralName[] _generalNames;

        public X509CertBuilder(string[] validWithDomainNames, string issuer, CertStrength certStrength)
        {
            _random = new SecureRandom(_randomGenerator);
            _issuer = new X509Name(issuer);
            _strength = (int) certStrength;

            _generalNames = new GeneralName[validWithDomainNames.Length];
            for (var t = 0; t < validWithDomainNames.Length; t++)
            {
                _generalNames[t] = new GeneralName(new X509Name(validWithDomainNames[t]));
            }
        }

        public X509Certificate2 MakeCertificate(string password, string issuedToDomainName, int validYears, AsymmetricCipherKeyPair mykey=null)
        {
            _certificateGenerator.Reset();

            _certificateGenerator.SetSignatureAlgorithm(SignatureAlgorithm);
            var serialNumber = BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(long.MaxValue),
                _random);
            _certificateGenerator.SetSerialNumber(serialNumber);

            _certificateGenerator.SetSubjectDN(new X509Name(issuedToDomainName));
            _certificateGenerator.SetIssuerDN(_issuer);

            var subjectAlternativeNames = new Asn1Encodable[_generalNames.Length + 1];
            // first subject alternative name is the same as the subject
            subjectAlternativeNames[0] = new GeneralName(new X509Name(issuedToDomainName));
            for (var t = 1; t <= _generalNames.Length; t++)
            {
                subjectAlternativeNames[t] = _generalNames[t - 1];
            }
            var subjectAlternativeNamesExtension = new DerSequence(subjectAlternativeNames);
            _certificateGenerator.AddExtension(X509Extensions.SubjectAlternativeName.Id, false,
                subjectAlternativeNamesExtension);

            _certificateGenerator.SetNotBefore(DateTime.UtcNow.Date);
            _certificateGenerator.SetNotAfter(DateTime.UtcNow.Date.AddYears(validYears));
            var keyGenerationParameters = new KeyGenerationParameters(_random, _strength);

            var keyPairGenerator = new RsaKeyPairGenerator();


            keyPairGenerator.Init(keyGenerationParameters);
            var subjectKeyPair = keyPairGenerator.GenerateKeyPair();

            _certificateGenerator.SetPublicKey(subjectKeyPair.Public);

            //Previouse auto key
            //var issuerKeyPair = subjectKeyPair;

            //My mykey
            var issuerKeyPair = mykey;
            var certificate = _certificateGenerator.Generate(issuerKeyPair.Private,_random);


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

            using (var stream = new MemoryStream())
            {
                store.Save(stream, password.ToCharArray(), _random);
                return new X509Certificate2(stream.ToArray(), password,
                    X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable);
            }
        }
    }

1 个答案:

答案 0 :(得分:0)

编辑:对Java进行了错误的回答。 BouncyCastle C#API不易在线访问,但我相信您所寻找的是X509CertificateParser

如果你有DER格式的公钥,你可以简单地将编码的byte[]传递给java.security.cert.CertificateFactory.generateCertificate(),结果你会获得正确的X509Certificate

    private static X509Certificate formX509Certificate(byte[] encodedCertificate) throws CertificateException {
        try {
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
            ByteArrayInputStream bais = new ByteArrayInputStream(encodedCertificate);
            return (X509Certificate) cf.generateCertificate(bais);
        } catch (CertificateException e) {
            logger.error("Error converting the certificate", e);
            throw e;
        }
    }

您对X509CertBuilder的来电每次都会生成一个新密钥对的新证书。如果您已经生成了密钥对(来自Java代码或OpenSSL等),只需使用编码的证书值来构建证书对象。

如果您只拥有密钥对值但公钥未形成证书,请使用SubjectPublicKeyInfo.getInstance(keyPair.getPublic().getEncoded());

/**
     * Generates a self-signed {@link X509Certificate} suitable for use as a Certificate Authority.
     *
     * @param keyPair                 the {@link KeyPair} to generate the {@link X509Certificate} for
     * @param dn                      the distinguished name to user for the {@link X509Certificate}
     * @param signingAlgorithm        the signing algorithm to use for the {@link X509Certificate}
     * @param certificateDurationDays the duration in days for which the {@link X509Certificate} should be valid
     * @return a self-signed {@link X509Certificate} suitable for use as a Certificate Authority
     * @throws CertificateException      if there is an generating the new certificate
     */
    public static X509Certificate generateSelfSignedX509Certificate(KeyPair keyPair, String dn, String signingAlgorithm, int certificateDurationDays)
            throws CertificateException {
        try {
            ContentSigner sigGen = new JcaContentSignerBuilder(signingAlgorithm).setProvider(BouncyCastleProvider.PROVIDER_NAME).build(keyPair.getPrivate());
            SubjectPublicKeyInfo subPubKeyInfo = SubjectPublicKeyInfo.getInstance(keyPair.getPublic().getEncoded());
            Date startDate = new Date();
            Date endDate = new Date(startDate.getTime() + TimeUnit.DAYS.toMillis(certificateDurationDays));

            X509v3CertificateBuilder certBuilder = new X509v3CertificateBuilder(
                    reverseX500Name(new X500Name(dn)),
                    getUniqueSerialNumber(),
                    startDate, endDate,
                    reverseX500Name(new X500Name(dn)),
                    subPubKeyInfo);

            // Set certificate extensions
            // (1) digitalSignature extension
            certBuilder.addExtension(Extension.keyUsage, true, new KeyUsage(KeyUsage.digitalSignature | KeyUsage.keyEncipherment | KeyUsage.dataEncipherment
                    | KeyUsage.keyAgreement | KeyUsage.nonRepudiation | KeyUsage.cRLSign | KeyUsage.keyCertSign));

            certBuilder.addExtension(Extension.basicConstraints, false, new BasicConstraints(true));

            certBuilder.addExtension(Extension.subjectKeyIdentifier, false, new JcaX509ExtensionUtils().createSubjectKeyIdentifier(keyPair.getPublic()));

            certBuilder.addExtension(Extension.authorityKeyIdentifier, false, new JcaX509ExtensionUtils().createAuthorityKeyIdentifier(keyPair.getPublic()));

            // (2) extendedKeyUsage extension
            certBuilder.addExtension(Extension.extendedKeyUsage, false, new ExtendedKeyUsage(new KeyPurposeId[]{KeyPurposeId.id_kp_clientAuth, KeyPurposeId.id_kp_serverAuth}));

            // Sign the certificate
            X509CertificateHolder certificateHolder = certBuilder.build(sigGen);
            return new JcaX509CertificateConverter().setProvider(BouncyCastleProvider.PROVIDER_NAME).getCertificate(certificateHolder);
        } catch (CertIOException | NoSuchAlgorithmException | OperatorCreationException e) {
            throw new CertificateException(e);
        }
    }