/*
 * Copyright (c) 1998, 2014, 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 com.sun.crypto.provider;

import java.io.*;
import java.util.*;
import java.security.DigestInputStream;
import java.security.DigestOutputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.Key;
import java.security.PrivateKey;
import java.security.KeyStoreSpi;
import java.security.KeyStoreException;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.CertificateException;
import javax.crypto.SealedObject;

/**
 * This class provides the keystore implementation referred to as "jceks".
 * This implementation strongly protects the keystore private keys using
 * triple-DES, where the triple-DES encryption/decryption key is derived from
 * the user's password.
 * The encrypted private keys are stored in the keystore in a standard format,
 * namely the <code>EncryptedPrivateKeyInfo</code> format defined in PKCS #8.
 *
 * @author Jan Luehe
 *
 *
 * @see java.security.KeyStoreSpi
 */

public final class JceKeyStore extends KeyStoreSpi {

    private static final int JCEKS_MAGIC = 0xcececece;
    private static final int JKS_MAGIC = 0xfeedfeed;
    private static final int VERSION_1 = 0x01;
    private static final int VERSION_2 = 0x02;

    // Private key and supporting certificate chain
    private static final class PrivateKeyEntry {
        Date date; // the creation date of this entry
        byte[] protectedKey;
        Certificate chain[];
    };

    // Secret key
    private static final class SecretKeyEntry {
        Date date; // the creation date of this entry
        SealedObject sealedKey;
    }

    // Trusted certificate
    private static final class TrustedCertEntry {
        Date date; // the creation date of this entry
        Certificate cert;
    };

    /**
     * Private keys and certificates are stored in a hashtable.
     * Hash entries are keyed by alias names.
     */
    private Hashtable<String, Object> entries = new Hashtable<String, Object>();

    /**
     * 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
    {
        Key key = null;

        Object entry = entries.get(alias.toLowerCase(Locale.ENGLISH));

        if (!((entry instanceof PrivateKeyEntry) ||
              (entry instanceof SecretKeyEntry))) {
            return null;
        }

        KeyProtector keyProtector = new KeyProtector(password);

        if (entry instanceof PrivateKeyEntry) {
            byte[] encrBytes = ((PrivateKeyEntry)entry).protectedKey;
            EncryptedPrivateKeyInfo encrInfo;
            try {
                encrInfo = new EncryptedPrivateKeyInfo(encrBytes);
            } catch (IOException ioe) {
                throw new UnrecoverableKeyException("Private key not stored "
                                                    + "as PKCS #8 " +
                                                    "EncryptedPrivateKeyInfo");
            }
            key = keyProtector.recover(encrInfo);
        } else {
            key =
                keyProtector.unseal(((SecretKeyEntry)entry).sealedKey);
        }

        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)
    {
        Certificate[] chain = null;

        Object entry = entries.get(alias.toLowerCase(Locale.ENGLISH));

        if ((entry instanceof PrivateKeyEntry)
            && (((PrivateKeyEntry)entry).chain != null)) {
            chain = ((PrivateKeyEntry)entry).chain.clone();
        }

        return chain;
    }

    /**
     * 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) {
        Certificate cert = null;

        Object entry = entries.get(alias.toLowerCase(Locale.ENGLISH));

        if (entry != null) {
            if (entry instanceof TrustedCertEntry) {
                cert = ((TrustedCertEntry)entry).cert;
            } else if ((entry instanceof PrivateKeyEntry) &&
                       (((PrivateKeyEntry)entry).chain != null)) {
                cert = ((PrivateKeyEntry)entry).chain[0];
            }
        }

        return cert;
    }

    /**
     * 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) {
        Date date = null;

        Object entry = entries.get(alias.toLowerCase(Locale.ENGLISH));

        if (entry != null) {
            // We have to create a new instance of java.util.Date because
            // dates are not immutable
            if (entry instanceof TrustedCertEntry) {
                date = new Date(((TrustedCertEntry)entry).date.getTime());
            } else if (entry instanceof PrivateKeyEntry) {
                date = new Date(((PrivateKeyEntry)entry).date.getTime());
            } else {
                date = new Date(((SecretKeyEntry)entry).date.getTime());
            }
        }

        return date;
    }

    /**
     * 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 void engineSetKeyEntry(String alias, Key key, char[] password,
                                  Certificate[] chain)
        throws KeyStoreException
    {
        synchronized(entries) {
            try {
                KeyProtector keyProtector = new KeyProtector(password);

                if (key instanceof PrivateKey) {
                    PrivateKeyEntry entry = new PrivateKeyEntry();
                    entry.date = new Date();

                    // protect the private key
                    entry.protectedKey = keyProtector.protect((PrivateKey)key);

                    // clone the chain
                    if ((chain != null) &&
                        (chain.length !=0)) {
                        entry.chain = chain.clone();
                    } else {
                        entry.chain = null;
                    }

                    // store the entry
                    entries.put(alias.toLowerCase(Locale.ENGLISH), entry);

                } else {
                    SecretKeyEntry entry = new SecretKeyEntry();
                    entry.date = new Date();

                    // seal and store the key
                    entry.sealedKey = keyProtector.seal(key);
                    entries.put(alias.toLowerCase(Locale.ENGLISH), entry);
                }

            } catch (Exception e) {
                throw new KeyStoreException(e.getMessage());
            }
        }
    }

    /**
     * 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.
     *
     * <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 void engineSetKeyEntry(String alias, byte[] key,
                                  Certificate[] chain)
        throws KeyStoreException
    {
        synchronized(entries) {
            // We assume it's a private key, because there is no standard
            // (ASN.1) encoding format for wrapped secret keys
            PrivateKeyEntry entry = new PrivateKeyEntry();
            entry.date = new Date();

            entry.protectedKey = key.clone();
            if ((chain != null) &&
                (chain.length != 0)) {
                entry.chain = chain.clone();
            } else {
                entry.chain = null;
            }

            entries.put(alias.toLowerCase(Locale.ENGLISH), entry);
        }
    }

    /**
     * Assigns the given certificate to the given alias.
     *
     * <p>If the given alias already exists in this keystore and identifies a
     * <i>trusted certificate entry</i>, the certificate associated with it is
     * overridden by the given certificate.
     *
     * @param alias the alias name
     * @param cert the certificate
     *
     * @exception KeyStoreException if the given alias already exists and does
     * not identify a <i>trusted certificate entry</i>, or this operation
     * fails for some other reason.
     */
    public void engineSetCertificateEntry(String alias, Certificate cert)
        throws KeyStoreException
    {
        synchronized(entries) {

            Object entry = entries.get(alias.toLowerCase(Locale.ENGLISH));
            if (entry != null) {
                if (entry instanceof PrivateKeyEntry) {
                    throw new KeyStoreException("Cannot overwrite own "
                                                + "certificate");
                } else if (entry instanceof SecretKeyEntry) {
                    throw new KeyStoreException("Cannot overwrite secret key");
                }
            }

            TrustedCertEntry trustedCertEntry = new TrustedCertEntry();
            trustedCertEntry.cert = cert;
            trustedCertEntry.date = new Date();
            entries.put(alias.toLowerCase(Locale.ENGLISH), trustedCertEntry);
        }
    }

    /**
     * Deletes the entry identified by the given alias from this keystore.
     *
     * @param alias the alias name
     *
     * @exception KeyStoreException if the entry cannot be removed.
     */
    public void engineDeleteEntry(String alias)
        throws KeyStoreException
    {
        synchronized(entries) {
            entries.remove(alias.toLowerCase(Locale.ENGLISH));
        }
    }

    /**
     * Lists all the alias names of this keystore.
     *
     * @return enumeration of the alias names
     */
    public Enumeration<String> engineAliases() {
        return entries.keys();
    }

    /**
     * Checks if the given alias exists in this keystore.
     *
     * @param alias the alias name
     *
     * @return true if the alias exists, false otherwise
     */
    public boolean engineContainsAlias(String alias) {
        return entries.containsKey(alias.toLowerCase(Locale.ENGLISH));
    }

    /**
     * Retrieves the number of entries in this keystore.
     *
     * @return the number of entries in this keystore
     */
    public int engineSize() {
        return entries.size();
    }

    /**
     * Returns true if the entry identified by the given alias is a
     * <i>key entry</i>, and false otherwise.
     *
     * @return true if the entry identified by the given alias is a
     * <i>key entry</i>, false otherwise.
     */
    public boolean engineIsKeyEntry(String alias) {
        boolean isKey = false;

        Object entry = entries.get(alias.toLowerCase(Locale.ENGLISH));
        if ((entry instanceof PrivateKeyEntry)
            || (entry instanceof SecretKeyEntry)) {
            isKey = true;
        }

        return isKey;
    }

    /**
     * Returns true if the entry identified by the given alias is a
     * <i>trusted certificate entry</i>, and false otherwise.
     *
     * @return true if the entry identified by the given alias is a
     * <i>trusted certificate entry</i>, false otherwise.
     */
    public boolean engineIsCertificateEntry(String alias) {
        boolean isCert = false;
        Object entry = entries.get(alias.toLowerCase(Locale.ENGLISH));
        if (entry instanceof TrustedCertEntry) {
            isCert = true;
        }
        return isCert;
    }

    /**
     * Returns the (alias) name of the first keystore entry whose certificate
     * matches the given certificate.
     *
     * <p>This method attempts to match the given certificate with each
     * keystore entry. If the entry being considered
     * is a <i>trusted certificate entry</i>, the given certificate is
     * compared to that entry's certificate. If the entry being considered is
     * a <i>key entry</i>, the given certificate is compared to the first
     * element of that entry's certificate chain (if a chain exists).
     *
     * @param cert the certificate to match with.
     *
     * @return the (alias) name of the first entry with matching certificate,
     * or null if no such entry exists in this keystore.
     */
    public String engineGetCertificateAlias(Certificate cert) {
        Certificate certElem;

        Enumeration<String> e = entries.keys();
        while (e.hasMoreElements()) {
            String alias = e.nextElement();
            Object entry = entries.get(alias);
            if (entry instanceof TrustedCertEntry) {
                certElem = ((TrustedCertEntry)entry).cert;
            } else if ((entry instanceof PrivateKeyEntry) &&
                       (((PrivateKeyEntry)entry).chain != null)) {
                certElem = ((PrivateKeyEntry)entry).chain[0];
            } else {
                continue;
            }
            if (certElem.equals(cert)) {
                return alias;
            }
        }
        return null;
    }

    /**
     * Stores this keystore to the given output stream, and protects its
     * integrity with the given password.
     *
     * @param stream the output stream to which this keystore is written.
     * @param password the password to generate the keystore integrity check
     *
     * @exception IOException if there was an I/O problem with data
     * @exception NoSuchAlgorithmException if the appropriate data integrity
     * algorithm could not be found
     * @exception CertificateException if any of the certificates included in
     * the keystore data could not be stored
     */
    public void engineStore(OutputStream stream, char[] password)
        throws IOException, NoSuchAlgorithmException, CertificateException
    {
        synchronized(entries) {
            /*
             * KEYSTORE FORMAT:
             *
             * Magic number (big-endian integer),
             * Version of this file format (big-endian integer),
             *
             * Count (big-endian integer),
             * followed by "count" instances of either:
             *
             *     {
             *      tag=1 (big-endian integer)
             *      alias (UTF string)
             *      timestamp
             *      encrypted private-key info according to PKCS #8
             *          (integer length followed by encoding)
             *      cert chain (integer count followed by certs;
             *          for each cert: type UTF string, followed by integer
             *              length, followed by encoding)
             *     }
             *
             * or:
             *
             *     {
             *      tag=2 (big-endian integer)
             *      alias (UTF string)
             *      timestamp
             *      cert (type UTF string, followed by integer length,
             *          followed by encoding)
             *     }
             *
             * or:
             *
             *     {
             *      tag=3 (big-endian integer)
             *      alias (UTF string)
             *      timestamp
             *      sealed secret key (in serialized form)
             *     }
             *
             * ended by a keyed SHA1 hash (bytes only) of
             *     { password + whitener + preceding body }
             */

            // password is mandatory when storing
            if (password == null) {
                throw new IllegalArgumentException("password can't be null");
            }

            byte[] encoded; // the certificate encoding

            MessageDigest md = getPreKeyedHash(password);
            DataOutputStream dos
                = new DataOutputStream(new DigestOutputStream(stream, md));
            // NOTE: don't pass dos to oos at this point or it'll corrupt
            // the keystore!!!
            ObjectOutputStream oos = null;
            try {
                dos.writeInt(JCEKS_MAGIC);
                dos.writeInt(VERSION_2); // always write the latest version

                dos.writeInt(entries.size());

                Enumeration<String> e = entries.keys();
                while (e.hasMoreElements()) {

                    String alias = e.nextElement();
                    Object entry = entries.get(alias);

                    if (entry instanceof PrivateKeyEntry) {

                        PrivateKeyEntry pentry = (PrivateKeyEntry)entry;

                        // write PrivateKeyEntry tag
                        dos.writeInt(1);

                        // write the alias
                        dos.writeUTF(alias);

                        // write the (entry creation) date
                        dos.writeLong(pentry.date.getTime());

                        // write the protected private key
                        dos.writeInt(pentry.protectedKey.length);
                        dos.write(pentry.protectedKey);

                        // write the certificate chain
                        int chainLen;
                        if (pentry.chain == null) {
                            chainLen = 0;
                        } else {
                            chainLen = pentry.chain.length;
                        }
                        dos.writeInt(chainLen);
                        for (int i = 0; i < chainLen; i++) {
                            encoded = pentry.chain[i].getEncoded();
                            dos.writeUTF(pentry.chain[i].getType());
                            dos.writeInt(encoded.length);
                            dos.write(encoded);
                        }

                    } else if (entry instanceof TrustedCertEntry) {

                        // write TrustedCertEntry tag
                        dos.writeInt(2);

                        // write the alias
                        dos.writeUTF(alias);

                        // write the (entry creation) date
                        dos.writeLong(((TrustedCertEntry)entry).date.getTime());

                        // write the trusted certificate
                        encoded = ((TrustedCertEntry)entry).cert.getEncoded();
                        dos.writeUTF(((TrustedCertEntry)entry).cert.getType());
                        dos.writeInt(encoded.length);
                        dos.write(encoded);

                    } else {

                        // write SecretKeyEntry tag
                        dos.writeInt(3);

                        // write the alias
                        dos.writeUTF(alias);

                        // write the (entry creation) date
                        dos.writeLong(((SecretKeyEntry)entry).date.getTime());

                        // write the sealed key
                        oos = new ObjectOutputStream(dos);
                        oos.writeObject(((SecretKeyEntry)entry).sealedKey);
                        // NOTE: don't close oos here since we are still
                        // using dos!!!
                    }
                }

                /*
                 * Write the keyed hash which is used to detect tampering with
                 * the keystore (such as deleting or modifying key or
                 * certificate entries).
                 */
                byte digest[] = md.digest();

                dos.write(digest);
                dos.flush();
            } finally {
                if (oos != null) {
                    oos.close();
                } else {
                    dos.close();
                }
            }
        }
    }

    /**
     * Loads the keystore from the given input stream.
     *
     * <p>If a password is given, it is used to check the integrity of the
     * keystore data. Otherwise, the integrity of the keystore is not checked.
     *
     * @param stream the input stream from which the keystore is loaded
     * @param password the (optional) password used to check the integrity of
     * the keystore.
     *
     * @exception IOException if there is an I/O or format problem with the
     * keystore data
     * @exception NoSuchAlgorithmException if the algorithm used to check
     * the integrity of the keystore cannot be found
     * @exception CertificateException if any of the certificates in the
     * keystore could not be loaded
     */
    public void engineLoad(InputStream stream, char[] password)
        throws IOException, NoSuchAlgorithmException, CertificateException
    {
        synchronized(entries) {
            DataInputStream dis;
            MessageDigest md = null;
            CertificateFactory cf = null;
            Hashtable<String, CertificateFactory> cfs = null;
            ByteArrayInputStream bais = null;
            byte[] encoded = null;

            if (stream == null)
                return;

            if (password != null) {
                md = getPreKeyedHash(password);
                dis = new DataInputStream(new DigestInputStream(stream, md));
            } else {
                dis = new DataInputStream(stream);
            }
            // NOTE: don't pass dis to ois at this point or it'll fail to load
            // the keystore!!!
            ObjectInputStream ois = null;

            try {
                // Body format: see store method

                int xMagic = dis.readInt();
                int xVersion = dis.readInt();

                // Accept the following keystore implementations:
                // - JCEKS (this implementation), versions 1 and 2
                // - JKS (Sun's keystore implementation in JDK 1.2),
                //   versions 1 and 2
                if (((xMagic != JCEKS_MAGIC) && (xMagic != JKS_MAGIC)) ||
                    ((xVersion != VERSION_1) && (xVersion != VERSION_2))) {
                    throw new IOException("Invalid keystore format");
                }

                if (xVersion == VERSION_1) {
                    cf = CertificateFactory.getInstance("X509");
                } else {
                    // version 2
                    cfs = new Hashtable<String, CertificateFactory>(3);
                }

                entries.clear();
                int count = dis.readInt();

                for (int i = 0; i < count; i++) {
                    int tag;
                    String alias;

                    tag = dis.readInt();

                    if (tag == 1) { // private-key entry

                        PrivateKeyEntry entry = new PrivateKeyEntry();

                        // read the alias
                        alias = dis.readUTF();

                        // read the (entry creation) date
                        entry.date = new Date(dis.readLong());

                        // read the private key
                        try {
                            entry.protectedKey = new byte[dis.readInt()];
                        } catch (OutOfMemoryError e) {
                            throw new IOException("Keysize too big");
                        }
                        dis.readFully(entry.protectedKey);

                        // read the certificate chain
                        int numOfCerts = dis.readInt();
                        try {
                            if (numOfCerts > 0) {
                                entry.chain = new Certificate[numOfCerts];
                            }
                        } catch (OutOfMemoryError e) {
                            throw new IOException("Too many certificates in "
                                                  + "chain");
                        }
                        for (int j = 0; j < numOfCerts; j++) {
                            if (xVersion == 2) {
                                // read the certificate type, and instantiate a
                                // certificate factory of that type (reuse
                                // existing factory if possible)
                                String certType = dis.readUTF();
                                if (cfs.containsKey(certType)) {
                                // reuse certificate factory
                                    cf = cfs.get(certType);
                                } else {
                                // create new certificate factory
                                    cf = CertificateFactory.getInstance(
                                        certType);
                                // store the certificate factory so we can
                                // reuse it later
                                    cfs.put(certType, cf);
                                }
                            }
                            // instantiate the certificate
                            try {
                                encoded = new byte[dis.readInt()];
                            } catch (OutOfMemoryError e) {
                                throw new IOException("Certificate too big");
                            }
                            dis.readFully(encoded);
                            bais = new ByteArrayInputStream(encoded);
                            entry.chain[j] = cf.generateCertificate(bais);
                        }

                        // Add the entry to the list
                        entries.put(alias, entry);

                    } else if (tag == 2) { // trusted certificate entry

                        TrustedCertEntry entry = new TrustedCertEntry();

                        // read the alias
                        alias = dis.readUTF();

                        // read the (entry creation) date
                        entry.date = new Date(dis.readLong());

                        // read the trusted certificate
                        if (xVersion == 2) {
                            // read the certificate type, and instantiate a
                            // certificate factory of that type (reuse
                            // existing factory if possible)
                            String certType = dis.readUTF();
                            if (cfs.containsKey(certType)) {
                                // reuse certificate factory
                                cf = cfs.get(certType);
                            } else {
                                // create new certificate factory
                                cf = CertificateFactory.getInstance(certType);
                                // store the certificate factory so we can
                                // reuse it later
                                cfs.put(certType, cf);
                            }
                        }
                        try {
                            encoded = new byte[dis.readInt()];
                        } catch (OutOfMemoryError e) {
                            throw new IOException("Certificate too big");
                        }
                        dis.readFully(encoded);
                        bais = new ByteArrayInputStream(encoded);
                        entry.cert = cf.generateCertificate(bais);

                        // Add the entry to the list
                        entries.put(alias, entry);

                    } else if (tag == 3) { // secret-key entry

                        SecretKeyEntry entry = new SecretKeyEntry();

                        // read the alias
                        alias = dis.readUTF();

                        // read the (entry creation) date
                        entry.date = new Date(dis.readLong());

                        // read the sealed key
                        try {
                            ois = new ObjectInputStream(dis);
                            entry.sealedKey = (SealedObject)ois.readObject();
                            // NOTE: don't close ois here since we are still
                            // using dis!!!
                        } catch (ClassNotFoundException cnfe) {
                            throw new IOException(cnfe.getMessage());
                        }

                        // Add the entry to the list
                        entries.put(alias, entry);

                    } else {
                        throw new IOException("Unrecognized keystore entry");
                    }
                }

                /*
                 * If a password has been provided, we check the keyed digest
                 * at the end. If this check fails, the store has been tampered
                 * with
                 */
                if (password != null) {
                    byte computed[], actual[];
                    computed = md.digest();
                    actual = new byte[computed.length];
                    dis.readFully(actual);
                    for (int i = 0; i < computed.length; i++) {
                        if (computed[i] != actual[i]) {
                            throw new IOException(
                                "Keystore was tampered with, or "
                                + "password was incorrect");
                        }
                    }
                }
            }  finally {
                if (ois != null) {
                    ois.close();
                } else {
                    dis.close();
                }
            }
        }
    }

    /**
     * To guard against tampering with the keystore, we append a keyed
     * hash with a bit of whitener.
     */
    private MessageDigest getPreKeyedHash(char[] password)
    throws NoSuchAlgorithmException, UnsupportedEncodingException {
        int i, j;

        MessageDigest md = MessageDigest.getInstance("SHA");
        byte[] passwdBytes = new byte[password.length * 2];
        for (i=0, j=0; i<password.length; i++) {
            passwdBytes[j++] = (byte)(password[i] >> 8);
            passwdBytes[j++] = (byte)password[i];
        }
        md.update(passwdBytes);
        for (i=0; i<passwdBytes.length; i++)
            passwdBytes[i] = 0;
        md.update("Mighty Aphrodite".getBytes("UTF8"));
        return md;
    }
}
