2549N/A * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. 0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 0N/A * This code is free software; you can redistribute it and/or modify it 0N/A * under the terms of the GNU General Public License version 2 only, as 2362N/A * published by the Free Software Foundation. Oracle designates this 0N/A * particular file as subject to the "Classpath" exception as provided 2362N/A * by Oracle in the LICENSE file that accompanied this code. 0N/A * This code is distributed in the hope that it will be useful, but WITHOUT 0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 0N/A * version 2 for more details (a copy is included in the LICENSE file that 0N/A * accompanied this code). 0N/A * You should have received a copy of the GNU General Public License version 0N/A * 2 along with this work; if not, write to the Free Software Foundation, 0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2362N/A * or visit www.oracle.com if you need additional information or have any 0N/A * This class provides the keystore implementation referred to as "PKCS12". 0N/A * Implements the PKCS#12 PFX protected using the Password privacy mode. 0N/A * The contents are protected using Password integrity mode. 0N/A * Currently we support following PBE algorithms: 0N/A * - pbeWithSHAAnd3KeyTripleDESCBC to encrypt private keys 0N/A * - pbeWithSHAAnd40BitRC2CBC to encrypt certificates 0N/A * Supported encryption of various implementations : 0N/A * Software and mode. Certificate encryption Private key encryption 0N/A * --------------------------------------------------------------------- 0N/A * MSIE4 (domestic 40 bit RC2. 40 bit RC2 0N/A * and xport versions) 0N/A * MSIE4, 5 (domestic 40 bit RC2, 40 bit RC2, 0N/A * and export versions) 3 key triple DES 3 key triple DES 0N/A * MSIE5 40 bit RC2 3 key triple DES, 0N/A * PKCS#12 export. with SHA1 (168 bits) 0N/A * Netscape Communicator 40 bit RC2 3 key triple DES, 0N/A * (domestic and export with SHA1 (168 bits) 0N/A * versions) PKCS#12 export 0N/A * Netscape Communicator 40 bit ciphers only All. 0N/A * Netscape Communicator All. All. 0N/A * (domestic or fortified 0N/A * version) PKCS#12 import. 0N/A * OpenSSL PKCS#12 code. All. All. 0N/A * --------------------------------------------------------------------- 0N/A * NOTE: Currently PKCS12 KeyStore does not support TrustedCertEntries. 0N/A * PKCS#12 is mainly used to deliver private keys with their associated 0N/A * certificate chain and aliases. In a PKCS12 keystore, entries are 0N/A * identified by the alias, and a localKeyId is required to match the 0N/A * private key with the certificate. 0N/A * @author Seema Malkani 0N/A * @author Jeff Nisewanger 0N/A * @see java.security.KeyStoreSpi 0N/A private static final int keyBag[] = {
1,
2,
840,
113549,
1,
12,
10,
1,
2};
0N/A private static final int certBag[] = {
1,
2,
840,
113549,
1,
12,
10,
1,
3};
0N/A private static final int pkcs9Name[] = {
1,
2,
840,
113549,
1,
9,
20};
0N/A private static final int pkcs9KeyId[] = {
1,
2,
840,
113549,
1,
9,
21};
0N/A {
1,
2,
840,
113549,
1,
12,
1,
6};
0N/A {
1,
2,
840,
113549,
1,
12,
1,
3};
0N/A // private key count 0N/A // Note: This is a workaround to allow null localKeyID attribute 0N/A // in pkcs12 with one private key entry and associated cert-chain 0N/A // the source of randomness 0N/A // should not happen 0N/A // Private keys and their supporting certificate chains 2549N/A // A certificate with its PKCS #9 attributes 0N/A * Private keys and certificates are stored in a hashtable. 0N/A * Hash entries are keyed by alias names. 0N/A * Returns the key associated with the given alias, using the given 0N/A * password to recover it. 0N/A * @param alias the alias name 0N/A * @param password the password for recovering the key 0N/A * @return the requested key, or null if the given alias does not exist 0N/A * or does not identify a <i>key entry</i>. 0N/A * @exception NoSuchAlgorithmException if the algorithm for recovering the 0N/A * key cannot be found 0N/A * @exception UnrecoverableKeyException if the key cannot be recovered 0N/A * (e.g., the given password is wrong). 0N/A // get the encoded private key 0N/A // get the encrypted private key 0N/A // parse Algorithm parameters 0N/A +
"PKCS#8 EncryptedPrivateKeyInfo: " +
ioe);
4784N/A // Retry using an empty password 4784N/A // without a NULL terminator. 0N/A * Parse the key algorithm and then use a JCA key factory 0N/A * to create the private key. 0N/A * Returns the certificate chain associated with the given alias. 0N/A * @param alias the alias name 0N/A * @return the certificate chain (ordered with the user's certificate first 0N/A * and the root certificate authority last), or null if the given alias 0N/A * does not exist or does not contain a certificate chain (i.e., the given 0N/A * alias identifies either a <i>trusted certificate entry</i> or a 0N/A * <i>key entry</i> without a certificate chain). 0N/A * Returns the certificate associated with the given alias. 0N/A * <p>If the given alias name identifies a 0N/A * <i>trusted certificate entry</i>, the certificate associated with that 0N/A * entry is returned. If the given alias name identifies a 0N/A * <i>key entry</i>, the first element of the certificate chain of that 0N/A * entry is returned, or null if that entry does not have a certificate 0N/A * @param alias the alias name 0N/A * @return the certificate, or null if the given alias does not exist or 0N/A * does not contain a certificate. 0N/A * Returns the creation date of the entry identified by the given alias. 0N/A * @param alias the alias name 0N/A * @return the creation date of this entry, or null if the given alias does 0N/A * Assigns the given key to the given alias, protecting it with the given 0N/A * <p>If the given key is of type <code>java.security.PrivateKey</code>, 0N/A * it must be accompanied by a certificate chain certifying the 0N/A * corresponding public key. 0N/A * <p>If the given alias already exists, the keystore information 0N/A * associated with it is overridden by the given key (and possibly 0N/A * certificate chain). 0N/A * @param alias the alias name 0N/A * @param key the key to be associated with the alias 0N/A * @param password the password to protect the key 0N/A * @param chain the certificate chain for the corresponding public 0N/A * key (only required if the given key is of type 0N/A * <code>java.security.PrivateKey</code>). 0N/A * @exception KeyStoreException if the given key cannot be protected, or 0N/A * this operation fails for some other reason 0N/A // Encrypt the private key 0N/A // validate cert-chain 0N/A // set the keyId to current date 0N/A * Assigns the given key (that has already been protected) to the given 0N/A * <p>If the protected key is of type 0N/A * <code>java.security.PrivateKey</code>, it must be accompanied by a 0N/A * certificate chain certifying the corresponding public key. If the 0N/A * underlying keystore implementation is of type <code>jks</code>, 0N/A * <code>key</code> must be encoded as an 0N/A * <code>EncryptedPrivateKeyInfo</code> as defined in the PKCS #8 standard. 0N/A * <p>If the given alias already exists, the keystore information 0N/A * associated with it is overridden by the given key (and possibly 0N/A * certificate chain). 0N/A * @param alias the alias name 0N/A * @param key the key (in protected format) to be associated with the alias 0N/A * @param chain the certificate chain for the corresponding public 0N/A * key (only useful if the protected key is of type 0N/A * <code>java.security.PrivateKey</code>). 0N/A * @exception KeyStoreException if this operation fails. 0N/A // key must be encoded as EncryptedPrivateKeyInfo 0N/A // as defined in PKCS#8 0N/A +
" stored as PKCS#8 EncryptedPrivateKeyInfo: " +
ioe);
2549N/A // set the keyId to current date 0N/A * Generate random salt 0N/A // Generate a random salt. 0N/A * Generate PBE Algorithm Parameters 0N/A // create PBE parameters from salt and iteration count 0N/A * parse Algorithm Parameters 0N/A * Encrypt private key using Password-based encryption (PBE) 0N/A * as defined in PKCS#5. 0N/A * NOTE: Currently pbeWithSHAAnd3-KeyTripleDES-CBC algorithmID is 0N/A * used to derive the key and IV. 0N/A * @return encrypted private key encoded as EncryptedPrivateKeyInfo 0N/A // create AlgorithmParameters 0N/A // wrap encrypted private key in EncryptedPrivateKeyInfo 0N/A // as defined in PKCS#8 0N/A * Assigns the given certificate to the given alias. 0N/A * <p>If the given alias already exists in this keystore and identifies a 0N/A * <i>trusted certificate entry</i>, the certificate associated with it is 0N/A * overridden by the given certificate. 0N/A * @param alias the alias name 0N/A * @param cert the certificate 0N/A * @exception KeyStoreException if the given alias already exists and does 0N/A * identify a <i>key entry</i>, or on an attempt to create a 0N/A * <i>trusted cert entry</i> which is currently not supported. 0N/A * Deletes the entry identified by the given alias from this keystore. 0N/A * @param alias the alias name 0N/A * @exception KeyStoreException if the entry cannot be removed. 0N/A * Lists all the alias names of this keystore. 0N/A * @return enumeration of the alias names 0N/A * Checks if the given alias exists in this keystore. 0N/A * @param alias the alias name 0N/A * @return true if the alias exists, false otherwise 0N/A * Retrieves the number of entries in this keystore. 0N/A * @return the number of entries in this keystore 0N/A * Returns true if the entry identified by the given alias is a 0N/A * <i>key entry</i>, and false otherwise. 0N/A * @return true if the entry identified by the given alias is a 0N/A * <i>key entry</i>, false otherwise. 0N/A * Returns true if the entry identified by the given alias is a 0N/A * <i>trusted certificate entry</i>, and false otherwise. 0N/A * @return true if the entry identified by the given alias is a 0N/A * <i>trusted certificate entry</i>, false otherwise. 0N/A // TrustedCertEntry is not supported 0N/A * Returns the (alias) name of the first keystore entry whose certificate 0N/A * matches the given certificate. 0N/A * <p>This method attempts to match the given certificate with each 0N/A * keystore entry. If the entry being considered 0N/A * is a <i>trusted certificate entry</i>, the given certificate is 0N/A * compared to that entry's certificate. If the entry being considered is 0N/A * a <i>key entry</i>, the given certificate is compared to the first 0N/A * element of that entry's certificate chain (if a chain exists). 0N/A * @param cert the certificate to match with. 0N/A * @return the (alias) name of the first entry with matching certificate, 0N/A * or null if no such entry exists in this keystore. 0N/A * Stores this keystore to the given output stream, and protects its 0N/A * integrity with the given password. 0N/A * @param stream the output stream to which this keystore is written. 0N/A * @param password the password to generate the keystore integrity check 0N/A * @exception IOException if there was an I/O problem with data 0N/A * @exception NoSuchAlgorithmException if the appropriate data integrity 0N/A * algorithm could not be found 0N/A * @exception CertificateException if any of the certificates included in 0N/A * the keystore data could not be stored 0N/A // password is mandatory when storing 0N/A // PFX version (always write the latest version) 0N/A // -- Create AuthSafe 0N/A // -- Create ContentInfos 0N/A // -- create safeContent Data ContentInfo 0N/A // -- create EncryptedContentInfo 0N/A // wrap as SequenceOf ContentInfos 0N/A // Create Encapsulated ContentInfo 0N/A // write PFX to output stream 0N/A * Calculate MAC using HMAC algorithm (required for password integrity) 0N/A * Hash-based MAC algorithm combines secret key with message digest to 0N/A * create a message authentication code (MAC) 0N/A // Generate a random salt. 0N/A // generate MAC (MAC key is generated within JCE) 0N/A // encode as MacData 0N/A * Validate Certificate Chain 0N/A * Create PKCS#12 Attributes, friendlyName and localKeyId. 0N/A * Although attributes are optional, they could be required. 0N/A * For e.g. localKeyId attribute is required to match the 0N/A * private key with the associated end-entity certificate. 0N/A * PKCS8ShroudedKeyBags include unique localKeyID and friendlyName. 0N/A * CertBags may or may not include attributes depending on the type 0N/A * of Certificate. In end-entity certificates, localKeyID should be 0N/A * unique, and the corresponding private key should have the same 0N/A * localKeyID. For trusted CA certs in the cert-chain, localKeyID 0N/A * attribute is not required, hence most vendors don't include it. 0N/A * Here is a list of pkcs12 attribute values in CertBags. 0N/A * -------------------------------------------------------------- 0N/A * NULL in CA certs) true true true true 0N/A * friendlyName unique same/ same/ unique 0N/A * Note: OpenSSL adds friendlyName for end-entity cert only, and 0N/A * removes the localKeyID and friendlyName for CA certs. 0N/A * If the CertBag did not have a friendlyName, most vendors will 0N/A * add it, and assign it to the DN of the cert. 0N/A // return null if both attributes are null 0N/A // SafeBag Attributes 0N/A // Encode the friendlyname oid. 0N/A // Encode the localkeyId oid. 0N/A * Create EncryptedData content type, that contains EncryptedContentInfo. 0N/A * Includes certificates in individual SafeBags of type CertBag. 0N/A * Each CertBag may include pkcs12 attributes 0N/A * (see comments in getBagAttributes) 0N/A // certificate chain 0N/A // create SafeBag of Type CertBag 0N/A // write encoded certs in a context-specific tag 0N/A // wrap CertBag in a Sequence 0N/A // Wrap the CertBag encoding in a context-specific tag. 0N/A // write SafeBag Value 0N/A // write SafeBag Attributes 0N/A // All Certs should have a unique friendlyName. 0N/A // This change is made to meet NSS requirements. 0N/A // Only End-Entity Cert should have a localKeyId. 0N/A // Trusted root CA certs and Intermediate CA certs do not 0N/A // need to have a localKeyId, and hence localKeyId is null 0N/A // NSS pkcs12 library requires trusted CA certs in the 0N/A // certificate chain to have unique or null localKeyID. 0N/A // wrap as SequenceOf SafeBag 0N/A // encrypt the content (EncryptedContentInfo) 0N/A // -- SEQUENCE of EncryptedData 0N/A * Create SafeContent Data content type. 0N/A * Includes encrypted private key in a SafeBag of type PKCS8ShroudedKeyBag. 0N/A * Each PKCS8ShroudedKeyBag includes pkcs12 attributes 0N/A * (see comments in getBagAttributes) 0N/A // Create SafeBag of type pkcs8ShroudedKeyBag 0N/A // get the encrypted private key 0N/A // Wrap the EncryptedPrivateKeyInfo in a context-specific tag. 0N/A // write SafeBag Attributes 0N/A * Encrypt the contents using Password-based (PBE) encryption 0N/A * as defined in PKCS #5. 0N/A * NOTE: Currently pbeWithSHAAnd40BiteRC2-CBC algorithmID is used 0N/A * to derive the key and IV. 0N/A * @return encrypted contents encoded as EncryptedContentInfo 0N/A // create AlgorithmParameters 0N/A " safe contents entry: " + e);
0N/A // create EncryptedContentInfo 0N/A // Wrap encrypted data in a context-specific tag. 0N/A // wrap EncryptedContentInfo in a Sequence 0N/A * Loads the keystore from the given input stream. 0N/A * <p>If a password is given, it is used to check the integrity of the 0N/A * keystore data. Otherwise, the integrity of the keystore is not checked. 0N/A * @param stream the input stream from which the keystore is loaded 0N/A * @param password the (optional) password used to check the integrity of 0N/A * @exception IOException if there is an I/O or format problem with the 0N/A * @exception NoSuchAlgorithmException if the algorithm used to check 0N/A * the integrity of the keystore cannot be found 0N/A * @exception CertificateException if any of the certificates in the 0N/A * keystore could not be loaded 0N/A // reset the counter 0N/A * Read the authSafe. 0N/A }
else /* signed data */ {
0N/A // reset the count at the start 0N/A * Spin over the ContentInfos. 0N/A // parse Algorithm parameters 4784N/A // Retry using an empty password 4784N/A // without a NULL terminator. 4784N/A "failed to decrypt safe contents entry: " + e, e);
0N/A // The MacData is optional. 0N/A // generate MAC (MAC key is created within JCE) 0N/A " integrity checking");
0N/A * Match up private keys with certificate chains. 0N/A /* Update existing KeyEntry in entries table */ 2549N/A * Locates a matched CertEntry from certEntries, and returns its cert. 2549N/A * @param entry the KeyEntry to match 2549N/A * @return a certificate, null if not found 2549N/A // keyId match first, for compatibility 0N/A * Spin over the SafeBags. 0N/A // log error message for "unsupported PKCS12 bag type" 0N/A // entry does not have attributes 0N/A // Note: CA certs can have no attributes 0N/A // OpenSSL generates pkcs12 with no attr for CA certs. 0N/A // log error message for "unknown attr" 0N/A * As per PKCS12 v1.0 friendlyname (alias) and localKeyId (keyId) 0N/A * are optional PKCS12 bagAttributes. But entries in the keyStore 0N/A * are identified by their alias. Hence we need to have an 0N/A * Unfriendlyname in the alias, if alias is null. The keyId 0N/A * attribute is required to match the private key with the 0N/A * certificate. If we get a bagItem of type KeyEntry with a 0N/A * null keyId, we should skip it entirely. 0N/A // Insert a localKeyID for the privateKey 0N/A // Note: This is a workaround to allow null localKeyID 0N/A // attribute in pkcs12 with one private key entry and 0N/A // associated cert-chain 0N/A // restore date if it exists 0N/A // Insert a localKeyID for the corresponding cert 0N/A // Note: This is a workaround to allow null localKeyID 0N/A // attribute in pkcs12 with one private key entry and 0N/A // associated cert-chain 0N/A // insert localKeyID only for EE cert or self-signed cert