【问题标题】:Create a keystore file (.jks) and a self signed certificate (.cer/.crt) in Java在 Java 中创建密钥库文件 (.jks) 和自签名证书 (.cer/.crt)
【发布时间】:2016-06-23 10:30:57
【问题描述】:

我想用 Java 创建一个密钥库文件 (.jks) 和一个自签名证书 (.cer/.crt)。我正在尝试这个:

生成密钥库:

protected void getKeyStore(X509Certificate certificate)
{
    File newSnKeyStoreFile = new File("Mypath..\\keyStore.jks");

    try {

        KeyStore keyStore = KeyStore.getInstance("JKS");
        keyStore.load(null, null);

        if(!certificate.toString().isEmpty())
        {
            keyStore.store(new FileOutputStream(newSnKeyStoreFile), "password".toCharArray());
            if (keyStore.getCertificateAlias(certificate) == null) {
                keyStore.setCertificateEntry("cert"+ count++, certificate);
            }
        }
        keyStore.store(new FileOutputStream(newSnKeyStoreFile), KEYSTORE_PASSWORD.toCharArray());

        // Write to .jks file
        BufferedWriter out = null;
        try {
            out = new BufferedWriter(new FileWriter(newSnKeyStoreFile));
            out.write(keyStore.toString());
        } catch ( Exception e ) {
            e.printStackTrace();
        } finally {
            if ( out != null ) out.close();
        }
    }catch(Exception ke){
        System.out.print("Error occurred while setting up keyStore: " + ke.getMessage());
    }
}

我生成证书:

protected X509Certificate genCertificate()
{
    try {
        //Generate self signed certificate
        CertAndKeyGen gen = new CertAndKeyGen("RSA", "SHA1WithRSA")
        gen.generate(1024);
        X509Certificate cert = gen.getSelfCertificate(new X500Name("CN=ROOT"), (long) 365 * 24 * 3600);

        File certFile = new File("Mypath..\\Cert.cer");
        // Write to .cer file
        BufferedWriter out = null;
        try {
            out = new BufferedWriter(new FileWriter(certFile));
            out.write(certificate.getEncoded().toString());
        } catch ( Exception e ) {
            e.printStackTrace();
        } finally {
            if ( out != null ) out.close();
        }
        return cert;

    }catch (Exception e) {
        System.out.println("Error : " + e.getMessage());
    }
    return null;
}

现在,当我运行它时,会创建 .jks 和 .cer 文件,但是当我尝试使用 cmd 命令检查密钥库时出现错误:

命令 - keytool -list -keystore keyStore.jks

keytool error: java.io.IOException: Invalid keystore format

命令 - keytool -printcert -v -file Cert.cer

keytool error: java.lang.Exception: Empty input
java.lang.Exception: Empty input
        at sun.security.tools.KeyTool.printCertFromStream(KeyTool.java:2234)
        at sun.security.tools.KeyTool.doPrintCert(KeyTool.java:2423)
        at sun.security.tools.KeyTool.doCommands(KeyTool.java:1069)
        at sun.security.tools.KeyTool.run(KeyTool.java:340)
        at sun.security.tools.KeyTool.main(KeyTool.java:333)

任何关于我可能出错的地方的指示?

【问题讨论】:

    标签: java ssl ssl-certificate jks


    【解决方案1】:
    protected void getKeyStore(X509Certificate certificate)
    {
        File newSnKeyStoreFile = new File("Mypath..\\keyStore.jks");
    
        try {
    
            KeyStore keyStore = KeyStore.getInstance("JKS");
            keyStore.load(null, null);
    
            if(!certificate.toString().isEmpty())
    

    这个测试毫无意义。如果您有证书,则其字符串表示形式不会为空。如果你不这样做,你根本不应该调用这个方法。删除。

            {
                keyStore.store(new FileOutputStream(newSnKeyStoreFile), "password".toCharArray());
    

    为什么?里面还什么都没有。删除。

                if (keyStore.getCertificateAlias(certificate) == null) {
                    keyStore.setCertificateEntry("cert"+ count++, certificate);
    

    如果它不为空,则无论如何都应该覆盖该条目或抛出异常,而不是默默地忽略条件。

                }
            }
            keyStore.store(new FileOutputStream(newSnKeyStoreFile), KEYSTORE_PASSWORD.toCharArray());
    

    很好,但你需要关闭这个FileOutputStream

            // Write to .jks file
            BufferedWriter out = null;
            try {
                out = new BufferedWriter(new FileWriter(newSnKeyStoreFile));
                out.write(keyStore.toString());
            } catch ( Exception e ) {
                e.printStackTrace();
            } finally {
                if ( out != null ) out.close();
            }
    

    删除所有这些无意义的垃圾。您已经存储了密钥库。你在这里所做的只是破坏它。

       File certFile = new File("Mypath..\\Cert.cer");
        // Write to .cer file
        BufferedWriter out = null;
    

    错了。证书文件是二进制的。使用FileOutputStream.

        try {
            out = new BufferedWriter(new FileWriter(certFile));
    

    错了,见上。 out = new FileOutputStream(certFile);

            out.write(certificate.getEncoded().toString());
    

    又错了。这应该是

    out.write(certificate.getEncoded());
    

    您似乎热衷于将事物转换为字符串。尝试逐渐减少。

    【讨论】:

    • 感谢您的回复。关于Remove all this pointless junk. You've already stored the keystore. All you're accomplishing here is corrupting it. 只需将证书添加到密钥库对象就会更新我的 .jks 文件?
    • 很好回答我上面的评论,是的。谢谢你的回答,我会清理我的代码:)
    • 只需将证书添加到 KeyStore 对象将更新 KeyStore 对象。将其存储到文件将更新文件。使用错误的代码第二次或第三次存储到文件中要么什么都不做,要么破坏它。
    • 我面临的另一个问题是,.jks 文件只包含 1 个证书,如何打开现有的 jks 并向其中添加新证书,以便可以在同一个文件中保存多个条目?跨度>
    • 而不是加载 null, null 从连接到现有文件的输入流中加载它。当 keytool 已经存在时,很难理解为什么要为此编写代码。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-08-15
    • 1970-01-01
    • 1970-01-01
    • 2012-08-13
    • 1970-01-01
    • 1970-01-01
    • 2017-07-12
    相关资源
    最近更新 更多