blob: a69aa06d3b77ba1051ae46d94eae91ede2e099ef [file] [log] [blame]
/*******************************************************************************
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.ofbiz.base.util;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.io.Reader;
import java.io.StringReader;
import java.net.URL;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.Principal;
import java.security.PrivateKey;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
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.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.codec.binary.Base64;
import org.ofbiz.base.component.ComponentConfig;
import org.ofbiz.base.config.GenericConfigException;
/**
* KeyStoreUtil - Utilities for getting KeyManagers and TrustManagers
*
*/
public class KeyStoreUtil {
public static final String module = KeyStoreUtil.class.getName();
public static void storeComponentKeyStore(String componentName, String keyStoreName, KeyStore store) throws IOException, GenericConfigException, NoSuchAlgorithmException, CertificateException, KeyStoreException {
ComponentConfig.KeystoreInfo ks = ComponentConfig.getKeystoreInfo(componentName, keyStoreName);
File file = FileUtil.getFile(ks.createResourceHandler().getFullLocation());
FileOutputStream out = new FileOutputStream(file);
try {
store.store(out, ks.getPassword().toCharArray());
} finally {
out.close();
}
}
public static KeyStore getComponentKeyStore(String componentName, String keyStoreName) throws IOException, GeneralSecurityException, GenericConfigException {
ComponentConfig.KeystoreInfo ks = ComponentConfig.getKeystoreInfo(componentName, keyStoreName);
return getStore(ks.createResourceHandler().getURL(), ks.getPassword(), ks.getType());
}
public static KeyStore getStore(URL url, String password) throws IOException, GeneralSecurityException {
return getStore(url, password, "jks");
}
public static KeyStore getStore(URL url, String password, String type) throws IOException, GeneralSecurityException {
if (type == null) {
throw new IOException("Invalid keystore type; null");
}
KeyStore ks = KeyStore.getInstance(type);
InputStream in = url.openStream();
try {
ks.load(in, password.toCharArray());
} finally {
in.close();
}
return ks;
}
public static KeyStore getSystemTrustStore() throws IOException, GeneralSecurityException {
String javaHome = System.getProperty("java.home");
String fileName = System.getProperty("javax.net.ssl.trustStore");
String password = System.getProperty("javax.net.ssl.trustStorePassword");
if (password == null) {
password = "changeit";
}
KeyStore ks = KeyStore.getInstance("jks");
File keyFile = null;
if (fileName != null) {
keyFile = FileUtil.getFile(fileName);
} else {
keyFile = FileUtil.getFile(javaHome + "/lib/security/jssecacerts");
if (!keyFile.exists() || !keyFile.canRead()) {
keyFile = FileUtil.getFile(javaHome + "/lib/security/cacerts");
}
}
if (keyFile.exists() && keyFile.canRead()) {
InputStream in = new FileInputStream(keyFile);
try {
ks.load(in, password.toCharArray());
} finally {
in.close();
}
} else {
ks.load(null, "changeit".toCharArray());
}
return ks;
}
public static X509Certificate readCertificate(byte[] certChain) throws CertificateException {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
ByteArrayInputStream bais = new ByteArrayInputStream(certChain);
return (X509Certificate) cf.generateCertificate(bais);
}
public static Map<String, String> getCertX500Map(java.security.cert.X509Certificate cert) {
return getX500Map(cert.getSubjectX500Principal());
}
public static Map<String, String> getCertX500Map(javax.security.cert.X509Certificate cert) {
return getX500Map(cert.getSubjectDN());
}
public static Map<String, String> getX500Map(Principal x500) {
Map<String, String> x500Map = new HashMap<String, String>();
String name = x500.getName().replaceAll("\\\\,", "&com;");
String[] x500Opts = name.split("\\,");
for (String opt: x500Opts) {
if (opt.indexOf("=") > -1) {
String[] nv = opt.split("\\=", 2);
x500Map.put(nv[0].replaceAll("&com;", ","), nv[1].replaceAll("&com;", ","));
}
}
return x500Map;
}
public static void importPKCS8CertChain(KeyStore ks, String alias, byte[] keyBytes, String keyPass, byte[] certChain) throws InvalidKeySpecException, NoSuchAlgorithmException, CertificateException, KeyStoreException {
// load the private key
KeyFactory kf = KeyFactory.getInstance("RSA");
PKCS8EncodedKeySpec keysp = new PKCS8EncodedKeySpec(keyBytes);
PrivateKey pk = kf.generatePrivate(keysp);
// load the cert chain
CertificateFactory cf = CertificateFactory.getInstance("X.509");
ByteArrayInputStream bais = new ByteArrayInputStream(certChain);
Collection<? extends Certificate> certCol = cf.generateCertificates(bais);
Certificate[] certs = new Certificate[certCol.toArray().length];
if (certCol.size() == 1) {
Debug.logInfo("Single certificate; no chain", module);
bais = new ByteArrayInputStream(certChain);
Certificate cert = cf.generateCertificate(bais);
certs[0] = cert;
} else {
Debug.logInfo("Certificate chain length : " + certCol.size(), module);
certs = certCol.toArray(new Certificate[certCol.size()]);
}
ks.setKeyEntry(alias, pk, keyPass.toCharArray(), certs);
}
public static String certToString(Certificate cert) throws CertificateEncodingException {
byte[] certBuf = cert.getEncoded();
StringBuilder buf = new StringBuilder();
buf.append("-----BEGIN CERTIFICATE-----\n");
buf.append(new String(Base64.encodeBase64Chunked(certBuf)));
buf.append("\n-----END CERTIFICATE-----\n");
return buf.toString();
}
public static Certificate pemToCert(String certString) throws IOException, CertificateException {
return pemToCert(new StringReader(certString));
}
public static Certificate pemToCert(File certFile) throws IOException, CertificateException {
return pemToCert(new FileInputStream(certFile));
}
public static Certificate pemToCert(InputStream is) throws IOException, CertificateException {
return pemToCert(new InputStreamReader(is));
}
public static Certificate pemToCert(Reader r) throws IOException, CertificateException {
String header = "-----BEGIN CERTIFICATE-----";
String footer = "-----END CERTIFICATE-----";
BufferedReader reader = new BufferedReader(r);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PrintStream ps = new PrintStream(baos);
String line;
// ignore up to the header
while ((line = reader.readLine()) != null && !line.equals(header)) {
}
// no header found
if (line == null) {
throw new IOException("Error reading certificate, missing BEGIN boundary");
}
// in between the header and footer is the actual certificate
while ((line = reader.readLine()) != null && !line.equals(footer)) {
line = line.replaceAll("\\s", "");
ps.print(line);
}
// no footer found
if (line == null) {
throw new IOException("Error reading certificate, missing END boundary");
}
ps.close();
// decode the buffer to a X509Certificate
CertificateFactory cf = CertificateFactory.getInstance("X.509");
byte[] certBytes = Base64.decodeBase64(baos.toByteArray());
return cf.generateCertificate(new ByteArrayInputStream(certBytes));
}
public static String pemToPkHex(String certString) throws IOException, CertificateException {
Certificate cert = pemToCert(certString);
return StringUtil.toHexString(cert.getPublicKey().getEncoded());
}
}