blob: 8bac58f3259facc9ee3138113c3376c0a7cafea9 [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.apache.slider.funtest.accumulo;
import org.apache.slider.accumulo.ProviderUtil;
import sun.security.x509.AlgorithmId;
import sun.security.x509.CertificateAlgorithmId;
import sun.security.x509.CertificateIssuerName;
import sun.security.x509.CertificateSerialNumber;
import sun.security.x509.CertificateSubjectName;
import sun.security.x509.CertificateValidity;
import sun.security.x509.CertificateVersion;
import sun.security.x509.CertificateX509Key;
import sun.security.x509.X500Name;
import sun.security.x509.X509CertImpl;
import sun.security.x509.X509CertInfo;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.SignatureException;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Date;
import java.util.Enumeration;
public class CertUtil {
public static void createRootKeyPair(String keyStoreFile,
String keyStorePasswordProperty, String trustStoreFile,
String trustStorePasswordProperty, String credentialProvider)
throws Exception {
char[] keyStorePassword = ProviderUtil.getPassword(credentialProvider,
keyStorePasswordProperty);
char[] trustStorePassword = ProviderUtil.getPassword(credentialProvider,
trustStorePasswordProperty);
createSelfSignedCert(keyStoreFile, "root", keyStorePassword);
createPublicCert(trustStoreFile, "root", keyStoreFile, keyStorePassword,
trustStorePassword);
}
public static void createServerKeyPair(String keyStoreFile,
String keyStorePasswordProperty, String rootKeyStoreFile,
String rootKeyStorePasswordProperty, String credentialProvider,
String hostname)
throws Exception {
char[] keyStorePassword = ProviderUtil.getPassword(credentialProvider,
keyStorePasswordProperty);
char[] rootKeyStorePassword = ProviderUtil.getPassword(credentialProvider,
rootKeyStorePasswordProperty);
createSignedCert(keyStoreFile, "server", hostname, keyStorePassword,
rootKeyStoreFile, rootKeyStorePassword);
}
private static final String keystoreType = "JKS";
private static final int keysize = 2048;
private static final String encryptionAlgorithm = "RSA";
private static final String signingAlgorithm = "SHA256WITHRSA";
private static final String issuerDirString = ",O=Apache Slider";
public static void createPublicCert(String targetKeystoreFile, String keyName,
String rootKeystorePath, char[] rootKeystorePassword,
char[] truststorePassword) throws KeyStoreException,
IOException, CertificateException, NoSuchAlgorithmException {
KeyStore signerKeystore = KeyStore.getInstance(keystoreType);
char[] signerPasswordArray = rootKeystorePassword;
FileInputStream rootKeystoreInputStream = null;
try{
rootKeystoreInputStream = new FileInputStream(rootKeystorePath);
signerKeystore.load(rootKeystoreInputStream, signerPasswordArray);
} finally {
if(rootKeystoreInputStream != null) {
rootKeystoreInputStream.close();
}
}
Certificate rootCert = findCert(signerKeystore);
KeyStore keystore = KeyStore.getInstance(keystoreType);
keystore.load(null, null);
keystore.setCertificateEntry(keyName + "Cert", rootCert);
FileOutputStream targetKeystoreOutputStream = null;
try{
targetKeystoreOutputStream = new FileOutputStream(targetKeystoreFile);
keystore.store(targetKeystoreOutputStream, truststorePassword);
} finally {
if(targetKeystoreOutputStream != null) {
targetKeystoreOutputStream.close();
}
}
}
public static void createSignedCert(String targetKeystoreFile,
String keyName, String hostname, char[] keystorePassword,
String signerKeystorePath, char[] signerKeystorePassword)
throws Exception {
KeyStore signerKeystore = KeyStore.getInstance(keystoreType);
char[] signerPasswordArray = signerKeystorePassword;
FileInputStream signerKeystoreInputStream = null;
try{
signerKeystoreInputStream = new FileInputStream(signerKeystorePath);
signerKeystore.load(signerKeystoreInputStream, signerPasswordArray);
} finally {
if (signerKeystoreInputStream != null) {
signerKeystoreInputStream.close();
}
}
Certificate signerCert = findCert(signerKeystore);
PrivateKey signerKey = findPrivateKey(signerKeystore, signerPasswordArray);
KeyPair kp = generateKeyPair();
Certificate cert = generateCert(hostname, kp, false,
signerCert.getPublicKey(), signerKey);
char[] password = keystorePassword;
KeyStore keystore = KeyStore.getInstance(keystoreType);
keystore.load(null, null);
keystore.setCertificateEntry(keyName + "Cert", cert);
keystore.setKeyEntry(keyName + "Key", kp.getPrivate(), password, new Certificate[] {cert, signerCert});
FileOutputStream targetKeystoreOutputStream = null;
try{
targetKeystoreOutputStream = new FileOutputStream(targetKeystoreFile);
keystore.store(targetKeystoreOutputStream, password);
} finally {
if (targetKeystoreOutputStream != null){
targetKeystoreOutputStream.close();
}
}
}
public static void createSelfSignedCert(String targetKeystoreFileName,
String keyName, char[] keystorePassword)
throws IOException, NoSuchAlgorithmException, CertificateException,
NoSuchProviderException, InvalidKeyException, SignatureException,
KeyStoreException {
File targetKeystoreFile = new File(targetKeystoreFileName);
if (targetKeystoreFile.exists()) {
throw new IOException("File exists: "+targetKeystoreFile);
}
KeyPair kp = generateKeyPair();
Certificate cert = generateCert(null, kp, true,
kp.getPublic(), kp.getPrivate());
char[] password = keystorePassword;
KeyStore keystore = KeyStore.getInstance(keystoreType);
keystore.load(null, null);
keystore.setCertificateEntry(keyName + "Cert", cert);
keystore.setKeyEntry(keyName + "Key", kp.getPrivate(), password, new Certificate[] {cert});
FileOutputStream targetKeystoreOutputStream = null;
try{
targetKeystoreOutputStream = new FileOutputStream(targetKeystoreFile);
keystore.store(targetKeystoreOutputStream, password);
} finally {
if (targetKeystoreOutputStream != null) {
targetKeystoreOutputStream.close();
}
}
}
private static KeyPair generateKeyPair() throws NoSuchAlgorithmException {
KeyPairGenerator gen = KeyPairGenerator.getInstance(encryptionAlgorithm);
gen.initialize(keysize);
return gen.generateKeyPair();
}
private static X509Certificate generateCert(
String hostname, KeyPair kp, boolean isCertAuthority,
PublicKey signerPublicKey, PrivateKey signerPrivateKey)
throws IOException, CertificateException, NoSuchProviderException,
NoSuchAlgorithmException, InvalidKeyException, SignatureException {
X500Name issuer = new X500Name("CN=root" + issuerDirString);
X500Name subject;
if (hostname == null) {
subject = issuer;
} else {
subject = new X500Name("CN=" + hostname + issuerDirString);
}
X509CertInfo info = new X509CertInfo();
Date from = new Date();
Date to = new Date(from.getTime() + 365 * 86400000l);
CertificateValidity interval = new CertificateValidity(from, to);
BigInteger sn = new BigInteger(64, new SecureRandom());
info.set(X509CertInfo.VALIDITY, interval);
info.set(X509CertInfo.SERIAL_NUMBER, new CertificateSerialNumber(sn));
info.set(X509CertInfo.SUBJECT, new CertificateSubjectName(subject));
info.set(X509CertInfo.ISSUER, new CertificateIssuerName(issuer));
info.set(X509CertInfo.KEY, new CertificateX509Key(kp.getPublic()));
info.set(X509CertInfo.VERSION, new CertificateVersion(CertificateVersion.V3));
AlgorithmId algo = new AlgorithmId(AlgorithmId.md5WithRSAEncryption_oid);
info.set(X509CertInfo.ALGORITHM_ID, new CertificateAlgorithmId(algo));
// Sign the cert to identify the algorithm that's used.
X509CertImpl cert = new X509CertImpl(info);
cert.sign(signerPrivateKey, signingAlgorithm);
// Update the algorithm, and resign.
algo = (AlgorithmId)cert.get(X509CertImpl.SIG_ALG);
info.set(CertificateAlgorithmId.NAME + "." + CertificateAlgorithmId.ALGORITHM, algo);
cert = new X509CertImpl(info);
cert.sign(signerPrivateKey, signingAlgorithm);
return cert;
}
private static Certificate findCert(KeyStore keyStore) throws KeyStoreException {
Enumeration<String> aliases = keyStore.aliases();
Certificate cert = null;
while (aliases.hasMoreElements()) {
String alias = aliases.nextElement();
if (keyStore.isCertificateEntry(alias)) {
// assume only one cert
cert = keyStore.getCertificate(alias);
break;
}
}
if (cert == null) {
throw new KeyStoreException("Could not find cert in keystore");
}
return cert;
}
private static PrivateKey findPrivateKey(KeyStore keyStore, char[] keystorePassword)
throws KeyStoreException, UnrecoverableKeyException, NoSuchAlgorithmException {
Enumeration<String> aliases = keyStore.aliases();
PrivateKey key = null;
while (aliases.hasMoreElements()) {
String alias = aliases.nextElement();
if (keyStore.isKeyEntry(alias)) {
// assume only one key
key = (PrivateKey) keyStore.getKey(alias, keystorePassword);
break;
}
}
if (key == null) {
throw new KeyStoreException("Could not find private key in keystore");
}
return key;
}
}