2013-10-16 32 views
6

这就是我现在生成的数字证书。现在我可以生成一个密码为私钥保护的数字证书。使用BouncyCastle和Java生成X509Certificate

public static void main(String[] args) throws Exception { 
    Security.addProvider(new BouncyCastleProvider()); 
    testKeyStore(); 
} 

public static void testKeyStore() throws Exception { 
    try { 
     String storeName = "d://suresh_test.cer"; 
     java.security.KeyPairGenerator keyPairGenerator = KeyPairGenerator 
       .getInstance("RSA"); 
     keyPairGenerator.initialize(2048); 
     KeyPair keyPair = keyPairGenerator.generateKeyPair(); 
     PublicKey publicKey = keyPair.getPublic(); 
     PrivateKey privateKey = keyPair.getPrivate(); 
     X509Certificate trustCert = createCertificate("CN=CA", "CN=CA", 
       publicKey, privateKey); 
     java.security.cert.Certificate[] outChain = { 
       createCertificate("CN=Client", "CN=CA", publicKey, 
         privateKey), trustCert }; 
     KeyStore outStore = KeyStore.getInstance("PKCS12"); 
     outStore.load(null, "suresh_".toCharArray()); 
     outStore.setKeyEntry("mykey", privateKey, "suresh_".toCharArray(), 
       outChain); 
     OutputStream outputStream = new FileOutputStream(storeName); 
     outStore.store(outputStream, "suresh_".toCharArray()); 
     outputStream.flush(); 
     outputStream.close(); 

     KeyStore inStore = KeyStore.getInstance("PKCS12"); 
     inStore.load(new FileInputStream(storeName), 
       "suresh_".toCharArray()); 
    } catch (Exception e) { 
     e.printStackTrace(); 
     throw new AssertionError(e.getMessage()); 
    } 
} 

private static X509Certificate createCertificate(String dn, String issuer, 
     PublicKey publicKey, PrivateKey privateKey) throws Exception { 
    X509V3CertificateGenerator certGenerator = new X509V3CertificateGenerator(); 
    certGenerator.setSerialNumber(BigInteger.valueOf(Math.abs(new Random() 
      .nextLong()))); 
    certGenerator.setIssuerDN(new X509Name(dn)); 
    certGenerator.setSubjectDN(new X509Name(dn)); 
    certGenerator.setIssuerDN(new X509Name(issuer)); // Set issuer! 
    certGenerator.setNotBefore(Calendar.getInstance().getTime()); 
    certGenerator.setNotAfter(Calendar.getInstance().getTime()); 
    certGenerator.setPublicKey(publicKey); 
    certGenerator.setSignatureAlgorithm("SHA1WithRSAEncryption"); 
    X509Certificate certificate = (X509Certificate) certGenerator.generate(
      privateKey, "BC"); 
    return certificate; 
} 

如何让它自我签名?

我没有线索。

我该怎么做?

感谢您的任何提示。

+1

你的问题并没有解释你已经做了什么尝试和解决问题;它目前的读取方式类似于代码请求。请分享您尝试的实施方式,并解释如何达不到您的要求。 –

+0

@DuncanJones嗯,我生成了证书。但不知道如何使用弹性城堡API来签名,在他们的网站上没有发现任何东西。谢谢您的帮助。 –

回答

4

您拥有生成自签名证书所需的全部代码。你只需要确保你的链只包含一个证书。

public static void testKeyStore() throws Exception { 
    try { 
    String storeName = "path/to/store"; 
    java.security.KeyPairGenerator keyPairGenerator = KeyPairGenerator 
     .getInstance("RSA"); 
    keyPairGenerator.initialize(2048); 
    KeyPair keyPair = keyPairGenerator.generateKeyPair(); 
    PublicKey publicKey = keyPair.getPublic(); 
    PrivateKey privateKey = keyPair.getPrivate(); 
    X509Certificate selfCert = createCertificate("CN=Client", "CN=Client", 
     publicKey, privateKey); 

    // Note: if you just want to store this certificate then write the 
    // contents of selfCert.getEncoded() to file 

    java.security.cert.Certificate[] outChain = { selfCert }; 
    KeyStore outStore = KeyStore.getInstance("PKCS12"); 
    outStore.load(null, PASSWORD.toCharArray()); 
    outStore.setKeyEntry("mykey", privateKey, PASSWORD.toCharArray(), 
     outChain); 
    OutputStream outputStream = new FileOutputStream(storeName); 
    outStore.store(outputStream, PASSWORD.toCharArray()); 
    outputStream.flush(); 
    outputStream.close(); 

    KeyStore inStore = KeyStore.getInstance("PKCS12"); 
    inStore.load(new FileInputStream(storeName), PASSWORD.toCharArray()); 
    } catch (Exception e) { 
    e.printStackTrace(); 
    throw new AssertionError(e.getMessage()); 
    } 
} 

我会建议你不要扔AssertionError。这应该只被Java本身用来表示assert陈述是错误的。

+1

谢谢琼斯,一个小小的怀疑。 'outStore.load(null,PASSWORD.toCharArray());'和 'outStore.setKeyEntry(“mykey”,privateKey,PASSWORD.toCharArray(), outChain);'为什么我们使用的两个密码?密钥库文件是否需要?两个密码可以不同吗? –

+0

@sᴜʀᴇsʜᴀᴛᴛᴀ首先,这些行在我的代码示例中,因为它们在您的原始代码中。检查'KeyStore'的文档以了解它们的含义。 –

+0

是的,我也这样做。 :) 谢谢您的帮助。如果你有时间,请看看这个。 http://stackoverflow.com/questions/19421571/providing-key-usage-to-x509certificate-generated-with-with-java-bouncycastle –

2

花了周末的时间将我们的BC版本从143改为154后,我发布了一些学习过的东西,希望能够为将来某个人节省一些时间。

1)来自BC的PKI eXtention API已被移至自己的jar中。我在bcprov-jdk15on-154.jar中突然找到PemParser。 PemParser的实现在bcpkix-jdk15on-154.jar中。不用说pkix jar取决于核心bc jar。

2)PEMReader类在最新的154版本中不可用。这已被PemParser取代。

3)从文件在磁盘上读一本公证书:

Security.addProvider(new BouncyCastleProvider()); 
File file = new File("c:/mycert.crt"); 
X509Certificate cert = null; 
PEMParser pemParser = new PEMParser(new FileReader(file)); 
Object object = pemParser.readObject(); 
if (object instanceof X509CertificateHolder) { 
    X509CertificateHolder holder = (X509CertificateHolder)object; 
    cert = new JcaX509CertificateConverter().setProvider("BC").getCertificate(holder); 
} 
if (cert == null) { 
    throw new Exception("mycert.crt" + " doesn't contain X509Certificate!"); 
} 
return cert; 
//If you need publicKey use cert.getPublicKey() method. 

4)读取密码保护的私有密钥从盘:

Security.addProvider(new BouncyCastleProvider()); 
KeyPair keyPair = null; 
File file = new File("c:/myprivate.key"); 
PEMParser pemParser = new PEMParser(new FileReader(file)); 
Object object = pemParser.readObject(); 
if (object instanceof PEMEncryptedKeyPair) { 
    JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC"); 
    PEMEncryptedKeyPair ckp = (PEMEncryptedKeyPair) object; 
    PEMDecryptorProvider decProv = 
      new JcePEMDecryptorProviderBuilder().build("strongpasswordfor_myprivate.key".toCharArray()); 
    keyPair = converter.getKeyPair(ckp.decryptKeyPair(decProv)); 
} 
return keyPair; 
//Once we have the keypair, we can get keyPair.getPrivate() [PrivateKey.class] 
//or keyPair.getPublic() [PublicKey.class] 

5)读取基于字符串的证书,这是通常是我们想要进行SSL相互认证的情况,并让Web服务器将客户端证书转发到Http Request Header中的应用服务器:

Security.addProvider(new BouncyCastleProvider()); 
X509Certificate cert = null; 
    String myClientCert = "-----BEGIN CERTIFICATE----- CERTCONTENTS -----END CERTIFICATE-----" 
    String cert1 = myClientCert.replaceAll("-----BEGIN CERTIFICATE-----", "").replaceAll("-----END CERTIFICATE-----", "").replaceAll(" ", System.lineSeparator()); 
    int ind = cert1.lastIndexOf(System.lineSeparator()); 
    cert1 = new StringBuilder(cert1).replace(ind, ind + System.lineSeparator().length(), "").toString(); 
    cert1 = BEGIN_CERT + cert1 + END_CERT; 
    PEMParser pemParser = new PEMParser(new StringReader(cert1)); 
    Object object = pemParser.readObject(); 
    if (object instanceof X509CertificateHolder) { 
     X509CertificateHolder holder = (X509CertificateHolder)object; 
     cert = new JcaX509CertificateConverter().setProvider("BC").getCertificate(holder); 
    } 
    return cert; 

6)不用说,添加错误处理,异常管理&清理你的口味。

相关问题