You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by dr...@apache.org on 2016/01/03 13:39:16 UTC
[14/16] directory-kerby git commit: Clean up for RC2,
removing commons-ssl codes
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/63dcb1a5/kerby-pkix/src/main/java/org/apache/commons/ssl/KeyStoreBuilder.java
----------------------------------------------------------------------
diff --git a/kerby-pkix/src/main/java/org/apache/commons/ssl/KeyStoreBuilder.java b/kerby-pkix/src/main/java/org/apache/commons/ssl/KeyStoreBuilder.java
deleted file mode 100644
index 1b3267a..0000000
--- a/kerby-pkix/src/main/java/org/apache/commons/ssl/KeyStoreBuilder.java
+++ /dev/null
@@ -1,692 +0,0 @@
-/*
- * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.16/src/java/org/apache/commons/ssl/KeyStoreBuilder.java $
- * $Revision: 180 $
- * $Date: 2014-09-23 11:33:47 -0700 (Tue, 23 Sep 2014) $
- *
- * ====================================================================
- * 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.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- */
-
-package org.apache.commons.ssl;
-
-import org.apache.kerby.asn1.type.Asn1Integer;
-import org.apache.kerby.asn1.type.Asn1Sequence;
-import org.apache.kerby.util.Util;
-
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.math.BigInteger;
-import java.security.GeneralSecurityException;
-import java.security.InvalidKeyException;
-import java.security.Key;
-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.UnrecoverableKeyException;
-import java.security.cert.Certificate;
-import java.security.cert.CertificateException;
-import java.security.cert.CertificateFactory;
-import java.security.cert.X509Certificate;
-import java.security.interfaces.DSAParams;
-import java.security.interfaces.DSAPrivateKey;
-import java.security.interfaces.RSAPrivateCrtKey;
-import java.security.interfaces.RSAPublicKey;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-
-/**
- * Builds Java Key Store files out of pkcs12 files, or out of pkcs8 files +
- * certificate chains. Also supports OpenSSL style private keys (encrypted or
- * unencrypted).
- *
- * @author Credit Union Central of British Columbia
- * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
- * @author <a href="mailto:juliusdavies@cucbc.com">juliusdavies@cucbc.com</a>
- * @since 4-Nov-2006
- */
-public class KeyStoreBuilder {
- private static final String PKCS7_ENCRYPTED = "1.2.840.113549.1.7.6";
-
- public static KeyStore build(byte[] jksOrCerts, char[] password)
- throws IOException, CertificateException, KeyStoreException,
- NoSuchAlgorithmException, InvalidKeyException,
- NoSuchProviderException, ProbablyBadPasswordException,
- UnrecoverableKeyException {
- return build(jksOrCerts, null, password);
- }
-
- public static KeyStore build(byte[] jksOrCerts, byte[] privateKey,
- char[] password)
- throws IOException, CertificateException, KeyStoreException,
- NoSuchAlgorithmException, InvalidKeyException,
- NoSuchProviderException, ProbablyBadPasswordException,
- UnrecoverableKeyException {
- return build(jksOrCerts, privateKey, password, null);
- }
-
-
- public static KeyStore build(byte[] jksOrCerts, byte[] privateKey,
- char[] jksPassword, char[] keyPassword)
- throws IOException, CertificateException, KeyStoreException,
- NoSuchAlgorithmException, InvalidKeyException,
- NoSuchProviderException, ProbablyBadPasswordException,
- UnrecoverableKeyException {
-
- if (keyPassword == null || keyPassword.length <= 0) {
- keyPassword = jksPassword;
- }
-
- BuildResult br1 = parse(jksOrCerts, jksPassword, keyPassword);
- BuildResult br2 = null;
- KeyStore jks = null;
- if (br1.jks != null) {
- jks = br1.jks;
- } else if (privateKey != null && privateKey.length > 0) {
- br2 = parse(privateKey, jksPassword, keyPassword);
- if (br2.jks != null) {
- jks = br2.jks;
- }
- }
-
- // If we happened to find a JKS file, let's just return that.
- // JKS files get priority (in case some weirdo specifies both a PKCS12
- // and a JKS file!).
- if (jks != null) {
- // Make sure the keystore we found is not corrupt.
- br1 = validate(jks, keyPassword);
- if (br1 == null) {
- return jks;
- }
- }
-
- List keys = br1.keys;
- List chains = br1.chains;
- boolean atLeastOneNotSet = keys == null || chains == null || keys.isEmpty() || chains.isEmpty();
- if (atLeastOneNotSet && br2 != null) {
- if (br2.keys != null && !br2.keys.isEmpty()) {
- // Notice that the key from build-result-2 gets priority over the
- // key from build-result-1 (if both had valid keys).
- keys = br2.keys;
- }
- if (chains == null || chains.isEmpty()) {
- chains = br2.chains;
- }
- }
-
- atLeastOneNotSet = keys == null || chains == null || keys.isEmpty() || chains.isEmpty();
- if (atLeastOneNotSet) {
- String missing = "";
- if (keys == null) {
- missing = " [Private key missing (bad password?)]";
- }
- if (chains == null) {
- missing += " [Certificate chain missing]";
- }
- throw new KeyStoreException("Can't build keystore:" + missing);
- } else {
- KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
- ks.load(null, jksPassword);
- Iterator keysIt = keys.iterator();
- Iterator chainsIt = chains.iterator();
- int i = 1;
- while (keysIt.hasNext() && chainsIt.hasNext()) {
- Key key = (Key) keysIt.next();
- Certificate[] c = (Certificate[]) chainsIt.next();
- X509Certificate theOne = buildChain(key, c);
- String alias = "alias_" + i++;
- // The theOne is not null, then our chain was probably altered.
- // Need to trim out the newly introduced null entries at the end of
- // our chain.
- if (theOne != null) {
- c = Certificates.trimChain(c);
- alias = Certificates.getCN(theOne);
- alias = alias.replace(' ', '_');
- }
- ks.setKeyEntry(alias, key, keyPassword, c);
- }
- return ks;
- }
- }
-
- /**
- * Builds the chain up such that chain[ 0 ] contains the public key
- * corresponding to the supplied private key.
- *
- * @param key private key
- * @param chain array of certificates to build chain from
- * @return theOne!
- * @throws java.security.KeyStoreException no certificates correspond to private key
- * @throws java.security.cert.CertificateException java libraries complaining
- * @throws java.security.NoSuchAlgorithmException java libraries complaining
- * @throws java.security.InvalidKeyException java libraries complaining
- * @throws java.security.NoSuchProviderException java libraries complaining
- */
- public static X509Certificate buildChain(Key key, Certificate[] chain)
- throws CertificateException, KeyStoreException,
- NoSuchAlgorithmException, InvalidKeyException,
- NoSuchProviderException {
- X509Certificate theOne = null;
- if (key instanceof RSAPrivateCrtKey) {
- final RSAPrivateCrtKey rsa = (RSAPrivateCrtKey) key;
- BigInteger publicExponent = rsa.getPublicExponent();
- BigInteger modulus = rsa.getModulus();
- for (int i = 0; i < chain.length; i++) {
- X509Certificate c = (X509Certificate) chain[i];
- PublicKey pub = c.getPublicKey();
- if (pub instanceof RSAPublicKey) {
- RSAPublicKey certKey = (RSAPublicKey) pub;
- BigInteger pe = certKey.getPublicExponent();
- BigInteger mod = certKey.getModulus();
- if (publicExponent.equals(pe) && modulus.equals(mod)) {
- theOne = c;
- }
- }
- }
- if (theOne == null) {
- throw new KeyStoreException("Can't build keystore: [No certificates belong to the private-key]");
- }
- X509Certificate[] newChain;
- newChain = X509CertificateChainBuilder.buildPath(theOne, chain);
- Arrays.fill(chain, null);
- System.arraycopy(newChain, 0, chain, 0, newChain.length);
- }
- return theOne;
- }
-
- public static BuildResult validate(KeyStore jks, char[] keyPass)
- throws CertificateException, KeyStoreException,
- NoSuchAlgorithmException, InvalidKeyException,
- NoSuchProviderException, UnrecoverableKeyException {
- Enumeration en = jks.aliases();
- boolean atLeastOneSuccess = false;
- boolean atLeastOneFailure = false;
-
- List keys = new LinkedList();
- List chains = new LinkedList();
- while (en.hasMoreElements()) {
- String alias = (String) en.nextElement();
- if (jks.isKeyEntry(alias)) {
- try {
- PrivateKey key = (PrivateKey) jks.getKey(alias, keyPass);
- // No Exception thrown, so we're good!
- atLeastOneSuccess = true;
- Certificate[] chain = jks.getCertificateChain(alias);
- X509Certificate[] c;
- if (chain != null) {
- c = Certificates.x509ifyChain(chain);
- X509Certificate theOne = buildChain(key, c);
- // The theOne is not null, then our chain was probably
- // altered. Need to trim out the newly introduced null
- // entries at the end of our chain.
- if (theOne != null) {
- c = (X509Certificate[]) Certificates.trimChain(c);
- jks.deleteEntry(alias);
- jks.setKeyEntry(alias, key, keyPass, c);
- }
- keys.add(key);
- chains.add(c);
- }
- } catch (GeneralSecurityException gse) {
- atLeastOneFailure = true;
- // This is not the key you're looking for.
- }
- }
- }
- if (!atLeastOneSuccess) {
- throw new KeyStoreException("No private keys found in keystore!");
- }
- // The idea is a bit hacky: if we return null, all is cool. If
- // we return a list, we're telling upstairs to abandon the JKS and
- // build a new one from the BuildResults we provide.
- // (Sun's builtin SSL refuses to deal with keystores where not all
- // keys can be decrypted).
- return atLeastOneFailure ? new BuildResult(keys, chains, null) : null;
- }
-
- public static class BuildResult {
- protected final List keys;
- protected final List chains;
- protected final KeyStore jks;
-
- protected BuildResult(List keys, List chains, KeyStore jks) {
- if (keys == null || keys.isEmpty()) {
- this.keys = null;
- } else {
- this.keys = Collections.unmodifiableList(keys);
- }
- this.jks = jks;
- List x509Chains = new LinkedList();
- if (chains != null) {
- Iterator it = chains.iterator();
- while (it.hasNext()) {
- Certificate[] chain = (Certificate[]) it.next();
- if (chain != null && chain.length > 0) {
- int len = chain.length;
- X509Certificate[] x509 = new X509Certificate[len];
- for (int i = 0; i < x509.length; i++) {
- x509[i] = (X509Certificate) chain[i];
- }
- x509Chains.add(x509);
- }
- }
- }
- if (x509Chains == null || x509Chains.isEmpty()) {
- this.chains = null;
- } else {
- this.chains = Collections.unmodifiableList(x509Chains);
- }
- }
- }
-
-
- public static BuildResult parse(byte[] stuff, char[] jksPass,
- char[] keyPass)
- throws IOException, CertificateException, KeyStoreException,
- ProbablyBadPasswordException {
-
- return parse(stuff, jksPass, keyPass, false);
- }
-
- static BuildResult parse(byte[] stuff, char[] jksPass,
- char[] keyPass, boolean forTrustMaterial)
- throws IOException, CertificateException, KeyStoreException,
- ProbablyBadPasswordException {
- CertificateFactory cf = CertificateFactory.getInstance("X.509");
- Key key = null;
- Certificate[] chain = null;
- try {
- PKCS8Key pkcs8Key = new PKCS8Key(stuff, jksPass);
- key = pkcs8Key.getPrivateKey();
- } catch (ProbablyBadPasswordException pbpe) {
- throw pbpe;
- } catch (GeneralSecurityException gse) {
- // no luck
- System.err.println(gse);
- }
-
- List pemItems = PEMUtil.decode(stuff);
- Iterator it = pemItems.iterator();
- LinkedList certificates = new LinkedList();
- while (it.hasNext()) {
- PEMItem item = (PEMItem) it.next();
- byte[] derBytes = item.getDerBytes();
- String type = item.pemType.trim().toUpperCase();
- if (type.startsWith("CERT")
- || type.startsWith("X509")
- || type.startsWith("PKCS7")) {
- ByteArrayInputStream in = new ByteArrayInputStream(derBytes);
- X509Certificate c = (X509Certificate) cf.generateCertificate(in);
- certificates.add(c);
- }
- chain = toChain(certificates);
- }
-
- if (chain != null || key != null) {
- List chains = chain != null ? Collections.singletonList(chain) : null;
- List keys = key != null ? Collections.singletonList(key) : null;
- return new BuildResult(keys, chains, null);
- }
-
- boolean isProbablyPKCS12 = false;
- boolean isASN = false;
- PkcsStructure asn1 = null;
- try {
- asn1 = PkcsUtil.analyze(stuff);
- isASN = true;
- isProbablyPKCS12 = asn1.oids.contains(PKCS7_ENCRYPTED);
- if (!isProbablyPKCS12 && asn1.bigPayload != null) {
- asn1 = PkcsUtil.analyze(asn1.bigPayload);
- isProbablyPKCS12 = asn1.oids.contains(PKCS7_ENCRYPTED);
- }
- } catch (Exception e) {
- // isProbablyPKCS12 and isASN are set properly by now.
- System.err.println(e);
- }
-
- ByteArrayInputStream stuffStream = new ByteArrayInputStream(stuff);
- // Try default keystore... then try others.
- BuildResult br = tryJKS(KeyStore.getDefaultType(), stuffStream, jksPass, keyPass, forTrustMaterial);
- if (br == null) {
- br = tryJKS("jks", stuffStream, jksPass, keyPass, forTrustMaterial);
- if (br == null) {
- br = tryJKS("jceks", stuffStream, jksPass, keyPass, forTrustMaterial);
- if (br == null) {
- br = tryJKS("BKS", stuffStream, jksPass, keyPass, forTrustMaterial);
- if (br == null) {
- br = tryJKS("UBER", stuffStream, jksPass, keyPass, forTrustMaterial);
- }
- }
- }
- }
- if (br != null) {
- return br;
- }
- if (isASN && isProbablyPKCS12) {
- br = tryJKS("pkcs12", stuffStream, jksPass, null, forTrustMaterial);
- }
-
- if (br == null) {
- // Okay, it's ASN.1, but it's not PKCS12. Only one possible
- // interesting things remains: X.509.
- stuffStream.reset();
-
- try {
- certificates = new LinkedList();
- Collection certs = cf.generateCertificates(stuffStream);
- it = certs.iterator();
- while (it.hasNext()) {
- X509Certificate x509 = (X509Certificate) it.next();
- certificates.add(x509);
- }
- chain = toChain(certificates);
- if (chain != null && chain.length > 0) {
- List chains = Collections.singletonList(chain);
- return new BuildResult(null, chains, null);
- }
- } catch (CertificateException ce) {
- // oh well
- System.err.println(ce);
- }
-
- stuffStream.reset();
- // Okay, still no luck. Maybe it's an ASN.1 DER stream
- // containing only a single certificate? (I don't completely
- // trust CertificateFactory.generateCertificates).
- try {
- Certificate c = cf.generateCertificate(stuffStream);
- X509Certificate x509 = (X509Certificate) c;
- chain = toChain(Collections.singleton(x509));
- if (chain != null && chain.length > 0) {
- List chains = Collections.singletonList(chain);
- return new BuildResult(null, chains, null);
- }
- } catch (CertificateException ce) {
- // oh well
- System.err.println(ce);
- }
- }
-
- br = tryJKS("pkcs12", stuffStream, jksPass, null, forTrustMaterial);
- if (br != null) {
- // no exception thrown, so must be PKCS12.
- /*
- Hmm, well someone finally reported this bug! And they want the library to be quiet....
- Commenting out for now, maybe investigate why it's happening one day....
-
- System.out.println("Please report bug!");
- System.out.println("PKCS12 detection failed to realize this was PKCS12!");
- System.out.println(asn1);
- */
- return br;
- }
- throw new KeyStoreException("failed to extract any certificates or private keys - maybe bad password?");
- }
-
- private static BuildResult tryJKS(
- String keystoreType, ByteArrayInputStream in, char[] jksPassword, char[] keyPassword,
- boolean forTrustMaterial
- ) throws ProbablyBadPasswordException {
- in.reset();
- if (keyPassword == null || keyPassword.length <= 0) {
- keyPassword = jksPassword;
- }
-
- keystoreType = keystoreType.trim().toLowerCase();
- boolean isPKCS12 = "pkcs12".equalsIgnoreCase(keystoreType);
- try {
- Key key = null;
- Certificate[] chain = null;
- UnrecoverableKeyException uke = null;
- KeyStore jksKeyStore = KeyStore.getInstance(keystoreType);
- jksKeyStore.load(in, jksPassword);
- Enumeration en = jksKeyStore.aliases();
- while (en.hasMoreElements()) {
- String alias = (String) en.nextElement();
- if (jksKeyStore.isKeyEntry(alias)) {
- try {
- if (keyPassword != null) {
- key = jksKeyStore.getKey(alias, keyPassword);
- }
- if (key instanceof PrivateKey) {
- chain = jksKeyStore.getCertificateChain(alias);
- break;
- }
- } catch (UnrecoverableKeyException e) {
- uke = e; // We might throw this one later.
- } catch (GeneralSecurityException gse) {
- // Swallow... keep looping.
- System.err.println(gse);
- }
- }
- if (isPKCS12 && en.hasMoreElements()) {
- System.out.println("what kind of weird pkcs12 file has more than one alias?");
- }
- }
- if (key == null && uke != null && !forTrustMaterial) {
- // If we're trying to load KeyMaterial, then we *need* that key we spotted.
- // But if we're trying to load TrustMaterial, then we're fine, and we can ignore the key.
- throw new ProbablyBadPasswordException("Probably bad JKS-Key password: " + uke);
- }
- if (isPKCS12) {
- // PKCS12 is supposed to be just a key and a chain, anyway.
- jksKeyStore = null;
- }
-
- List keys = Collections.singletonList(key);
- List chains = Collections.singletonList(chain);
- return new BuildResult(keys, chains, jksKeyStore);
- } catch (ProbablyBadPasswordException pbpe) {
- throw pbpe;
- } catch (GeneralSecurityException gse) {
- // swallow it, return null
- return null;
- } catch (IOException ioe) {
- String msg = ioe.getMessage();
- msg = msg != null ? msg.trim().toLowerCase() : "";
- if (isPKCS12) {
- int x = msg.indexOf("failed to decrypt");
- int y = msg.indexOf("verify mac");
- x = Math.max(x, y);
- if (x >= 0) {
- throw new ProbablyBadPasswordException("Probably bad PKCS12 password: " + ioe);
- }
- } else {
- int x = msg.indexOf("password");
- if (x >= 0) {
- throw new ProbablyBadPasswordException("Probably bad JKS password: " + ioe);
- }
- }
- // swallow it, return null.
- return null;
- }
- }
-
- private static X509Certificate[] toChain(Collection certs) {
- if (certs != null && !certs.isEmpty()) {
- X509Certificate[] x509Chain = new X509Certificate[certs.size()];
- certs.toArray(x509Chain);
- return x509Chain;
- } else {
- return null;
- }
- }
-
-
- public static void main(String[] args) throws Exception {
- if (args.length < 2) {
- System.out.println("KeyStoreBuilder: creates '[alias].jks' (Java Key Store)");
- System.out.println(" -topk8 mode: creates '[alias].pem' (x509 chain + unencrypted pkcs8)");
- System.out.println("[alias] will be set to the first CN value of the X509 certificate.");
- System.out.println("-------------------------------------------------------------------");
- System.out.println("Usage1: [password] [file:pkcs12]");
- System.out.println("Usage2: [password] [file:private-key] [file:certificate-chain]");
- System.out.println("Usage3: -topk8 [password] [file:jks]");
- System.out.println("-------------------------------------------------------------------");
- System.out.println("[private-key] can be openssl format, or pkcs8.");
- System.out.println("[password] decrypts [private-key], and also encrypts outputted JKS file.");
- System.out.println("All files can be PEM or DER.");
- System.exit(1);
- }
- char[] password = args[0].toCharArray();
- boolean toPKCS8 = false;
- if ("-topk8".equalsIgnoreCase(args[0])) {
- toPKCS8 = true;
- password = args[1].toCharArray();
- args[1] = args[2];
- args[2] = null;
- }
-
- FileInputStream fin1 = new FileInputStream(args[1]);
- byte[] bytes1 = Util.streamToBytes(fin1);
- byte[] bytes2 = null;
- if (args.length > 2 && args[2] != null) {
- FileInputStream fin2 = new FileInputStream(args[2]);
- bytes2 = Util.streamToBytes(fin2);
- }
-
- KeyStore ks = build(bytes1, bytes2, password);
- Enumeration en = ks.aliases();
- String alias = "keystorebuilder";
-
- // We're going to assume that the biggest key is the one we want
- // to convert to PKCS8 (PEM). That's until someone figures out a
- // better way to deal with this annoying situation (more than 1
- // key in the KeyStore).
- int biggestKey = 0;
- while (en.hasMoreElements()) {
- String s = (String) en.nextElement();
- try {
- PrivateKey pk = (PrivateKey) ks.getKey(s, password);
- byte[] encoded = pk.getEncoded();
- int len = encoded != null ? encoded.length : 0;
- if (len >= biggestKey) {
- biggestKey = len;
- alias = s;
- }
- } catch (Exception e) {
- // oh well, try next one.
- System.err.println(e);
- }
- }
-
- String suffix = toPKCS8 ? ".pem" : ".jks";
- String fileName = alias;
- Certificate[] chain = ks.getCertificateChain(alias);
- if (chain != null && chain[0] != null) {
- String cn = Certificates.getCN((X509Certificate) chain[0]);
- cn = cn != null ? cn.trim() : "";
- if (!"".equals(cn)) {
- fileName = cn;
- }
- }
-
- File f = new File(fileName + suffix);
- int count = 1;
- while (f.exists()) {
- f = new File(alias + "_" + count + suffix);
- count++;
- }
-
- FileOutputStream fout = new FileOutputStream(f);
- if (toPKCS8) {
- List pemItems = new LinkedList();
- PrivateKey key = (PrivateKey) ks.getKey(alias, password);
- chain = ks.getCertificateChain(alias);
- byte[] pkcs8DerBytes = null;
- if (key instanceof RSAPrivateCrtKey) {
- RSAPrivateCrtKey rsa = (RSAPrivateCrtKey) key;
- Asn1Sequence seq = new Asn1Sequence();
- seq.addItem(new Asn1Integer(BigInteger.ZERO));
- seq.addItem(new Asn1Integer(rsa.getModulus()));
- seq.addItem(new Asn1Integer(rsa.getPublicExponent()));
- seq.addItem(new Asn1Integer(rsa.getPrivateExponent()));
- seq.addItem(new Asn1Integer(rsa.getPrimeP()));
- seq.addItem(new Asn1Integer(rsa.getPrimeQ()));
- seq.addItem(new Asn1Integer(rsa.getPrimeExponentP()));
- seq.addItem(new Asn1Integer(rsa.getPrimeExponentQ()));
- seq.addItem(new Asn1Integer(rsa.getCrtCoefficient()));
- byte[] derBytes = seq.encode();
- PKCS8Key pkcs8 = new PKCS8Key(derBytes, null);
- pkcs8DerBytes = pkcs8.getDecryptedBytes();
- } else if (key instanceof DSAPrivateKey) {
- DSAPrivateKey dsa = (DSAPrivateKey) key;
- DSAParams params = dsa.getParams();
- BigInteger g = params.getG();
- BigInteger p = params.getP();
- BigInteger q = params.getQ();
- BigInteger x = dsa.getX();
- BigInteger y = q.modPow(x, p);
-
- Asn1Sequence seq = new Asn1Sequence();
- seq.addItem(new Asn1Integer(BigInteger.ZERO));
- seq.addItem(new Asn1Integer(p));
- seq.addItem(new Asn1Integer(q));
- seq.addItem(new Asn1Integer(g));
- seq.addItem(new Asn1Integer(y));
- seq.addItem(new Asn1Integer(x));
- byte[] derBytes = seq.encode();
- PKCS8Key pkcs8 = new PKCS8Key(derBytes, null);
- pkcs8DerBytes = pkcs8.getDecryptedBytes();
- }
- if (chain != null && chain.length > 0) {
- for (int i = 0; i < chain.length; i++) {
- X509Certificate x509 = (X509Certificate) chain[i];
- byte[] derBytes = x509.getEncoded();
- PEMItem item = new PEMItem(derBytes, "CERTIFICATE");
- pemItems.add(item);
- }
- }
- if (pkcs8DerBytes != null) {
- PEMItem item = new PEMItem(pkcs8DerBytes, "PRIVATE KEY");
- pemItems.add(item);
- }
- byte[] pem = PEMUtil.encode(pemItems);
- fout.write(pem);
- } else {
- // If we're not converting to unencrypted PKCS8 style PEM,
- // then we are converting to Sun JKS. It happens right here:
- KeyStore jks = KeyStore.getInstance(KeyStore.getDefaultType());
- jks.load(null, password);
- jks.setKeyEntry(alias, ks.getKey(alias, password), password, ks.getCertificateChain(alias));
- jks.store(fout, password);
- }
- fout.flush();
- fout.close();
- System.out.println("Successfuly wrote: [" + f.getPath() + "]");
- }
-
-
-}
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/63dcb1a5/kerby-pkix/src/main/java/org/apache/commons/ssl/OpenSSL.java
----------------------------------------------------------------------
diff --git a/kerby-pkix/src/main/java/org/apache/commons/ssl/OpenSSL.java b/kerby-pkix/src/main/java/org/apache/commons/ssl/OpenSSL.java
deleted file mode 100644
index 0eda1db..0000000
--- a/kerby-pkix/src/main/java/org/apache/commons/ssl/OpenSSL.java
+++ /dev/null
@@ -1,725 +0,0 @@
-/*
- * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.16/src/java/org/apache/commons/ssl/OpenSSL.java $
- * $Revision: 144 $
- * $Date: 2009-05-25 11:14:29 -0700 (Mon, 25 May 2009) $
- *
- * ====================================================================
- * 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.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- */
-
-package org.apache.commons.ssl;
-
-import org.apache.kerby.util.Base64;
-import org.apache.kerby.util.Base64InputStream;
-import org.apache.kerby.util.Hex;
-import org.apache.kerby.util.Util;
-
-import javax.crypto.Cipher;
-import javax.crypto.CipherInputStream;
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.ByteArrayInputStream;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.security.GeneralSecurityException;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.security.SecureRandom;
-import java.util.StringTokenizer;
-
-/**
- * Class for encrypting or decrypting data with a password (PBE - password
- * based encryption). Compatible with "openssl enc" unix utility. An OpenSSL
- * compatible cipher name must be specified along with the password (try "man enc" on a
- * unix box to see what's possible). Some examples:
- * <ul><li>des, des3, des-ede3-cbc
- * <li>aes128, aes192, aes256, aes-256-cbc
- * <li>rc2, rc4, bf</ul>
- * <pre>
- * <em style="color: green;">// Encrypt!</em>
- * byte[] encryptedData = OpenSSL.encrypt( "des3", password, data );
- * </pre>
- * <p/>
- * If you want to specify a raw key and iv directly (without using PBE), use
- * the methods that take byte[] key, byte[] iv. Those byte[] arrays can be
- * the raw binary, or they can be ascii (hex representation: '0' - 'F'). If
- * you want to use PBE to derive the key and iv, then use the methods that
- * take char[] password.
- * <p/>
- * This class is able to decrypt files encrypted with "openssl" unix utility.
- * <p/>
- * The "openssl" unix utility is able to decrypt files encrypted by this class.
- * <p/>
- * This class is also able to encrypt and decrypt its own files.
- *
- * @author <a href="mailto:juliusdavies@cucbc.com">juliusdavies@gmail.com</a>
- * @since 18-Oct-2007
- */
-public class OpenSSL {
-
-
- /**
- * Decrypts data using a password and an OpenSSL compatible cipher
- * name.
- *
- * @param cipher The OpenSSL compatible cipher to use (try "man enc" on a
- * unix box to see what's possible). Some examples:
- * <ul><li>des, des3, des-ede3-cbc
- * <li>aes128, aes192, aes256, aes-256-cbc
- * <li>rc2, rc4, bf</ul>
- * @param pwd password to use for this PBE decryption
- * @param encrypted byte array to decrypt. Can be raw, or base64.
- * @return decrypted bytes
- * @throws java.io.IOException problems with encrypted bytes (unlikely!)
- * @throws java.security.GeneralSecurityException problems decrypting
- */
- public static byte[] decrypt(String cipher, char[] pwd, byte[] encrypted)
- throws IOException, GeneralSecurityException {
- ByteArrayInputStream in = new ByteArrayInputStream(encrypted);
- InputStream decrypted = decrypt(cipher, pwd, in);
- return Util.streamToBytes(decrypted);
- }
-
- /**
- * Decrypts data using a password and an OpenSSL compatible cipher
- * name.
- *
- * @param cipher The OpenSSL compatible cipher to use (try "man enc" on a
- * unix box to see what's possible). Some examples:
- * <ul><li>des, des3, des-ede3-cbc
- * <li>aes128, aes192, aes256, aes-256-cbc
- * <li>rc2, rc4, bf</ul>
- * @param pwd password to use for this PBE decryption
- * @param encrypted InputStream to decrypt. Can be raw, or base64.
- * @return decrypted bytes as an InputStream
- * @throws java.io.IOException problems with InputStream
- * @throws java.security.GeneralSecurityException problems decrypting
- */
- public static InputStream decrypt(String cipher, char[] pwd,
- InputStream encrypted)
- throws IOException, GeneralSecurityException {
- CipherInfo cipherInfo = lookup(cipher);
- boolean salted = false;
-
- // First 16 bytes of raw binary will hopefully be OpenSSL's
- // "Salted__[8 bytes of hex]" thing. Might be in Base64, though.
- byte[] saltLine = Util.streamToBytes(encrypted, 16);
- if (saltLine.length <= 0) {
- throw new IOException("encrypted InputStream is empty");
- }
- String firstEightBytes = "";
- if (saltLine.length >= 8) {
- firstEightBytes = new String(saltLine, 0, 8);
- }
- if ("SALTED__".equalsIgnoreCase(firstEightBytes)) {
- salted = true;
- } else {
- // Maybe the reason we didn't find the salt is because we're in
- // base64.
- if (Base64.isArrayByteBase64(saltLine)) {
- InputStream head = new ByteArrayInputStream(saltLine);
- // Need to put that 16 byte "saltLine" back into the Stream.
- encrypted = new ComboInputStream(head, encrypted);
- encrypted = new Base64InputStream(encrypted);
- saltLine = Util.streamToBytes(encrypted, 16);
-
- if (saltLine.length >= 8) {
- firstEightBytes = new String(saltLine, 0, 8);
- }
- if ("SALTED__".equalsIgnoreCase(firstEightBytes)) {
- salted = true;
- }
- }
- }
-
- byte[] salt = null;
- if (salted) {
- salt = new byte[8];
- System.arraycopy(saltLine, 8, salt, 0, 8);
- } else {
- // Encrypted data wasn't salted. Need to put the "saltLine" we
- // extracted back into the stream.
- InputStream head = new ByteArrayInputStream(saltLine);
- encrypted = new ComboInputStream(head, encrypted);
- }
-
- int keySize = cipherInfo.keySize;
- int ivSize = cipherInfo.ivSize;
- boolean des2 = cipherInfo.des2;
- DerivedKey dk = deriveKey(pwd, salt, keySize, ivSize, des2);
- Cipher c = PKCS8Key.generateCipher(
- cipherInfo.javaCipher, cipherInfo.blockMode, dk, des2, null, true
- );
-
- return new CipherInputStream(encrypted, c);
- }
-
- /**
- * Encrypts data using a password and an OpenSSL compatible cipher
- * name.
- *
- * @param cipher The OpenSSL compatible cipher to use (try "man enc" on a
- * unix box to see what's possible). Some examples:
- * <ul><li>des, des3, des-ede3-cbc
- * <li>aes128, aes192, aes256, aes-256-cbc
- * <li>rc2, rc4, bf</ul>
- * @param pwd password to use for this PBE encryption
- * @param data byte array to encrypt
- * @return encrypted bytes as an array in base64. First 16 bytes include the
- * special OpenSSL "Salted__" info encoded into base64.
- * @throws java.io.IOException problems with the data byte array
- * @throws java.security.GeneralSecurityException problems encrypting
- */
- public static byte[] encrypt(String cipher, char[] pwd, byte[] data)
- throws IOException, GeneralSecurityException {
- // base64 is the default output format.
- return encrypt(cipher, pwd, data, true);
- }
-
- /**
- * Encrypts data using a password and an OpenSSL compatible cipher
- * name.
- *
- * @param cipher The OpenSSL compatible cipher to use (try "man enc" on a
- * unix box to see what's possible). Some examples:
- * <ul><li>des, des3, des-ede3-cbc
- * <li>aes128, aes192, aes256, aes-256-cbc
- * <li>rc2, rc4, bf</ul>
- * @param pwd password to use for this PBE encryption
- * @param data InputStream to encrypt
- * @return encrypted bytes as an InputStream. First 16 bytes include the
- * special OpenSSL "Salted__" info encoded into base64.
- * @throws java.io.IOException problems with the data InputStream
- * @throws java.security.GeneralSecurityException problems encrypting
- */
- public static InputStream encrypt(String cipher, char[] pwd,
- InputStream data)
- throws IOException, GeneralSecurityException {
- // base64 is the default output format.
- return encrypt(cipher, pwd, data, true);
- }
-
- /**
- * Encrypts data using a password and an OpenSSL compatible cipher
- * name.
- *
- * @param cipher The OpenSSL compatible cipher to use (try "man enc" on a
- * unix box to see what's possible). Some examples:
- * <ul><li>des, des3, des-ede3-cbc
- * <li>aes128, aes192, aes256, aes-256-cbc
- * <li>rc2, rc4, bf</ul>
- * @param pwd password to use for this PBE encryption
- * @param data byte array to encrypt
- * @param toBase64 true if resulting InputStream should contain base64,
- * <br>false if InputStream should contain raw binary.
- * @return encrypted bytes as an array. First 16 bytes include the
- * special OpenSSL "Salted__" info.
- * @throws java.io.IOException problems with the data byte array
- * @throws java.security.GeneralSecurityException problems encrypting
- */
- public static byte[] encrypt(String cipher, char[] pwd, byte[] data,
- boolean toBase64)
- throws IOException, GeneralSecurityException {
- // we use a salt by default.
- return encrypt(cipher, pwd, data, toBase64, true);
- }
-
- /**
- * Encrypts data using a password and an OpenSSL compatible cipher
- * name.
- *
- * @param cipher The OpenSSL compatible cipher to use (try "man enc" on a
- * unix box to see what's possible). Some examples:
- * <ul><li>des, des3, des-ede3-cbc
- * <li>aes128, aes192, aes256, aes-256-cbc
- * <li>rc2, rc4, bf</ul>
- * @param pwd password to use for this PBE encryption
- * @param data InputStream to encrypt
- * @param toBase64 true if resulting InputStream should contain base64,
- * <br>false if InputStream should contain raw binary.
- * @return encrypted bytes as an InputStream. First 16 bytes include the
- * special OpenSSL "Salted__" info.
- * @throws java.io.IOException problems with the data InputStream
- * @throws java.security.GeneralSecurityException problems encrypting
- */
- public static InputStream encrypt(String cipher, char[] pwd,
- InputStream data, boolean toBase64)
- throws IOException, GeneralSecurityException {
- // we use a salt by default.
- return encrypt(cipher, pwd, data, toBase64, true);
- }
-
- /**
- * Encrypts data using a password and an OpenSSL compatible cipher
- * name.
- *
- * @param cipher The OpenSSL compatible cipher to use (try "man enc" on a
- * unix box to see what's possible). Some examples:
- * <ul><li>des, des3, des-ede3-cbc
- * <li>aes128, aes192, aes256, aes-256-cbc
- * <li>rc2, rc4, bf</ul>
- * @param pwd password to use for this PBE encryption
- * @param data byte array to encrypt
- * @param toBase64 true if resulting InputStream should contain base64,
- * <br>false if InputStream should contain raw binary.
- * @param useSalt true if a salt should be used to derive the key.
- * <br>false otherwise. (Best security practises
- * always recommend using a salt!).
- * @return encrypted bytes as an array. First 16 bytes include the
- * special OpenSSL "Salted__" info if <code>useSalt</code> is true.
- * @throws java.io.IOException problems with the data InputStream
- * @throws java.security.GeneralSecurityException problems encrypting
- */
- public static byte[] encrypt(String cipher, char[] pwd, byte[] data,
- boolean toBase64, boolean useSalt)
- throws IOException, GeneralSecurityException {
- ByteArrayInputStream in = new ByteArrayInputStream(data);
- InputStream encrypted = encrypt(cipher, pwd, in, toBase64, useSalt);
- return Util.streamToBytes(encrypted);
- }
-
- /**
- * Encrypts data using a password and an OpenSSL compatible cipher
- * name.
- *
- * @param cipher The OpenSSL compatible cipher to use (try "man enc" on a
- * unix box to see what's possible). Some examples:
- * <ul><li>des, des3, des-ede3-cbc
- * <li>aes128, aes192, aes256, aes-256-cbc
- * <li>rc2, rc4, bf</ul>
- * @param pwd password to use for this PBE encryption
- * @param data InputStream to encrypt
- * @param toBase64 true if resulting InputStream should contain base64,
- * <br>false if InputStream should contain raw binary.
- * @param useSalt true if a salt should be used to derive the key.
- * <br>false otherwise. (Best security practises
- * always recommend using a salt!).
- * @return encrypted bytes as an InputStream. First 16 bytes include the
- * special OpenSSL "Salted__" info if <code>useSalt</code> is true.
- * @throws java.io.IOException problems with the data InputStream
- * @throws java.security.GeneralSecurityException problems encrypting
- */
- public static InputStream encrypt(String cipher, char[] pwd,
- InputStream data, boolean toBase64,
- boolean useSalt)
- throws IOException, GeneralSecurityException {
- CipherInfo cipherInfo = lookup(cipher);
- byte[] salt = null;
- if (useSalt) {
- SecureRandom rand = SecureRandom.getInstance("SHA1PRNG");
- salt = new byte[8];
- rand.nextBytes(salt);
- }
-
- int keySize = cipherInfo.keySize;
- int ivSize = cipherInfo.ivSize;
- boolean des2 = cipherInfo.des2;
- DerivedKey dk = deriveKey(pwd, salt, keySize, ivSize, des2);
- Cipher c = PKCS8Key.generateCipher(
- cipherInfo.javaCipher, cipherInfo.blockMode, dk, des2, null, false
- );
-
- InputStream cipherStream = new CipherInputStream(data, c);
-
- if (useSalt) {
- byte[] saltLine = new byte[16];
- byte[] salted = "Salted__".getBytes();
- System.arraycopy(salted, 0, saltLine, 0, salted.length);
- System.arraycopy(salt, 0, saltLine, salted.length, salt.length);
- InputStream head = new ByteArrayInputStream(saltLine);
- cipherStream = new ComboInputStream(head, cipherStream);
- }
- if (toBase64) {
- cipherStream = new Base64InputStream(cipherStream, true);
- }
- return cipherStream;
- }
-
-
- public static byte[] decrypt(String cipher, byte[] key, byte[] iv,
- byte[] encrypted)
- throws IOException, GeneralSecurityException {
- ByteArrayInputStream in = new ByteArrayInputStream(encrypted);
- InputStream decrypted = decrypt(cipher, key, iv, in);
- return Util.streamToBytes(decrypted);
- }
-
- public static InputStream decrypt(String cipher, byte[] key, byte[] iv,
- InputStream encrypted)
- throws IOException, GeneralSecurityException {
- CipherInfo cipherInfo = lookup(cipher);
- byte[] firstLine = Util.streamToBytes(encrypted, 16);
- if (Base64.isArrayByteBase64(firstLine)) {
- InputStream head = new ByteArrayInputStream(firstLine);
- // Need to put that 16 byte "firstLine" back into the Stream.
- encrypted = new ComboInputStream(head, encrypted);
- encrypted = new Base64InputStream(encrypted);
- } else {
- // Encrypted data wasn't base64. Need to put the "firstLine" we
- // extracted back into the stream.
- InputStream head = new ByteArrayInputStream(firstLine);
- encrypted = new ComboInputStream(head, encrypted);
- }
-
- int keySize = cipherInfo.keySize;
- int ivSize = cipherInfo.ivSize;
- // Looks like key is in hex
- if (key.length == keySize / 4) {
- key = Hex.decode(key);
- }
- // Looks like IV is in hex
- if (iv.length == ivSize / 4) {
- iv = Hex.decode(iv);
- }
- DerivedKey dk = new DerivedKey(key, iv);
- Cipher c = PKCS8Key.generateCipher(cipherInfo.javaCipher,
- cipherInfo.blockMode,
- dk, cipherInfo.des2, null, true);
- return new CipherInputStream(encrypted, c);
- }
-
- public static byte[] encrypt(String cipher, byte[] key, byte[] iv,
- byte[] data)
- throws IOException, GeneralSecurityException {
- return encrypt(cipher, key, iv, data, true);
- }
-
- public static byte[] encrypt(String cipher, byte[] key, byte[] iv,
- byte[] data, boolean toBase64)
- throws IOException, GeneralSecurityException {
- ByteArrayInputStream in = new ByteArrayInputStream(data);
- InputStream encrypted = encrypt(cipher, key, iv, in, toBase64);
- return Util.streamToBytes(encrypted);
- }
-
-
- public static InputStream encrypt(String cipher, byte[] key, byte[] iv,
- InputStream data)
- throws IOException, GeneralSecurityException {
- return encrypt(cipher, key, iv, data, true);
- }
-
- public static InputStream encrypt(String cipher, byte[] key, byte[] iv,
- InputStream data, boolean toBase64)
- throws IOException, GeneralSecurityException {
- CipherInfo cipherInfo = lookup(cipher);
- int keySize = cipherInfo.keySize;
- int ivSize = cipherInfo.ivSize;
- if (key.length == keySize / 4) {
- key = Hex.decode(key);
- }
- if (iv.length == ivSize / 4) {
- iv = Hex.decode(iv);
- }
- DerivedKey dk = new DerivedKey(key, iv);
- Cipher c = PKCS8Key.generateCipher(cipherInfo.javaCipher,
- cipherInfo.blockMode,
- dk, cipherInfo.des2, null, false);
-
- InputStream cipherStream = new CipherInputStream(data, c);
- if (toBase64) {
- cipherStream = new Base64InputStream(cipherStream, true);
- }
- return cipherStream;
- }
-
-
- public static DerivedKey deriveKey(char[] password, byte[] salt,
- int keySize, boolean des2)
- throws NoSuchAlgorithmException {
- return deriveKey(password, salt, keySize, 0, des2);
- }
-
- @SuppressWarnings("PMD.UselessParentheses")
- public static DerivedKey deriveKey(char[] password, byte[] salt,
- int keySize, int ivSize, boolean des2)
- throws NoSuchAlgorithmException {
- if (des2) {
- keySize = 128;
- }
- MessageDigest md = MessageDigest.getInstance("MD5");
- byte[] pwdAsBytes = new byte[password.length];
- for (int i = 0; i < password.length; i++) {
- pwdAsBytes[i] = (byte) password[i];
- }
-
- md.reset();
- byte[] keyAndIv = new byte[(keySize / 8) + (ivSize / 8)];
- if (salt == null || salt.length == 0) {
- // Unsalted! Bad idea!
- salt = null;
- }
- byte[] result;
- int currentPos = 0;
- while (currentPos < keyAndIv.length) {
- md.update(pwdAsBytes);
- if (salt != null) {
- // First 8 bytes of salt ONLY! That wasn't obvious to me
- // when using AES encrypted private keys in "Traditional
- // SSLeay Format".
- //
- // Example:
- // DEK-Info: AES-128-CBC,8DA91D5A71988E3D4431D9C2C009F249
- //
- // Only the first 8 bytes are salt, but the whole thing is
- // re-used again later as the IV. MUCH gnashing of teeth!
- md.update(salt, 0, 8);
- }
- result = md.digest();
- int stillNeed = keyAndIv.length - currentPos;
- // Digest gave us more than we need. Let's truncate it.
- if (result.length > stillNeed) {
- byte[] b = new byte[stillNeed];
- System.arraycopy(result, 0, b, 0, b.length);
- result = b;
- }
- System.arraycopy(result, 0, keyAndIv, currentPos, result.length);
- currentPos += result.length;
- if (currentPos < keyAndIv.length) {
- // Next round starts with a hash of the hash.
- md.reset();
- md.update(result);
- }
- }
- if (des2) {
- keySize = 192;
- byte[] buf = new byte[keyAndIv.length + 8];
- // Make space where 3rd key needs to go (16th - 24th bytes):
- System.arraycopy(keyAndIv, 0, buf, 0, 16);
- if (ivSize > 0) {
- System.arraycopy(keyAndIv, 16, buf, 24, keyAndIv.length - 16);
- }
- keyAndIv = buf;
- // copy first 8 bytes into last 8 bytes to create 2DES key.
- System.arraycopy(keyAndIv, 0, keyAndIv, 16, 8);
- }
- if (ivSize == 0) {
- // if ivSize == 0, then "keyAndIv" array is actually all key.
-
- // Must be "Traditional SSLeay Format" encrypted private key in
- // PEM. The "salt" in its entirety (not just first 8 bytes) will
- // probably be re-used later as the IV (initialization vector).
- return new DerivedKey(keyAndIv, salt);
- } else {
- byte[] key = new byte[keySize / 8];
- byte[] iv = new byte[ivSize / 8];
- System.arraycopy(keyAndIv, 0, key, 0, key.length);
- System.arraycopy(keyAndIv, key.length, iv, 0, iv.length);
- return new DerivedKey(key, iv);
- }
- }
-
-
- public static class CipherInfo {
- public final String javaCipher;
- public final String blockMode;
- public final int keySize;
- public final int ivSize;
- public final boolean des2;
-
- public CipherInfo(String javaCipher, String blockMode, int keySize,
- int ivSize, boolean des2) {
- this.javaCipher = javaCipher;
- this.blockMode = blockMode;
- this.keySize = keySize;
- this.ivSize = ivSize;
- this.des2 = des2;
- }
-
- public String toString() {
- return javaCipher + "/" + blockMode + " " + keySize + "bit des2=" + des2;
- }
- }
-
- /**
- * Converts the way OpenSSL names its ciphers into a Java-friendly naming.
- *
- * @param openSSLCipher OpenSSL cipher name, e.g. "des3" or "des-ede3-cbc".
- * Try "man enc" on a unix box to see what's possible.
- * @return CipherInfo object with the Java-friendly cipher information.
- */
- public static CipherInfo lookup(String openSSLCipher) {
- openSSLCipher = openSSLCipher.trim();
- if (openSSLCipher.charAt(0) == '-') {
- openSSLCipher = openSSLCipher.substring(1);
- }
- String javaCipher = openSSLCipher.toUpperCase();
- String blockMode = "CBC";
- int keySize = -1;
- int ivSize = 64;
- boolean des2 = false;
-
-
- StringTokenizer st = new StringTokenizer(openSSLCipher, "-");
- if (st.hasMoreTokens()) {
- javaCipher = st.nextToken().toUpperCase();
- if (st.hasMoreTokens()) {
- // Is this the middle token? Or the last token?
- String tok = st.nextToken();
- if (st.hasMoreTokens()) {
- try {
- keySize = Integer.parseInt(tok);
- } catch (NumberFormatException nfe) {
- // I guess 2nd token isn't an integer
- String upper = tok.toUpperCase();
- if (upper.startsWith("EDE3")) {
- javaCipher = "DESede";
- } else if (upper.startsWith("EDE")) {
- javaCipher = "DESede";
- des2 = true;
- }
- }
- blockMode = st.nextToken().toUpperCase();
- } else {
- try {
- keySize = Integer.parseInt(tok);
- } catch (NumberFormatException nfe) {
- // It's the last token, so must be mode (usually "CBC").
- blockMode = tok.toUpperCase();
- if (blockMode.startsWith("EDE3")) {
- javaCipher = "DESede";
- blockMode = "ECB";
- } else if (blockMode.startsWith("EDE")) {
- javaCipher = "DESede";
- blockMode = "ECB";
- des2 = true;
- }
- }
- }
- }
- }
- if (javaCipher.startsWith("BF")) {
- javaCipher = "Blowfish";
- } else if (javaCipher.startsWith("TWOFISH")) {
- javaCipher = "Twofish";
- ivSize = 128;
- } else if (javaCipher.startsWith("IDEA")) {
- javaCipher = "IDEA";
- } else if (javaCipher.startsWith("CAST6")) {
- javaCipher = "CAST6";
- ivSize = 128;
- } else if (javaCipher.startsWith("CAST")) {
- javaCipher = "CAST5";
- } else if (javaCipher.startsWith("GOST")) {
- keySize = 256;
- } else if (javaCipher.startsWith("DESX")) {
- javaCipher = "DESX";
- } else if ("DES3".equals(javaCipher)) {
- javaCipher = "DESede";
- } else if ("DES2".equals(javaCipher)) {
- javaCipher = "DESede";
- des2 = true;
- } else if (javaCipher.startsWith("RIJNDAEL")) {
- javaCipher = "Rijndael";
- ivSize = 128;
- } else if (javaCipher.startsWith("SEED")) {
- javaCipher = "SEED";
- ivSize = 128;
- } else if (javaCipher.startsWith("SERPENT")) {
- javaCipher = "Serpent";
- ivSize = 128;
- } else if (javaCipher.startsWith("Skipjack")) {
- javaCipher = "Skipjack";
- ivSize = 128;
- } else if (javaCipher.startsWith("RC6")) {
- javaCipher = "RC6";
- ivSize = 128;
- } else if (javaCipher.startsWith("TEA")) {
- javaCipher = "TEA";
- } else if (javaCipher.startsWith("XTEA")) {
- javaCipher = "XTEA";
- } else if (javaCipher.startsWith("AES")) {
- if (javaCipher.startsWith("AES128")) {
- keySize = 128;
- } else if (javaCipher.startsWith("AES192")) {
- keySize = 192;
- } else if (javaCipher.startsWith("AES256")) {
- keySize = 256;
- }
- javaCipher = "AES";
- ivSize = 128;
- } else if (javaCipher.startsWith("CAMELLIA")) {
- if (javaCipher.startsWith("CAMELLIA128")) {
- keySize = 128;
- } else if (javaCipher.startsWith("CAMELLIA192")) {
- keySize = 192;
- } else if (javaCipher.startsWith("CAMELLIA256")) {
- keySize = 256;
- }
- javaCipher = "CAMELLIA";
- ivSize = 128;
- }
- if (keySize == -1) {
- if (javaCipher.startsWith("DESede")) {
- keySize = 192;
- } else if (javaCipher.startsWith("DES")) {
- keySize = 64;
- } else {
- // RC2, RC4, RC5 and Blowfish ?
- keySize = 128;
- }
- }
- return new CipherInfo(javaCipher, blockMode, keySize, ivSize, des2);
- }
-
-
- /**
- * @param args command line arguments: [password] [cipher] [file-to-decrypt]
- * <br>[cipher] == OpenSSL cipher name, e.g. "des3" or "des-ede3-cbc".
- * Try "man enc" on a unix box to see what's possible.
- * @throws java.io.IOException problems with the [file-to-decrypt]
- * @throws java.security.GeneralSecurityException decryption problems
- */
- public static void main(String[] args)
- throws IOException, GeneralSecurityException {
- if (args.length < 3) {
- System.out.println(Version.versionString());
- System.out.println("Pure-java utility to decrypt files previously encrypted by \'openssl enc\'");
- System.out.println();
- System.out.println("Usage: java -cp commons-ssl.jar org.apache.commons.ssl.OpenSSL [args]");
- System.out.println(" [args] == [password] [cipher] [file-to-decrypt]");
- System.out.println(" [cipher] == des, des3, des-ede3-cbc, aes256, rc2, rc4, bf, bf-cbc, etc...");
- System.out.println(" Try 'man enc' on a unix box to see what's possible.");
- System.out.println();
- System.out.println("This utility can handle base64 or raw, salted or unsalted.");
- System.out.println();
- System.exit(1);
- }
- char[] password = args[0].toCharArray();
-
- InputStream in = new FileInputStream(args[2]);
- in = decrypt(args[1], password, in);
-
- // in = encrypt( args[ 1 ], pwdAsBytes, in, true );
-
- in = new BufferedInputStream(in);
- BufferedOutputStream bufOut = new BufferedOutputStream(System.out);
- Util.pipeStream(in, bufOut, false);
- bufOut.flush();
- System.out.flush();
- }
-
-}
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/63dcb1a5/kerby-pkix/src/main/java/org/apache/commons/ssl/PBETestCreate.java
----------------------------------------------------------------------
diff --git a/kerby-pkix/src/main/java/org/apache/commons/ssl/PBETestCreate.java b/kerby-pkix/src/main/java/org/apache/commons/ssl/PBETestCreate.java
deleted file mode 100644
index 0aef858..0000000
--- a/kerby-pkix/src/main/java/org/apache/commons/ssl/PBETestCreate.java
+++ /dev/null
@@ -1,79 +0,0 @@
-package org.apache.commons.ssl;
-
-import org.apache.kerby.util.Util;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Properties;
-import java.util.TreeSet;
-
-/**
- * @author Julius Davies
- * @since 4-Jul-2007
- */
-public class PBETestCreate {
-
- public static void main(String[] args) throws Exception {
- FileInputStream in = new FileInputStream(args[0]);
- Properties p = new Properties();
- p.load(in);
- in.close();
-
- String targetDir = p.getProperty("target");
- File dir = new File(targetDir);
- dir.mkdirs();
- if (!dir.exists()) {
- throw new IOException(dir.getCanonicalPath() + " doesn't exist!");
- }
-
- TreeSet ciphers = new TreeSet();
- Iterator it = p.entrySet().iterator();
- while (it.hasNext()) {
- Map.Entry entry = (Map.Entry) it.next();
- String key = (String) entry.getKey();
- if (!"target".equalsIgnoreCase(key)) {
- ciphers.add(key);
- ciphers.add(key + "-cbc");
- ciphers.add(key + "-cfb");
- ciphers.add(key + "-cfb1");
- ciphers.add(key + "-cfb8");
- ciphers.add(key + "-ecb");
- ciphers.add(key + "-ofb");
- }
- }
-
- byte[] toEncrypt = "Hello World!".getBytes("UTF-8");
- char[] pwd = "changeit".toCharArray();
- it = ciphers.iterator();
- while (it.hasNext()) {
- String cipher = (String) it.next();
- String cipherPadded = Util.pad(cipher, 15, false);
- String fileNameBase64 = cipher + ".base64";
- String fileNameRaw = cipher + ".raw";
- String d = dir.getCanonicalPath() + "/";
- try {
- byte[] base64 = OpenSSL.encrypt(cipher, pwd, toEncrypt, true);
- FileOutputStream out = new FileOutputStream(d + fileNameBase64);
- out.write(base64);
- out.close();
- } catch (Exception e) {
- System.err.println("FAILURE \t" + cipherPadded + "\t" + fileNameBase64 + "\t" + e);
- }
-
- try {
- byte[] raw = OpenSSL.encrypt(cipher, pwd, toEncrypt, false);
- FileOutputStream out = new FileOutputStream(d + fileNameRaw);
- out.write(raw);
- out.close();
- } catch (Exception e) {
- System.err.println("FAILURE \t" + cipherPadded + "\t" + fileNameRaw + "\t" + e);
- }
-
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/63dcb1a5/kerby-pkix/src/main/java/org/apache/commons/ssl/PEMItem.java
----------------------------------------------------------------------
diff --git a/kerby-pkix/src/main/java/org/apache/commons/ssl/PEMItem.java b/kerby-pkix/src/main/java/org/apache/commons/ssl/PEMItem.java
deleted file mode 100644
index 846340a..0000000
--- a/kerby-pkix/src/main/java/org/apache/commons/ssl/PEMItem.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.16/src/java/org/apache/commons/ssl/PEMItem.java $
- * $Revision: 121 $
- * $Date: 2007-11-13 21:26:57 -0800 (Tue, 13 Nov 2007) $
- *
- * ====================================================================
- * 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.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- */
-
-package org.apache.commons.ssl;
-
-import org.apache.kerby.util.Hex;
-
-import java.util.Collections;
-import java.util.Map;
-import java.util.StringTokenizer;
-import java.util.TreeMap;
-
-/**
- * @author Credit Union Central of British Columbia
- * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
- * @author <a href="mailto:juliusdavies@cucbc.com">juliusdavies@cucbc.com</a>
- * @since 13-Aug-2006
- */
-public class PEMItem {
- public static final String DEK_INFO = "dek-info";
-
- private final byte[] derBytes;
- public final String pemType;
- public final Map properties;
-
- public final String dekInfo;
- public final byte[] iv;
- public final String cipher;
- public final boolean des2;
- public final String mode;
- public final int keySizeInBits;
-
- public PEMItem(byte[] derBytes, String type) {
- this(derBytes, type, null);
- }
-
- public PEMItem(byte[] derBytes, String type, Map properties) {
- this.derBytes = derBytes;
- this.pemType = type;
- if (properties == null) {
- properties = new TreeMap(); // empty map
- }
- this.properties = Collections.unmodifiableMap(properties);
- String di = (String) properties.get(DEK_INFO);
- String diCipher = "";
- String diIV = "";
- if (di != null) {
- StringTokenizer st = new StringTokenizer(di, ",");
- if (st.hasMoreTokens()) {
- diCipher = st.nextToken().trim().toLowerCase();
- }
- if (st.hasMoreTokens()) {
- diIV = st.nextToken().trim().toLowerCase();
- }
- }
- this.dekInfo = diCipher;
- this.iv = Hex.decode(diIV);
- if (!"".equals(diCipher)) {
- OpenSSL.CipherInfo cipherInfo = OpenSSL.lookup(diCipher);
- this.cipher = cipherInfo.javaCipher;
- this.mode = cipherInfo.blockMode;
- this.keySizeInBits = cipherInfo.keySize;
- this.des2 = cipherInfo.des2;
- } else {
- this.mode = "";
- cipher = "UNKNOWN";
- keySizeInBits = -1;
- des2 = false;
- }
- }
-
- public byte[] getDerBytes() {
- byte[] b = new byte[derBytes.length];
- System.arraycopy(derBytes, 0, b, 0, derBytes.length);
- return b;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/63dcb1a5/kerby-pkix/src/main/java/org/apache/commons/ssl/PEMUtil.java
----------------------------------------------------------------------
diff --git a/kerby-pkix/src/main/java/org/apache/commons/ssl/PEMUtil.java b/kerby-pkix/src/main/java/org/apache/commons/ssl/PEMUtil.java
deleted file mode 100644
index a062d62..0000000
--- a/kerby-pkix/src/main/java/org/apache/commons/ssl/PEMUtil.java
+++ /dev/null
@@ -1,259 +0,0 @@
-/*
- * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.16/src/java/org/apache/commons/ssl/PEMUtil.java $
- * $Revision: 153 $
- * $Date: 2009-09-15 22:40:53 -0700 (Tue, 15 Sep 2009) $
- *
- * ====================================================================
- * 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.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- */
-
-package org.apache.commons.ssl;
-
-import org.apache.kerby.util.Base64;
-import org.apache.kerby.util.ByteArrayReadLine;
-import org.apache.kerby.util.Util;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.math.BigInteger;
-import java.security.PublicKey;
-import java.security.interfaces.DSAPublicKey;
-import java.security.interfaces.RSAPrivateCrtKey;
-import java.security.interfaces.RSAPublicKey;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-
-/**
- * @author Credit Union Central of British Columbia
- * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
- * @author <a href="mailto:juliusdavies@cucbc.com">juliusdavies@cucbc.com</a>
- * @since 13-Aug-2006
- */
-public class PEMUtil {
- static final String LINE_SEPARATOR = System.getProperty("line.separator");
-
- public static byte[] encode(Collection items) throws IOException {
- final byte[] lineSeparatorBytes = LINE_SEPARATOR.getBytes("UTF-8");
- ByteArrayOutputStream out = new ByteArrayOutputStream(8192);
- Iterator it = items.iterator();
- while (it.hasNext()) {
- PEMItem item = (PEMItem) it.next();
- out.write("-----BEGIN ".getBytes("UTF-8"));
- out.write(item.pemType.getBytes("UTF-8"));
- out.write("-----".getBytes("UTF-8"));
- out.write(lineSeparatorBytes);
-
- byte[] derBytes = item.getDerBytes();
- ByteArrayInputStream bin = new ByteArrayInputStream(derBytes);
- byte[] line = Util.streamToBytes(bin, 48);
- while (line.length == 48) {
- byte[] base64Line = Base64.encodeBase64(line);
- out.write(base64Line);
- out.write(lineSeparatorBytes);
- line = Util.streamToBytes(bin, 48);
- }
- if (line.length > 0) {
- byte[] base64Line = Base64.encodeBase64(line);
- out.write(base64Line);
- out.write(lineSeparatorBytes);
- }
- out.write("-----END ".getBytes("UTF-8"));
- out.write(item.pemType.getBytes("UTF-8"));
- out.write("-----".getBytes("UTF-8"));
- out.write(lineSeparatorBytes);
- }
- return out.toByteArray();
- }
-
- public static List decode(byte[] pemBytes) {
- LinkedList pemItems = new LinkedList();
- ByteArrayInputStream in = new ByteArrayInputStream(pemBytes);
- ByteArrayReadLine readLine = new ByteArrayReadLine(in);
- String line = readLine.next();
- while (line != null) {
- int len = 0;
- byte[] decoded;
- ArrayList listOfByteArrays = new ArrayList(64);
- Map properties = new HashMap();
- String type = "[unknown]";
- while (line != null && !beginBase64(line)) {
- line = readLine.next();
- }
- if (line != null) {
- String upperLine = line.toUpperCase();
- int x = upperLine.indexOf("-BEGIN") + "-BEGIN".length();
- int y = upperLine.indexOf("-", x);
- type = upperLine.substring(x, y).trim();
- line = readLine.next();
- }
- while (line != null && !endBase64(line)) {
- line = Util.trim(line);
- if (!"".equals(line)) {
- int x = line.indexOf(':');
- if (x > 0) {
- String k = line.substring(0, x).trim();
- String v = "";
- if (line.length() > x + 1) {
- v = line.substring(x + 1).trim();
- }
- properties.put(k.toLowerCase(), v.toLowerCase());
- } else {
- byte[] base64 = line.getBytes();
- byte[] rawBinary = Base64.decodeBase64(base64);
- listOfByteArrays.add(rawBinary);
- len += rawBinary.length;
- }
- }
- line = readLine.next();
- }
- if (line != null) {
- line = readLine.next();
- }
-
- if (!listOfByteArrays.isEmpty()) {
- decoded = new byte[len];
- int pos = 0;
- Iterator it = listOfByteArrays.iterator();
- while (it.hasNext()) {
- byte[] oneLine = (byte[]) it.next();
- System.arraycopy(oneLine, 0, decoded, pos, oneLine.length);
- pos += oneLine.length;
- }
- PEMItem item = new PEMItem(decoded, type, properties);
- pemItems.add(item);
- }
- }
-
- // closing ByteArrayInputStream is a NO-OP
- // in.close();
-
- return pemItems;
- }
-
- private static boolean beginBase64(String line) {
- line = line != null ? line.trim().toUpperCase() : "";
- int x = line.indexOf("-BEGIN");
- return x > 0 && startsAndEndsWithDashes(line);
- }
-
- private static boolean endBase64(String line) {
- line = line != null ? line.trim().toUpperCase() : "";
- int x = line.indexOf("-END");
- return x > 0 && startsAndEndsWithDashes(line);
- }
-
- private static boolean startsAndEndsWithDashes(String line) {
- line = Util.trim(line);
- char c = line.charAt(0);
- char d = line.charAt(line.length() - 1);
- return c == '-' && d == '-';
- }
-
- public static String formatRSAPrivateKey(RSAPrivateCrtKey key) {
- StringBuffer buf = new StringBuffer(2048);
- buf.append("Private-Key:");
- buf.append(LINE_SEPARATOR);
- buf.append("modulus:");
- buf.append(LINE_SEPARATOR);
- buf.append(formatBigInteger(key.getModulus(), 129 * 2));
- buf.append(LINE_SEPARATOR);
- buf.append("publicExponent: ");
- buf.append(key.getPublicExponent());
- buf.append(LINE_SEPARATOR);
- buf.append("privateExponent:");
- buf.append(LINE_SEPARATOR);
- buf.append(formatBigInteger(key.getPrivateExponent(), 128 * 2));
- buf.append(LINE_SEPARATOR);
- buf.append("prime1:");
- buf.append(LINE_SEPARATOR);
- buf.append(formatBigInteger(key.getPrimeP(), 65 * 2));
- buf.append(LINE_SEPARATOR);
- buf.append("prime2:");
- buf.append(LINE_SEPARATOR);
- buf.append(formatBigInteger(key.getPrimeQ(), 65 * 2));
- buf.append(LINE_SEPARATOR);
- buf.append("exponent1:");
- buf.append(LINE_SEPARATOR);
- buf.append(formatBigInteger(key.getPrimeExponentP(), 65 * 2));
- buf.append(LINE_SEPARATOR);
- buf.append("exponent2:");
- buf.append(LINE_SEPARATOR);
- buf.append(formatBigInteger(key.getPrimeExponentQ(), 65 * 2));
- buf.append(LINE_SEPARATOR);
- buf.append("coefficient:");
- buf.append(LINE_SEPARATOR);
- buf.append(formatBigInteger(key.getCrtCoefficient(), 65 * 2));
- return buf.toString();
- }
-
- public static String formatBigInteger(BigInteger bi, int length) {
- String s = bi.toString(16);
- StringBuffer buf = new StringBuffer(s.length());
- int zeroesToAppend = length - s.length();
- int count = 0;
- buf.append(" ");
- for (int i = 0; i < zeroesToAppend; i++) {
- count++;
- buf.append('0');
- if (i % 2 == 1) {
- buf.append(':');
- }
- }
- for (int i = 0; i < s.length() - 2; i++) {
- count++;
- buf.append(s.charAt(i));
- if (i % 2 == 1) {
- buf.append(':');
- }
- if (count % 30 == 0) {
- buf.append(LINE_SEPARATOR);
- buf.append(" ");
- }
- }
- buf.append(s.substring(s.length() - 2));
- return buf.toString();
- }
-
- public static String toPem(PublicKey key) throws IOException {
- PEMItem item = null;
- if (key instanceof RSAPublicKey) {
- item = new PEMItem(key.getEncoded(), "PUBLIC KEY");
- } else if (key instanceof DSAPublicKey) {
- item = new PEMItem(key.getEncoded(), "PUBLIC KEY");
- } else {
- throw new IOException("Not an RSA or DSA key");
- }
- byte[] pem = encode(Collections.singleton(item));
- return new String(pem, "UTF-8");
- }
-
-}