| /* |
| * 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; |
| } |
| |
| } |