Java BouncyCaSTLe ECC key 和自签名证书

标签 java cryptography bouncycastle

我已经在互联网上搜索了几个小时,寻找用于创建椭圆曲线 (EC) key 和自签名证书的 Java 示例。到目前为止,我只找到了片段和示例,其中许多都不起作用。

更新:

我在这里取得了一些进展,这是我的代码,供任何可能觉得有用的人使用!现在只需要弄清楚如何 self 签名!

 import org.bouncycastle.asn1.x500.X500Name;

 import org.bouncycastle.jce.ECNamedCurveTable;
 import org.bouncycastle.jce.provider.BouncyCastleProvider;
 import org.bouncycastle.jce.spec.ECParameterSpec;
 import org.bouncycastle.operator.ContentSigner;
 import org.bouncycastle.operator.ContentVerifierProvider;
 import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
 import org.bouncycastle.operator.jcajce.JcaContentVerifierProviderBuilder;
 import org.bouncycastle.pkcs.PKCS10CertificationRequest;
 import org.bouncycastle.pkcs.PKCS10CertificationRequestBuilder;
 import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequestBuilder;
 import java.security.*;

 /**
  * A simple example showing generation and verification of a PKCS#10 request.
  */
 public class genECKeyExample {
     private static final String BC = BouncyCastleProvider.PROVIDER_NAME;
     public static void main(String[] args)
             throws Exception {
         Security.addProvider(new BouncyCastleProvider());


         // Create an eliptic curve key

         ECParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec("prime192v1");
         KeyPairGenerator g = KeyPairGenerator.getInstance("ECDSA", "BC");
         g.initialize(ecSpec, new SecureRandom());
         KeyPair pair = g.generateKeyPair();
         System.out.println(pemUtils.toPem(pair.getPrivate()));
         System.out.println(pemUtils.toPem(pair.getPublic()));

         ContentSigner signer = new JcaContentSignerBuilder("SHA1withECDSA").setProvider(BC).build(pair.getPrivate());


         PKCS10CertificationRequestBuilder reqBuilder = new JcaPKCS10CertificationRequestBuilder(new X500Name("CN=XXX"), pair.getPublic());
         PKCS10CertificationRequest req = reqBuilder.build(signer);

         ContentVerifierProvider verifier = new JcaContentVerifierProviderBuilder().setProvider(BC).build(pair.getPublic());
         // System.out.println(verifier);

         req = new PKCS10CertificationRequest(req.getEncoded());
         System.out.println(pemUtils.toPem(req));
         pemUtils.toFile("csr.pem", pemUtils.toPem(req));
         pemUtils.toFile("pkey.pem", pemUtils.toPem(pair.getPrivate()));


     }

 }

这是我得到的最接近的,但没有创建 CSR 或证书。此外,它似乎不允许选择不同的键大小(我认为它们是曲线)。有没有人可以分享一些现实中的例子?

 import org.bouncycastle.openssl.PEMWriter;

 import java.io.StringWriter;
 import java.math.BigInteger;
 import java.security.KeyPair;
 import java.security.KeyPairGenerator;
 import java.security.MessageDigest;
 import java.security.SecureRandom;
 import java.security.Security;
 import java.security.spec.ECFieldFp;
 import java.security.spec.ECParameterSpec;
 import java.security.spec.ECPoint;
 import java.security.spec.EllipticCurve;

 import javax.crypto.KeyAgreement;

 public class X509CertificateGenerator {
     public static void main(String[] args) throws Exception {
         Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());

         KeyPairGenerator keyGen = KeyPairGenerator.getInstance("ECDH", "BC");
         EllipticCurve curve = new EllipticCurve(new ECFieldFp(new BigInteger(
                 "fffffffffffffffffffffffffffffffeffffffffffffffff", 16)), new BigInteger(
                 "fffffffffffffffffffffffffffffffefffffffffffffffc", 16), new BigInteger(
                 "fffffffffffffffffffffffffffffffefffffffffffffffc", 16));

         ECParameterSpec ecSpec = new ECParameterSpec(curve, new ECPoint(new BigInteger(
                 "fffffffffffffffffffffffffffffffefffffffffffffffc", 16), new BigInteger(
                 "fffffffffffffffffffffffffffffffefffffffffffffffc", 16)), new BigInteger(
                 "fffffffffffffffffffffffffffffffefffffffffffffffc", 16), 1);

         keyGen.initialize(ecSpec, new SecureRandom());

         KeyAgreement aKeyAgree = KeyAgreement.getInstance("ECDH", "BC");
         KeyPair aPair = keyGen.generateKeyPair();
         KeyAgreement bKeyAgree = KeyAgreement.getInstance("ECDH", "BC");
         KeyPair bPair = keyGen.generateKeyPair();

         aKeyAgree.init(aPair.getPrivate());
         bKeyAgree.init(bPair.getPrivate());

         aKeyAgree.doPhase(bPair.getPublic(), true);
         bKeyAgree.doPhase(aPair.getPublic(), true);

         MessageDigest hash = MessageDigest.getInstance("SHA1", "BC");

         System.out.println(new String(hash.digest(aKeyAgree.generateSecret())));
         System.out.println(new String(hash.digest(bKeyAgree.generateSecret())));
         System.out.println(aPair.getPrivate());

         StringWriter pemWrtPublic = new StringWriter();
         PEMWriter pubkey = new PEMWriter(pemWrtPublic);
         pubkey.writeObject(aPair.getPublic());
         pubkey.flush();
         String pemPublicKey = pemWrtPublic.toString();
         System.out.println(pemPublicKey);

         StringWriter pemWrtPrivate = new StringWriter();
         PEMWriter privkey = new PEMWriter(pemWrtPrivate);
         privkey.writeObject(aPair.getPrivate());
         privkey.flush();
         String pemPrivateKey = pemWrtPrivate.toString();
         System.out.println(pemPrivateKey);
     }
 }     

最佳答案

我已经按照这些步骤以编程方式创建了一个 CSR(假设您有一个存储在 keystore 中的 X509 证书):

X509Certificate generatedCertificate = (X509Certificate)getKeystore().getCertificate(r.keystoreAlias);
PrivateKey      privateRequestKey    = (PrivateKey)getKeystore().getKey("alias", "password".toCharArray());
Signature       signature            = Signature.getInstance("MD5WithRSA");

signature.initSign(privateRequestKey);

X500NameBuilder x500NameBld = new X500NameBuilder(BCStyle.INSTANCE);

//possibly less or more of these, depending on your needs
x500NameBld.addRDN(BCStyle.C, "country");
x500NameBld.addRDN(BCStyle.O, "ORG");
x500NameBld.addRDN(BCStyle.E, "email");
x500NameBld.addRDN(BCStyle.CN, "SubjectName");
x500NameBld.addRDN(BCStyle.SN, "12345678");


X500Name                   subject = x500NameBld.build();
PKCS10CertificationRequest req     = new PKCS10CertificationRequest("MD5WithRSA",X509Name.getInstance(subject),generatedCertificate.getPublicKey(),new DERSet(),privateRequestKey);

请注意,此代码适用于“常规” key 对,但应该适用于所有公钥/私钥对。

关于Java BouncyCaSTLe ECC key 和自签名证书,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22287795/

相关文章:

java - 为什么这个 Java RSA 解密不起作用?

java - RSA Java 投诉签名和验证

java - Java 中 vector 不随 "AES/CBC/pkcs7padding"变化

c# - BouncyCaSTLe PrivateKey 到 X509Certificate2 PrivateKey

java - 为什么在方法参数上同步是 "dangerous"

java - 在 JTable 中将数字格式化为货币?

c++ - 我正在使用 Crypto++ 进行 RSA 加密。我的纯文本超过了 FixedMaxPlaintextLength。我应该怎么办?

C#序列化一个没有无参数构造函数的类

java - 如何加载特定于组件的资源包进行翻译?

java - JTable,当光标仍指向单元格内部时无法检索特定单元格上的数据