从 JKS keystore 中迁移证书到 Nginx/Apache

@2010-07-08 新版功能: 创建

在 @2019-01-19 版更改: 增加源代码,原链接失效

Tomcat SSL 服务使用的证书和密钥存储是存储在所谓 JKS 格式的 keystore 文件之中, 证书可以用 keytool 导出,但私钥则没有提供工具来导出,下面是相应的步骤 (tomcat3 是第一个命令的输出,password 是 keystore 的密码):

$ keytool -list -keystore keystore
输入keystore密码:

Keystore 类型: JKS
Keystore 提供者: SUN

您的 keystore 包含 1 输入

tomcat3, 2010-6-21, PrivateKeyEntry,
认证指纹 (MD5): ......................
$ keytool -exportcert -keystore keystore -rfc -alias tomcat3 > server.cer
输入keystore密码:
$ java -cp . ExportPrivateKey keystore JKS password tomcat3 server.key

server.cer 和 server.key 分别对应证书和私钥,apache 可以直接使用。

Java 程序 ExportPrivateKey 的源代码如下:

import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;

import sun.misc.BASE64Encoder;

public class ExportPrivateKey {
    private File keystoreFile;
    private String keyStoreType;
    private char[] password;
    private String alias;
    private File exportedFile;

    public static KeyPair getPrivateKey(KeyStore keystore, String alias, char[] password) {
        try {
            Key key=keystore.getKey(alias,password);
            if (key instanceof PrivateKey) {
                Certificate cert=keystore.getCertificate(alias);
                PublicKey publicKey=cert.getPublicKey();
                return new KeyPair(publicKey,(PrivateKey)key);
            }
        } catch (UnrecoverableKeyException e) {
        } catch (NoSuchAlgorithmException e) {
        } catch (KeyStoreException e) {
        }
        return null;
    }

    public void export() throws Exception{
        KeyStore keystore=KeyStore.getInstance(keyStoreType);
        BASE64Encoder encoder=new BASE64Encoder();
        keystore.load(new FileInputStream(keystoreFile),password);
        KeyPair keyPair=getPrivateKey(keystore,alias,password);
        PrivateKey privateKey=keyPair.getPrivate();
        String encoded=encoder.encode(privateKey.getEncoded());
        FileWriter fw=new FileWriter(exportedFile);
        fw.write("--BEGIN PRIVATE KEY--\n");
        fw.write(encoded);
        fw.write("\n");
        fw.write("--END PRIVATE KEY--");
        fw.close();
    }

    public static void main(String args[]) throws Exception{
        ExportPrivateKey export=new ExportPrivateKey();
        export.keystoreFile=new File(args[0]);
        export.keyStoreType=args[1];
        export.password=args[2].toCharArray();
        export.alias=args[3];
        export.exportedFile=new File(args[4]);
        export.export();
    }
}