web-dev-qa-db-ja.com

OpenSSLの有無にかかわらずSSL .pemを.p12に変換する

.pemファイルに変換する必要のある外部.p12ファイルを取得しました-ユーザー名とパスワードをプロセスに追加します。 (サードパーティのAPIを利用するには、これを行う必要があります。)

opensslを使用すると、コマンドは...

openssl pkcs12 -export -in xxxx.pem -inkey xxxx.pem -out xxx.p12 -passout pas:newpassword -name "newname"

これはターミナルセッションから実行でき、完全に機能します。

しかし、私はこれを頻繁に行う必要があり、これを処理するJavaクラスを記述します(私のアプリケーションはほとんどTomcatとApacheで.jspです)。同じコマンドをJavaを使用してRuntime.execを使用すると、「ランダムな状態を書き込むことができません」という恐ろしいエラーが表示されます( OpenSSLを使用すると、「ランダムな状態を書き込むことができません「」という意味ですか? )。

違いは、私がJavaから実行した場合、ユーザーが「ルート」ではないことだと思います。

したがって、Javaライブラリを使用してコマンドラインプログラム(つまりopenssl)を実行するよりも)を使用してpemから.p12に変換するより良い方法はありますか?

それ以外の場合は、サーバーでいくつかの構成を行う必要があると思います。サーバー上のどこにも.mdファイルが見つかりません。唯一のopenssl.cnfファイルは、奇妙なディレクトリ(/etc/pki/tls)にあります。新しいopenssl.cnfファイルを別の場所に作成する必要がありますか?

19
DrDave

これはあなたがしたいことをするはずです(上で提案されたようにBouncyCastle PEMReaderを使用します)-PEMエンコードされた秘密鍵と証明書を受け取り、PKCS#12ファイルを出力します。秘密鍵の保護に使用されたPKCS12と同じパスワードを使用します。

public static byte[] pemToPKCS12(final String keyFile, final String cerFile, final String password) throws Exception {
    // Get the private key
    FileReader reader = new FileReader(keyFile);

    PEMReader pem = new PEMReader(reader, new PasswordFinder() {
        @Override public char[] getPassword() {
            return password.toCharArray();
        }
    });

    PrivateKey key = ((KeyPair)pem.readObject()).getPrivate();

    pem.close();
    reader.close();

    // Get the certificate      
    reader = new FileReader(cerFile);
    pem = new PEMReader(reader);

    X509Certificate cert = (X509Certificate)pem.readObject();

    pem.close();
    reader.close();

    // Put them into a PKCS12 keystore and write it to a byte[]
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    KeyStore ks = KeyStore.getInstance("PKCS12");
    ks.load(null);
    ks.setKeyEntry("alias", (Key)key, password.toCharArray(), new Java.security.cert.Certificate[]{cert});
    ks.store(bos, password.toCharArray());
    bos.close();
    return bos.toByteArray();
}
15

@MugglesMerriweatherの回答に基づくと、v1.51への更新バージョンは次のとおりです。

public static byte[] convertPEMToPKCS12(final String keyFile, final String cerFile,
        final String password)
        throws IOException, CertificateException, KeyStoreException, NoSuchAlgorithmException
    {
        // Get the private key
        FileReader reader = new FileReader(keyFile);

        PEMParser pem = new PEMParser(reader);
        PEMKeyPair pemKeyPair = ((PEMKeyPair)pem.readObject());
        JcaPEMKeyConverter jcaPEMKeyConverter = new JcaPEMKeyConverter().setProvider("SC");
        KeyPair keyPair = jcaPEMKeyConverter.getKeyPair(pemKeyPair);

        PrivateKey key = keyPair.getPrivate();

        pem.close();
        reader.close();

        // Get the certificate
        reader = new FileReader(cerFile);
        pem = new PEMParser(reader);

        X509CertificateHolder certHolder = (X509CertificateHolder) pem.readObject();
        Java.security.cert.Certificate X509Certificate =
            new JcaX509CertificateConverter().setProvider("SC")
                .getCertificate(certHolder);

        pem.close();
        reader.close();

        // Put them into a PKCS12 keystore and write it to a byte[]
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        KeyStore ks = KeyStore.getInstance("PKCS12");
        ks.load(null);
        ks.setKeyEntry("alias", (Key) key, password.toCharArray(),
            new Java.security.cert.Certificate[]{X509Certificate});
        ks.store(bos, password.toCharArray());
        bos.close();
        return bos.toByteArray();
    }
2
EpicPandaForce

Javaでは Bouncycastle を使用しますが、学習曲線は急であり、ドキュメントは不足しています。ソース配布の一部として入手できる例をご覧になることを強くお勧めします

PemReaderから始めます。

1
Bruno Grieder

このソリューションは、@ sascha-arthurを次のように適応させたものです。

コード:

String alias="myalias";
char[] password = "mypassword".toCharArray();

// Private Key
PEMParser pem = new PEMParser(new FileReader(keyFile));
Object parsedObject = pem.readObject();

PrivateKeyInfo privateKeyInfo = parsedObject instanceof PEMKeyPair ? ((PEMKeyPair)parsedObject).getPrivateKeyInfo() : (PrivateKeyInfo)parsedObject;
PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(privateKeyInfo.getEncoded());
KeyFactory factory = KeyFactory.getInstance("RSA");
PrivateKey key = factory.generatePrivate(privateKeySpec);

List<X509Certificate> certs = new ArrayList<>();
X509CertificateHolder certHolder = (X509CertificateHolder)pem.readObject();
if(certHolder != null) {
    certs.add(new JcaX509CertificateConverter().setProvider("BC").getCertificate(certHolder));
}

// Certificate
pem = new PEMParser(new FileReader(certFile));
while((certHolder = (X509CertificateHolder)pem.readObject()) != null) {
    certs.add(new JcaX509CertificateConverter().setProvider("BC").getCertificate(certHolder));
}

// Keystore
KeyStore ks = KeyStore.getInstance("PKCS12");
ks.load(null);

for (int i = 0; i < certs.size(); i++) {
    ks.setCertificateEntry(alias + "_" + i, certs.get(i));
}

KeyStore keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(null);
keyStore.setKeyEntry(alias, key, password, certs.toArray(new X509Certificate[certs.size()]));

これをLetsEncrypt証明書で使用するには、次のファイルを使用する必要があります。

  • privkey.pem
  • fullchain.pem
0
tresf

答えに基づいて、Java 7クラスを作成しました。これは、有効なSSLContextを作成するためのすべてを処理します。また、必要なチェーンも作成します。TODO:必要に応じてTrustmanager。

public final class SSL_Context {
    private static SSL_Context instance = new SSL_Context();

public static SSL_Context getInstance() {
    return instance;
}

private SSLContext sslContext = null;
private SSL_Context() {
    try {
        sslContext = generateSSLContext();
    }
    catch (Exception e)
    {
        ErrorLogger.logException(e);
    }
}

final private void dumpKeyStore(KeyStore keyStore)
{
    try {
        // List the aliases
        Enumeration aliases = keyStore.aliases();
        for (; aliases.hasMoreElements(); ) {
            String alias = (String) aliases.nextElement();

            // Does alias refer to a private key?
            boolean a = keyStore.isKeyEntry(alias);

            // Does alias refer to a trusted certificate?
            boolean b = keyStore.isCertificateEntry(alias);
            ErrorLogger.log(alias + " " + a + " " + b, 2);
        }
    } catch (Exception e) {
        ErrorLogger.logException(e);
    }
}


final private KeyStore convertPEMToPKCS12(final String keyAndPubFile, final String chainFile, final String password) {
    try {
        Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());

        PrivateKey key;
        Certificate pubCert;

        try (FileReader reader = new FileReader(keyAndPubFile);
             PEMParser pem = new PEMParser(reader)) {
            PEMKeyPair pemKeyPair = ((PEMKeyPair) pem.readObject());
            JcaPEMKeyConverter jcaPEMKeyConverter = new JcaPEMKeyConverter().setProvider("BC");
            KeyPair keyPair = jcaPEMKeyConverter.getKeyPair(pemKeyPair);
            key = keyPair.getPrivate();


            X509CertificateHolder certHolder = (X509CertificateHolder) pem.readObject();
            pubCert = new JcaX509CertificateConverter().setProvider("BC").getCertificate(certHolder);
        }

        // Get the certificates
        try (FileReader reader = new FileReader(chainFile);
             PEMParser pem = new PEMParser(reader)) {

            //load all certs
            LinkedList<Certificate> certsll = new LinkedList<>();
            X509CertificateHolder certHolder = (X509CertificateHolder) pem.readObject();
            do {
                Certificate X509Certificate = new JcaX509CertificateConverter().setProvider("BC").getCertificate(certHolder);
                certsll.add(X509Certificate);
            }
            while ((certHolder = (X509CertificateHolder) pem.readObject()) != null);

            Certificate[] chain = new Certificate[certsll.size()+1];
            chain[0] = pubCert;

            KeyStore ks = KeyStore.getInstance("PKCS12");
            ks.load(null);

            int i = 1;
            for (Certificate cert : certsll) {
                ks.setCertificateEntry("chain" + i, cert);
                chain[i] = ks.getCertificate("chain" + i);
                i++;
            }

            ks.setKeyEntry("cert", key, password.toCharArray(), chain);

            return ks;
        }
    }
    catch (Exception e)
    {
        ErrorLogger.logException(e);
    }
    return null;
}

final private SSLContext generateSSLContext()
{
    String keyStorePassword = "";
    try {
        KeyStore keyStore = convertPEMToPKCS12("ssl/keyandcert.pem", "ssl/ca_bundle.crt", keyStorePassword);
        SSLContext sslContext = SSLContext.getInstance("TLSv1");
        KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        keyManagerFactory.init(keyStore, keyStorePassword.toCharArray());
        sslContext.init(keyManagerFactory.getKeyManagers(), null, new SecureRandom());
        return sslContext;

    } catch (Exception e) {
        ErrorLogger.logException(e);
    }
    return null;
}

final public SSLContext getContext() {
    return sslContext;
}

final public static void main(String args[])
{
        getInstance().getContext();
}

}
0
sascha.arthur