All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.dentrassi.crypto.pem.PemUtils Maven / Gradle / Ivy

/*
 * Copyright (c) 2018 Red Hat Inc and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Jens Reimann - initial API and implementation
 */

package de.dentrassi.crypto.pem;

import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.security.Key;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.PEMKeyPair;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;

import de.dentrassi.crypto.pem.AbstractPemKeyStore.Entry;

public class PemUtils {

    private static final String SOURCE_PREFIX = "source.";

    public static Map loadFrom(final InputStream stream, final boolean chained)
            throws CertificateException, IOException {

        final Map result = new HashMap<>();

        loadFrom(result, "pem", chained, stream);

        return result;
    }

    public static Map loadFromConfiguration(final InputStream stream)
            throws CertificateException, IOException {

        final Map result = new HashMap<>();

        final Properties p = new Properties();
        p.load(stream);

        final String alias = p.getProperty("alias", "pem");

        for (final String key : p.stringPropertyNames()) {
            if (key.startsWith(SOURCE_PREFIX)) {
                try (InputStream source = openResource(p.getProperty(key))) {
                    loadFrom(result, alias, true, source);
                }
            }
        }

        return result;

    }

    private static InputStream openResource(final String uri) throws IOException {
        if (uri.startsWith("classpath:")) {
            return Thread.currentThread().getContextClassLoader().getResourceAsStream(uri.substring(10));
        } else {
            return new FileInputStream(uri.startsWith("file://") ? uri.substring(7) : uri);
        }
    }

    private static void loadFrom(final Map result, final String alias, final boolean chained,
            final InputStream stream) throws CertificateException, IOException {

        final CertificateFactory factory = CertificateFactory.getInstance("X.509");
        final JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider(new BouncyCastleProvider());

        @SuppressWarnings("resource")
        final PEMParser reader = new PEMParser(new InputStreamReader(stream, StandardCharsets.UTF_8));

        final List chain = new ArrayList<>();
        Key key = null;
        int counter = 0;

        Object object;
        while ((object = reader.readObject()) != null) {

            if (object instanceof X509CertificateHolder) {

                final X509CertificateHolder certHolder = (X509CertificateHolder) object;

                final Collection certs = factory
                        .generateCertificates(new ByteArrayInputStream(certHolder.getEncoded()));

                for (final Certificate cert : certs) {
                    if (chained) {
                        if (cert instanceof X509Certificate) {
                            chain.add(cert);
                        }
                    } else {
                        result.put(alias + "-" + counter++, new Entry(null, new Certificate[] { cert }));
                    }
                }

            } else if (object instanceof PEMKeyPair) {

                key = converter.getKeyPair((PEMKeyPair) object).getPrivate();

            } else if (object instanceof PrivateKeyInfo) {

                key = converter.getPrivateKey((PrivateKeyInfo) object);

            }
        }

        final Certificate[] certificateChain = chain.isEmpty() ? null
                : chain.toArray(new X509Certificate[chain.size()]);

        final Entry e = new Entry(key, certificateChain);

        result.compute(alias, (k, v) -> {
            if (v != null) {
                return v.merge(e);
            } else {
                return e;
            }
        });

    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy