在Java中生成X509证书

在Java中生成X509证书,java,digital-signature,Java,Digital Signature,我需要生成一个公共X509证书,但我对Java的安全性几乎没有经验。我只是想确保我目前所做的一切都能奏效。首先,我已经使用以下代码生成了公钥和私钥: public static void generateKeys() { try { KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA"); SecureRandom random = Secure

我需要生成一个公共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));
}
有人能澄清一下这是否是用Java创建X509证书的正确方法吗?谢谢

我还没看到你在钥匙店装钥匙。您检索私钥/公钥的方法似乎不正确。
工作示例如下所示:

生成证书日志记录:

从密钥库提取并验证证书:

如果证书不存在:

如果
密钥库
别名
不匹配:

如果
密钥库
密码
不匹配:


虽然密钥存储库(有意地)在大多数情况下适合并方便存储密钥,但它不是唯一的方法;Q中的write(key.getEncoded())和readAllBytes+KeyFactory方法有效——尽管将未加密的私钥保存在文件中通常是不安全的。是的,Java安全结构的主要功能是为证书提供准确性和有效性。如果黑客截取或替换数据、密钥对或签名,编码的密钥将变得无用。证书在密钥库中加密后,
别名
允许存在真正的证书。虽然
加密
不允许篡改密钥库…这是我的理解…替换公钥和泄露私钥是不同的威胁(但两者都很重要)。私钥在基于文件的密钥库(JKS、JCEKS、PKCS12)中加密,并在其他密钥库(如PKCS11/HSM)中具有同等的保护;证书不需要加密,通常也不加密,但受到完整性措施的保护,如基于文件的存储上的PBMAC。我在
应答
中添加了
提取
输出。。。基于
提取
和验证逻辑,什么可以更好地保护证书?我洗耳恭听。我不知道你在问什么。如果您在通常的基于文件的Java密钥库中拥有证书,那么(PB)MAC会保护它不被替换(或更改);别名有助于组织密钥库,但不保护密钥库(攻击者可以很容易地枚举别名,即使在PKCS12中也是如此)。对于某些格式,证书是不加密的,因此不受暴露的保护,但这不是问题,因为证书(通常是公钥)被定义为公共的。OTOH私钥总是加密的(也包括在MAC中)。Neardupe
    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;
           
    }
Generating certificate in KeyStore /security/keystore/Andante-x509.jks

Encapsulating KeyPair with password in KeyStore... 

x.509 certificate is successfully generated!

Sitzung beendet wird. 
Certificate API Exception: The system cannot find the path specified. 
KeyStore Exception: Key cannot be retrieved. 
KeyStore Exception: Keystore was tampered with, or password was incorrect.