001: /*
002: * $Id: KeyStoreUtil.java,v 1.6 2003/12/04 18:39:14 ajzeneski Exp $
003: *
004: * Copyright (c) 2003 The Open For Business Project - www.ofbiz.org
005: *
006: * Permission is hereby granted, free of charge, to any person obtaining a
007: * copy of this software and associated documentation files (the "Software"),
008: * to deal in the Software without restriction, including without limitation
009: * the rights to use, copy, modify, merge, publish, distribute, sublicense,
010: * and/or sell copies of the Software, and to permit persons to whom the
011: * Software is furnished to do so, subject to the following conditions:
012: *
013: * The above copyright notice and this permission notice shall be included
014: * in all copies or substantial portions of the Software.
015: *
016: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
017: * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
018: * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
019: * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
020: * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
021: * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
022: * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
023: *
024: */
025: package org.ofbiz.base.util;
026:
027: import java.io.ByteArrayInputStream;
028: import java.io.File;
029: import java.io.FileInputStream;
030: import java.io.FileOutputStream;
031: import java.io.IOException;
032: import java.security.AlgorithmParameterGenerator;
033: import java.security.AlgorithmParameters;
034: import java.security.GeneralSecurityException;
035: import java.security.Key;
036: import java.security.KeyFactory;
037: import java.security.KeyPair;
038: import java.security.KeyPairGenerator;
039: import java.security.KeyStore;
040: import java.security.KeyStoreException;
041: import java.security.NoSuchAlgorithmException;
042: import java.security.PrivateKey;
043: import java.security.PublicKey;
044: import java.security.UnrecoverableKeyException;
045: import java.security.cert.Certificate;
046: import java.security.cert.CertificateEncodingException;
047: import java.security.cert.CertificateException;
048: import java.security.cert.CertificateFactory;
049: import java.security.spec.InvalidKeySpecException;
050: import java.security.spec.PKCS8EncodedKeySpec;
051: import java.security.spec.X509EncodedKeySpec;
052: import java.util.Collection;
053:
054: import javax.crypto.KeyAgreement;
055: import javax.crypto.SecretKey;
056: import javax.crypto.spec.DHParameterSpec;
057:
058: /**
059: * KeyStoreUtil - Utilities for getting KeyManagers and TrustManagers
060: *
061: * @author <a href="mailto:jaz@ofbiz.org">Andy Zeneski</a>
062: * @version $Revision: 1.6 $
063: * @since 3.0
064: */
065: public class KeyStoreUtil {
066:
067: public static final String module = KeyStoreUtil.class.getName();
068:
069: public static String getKeyStoreFileName() {
070: return UtilProperties.getPropertyValue("jsse.properties",
071: "ofbiz.keyStore", null);
072: }
073:
074: public static String getKeyStorePassword() {
075: return UtilProperties.getPropertyValue("jsse.properties",
076: "ofbiz.keyStore.password", null);
077: }
078:
079: public static String getKeyStoreType() {
080: return UtilProperties.getPropertyValue("jsse.properties",
081: "ofbiz.keyStore.type", "jks");
082: }
083:
084: public static String getTrustStoreFileName() {
085: return UtilProperties.getPropertyValue("jsse.properties",
086: "ofbiz.trustStore", null);
087: }
088:
089: public static String getTrustStorePassword() {
090: return UtilProperties.getPropertyValue("jsse.properties",
091: "ofbiz.trustStore.password", null);
092: }
093:
094: public static String getTrustStoreType() {
095: return UtilProperties.getPropertyValue("jsse.properties",
096: "ofbiz.trustStore.type", "jks");
097: }
098:
099: public static KeyStore getKeyStore() throws IOException,
100: GeneralSecurityException {
101: if (getKeyStoreFileName() != null
102: && !keyStoreExists(getKeyStoreFileName())) {
103: return null;
104: }
105: FileInputStream fis = new FileInputStream(getKeyStoreFileName());
106: KeyStore ks = KeyStore.getInstance(getKeyStoreType());
107: ks.load(fis, getKeyStorePassword().toCharArray());
108: fis.close();
109: return ks;
110: }
111:
112: public static void saveKeyStore(KeyStore ks) throws IOException,
113: KeyStoreException, NoSuchAlgorithmException,
114: CertificateException {
115: ks.store(new FileOutputStream(getKeyStoreFileName()),
116: getKeyStorePassword().toCharArray());
117: }
118:
119: public static KeyStore getTrustStore() throws IOException,
120: GeneralSecurityException {
121: if (getTrustStoreFileName() != null
122: && !keyStoreExists(getTrustStoreFileName())) {
123: return null;
124: }
125: FileInputStream fis = new FileInputStream(
126: getTrustStoreFileName());
127: KeyStore ks = KeyStore.getInstance(getTrustStoreType());
128: ks.load(fis, getTrustStorePassword().toCharArray());
129: fis.close();
130: return ks;
131: }
132:
133: public static void saveTrustStore(KeyStore ks) throws IOException,
134: KeyStoreException, NoSuchAlgorithmException,
135: CertificateException {
136: ks.store(new FileOutputStream(getTrustStoreFileName()),
137: getTrustStorePassword().toCharArray());
138: }
139:
140: public static boolean keyStoreExists(String fileName) {
141: File keyFile = new File(fileName);
142: return keyFile.exists();
143: }
144:
145: public static KeyStore createKeyStore(String fileName,
146: String password) throws KeyStoreException,
147: NoSuchAlgorithmException, CertificateException, IOException {
148: KeyStore ks = null;
149: ks = KeyStore.getInstance("jks");
150: ks.load(null, password.toCharArray());
151: ks
152: .store(new FileOutputStream(fileName), password
153: .toCharArray());
154: ks.load(new FileInputStream(fileName), password.toCharArray());
155: return ks;
156: }
157:
158: public static void renameKeyStoreEntry(String fromAlias,
159: String toAlias) throws GeneralSecurityException,
160: IOException {
161: KeyStore ks = getKeyStore();
162: String pass = getKeyStorePassword();
163: renameEntry(ks, pass, fromAlias, toAlias);
164: saveKeyStore(ks);
165: }
166:
167: private static void renameEntry(KeyStore ks, String pass,
168: String fromAlias, String toAlias) throws KeyStoreException,
169: UnrecoverableKeyException, NoSuchAlgorithmException {
170: if (ks.isKeyEntry(fromAlias)) {
171: Key fromKey = ks.getKey(fromAlias, pass.toCharArray());
172: if (fromKey instanceof PrivateKey) {
173: Certificate[] certs = ks.getCertificateChain(fromAlias);
174: ks.deleteEntry(fromAlias);
175: ks.setKeyEntry(toAlias, fromKey, pass.toCharArray(),
176: certs);
177: }
178: } else if (ks.isCertificateEntry(fromAlias)) {
179: Certificate cert = ks.getCertificate(fromAlias);
180: ks.deleteEntry(fromAlias);
181: ks.setCertificateEntry(toAlias, cert);
182: }
183: }
184:
185: public static void importPKCS8CertChain(KeyStore ks, String alias,
186: byte[] keyBytes, String keyPass, byte[] certChain)
187: throws InvalidKeySpecException, NoSuchAlgorithmException,
188: CertificateException, KeyStoreException {
189: // load the private key
190: KeyFactory kf = KeyFactory.getInstance("RSA");
191: PKCS8EncodedKeySpec keysp = new PKCS8EncodedKeySpec(keyBytes);
192: PrivateKey pk = kf.generatePrivate(keysp);
193:
194: // load the cert chain
195: CertificateFactory cf = CertificateFactory.getInstance("X.509");
196: ByteArrayInputStream bais = new ByteArrayInputStream(certChain);
197:
198: Collection certCol = cf.generateCertificates(bais);
199: Certificate[] certs = new Certificate[certCol.toArray().length];
200: if (certCol.size() == 1) {
201: Debug.log("Single certificate; no chain", module);
202: bais = new ByteArrayInputStream(certChain);
203: Certificate cert = cf.generateCertificate(bais);
204: certs[0] = cert;
205: } else {
206: Debug.log("Certificate chain length : " + certCol.size(),
207: module);
208: certs = (Certificate[]) certCol.toArray();
209: }
210:
211: ks.setKeyEntry(alias, pk, keyPass.toCharArray(), certs);
212: }
213:
214: // key pair generation methods
215: public static KeyPair createDHKeyPair() throws Exception {
216: AlgorithmParameterGenerator apGen = AlgorithmParameterGenerator
217: .getInstance("DH");
218: apGen.init(1024);
219:
220: AlgorithmParameters algParams = apGen.generateParameters();
221: DHParameterSpec dhParamSpec = (DHParameterSpec) algParams
222: .getParameterSpec(DHParameterSpec.class);
223:
224: KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DH");
225: keyGen.initialize(dhParamSpec);
226:
227: KeyPair keypair = keyGen.generateKeyPair();
228: return keypair;
229: }
230:
231: public static KeyPair getKeyPair(String alias, String password)
232: throws Exception {
233: KeyStore ks = getKeyStore();
234: Key key = ks.getKey(alias, password.toCharArray());
235: if (key instanceof PrivateKey) {
236: Certificate cert = ks.getCertificate(alias);
237: PublicKey publicKey = cert.getPublicKey();
238: return new KeyPair(publicKey, (PrivateKey) key);
239: } else {
240: Debug.logError("Key is not an instance of PrivateKey",
241: module);
242: }
243: return null;
244: }
245:
246: public static void storeCertificate(String alias, Certificate cert)
247: throws Exception {
248: KeyStore ks = getKeyStore();
249: ks.setCertificateEntry(alias, cert);
250: ks.store(new FileOutputStream(getKeyStoreFileName()),
251: getKeyStorePassword().toCharArray());
252: }
253:
254: public static void storeKeyPair(KeyPair keyPair, String alias,
255: String password) throws Exception {
256: KeyStore ks = getKeyStore();
257: CertificateFactory cf = CertificateFactory.getInstance("X.509");
258: PrivateKey privateKey = keyPair.getPrivate();
259: PublicKey publicKey = keyPair.getPublic();
260: // not sure what to do here. Do we need to create a cert to assoc with the private key?
261: // cannot find methods for just setting the private/public key; missing something
262: ks.store(new FileOutputStream(getKeyStoreFileName()),
263: getKeyStorePassword().toCharArray());
264: }
265:
266: public static String certToString(Certificate cert)
267: throws CertificateEncodingException {
268: byte[] certBuf = cert.getEncoded();
269: StringBuffer buf = new StringBuffer();
270: buf.append("-----BEGIN CERTIFICATE-----\n");
271: buf.append(new sun.misc.BASE64Encoder().encode(certBuf));
272: buf.append("\n-----END CERTIFICATE-----\n");
273: return buf.toString();
274: }
275:
276: public static Certificate stringToCert(String certString)
277: throws CertificateException {
278: CertificateFactory cf = CertificateFactory.getInstance("X.509");
279: return null;
280: }
281:
282: public static SecretKey generateSecretKey(PrivateKey ourKey,
283: PublicKey theirKey) throws Exception {
284: KeyAgreement ka = KeyAgreement.getInstance("DH");
285: ka.init(ourKey);
286: ka.doPhase(theirKey, true);
287: return ka.generateSecret("TripleDES");
288: }
289:
290: public static PublicKey readDHPublicKey(byte[] keyBytes)
291: throws NoSuchAlgorithmException, InvalidKeySpecException {
292: X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(
293: keyBytes);
294: KeyFactory keyFactory = KeyFactory.getInstance("DH");
295: return keyFactory.generatePublic(x509KeySpec);
296: }
297:
298: public static PrivateKey readDHPrivateKey(byte[] keyBytes)
299: throws NoSuchAlgorithmException, InvalidKeySpecException {
300: X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(
301: keyBytes);
302: KeyFactory keyFactory = KeyFactory.getInstance("DH");
303: return keyFactory.generatePrivate(x509KeySpec);
304: }
305:
306: }
|