在Java中生成X509证书

huangapple go评论71阅读模式
英文:

Generating an X509 Certificate in Java

问题

这是生成X509证书的Java代码。首先,我已经使用以下代码生成了公钥和私钥:

public static void generateKeys() {
    try {
        KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
        SecureRandom random = SecureRandom.getInstanceStrong();
        keyGen.initialize(2048, random);

        KeyPair pair = keyGen.generateKeyPair();
        PrivateKey priv = pair.getPrivate();
        PublicKey pub = pair.getPublic();
        byte[] encPriv = priv.getEncoded();
        FileOutputStream privfos = new FileOutputStream(PRIVATE_KEY_FILENAME);
        privfos.write(encPriv);
        privfos.close();

        byte[] encPub = pub.getEncoded();
        FileOutputStream pubfos = new FileOutputStream(PUBLIC_KEY_FILENAME);
        pubfos.write(encPub);
        pubfos.close();

    } catch (Exception e) {
        e.printStackTrace();
    }
}

然后,以下是用于生成X509证书的代码:

public static PrivateKey getPrivateKey() throws Exception {
    byte[] pkcs8EncodedBytes = Files.readAllBytes(PRIVATE_KEY_FILENAME);
    PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(pkcs8EncodedBytes);
    KeyFactory kf = KeyFactory.getInstance("RSA");
    return kf.generatePrivate(keySpec);
}

public static PublicKey getPublicKey() throws Exception {
    byte[] publicEncodedBytes = Files.readAllBytes(PUBLIC_KEY_FILENAME);
    X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(publicEncodedBytes);
    KeyFactory factory = KeyFactory.getInstance("RSA");
    return factory.generatePublic(publicKeySpec);
}

public static X509Certificate generateX509Certificate() throws Exception {
    PrivateKey privateKey = getPrivateKey();
    PublicKey publicKey = getPublicKey();
    KeyPair keyPair = new KeyPair(publicKey, privateKey);
    final Instant now = Instant.now();
    final Date notBefore = Date.from(now);
    final Date until = LocalDate.now().plusYears(100).toDate();
    final ContentSigner contentSigner = new JcaContentSignerBuilder("SHA256WITHRSA").build(keyPair.getPrivate());
    final X500Name x500Name = new X500Name("CN=Common Name,O=Organization,L=City,ST=State");
    final X509v3CertificateBuilder certificateBuilder = new JcaX509v3CertificateBuilder(x500Name,
            BigInteger.valueOf(now.toEpochMilli()), notBefore, until, x500Name, keyPair.getPublic());
    return new JcaX509CertificateConverter().setProvider(new BouncyCastleProvider())
            .getCertificate(certificateBuilder.build(contentSigner));
}

请注意,这些代码看起来是用于生成X509证书的,但我无法保证其完全正确性,因为代码的正确性可能受到许多因素的影响,例如配置和上下文环境。如果您需要确保代码的准确性,建议您在测试环境中进行测试并与安全专家一起审查代码。

英文:

I need to generate a public X509 Certificate but I have very little experience with Security in Java. I just want to make sure that what I am currently doing will work. First, I have already generated a public and private key with the following code:

public static void generateKeys() {
		try {
			KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
			SecureRandom random = SecureRandom.getInstanceStrong();
			keyGen.initialize(2048, random);

			KeyPair pair = keyGen.generateKeyPair();
			PrivateKey priv = pair.getPrivate();
			PublicKey pub = pair.getPublic();
			byte[] encPriv = priv.getEncoded();
			FileOutputStream privfos = new FileOutputStream(PRIVATE_KEY_FILENAME);
			privfos.write(encPriv);
			privfos.close();

			byte[] encPub = pub.getEncoded();
			FileOutputStream pubfos = new FileOutputStream(PUBLIC_KEY_FILENAME);
			pubfos.write(encPub);
			pubfos.close();

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

And here is the code used for generating the X509Certificate:

public static PrivateKey getPrivateKey() throws Exception {
	byte[] pkcs8EncodedBytes = Files.readAllBytes(PRIVATE_KEY_FILENAME);
	PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(pkcs8EncodedBytes);
	KeyFactory kf = KeyFactory.getInstance("RSA");
	return kf.generatePrivate(keySpec);
}

public static PublicKey getPublicKey() throws Exception {
	byte[] publicEncodedBytes = Files.readAllBytes(PUBLIC_KEY_FILENAME);
	X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(publicEncodedBytes);
	KeyFactory factory = KeyFactory.getInstance("RSA");
	return factory.generatePublic(publicKeySpec);
}

public static X509Certificate generateX509Certificate() throws Exception {
	PrivateKey privateKey = getPrivateKey();
	PublicKey publicKey = getPublicKey();
	KeyPair keyPair = new KeyPair(publicKey, privateKey);
	final Instant now = Instant.now();
	final Date notBefore = Date.from(now);
	final Date until = LocalDate.now().plusYears(100).toDate();
	final ContentSigner contentSigner = new JcaContentSignerBuilder("SHA256WITHRSA").build(keyPair.getPrivate());
	final X500Name x500Name = new X500Name("CN=Common Name,O=Organization,L=City,ST=State");
	final X509v3CertificateBuilder certificateBuilder = new JcaX509v3CertificateBuilder(x500Name,
			BigInteger.valueOf(now.toEpochMilli()), notBefore, until, x500Name, keyPair.getPublic());
	return new JcaX509CertificateConverter().setProvider(new BouncyCastleProvider())
			.getCertificate(certificateBuilder.build(contentSigner));
}

Can someone clarify if this is the correct way to create a X509Certificate in Java? Thanks!

答案1

得分: 3

> 我还没有看到你加载密钥库。你检索私钥/公钥的方法似乎不正确。
一个可工作的示例如下:

public static Certificate generateCertificate(KeyPair keyPair) throws CertificateException, OperatorCreationException 
{
    X500Name x500Name = new X500Name("CN=***.com, OU=Security&Defense, O=*** Crypto., L=Ottawa, ST=Ontario, C=CA");
    SubjectPublicKeyInfo pubKeyInfo = SubjectPublicKeyInfo.getInstance(keyPair.getPublic().getEncoded());
    final Date start = new Date();
    final Date until = Date.from(LocalDate.now().plus(365, ChronoUnit.DAYS).atStartOfDay().toInstant(ZoneOffset.UTC));
    final X509v3CertificateBuilder certificateBuilder = new X509v3CertificateBuilder(x500Name,
            new BigInteger(10, new SecureRandom()), start, until, x500Name, pubKeyInfo
    );
    ContentSigner contentSigner = new JcaContentSignerBuilder("SHA256WithRSA").build(keyPair.getPrivate());

    Certificate certificate = new JcaX509CertificateConverter().setProvider(new BouncyCastleProvider()).getCertificate(certificateBuilder.build(contentSigner));
    
    System.out.println("x.509证书已成功生成!");
    
    return certificate;
}

> 生成证书日志:

在密钥库/security/keystore/Andante-x509.jks中生成证书

使用密码在密钥库中封装KeyPair... 

x.509证书已成功生成!

会话结束。

> 从密钥库中提取和验证证书:
>> 如果证书不存在:

证书API异常:系统找不到指定的路径。

>> 如果KeyStore中的alias不匹配:

密钥库异常:无法检索密钥。

>> 如果KeyStore中的password不匹配:

密钥库异常:密钥库已被篡改,或密码不正确。
英文:

> I haven't seen your loading a Key Store. Your method of retrieving the private/public key doesn't seem right.
A working example looks like this:

    public static Certificate generateCertificate(KeyPair keyPair) throws CertificateException, OperatorCreationException 
    {
        X500Name x500Name = new X500Name("CN=***.com, OU=Security&Defense, O=*** Crypto., L=Ottawa, ST=Ontario, C=CA");
        SubjectPublicKeyInfo pubKeyInfo = SubjectPublicKeyInfo.getInstance(keyPair.getPublic().getEncoded());
        final Date start = new Date();
        final Date until = Date.from(LocalDate.now().plus(365, ChronoUnit.DAYS).atStartOfDay().toInstant(ZoneOffset.UTC));
        final X509v3CertificateBuilder certificateBuilder = new X509v3CertificateBuilder(x500Name,
                new BigInteger(10, new SecureRandom()), start,   until,  x500Name,  pubKeyInfo
        );
        ContentSigner contentSigner = new JcaContentSignerBuilder("SHA256WithRSA").build(keyPair.getPrivate());

        Certificate certificate = new JcaX509CertificateConverter().setProvider(new BouncyCastleProvider()).getCertificate(certificateBuilder.build(contentSigner));
	    
        System.out.println("x.509 certificate is successfully generated!");
        
        return certificate;
           
    }

> Generate certificate logging:

Generating certificate in KeyStore /security/keystore/Andante-x509.jks

Encapsulating KeyPair with password in KeyStore... 

x.509 certificate is successfully generated!

Sitzung beendet wird. 

> Extract and validate certificate from KeyStore:
>> If certificate doesn’t exist:

Certificate API Exception: The system cannot find the path specified. 

>> If KeyStore alias doesn’t match:

KeyStore Exception: Key cannot be retrieved. 

>> If KeyStore password doesn’t match:

KeyStore Exception: Keystore was tampered with, or password was incorrect. 



</details>



huangapple
  • 本文由 发表于 2020年7月26日 06:17:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/63094113.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定