/* * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package sun.security.pkcs12; import java.io.*;import java.security.MessageDigest;import java.security.NoSuchAlgorithmException;import java.security.Key;import java.security.KeyFactory;import java.security.PrivateKey;import java.security.KeyStoreSpi;import java.security.KeyStoreException;import java.security.UnrecoverableKeyException;import java.security.SecureRandom;import java.security.cert.Certificate;import java.security.cert.CertificateFactory;import java.security.cert.X509Certificate;import java.security.cert.CertificateException;import java.security.spec.PKCS8EncodedKeySpec;import java.util.*;import java.math.*; import java.security.AlgorithmParameters;import java.security.spec.AlgorithmParameterSpec;import javax.crypto.spec.PBEParameterSpec;import javax.crypto.spec.PBEKeySpec;import javax.crypto.spec.SecretKeySpec;import javax.crypto.SecretKeyFactory;import javax.crypto.SecretKey;import javax.crypto.Cipher;import javax.crypto.Mac;import javax.security.auth.x500.X500Principal; import sun.security.util.DerInputStream;import sun.security.util.DerOutputStream;import sun.security.util.DerValue;import sun.security.util.ObjectIdentifier;import sun.security.pkcs.ContentInfo;import sun.security.x509.AlgorithmId;import sun.security.pkcs.EncryptedPrivateKeyInfo; /** * This class provides the keystore implementation referred to as "PKCS12". * Implements the PKCS#12 PFX protected using the Password privacy mode. * The contents are protected using Password integrity mode. * * Currently we support following PBE algorithms: * - pbeWithSHAAnd3KeyTripleDESCBC to encrypt private keys * - pbeWithSHAAnd40BitRC2CBC to encrypt certificates * * Supported encryption of various implementations : * * Software and mode. Certificate encryption Private key encryption * --------------------------------------------------------------------- * MSIE4 (domestic 40 bit RC2. 40 bit RC2 * and xport versions) * PKCS#12 export. * * MSIE4, 5 (domestic 40 bit RC2, 40 bit RC2, * and export versions) 3 key triple DES 3 key triple DES * PKCS#12 import. * * MSIE5 40 bit RC2 3 key triple DES, * PKCS#12 export. with SHA1 (168 bits) * * Netscape Communicator 40 bit RC2 3 key triple DES, * (domestic and export with SHA1 (168 bits) * versions) PKCS#12 export * * Netscape Communicator 40 bit ciphers only All. * (export version) * PKCS#12 import. * * Netscape Communicator All. All. * (domestic or fortified * version) PKCS#12 import. * * OpenSSL PKCS#12 code. All. All. * --------------------------------------------------------------------- * * NOTE: Currently PKCS12 KeyStore does not support TrustedCertEntries. * PKCS#12 is mainly used to deliver private keys with their associated * certificate chain and aliases. In a PKCS12 keystore, entries are * identified by the alias, and a localKeyId is required to match the * private key with the certificate. * * @author Seema Malkani * @author Jeff Nisewanger * @author Jan Luehe * * @see KeyProtector * @see java.security.KeyStoreSpi * @see KeyTool * * */public final class PKCS12KeyStore extends KeyStoreSpi { public static final int VERSION_3 = 3; private static final int keyBag[] = {1, 2, 840, 113549, 1, 12, 10, 1, 2}; private static final int certBag[] = {1, 2, 840, 113549, 1, 12, 10, 1, 3}; private static final int pkcs9Name[] = {1, 2, 840, 113549, 1, 9, 20}; private static final int pkcs9KeyId[] = {1, 2, 840, 113549, 1, 9, 21}; private static final int pkcs9certType[] = {1, 2, 840, 113549, 1, 9, 22, 1}; private static final int pbeWithSHAAnd40BitRC2CBC[] = {1, 2, 840, 113549, 1, 12, 1, 6}; private static final int pbeWithSHAAnd3KeyTripleDESCBC[] = {1, 2, 840, 113549, 1, 12, 1, 3}; private static ObjectIdentifier PKCS8ShroudedKeyBag_OID; private static ObjectIdentifier CertBag_OID; private static ObjectIdentifier PKCS9FriendlyName_OID; private static ObjectIdentifier PKCS9LocalKeyId_OID; private static ObjectIdentifier PKCS9CertType_OID; private static ObjectIdentifier pbeWithSHAAnd40BitRC2CBC_OID; private static ObjectIdentifier pbeWithSHAAnd3KeyTripleDESCBC_OID; private int counter = 0; private static final int iterationCount = 1024; private static final int SALT_LEN = 20; // private key count // Note: This is a workaround to allow null localKeyID attribute // in pkcs12 with one private key entry and associated cert-chain private int privateKeyCount = 0; // the source of randomness private SecureRandom random; static { try { PKCS8ShroudedKeyBag_OID = new ObjectIdentifier(keyBag); CertBag_OID = new ObjectIdentifier(certBag); PKCS9FriendlyName_OID = new ObjectIdentifier(pkcs9Name); PKCS9LocalKeyId_OID = new ObjectIdentifier(pkcs9KeyId); PKCS9CertType_OID = new ObjectIdentifier(pkcs9certType); pbeWithSHAAnd40BitRC2CBC_OID = new ObjectIdentifier(pbeWithSHAAnd40BitRC2CBC); pbeWithSHAAnd3KeyTripleDESCBC_OID = new ObjectIdentifier(pbeWithSHAAnd3KeyTripleDESCBC); } catch (IOException ioe) { // should not happen } } // Private keys and their supporting certificate chains private static class KeyEntry { Date date; // the creation date of this entry byte[] protectedPrivKey; Certificate chain[]; byte[] keyId; String alias; }; // A certificate with its PKCS #9 attributes private static class CertEntry { final X509Certificate cert; final byte[] keyId; final String alias; CertEntry(X509Certificate cert, byte[] keyId, String alias) { this.cert = cert; this.keyId = keyId; this.alias = alias; } } /** * Private keys and certificates are stored in a hashtable. * Hash entries are keyed by alias names. */ private Hashtable<String, KeyEntry> entries = new Hashtable<String, KeyEntry>(); private ArrayList<KeyEntry> keyList = new ArrayList<KeyEntry>(); private LinkedHashMap<X500Principal, X509Certificate> certsMap = new LinkedHashMap<X500Principal, X509Certificate>(); private ArrayList<CertEntry> certEntries = new ArrayList<CertEntry>(); /** * Returns the key associated with the given alias, using the given * password to recover it. * * @param alias the alias name * @param password the password for recovering the key * * @return the requested key, or null if the given alias does not exist * or does not identify a <i>key entry</i>. * * @exception NoSuchAlgorithmException if the algorithm for recovering the * key cannot be found * @exception UnrecoverableKeyException if the key cannot be recovered * (e.g., the given password is wrong). */ public Key engineGetKey(String alias, char[] password) throws NoSuchAlgorithmException, UnrecoverableKeyException { KeyEntry entry = entries.get(alias.toLowerCase()); Key key = null; if (entry == null) { return null; } // get the encoded private key byte[] encrBytes = entry.protectedPrivKey; byte[] encryptedKey; AlgorithmParameters algParams; ObjectIdentifier algOid; try { // get the encrypted private key EncryptedPrivateKeyInfo encrInfo = new EncryptedPrivateKeyInfo(encrBytes); encryptedKey = encrInfo.getEncryptedData(); // parse Algorithm parameters DerValue val = new DerValue(encrInfo.getAlgorithm().encode()); DerInputStream in = val.toDerInputStream(); algOid = in.getOID(); algParams = parseAlgParameters(in); } catch (IOException ioe) { UnrecoverableKeyException uke = new UnrecoverableKeyException("Private key not stored as " + "PKCS#8 EncryptedPrivateKeyInfo: " + ioe); uke.initCause(ioe); throw uke; } try { // Use JCE SecretKey skey = getPBEKey(password); Cipher cipher = Cipher.getInstance(algOid.toString()); cipher.init(Cipher.DECRYPT_MODE, skey, algParams); byte[] privateKeyInfo = cipher.doFinal(encryptedKey); PKCS8EncodedKeySpec kspec = new PKCS8EncodedKeySpec(privateKeyInfo); /* * Parse the key algorithm and then use a JCA key factory * to create the private key. */ DerValue val = new DerValue(privateKeyInfo); DerInputStream in = val.toDerInputStream(); int i = in.getInteger(); DerValue[] value = in.getSequence(2); AlgorithmId algId = new AlgorithmId(value[0].getOID()); String algName = algId.getName(); KeyFactory kfac = KeyFactory.getInstance(algName); key = kfac.generatePrivate(kspec); } catch (Exception e) { UnrecoverableKeyException uke = new UnrecoverableKeyException("Get Key failed: " + e.getMessage()); uke.initCause(e); throw uke; } return key; } /** * Returns the certificate chain associated with the given alias. * * @param alias the alias name * * @return the certificate chain (ordered with the user's certificate first * and the root certificate authority last), or null if the given alias * does not exist or does not contain a certificate chain (i.e., the given * alias identifies either a <i>trusted certificate entry</i> or a * <i>key entry</i> without a certificate chain). */ public Certificate[] engineGetCertificateChain(String alias) { KeyEntry entry = entries.get(alias.toLowerCase()); if (entry != null) { if (entry.chain == null) { return null; } else { return entry.chain.clone(); } } else { return null; } } /** * Returns the certificate associated with the given alias. * * <p>If the given alias name identifies a * <i>trusted certificate entry</i>, the certificate associated with that * entry is returned. If the given alias name identifies a * <i>key entry</i>, the first element of the certificate chain of that * entry is returned, or null if that entry does not have a certificate * chain. * * @param alias the alias name * * @return the certificate, or null if the given alias does not exist or * does not contain a certificate. */ public Certificate engineGetCertificate(String alias) { KeyEntry entry = entries.get(alias.toLowerCase()); if (entry != null) { if (entry.chain == null) { return null; } else { return entry.chain[0]; } } else { return null; } } /** * Returns the creation date of the entry identified by the given alias. * * @param alias the alias name * * @return the creation date of this entry, or null if the given alias does * not exist */ public Date engineGetCreationDate(String alias) { KeyEntry entry = entries.get(alias.toLowerCase()); if (entry != null) { return new Date(entry.date.getTime()); } else { return null; } } /** * Assigns the given key to the given alias, protecting it with the given * password. * * <p>If the given key is of type <code>java.security.PrivateKey</code>, * it must be accompanied by a certificate chain certifying the * corresponding public key. * * <p>If the given alias already exists, the keystore information * associated with it is overridden by the given key (and possibly * certificate chain). * * @param alias the alias name * @param key the key to be associated with the alias * @param password the password to protect the key * @param chain the certificate chain for the corresponding public * key (only required if the given key is of type * <code>java.security.PrivateKey</code>). * * @exception KeyStoreException if the given key cannot be protected, or * this operation fails for some other reason */ public synchronized void engineSetKeyEntry(String alias, Key key, char[] password, Certificate[] chain) throws KeyStoreException { try { KeyEntry entry = new KeyEntry(); entry.date = new Date(); if (key instanceof PrivateKey) { if ((key.getFormat().equals("PKCS#8")) || (key.getFormat().equals("PKCS8"))) { // Encrypt the private key entry.protectedPrivKey = encryptPrivateKey(key.getEncoded(), password); } else { throw new KeyStoreException("Private key is not encoded" + "as PKCS#8"); } } else { throw new KeyStoreException("Key is not a PrivateKey"); } // clone the chain if (chain != null) { // validate cert-chain if ((chain.length > 1) && (!validateChain(chain))) throw new KeyStoreException("Certificate chain is " + "not validate"); entry.chain = chain.clone(); } // set the keyId to current date entry.keyId = ("Time " + (entry.date).getTime()).getBytes("UTF8"); // set the alias entry.alias = alias.toLowerCase(); // add the entry entries.put(alias.toLowerCase(), entry); } catch (Exception nsae) { KeyStoreException ke = new KeyStoreException("Key protection " + " algorithm not found: " + nsae); ke.initCause(nsae); throw ke; } } /** * Assigns the given key (that has already been protected) to the given * alias. * * <p>If the protected key is of type * <code>java.security.PrivateKey</code>, it must be accompanied by a * certificate chain certifying the corresponding public key. If the * underlying keystore implementation is of type <code>jks</code>, * <code>key</code> must be encoded as an * <code>EncryptedPrivateKeyInfo</code> as defined in the PKCS #8 standard. * * <p>If the given alias already exists, the keystore information * associated with it is overridden by the given key (and possibly * certificate chain). * * @param alias the alias name * @param key the key (in protected format) to be associated with the alias * @param chain the certificate chain for the corresponding public * key (only useful if the protected key is of type * <code>java.security.PrivateKey</code>). * * @exception KeyStoreException if this operation fails. */ public synchronized void engineSetKeyEntry(String alias, byte[] key, Certificate[] chain) throws KeyStoreException { // key must be encoded as EncryptedPrivateKeyInfo // as defined in PKCS#8 try { new EncryptedPrivateKeyInfo(key); } catch (IOException ioe) { KeyStoreException ke = new KeyStoreException("Private key is not" + " stored as PKCS#8 EncryptedPrivateKeyInfo: " + ioe); ke.initCause(ioe); throw ke; } KeyEntry entry = new KeyEntry(); entry.date = new Date(); try { // set the keyId to current date entry.keyId = ("Time " + (entry.date).getTime()).getBytes("UTF8"); } catch (UnsupportedEncodingException ex) { // Won't happen } // set the alias entry.alias = alias.toLowerCase(); entry.protectedPrivKey = key.clone(); if (chain != null) { entry.chain = chain.clone(); } // add the entry entries.put(alias.toLowerCase(), entry); } /* * Generate random salt */ private byte[] getSalt() { // Generate a random salt. byte[] salt = new byte[SALT_LEN]; if (random == null) { random = new SecureRandom(); } random.nextBytes(salt); return salt; } Lines 1–500 of 1536. Load more
/* * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package sun.security.pkcs12; import java.io.*; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.Key; import java.security.KeyFactory; import java.security.PrivateKey; import java.security.KeyStoreSpi; import java.security.KeyStoreException; import java.security.UnrecoverableKeyException; import java.security.SecureRandom; import java.security.cert.Certificate; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.security.cert.CertificateException; import java.security.spec.PKCS8EncodedKeySpec; import java.util.*; import java.math.*; import java.security.AlgorithmParameters; import java.security.spec.AlgorithmParameterSpec; import javax.crypto.spec.PBEParameterSpec; import javax.crypto.spec.PBEKeySpec; import javax.crypto.spec.SecretKeySpec; import javax.crypto.SecretKeyFactory; import javax.crypto.SecretKey; import javax.crypto.Cipher; import javax.crypto.Mac; import javax.security.auth.x500.X500Principal; import sun.security.util.DerInputStream; import sun.security.util.DerOutputStream; import sun.security.util.DerValue; import sun.security.util.ObjectIdentifier; import sun.security.pkcs.ContentInfo; import sun.security.x509.AlgorithmId; import sun.security.pkcs.EncryptedPrivateKeyInfo; /** * This class provides the keystore implementation referred to as "PKCS12". * Implements the PKCS#12 PFX protected using the Password privacy mode. * The contents are protected using Password integrity mode. * * Currently we support following PBE algorithms: * - pbeWithSHAAnd3KeyTripleDESCBC to encrypt private keys * - pbeWithSHAAnd40BitRC2CBC to encrypt certificates * * Supported encryption of various implementations : * * Software and mode. Certificate encryption Private key encryption * --------------------------------------------------------------------- * MSIE4 (domestic 40 bit RC2. 40 bit RC2 * and xport versions) * PKCS#12 export. * * MSIE4, 5 (domestic 40 bit RC2, 40 bit RC2, * and export versions) 3 key triple DES 3 key triple DES * PKCS#12 import. * * MSIE5 40 bit RC2 3 key triple DES, * PKCS#12 export. with SHA1 (168 bits) * * Netscape Communicator 40 bit RC2 3 key triple DES, * (domestic and export with SHA1 (168 bits) * versions) PKCS#12 export * * Netscape Communicator 40 bit ciphers only All. * (export version) * PKCS#12 import. * * Netscape Communicator All. All. * (domestic or fortified * version) PKCS#12 import. * * OpenSSL PKCS#12 code. All. All. * --------------------------------------------------------------------- * * NOTE: Currently PKCS12 KeyStore does not support TrustedCertEntries. * PKCS#12 is mainly used to deliver private keys with their associated * certificate chain and aliases. In a PKCS12 keystore, entries are * identified by the alias, and a localKeyId is required to match the * private key with the certificate. * * @author Seema Malkani * @author Jeff Nisewanger * @author Jan Luehe * * @see KeyProtector * @see java.security.KeyStoreSpi * @see KeyTool * * */ public final class PKCS12KeyStore extends KeyStoreSpi { public static final int VERSION_3 = 3; private static final int keyBag[] = {1, 2, 840, 113549, 1, 12, 10, 1, 2}; private static final int certBag[] = {1, 2, 840, 113549, 1, 12, 10, 1, 3}; private static final int pkcs9Name[] = {1, 2, 840, 113549, 1, 9, 20}; private static final int pkcs9KeyId[] = {1, 2, 840, 113549, 1, 9, 21}; private static final int pkcs9certType[] = {1, 2, 840, 113549, 1, 9, 22, 1}; private static final int pbeWithSHAAnd40BitRC2CBC[] = {1, 2, 840, 113549, 1, 12, 1, 6}; private static final int pbeWithSHAAnd3KeyTripleDESCBC[] = {1, 2, 840, 113549, 1, 12, 1, 3}; private static ObjectIdentifier PKCS8ShroudedKeyBag_OID; private static ObjectIdentifier CertBag_OID; private static ObjectIdentifier PKCS9FriendlyName_OID; private static ObjectIdentifier PKCS9LocalKeyId_OID; private static ObjectIdentifier PKCS9CertType_OID; private static ObjectIdentifier pbeWithSHAAnd40BitRC2CBC_OID; private static ObjectIdentifier pbeWithSHAAnd3KeyTripleDESCBC_OID; private int counter = 0; private static final int iterationCount = 1024; private static final int SALT_LEN = 20; // private key count // Note: This is a workaround to allow null localKeyID attribute // in pkcs12 with one private key entry and associated cert-chain private int privateKeyCount = 0; // the source of randomness private SecureRandom random; static { try { PKCS8ShroudedKeyBag_OID = new ObjectIdentifier(keyBag); CertBag_OID = new ObjectIdentifier(certBag); PKCS9FriendlyName_OID = new ObjectIdentifier(pkcs9Name); PKCS9LocalKeyId_OID = new ObjectIdentifier(pkcs9KeyId); PKCS9CertType_OID = new ObjectIdentifier(pkcs9certType); pbeWithSHAAnd40BitRC2CBC_OID = new ObjectIdentifier(pbeWithSHAAnd40BitRC2CBC); pbeWithSHAAnd3KeyTripleDESCBC_OID = new ObjectIdentifier(pbeWithSHAAnd3KeyTripleDESCBC); } catch (IOException ioe) { // should not happen } } // Private keys and their supporting certificate chains private static class KeyEntry { Date date; // the creation date of this entry byte[] protectedPrivKey; Certificate chain[]; byte[] keyId; String alias; }; // A certificate with its PKCS #9 attributes private static class CertEntry { final X509Certificate cert; final byte[] keyId; final String alias; CertEntry(X509Certificate cert, byte[] keyId, String alias) { this.cert = cert; this.keyId = keyId; this.alias = alias; } } /** * Private keys and certificates are stored in a hashtable. * Hash entries are keyed by alias names. */ private Hashtable<String, KeyEntry> entries = new Hashtable<String, KeyEntry>(); private ArrayList<KeyEntry> keyList = new ArrayList<KeyEntry>(); private LinkedHashMap<X500Principal, X509Certificate> certsMap = new LinkedHashMap<X500Principal, X509Certificate>(); private ArrayList<CertEntry> certEntries = new ArrayList<CertEntry>(); /** * Returns the key associated with the given alias, using the given * password to recover it. * * @param alias the alias name * @param password the password for recovering the key * * @return the requested key, or null if the given alias does not exist * or does not identify a <i>key entry</i>. * * @exception NoSuchAlgorithmException if the algorithm for recovering the * key cannot be found * @exception UnrecoverableKeyException if the key cannot be recovered * (e.g., the given password is wrong). */ public Key engineGetKey(String alias, char[] password) throws NoSuchAlgorithmException, UnrecoverableKeyException { KeyEntry entry = entries.get(alias.toLowerCase()); Key key = null; if (entry == null) { return null; } // get the encoded private key byte[] encrBytes = entry.protectedPrivKey; byte[] encryptedKey; AlgorithmParameters algParams; ObjectIdentifier algOid; try { // get the encrypted private key EncryptedPrivateKeyInfo encrInfo = new EncryptedPrivateKeyInfo(encrBytes); encryptedKey = encrInfo.getEncryptedData(); // parse Algorithm parameters DerValue val = new DerValue(encrInfo.getAlgorithm().encode()); DerInputStream in = val.toDerInputStream(); algOid = in.getOID(); algParams = parseAlgParameters(in); } catch (IOException ioe) { UnrecoverableKeyException uke = new UnrecoverableKeyException("Private key not stored as " + "PKCS#8 EncryptedPrivateKeyInfo: " + ioe); uke.initCause(ioe); throw uke; } try { // Use JCE SecretKey skey = getPBEKey(password); Cipher cipher = Cipher.getInstance(algOid.toString()); cipher.init(Cipher.DECRYPT_MODE, skey, algParams); byte[] privateKeyInfo = cipher.doFinal(encryptedKey); PKCS8EncodedKeySpec kspec = new PKCS8EncodedKeySpec(privateKeyInfo); /* * Parse the key algorithm and then use a JCA key factory * to create the private key. */ DerValue val = new DerValue(privateKeyInfo); DerInputStream in = val.toDerInputStream(); int i = in.getInteger(); DerValue[] value = in.getSequence(2); AlgorithmId algId = new AlgorithmId(value[0].getOID()); String algName = algId.getName(); KeyFactory kfac = KeyFactory.getInstance(algName); key = kfac.generatePrivate(kspec); } catch (Exception e) { UnrecoverableKeyException uke = new UnrecoverableKeyException("Get Key failed: " + e.getMessage()); uke.initCause(e); throw uke; } return key; } /** * Returns the certificate chain associated with the given alias. * * @param alias the alias name * * @return the certificate chain (ordered with the user's certificate first * and the root certificate authority last), or null if the given alias * does not exist or does not contain a certificate chain (i.e., the given * alias identifies either a <i>trusted certificate entry</i> or a * <i>key entry</i> without a certificate chain). */ public Certificate[] engineGetCertificateChain(String alias) { KeyEntry entry = entries.get(alias.toLowerCase()); if (entry != null) { if (entry.chain == null) { return null; } else { return entry.chain.clone(); } } else { return null; } } /** * Returns the certificate associated with the given alias. * * <p>If the given alias name identifies a * <i>trusted certificate entry</i>, the certificate associated with that * entry is returned. If the given alias name identifies a * <i>key entry</i>, the first element of the certificate chain of that * entry is returned, or null if that entry does not have a certificate * chain. * * @param alias the alias name * * @return the certificate, or null if the given alias does not exist or * does not contain a certificate. */ public Certificate engineGetCertificate(String alias) { KeyEntry entry = entries.get(alias.toLowerCase()); if (entry != null) { if (entry.chain == null) { return null; } else { return entry.chain[0]; } } else { return null; } } /** * Returns the creation date of the entry identified by the given alias. * * @param alias the alias name * * @return the creation date of this entry, or null if the given alias does * not exist */ public Date engineGetCreationDate(String alias) { KeyEntry entry = entries.get(alias.toLowerCase()); if (entry != null) { return new Date(entry.date.getTime()); } else { return null; } } /** * Assigns the given key to the given alias, protecting it with the given * password. * * <p>If the given key is of type <code>java.security.PrivateKey</code>, * it must be accompanied by a certificate chain certifying the * corresponding public key. * * <p>If the given alias already exists, the keystore information * associated with it is overridden by the given key (and possibly * certificate chain). * * @param alias the alias name * @param key the key to be associated with the alias * @param password the password to protect the key * @param chain the certificate chain for the corresponding public * key (only required if the given key is of type * <code>java.security.PrivateKey</code>). * * @exception KeyStoreException if the given key cannot be protected, or * this operation fails for some other reason */ public synchronized void engineSetKeyEntry(String alias, Key key, char[] password, Certificate[] chain) throws KeyStoreException { try { KeyEntry entry = new KeyEntry(); entry.date = new Date(); if (key instanceof PrivateKey) { if ((key.getFormat().equals("PKCS#8")) || (key.getFormat().equals("PKCS8"))) { // Encrypt the private key entry.protectedPrivKey = encryptPrivateKey(key.getEncoded(), password); } else { throw new KeyStoreException("Private key is not encoded" + "as PKCS#8"); } } else { throw new KeyStoreException("Key is not a PrivateKey"); } // clone the chain if (chain != null) { // validate cert-chain if ((chain.length > 1) && (!validateChain(chain))) throw new KeyStoreException("Certificate chain is " + "not validate"); entry.chain = chain.clone(); } // set the keyId to current date entry.keyId = ("Time " + (entry.date).getTime()).getBytes("UTF8"); // set the alias entry.alias = alias.toLowerCase(); // add the entry entries.put(alias.toLowerCase(), entry); } catch (Exception nsae) { KeyStoreException ke = new KeyStoreException("Key protection " + " algorithm not found: " + nsae); ke.initCause(nsae); throw ke; } } /** * Assigns the given key (that has already been protected) to the given * alias. * * <p>If the protected key is of type * <code>java.security.PrivateKey</code>, it must be accompanied by a * certificate chain certifying the corresponding public key. If the * underlying keystore implementation is of type <code>jks</code>, * <code>key</code> must be encoded as an * <code>EncryptedPrivateKeyInfo</code> as defined in the PKCS #8 standard. * * <p>If the given alias already exists, the keystore information * associated with it is overridden by the given key (and possibly * certificate chain). * * @param alias the alias name * @param key the key (in protected format) to be associated with the alias * @param chain the certificate chain for the corresponding public * key (only useful if the protected key is of type * <code>java.security.PrivateKey</code>). * * @exception KeyStoreException if this operation fails. */ public synchronized void engineSetKeyEntry(String alias, byte[] key, Certificate[] chain) throws KeyStoreException { // key must be encoded as EncryptedPrivateKeyInfo // as defined in PKCS#8 try { new EncryptedPrivateKeyInfo(key); } catch (IOException ioe) { KeyStoreException ke = new KeyStoreException("Private key is not" + " stored as PKCS#8 EncryptedPrivateKeyInfo: " + ioe); ke.initCause(ioe); throw ke; } KeyEntry entry = new KeyEntry(); entry.date = new Date(); try { // set the keyId to current date entry.keyId = ("Time " + (entry.date).getTime()).getBytes("UTF8"); } catch (UnsupportedEncodingException ex) { // Won't happen } // set the alias entry.alias = alias.toLowerCase(); entry.protectedPrivKey = key.clone(); if (chain != null) { entry.chain = chain.clone(); } // add the entry entries.put(alias.toLowerCase(), entry); } /* * Generate random salt */ private byte[] getSalt() { // Generate a random salt. byte[] salt = new byte[SALT_LEN]; if (random == null) { random = new SecureRandom(); } random.nextBytes(salt); return salt; }