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

org.teiid.spring.util.KeystoreUtil Maven / Gradle / Ivy

There is a newer version: 1.7.2
Show newest version
/*
 * Copyright 2012-2017 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.teiid.spring.util;

import static java.nio.charset.StandardCharsets.US_ASCII;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.RSAPrivateCrtKeySpec;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Collection;
import java.util.List;

import javax.security.auth.x500.X500Principal;

/**
 * Parts of the file are copied from This file is copied as is from Jolokia project at
 * https://github.com/rhuss/jolokia/blob/master/agent/jvm/src/main/java/org/jolokia/jvmagent/security/KeyStoreUtil.java
 * all credit goes to original authors
 *
 * modified slightly to fit needs
 */
public class KeystoreUtil {

    public static void createKeystore(String tlsKey, String tlsCert, String caCertFile, String keystoreFile,
            String password) throws Exception {

        KeyStore ks = KeyStore.getInstance("JKS");
        ks.load(null, password.toCharArray());

        List certificateChain = readCertificateChain(tlsCert);
        for (X509Certificate certificate : certificateChain) {
            X500Principal principal = certificate.getSubjectX500Principal();
            ks.setCertificateEntry(principal.getName("RFC2253"), certificate);
        }

        List keyBytes = decodePem(tlsKey);
        PrivateKey privateKey;

        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        try {
            // First let's try PKCS8
            privateKey = keyFactory.generatePrivate(new PKCS8EncodedKeySpec(keyBytes.get(0)));
        } catch (InvalidKeySpecException e) {
            // Otherwise try PKCS1
            RSAPrivateCrtKeySpec keySpec = PKCS1Util.decodePKCS1(keyBytes.get(0));
            privateKey = keyFactory.generatePrivate(keySpec);
        }
        ks.setKeyEntry("key-alias", privateKey, password.toCharArray(), certificateChain.stream().toArray(Certificate[]::new));

        // add trust store too (public key)
        File caCert = new File(caCertFile);
        if (caCert.exists()) {
            updateWithCaPem(ks, caCert);
        }

        try (FileOutputStream fos = new FileOutputStream(keystoreFile)) {
            ks.store(fos, password.toCharArray());
        }
    }

    /**
     * Update a keystore with a CA certificate
     *
     * @param pTrustStore the keystore to update
     * @param pCaCert     CA cert as PEM used for the trust store
     */
    public static void updateWithCaPem(KeyStore pTrustStore, File pCaCert)
            throws IOException, CertificateException, KeyStoreException, NoSuchAlgorithmException {
        InputStream is = new FileInputStream(pCaCert);
        try {
            CertificateFactory certFactory = CertificateFactory.getInstance("X509");
            Collection certificates = certFactory.generateCertificates(is);

            for (Certificate c : certificates) {
                X509Certificate cert = (X509Certificate) c;
                String alias = cert.getSubjectX500Principal().getName();
                pTrustStore.setCertificateEntry(alias, cert);
            }
        } finally {
            is.close();
        }
    }

    private static List readCertificateChain(String tlsCert)
            throws IOException, GeneralSecurityException {
        CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
        List certificates = new ArrayList<>();

        List certs = decodePem(tlsCert);
        for (byte[] cert : certs) {
            certificates.add((X509Certificate) certificateFactory.generateCertificate(new ByteArrayInputStream(cert)));
        }
        return certificates;
    }

    private static byte[] base64Decode(String base64) {
        return Base64.getMimeDecoder().decode(base64.getBytes(US_ASCII));
    }

    // This method is inspired and partly taken over from
    // http://oauth.googlecode.com/svn/code/java/
    // All credits to belong to them.
    private static List decodePem(String pemFile) throws IOException {
        ArrayList list = new ArrayList();
        BufferedReader reader = new BufferedReader(new StringReader(pemFile));
        try {
            String line;
            while ((line = reader.readLine()) != null) {
                if (line.contains("-----BEGIN ")) {
                    list.add(readBytes(reader, line.trim().replace("BEGIN", "END")));
                }
            }
            if (!list.isEmpty()) {
                return list;
            }
            throw new IOException("PEM " + pemFile + " is invalid: no begin marker");
        } finally {
            reader.close();
        }
    }

    private static byte[] readBytes(BufferedReader reader, String endMarker) throws IOException {
        String line;
        StringBuffer buf = new StringBuffer();

        while ((line = reader.readLine()) != null) {
            if (line.indexOf(endMarker) != -1) {
                return base64Decode(buf.toString());
            }
            buf.append(line.trim());
        }
        throw new IOException("Certificate is invalid : No end marker");
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy