/*
 * Copyright (c) 1996, 2004, 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.pkcs;

import java.io.*;
import java.util.Properties;
import java.math.*;
import java.security.Key;
import java.security.KeyRep;
import java.security.PrivateKey;
import java.security.KeyFactory;
import java.security.Security;
import java.security.Provider;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;

import sun.misc.HexDumpEncoder;
import sun.security.x509.*;
import sun.security.util.*;

/**
 * Holds a PKCS#8 key, for example a private key
 *
 * @author Dave Brownell
 * @author Benjamin Renaud
 */
public class PKCS8Key implements PrivateKey {

    /** use serialVersionUID from JDK 1.1. for interoperability */
    private static final long serialVersionUID = -3836890099307167124L;

    /* The algorithm information (name, parameters, etc). */
    protected AlgorithmId algid;

    /* The key bytes, without the algorithm information */
    protected byte[] key;

    /* The encoded for the key. */
    protected byte[] encodedKey;

    /* The version for this key */
    public static final BigInteger version = BigInteger.ZERO;

    /**
     * Default constructor.  The key constructed must have its key
     * and algorithm initialized before it may be used, for example
     * by using <code>decode</code>.
     */
    public PKCS8Key() { }

    /*
     * Build and initialize as a "default" key.  All PKCS#8 key
     * data is stored and transmitted losslessly, but no knowledge
     * about this particular algorithm is available.
     */
    private PKCS8Key (AlgorithmId algid, byte key [])
    throws InvalidKeyException {
        this.algid = algid;
        this.key = key;
        encode();
    }

    /*
     * Binary backwards compatibility. New uses should call parseKey().
     */
    public static PKCS8Key parse (DerValue in) throws IOException {
        PrivateKey key;

        key = parseKey(in);
        if (key instanceof PKCS8Key)
            return (PKCS8Key)key;

        throw new IOException("Provider did not return PKCS8Key");
    }

    /**
     * Construct PKCS#8 subject public key from a DER value.  If
     * the runtime environment is configured with a specific class for
     * this kind of key, a subclass is returned.  Otherwise, a generic
     * PKCS8Key object is returned.
     *
     * <P>This mechanism gurantees that keys (and algorithms) may be
     * freely manipulated and transferred, without risk of losing
     * information.  Also, when a key (or algorithm) needs some special
     * handling, that specific need can be accomodated.
     *
     * @param in the DER-encoded SubjectPublicKeyInfo value
     * @exception IOException on data format errors
     */
    public static PrivateKey parseKey (DerValue in) throws IOException
    {
        AlgorithmId algorithm;
        PrivateKey privKey;

        if (in.tag != DerValue.tag_Sequence)
            throw new IOException ("corrupt private key");

        BigInteger parsedVersion = in.data.getBigInteger();
        if (!version.equals(parsedVersion)) {
            throw new IOException("version mismatch: (supported: " +
                                  Debug.toHexString(version) +
                                  ", parsed: " +
                                  Debug.toHexString(parsedVersion));
        }

        algorithm = AlgorithmId.parse (in.data.getDerValue ());

        try {
            privKey = buildPKCS8Key (algorithm, in.data.getOctetString ());

        } catch (InvalidKeyException e) {
            throw new IOException("corrupt private key");
        }

        if (in.data.available () != 0)
            throw new IOException ("excess private key");
        return privKey;
    }

    /**
     * Parse the key bits.  This may be redefined by subclasses to take
     * advantage of structure within the key.  For example, RSA public
     * keys encapsulate two unsigned integers (modulus and exponent) as
     * DER values within the <code>key</code> bits; Diffie-Hellman and
     * DSS/DSA keys encapsulate a single unsigned integer.
     *
     * <P>This function is called when creating PKCS#8 SubjectPublicKeyInfo
     * values using the PKCS8Key member functions, such as <code>parse</code>
     * and <code>decode</code>.
     *
     * @exception IOException if a parsing error occurs.
     * @exception InvalidKeyException if the key encoding is invalid.
     */
    protected void parseKeyBits () throws IOException, InvalidKeyException {
        encode();
    }

    /*
     * Factory interface, building the kind of key associated with this
     * specific algorithm ID or else returning this generic base class.
     * See the description above.
     */
    static PrivateKey buildPKCS8Key (AlgorithmId algid, byte[] key)
    throws IOException, InvalidKeyException
    {
        /*
         * Use the algid and key parameters to produce the ASN.1 encoding
         * of the key, which will then be used as the input to the
         * key factory.
         */
        DerOutputStream pkcs8EncodedKeyStream = new DerOutputStream();
        encode(pkcs8EncodedKeyStream, algid, key);
        PKCS8EncodedKeySpec pkcs8KeySpec
            = new PKCS8EncodedKeySpec(pkcs8EncodedKeyStream.toByteArray());

        try {
            // Instantiate the key factory of the appropriate algorithm
            KeyFactory keyFac = KeyFactory.getInstance(algid.getName());

            // Generate the private key
            return keyFac.generatePrivate(pkcs8KeySpec);
        } catch (NoSuchAlgorithmException e) {
            // Return generic PKCS8Key with opaque key data (see below)
        } catch (InvalidKeySpecException e) {
            // Return generic PKCS8Key with opaque key data (see below)
        }

        /*
         * Try again using JDK1.1-style for backwards compatibility.
         */
        String classname = "";
        try {
            Properties props;
            String keytype;
            Provider sunProvider;

            sunProvider = Security.getProvider("SUN");
            if (sunProvider == null)
                throw new InstantiationException();
            classname = sunProvider.getProperty("PrivateKey.PKCS#8." +
              algid.getName());
            if (classname == null) {
                throw new InstantiationException();
            }

            Class keyClass = null;
            try {
                keyClass = Class.forName(classname);
            } catch (ClassNotFoundException e) {
                ClassLoader cl = ClassLoader.getSystemClassLoader();
                if (cl != null) {
                    keyClass = cl.loadClass(classname);
                }
            }

            Object      inst = null;
            PKCS8Key    result;

            if (keyClass != null)
                inst = keyClass.newInstance();
            if (inst instanceof PKCS8Key) {
                result = (PKCS8Key) inst;
                result.algid = algid;
                result.key = key;
                result.parseKeyBits();
                return result;
            }
        } catch (ClassNotFoundException e) {
        } catch (InstantiationException e) {
        } catch (IllegalAccessException e) {
            // this should not happen.
            throw new IOException (classname + " [internal error]");
        }

        PKCS8Key result = new PKCS8Key();
        result.algid = algid;
        result.key = key;
        return result;
    }

    /**
     * Returns the algorithm to be used with this key.
     */
    public String getAlgorithm() {
        return algid.getName();
    }

    /**
     * Returns the algorithm ID to be used with this key.
     */
    public AlgorithmId  getAlgorithmId () { return algid; }

    /**
     * PKCS#8 sequence on the DER output stream.
     */
    public final void encode(DerOutputStream out) throws IOException
    {
        encode(out, this.algid, this.key);
    }

    /**
     * Returns the DER-encoded form of the key as a byte array.
     */
    public synchronized byte[] getEncoded() {
        byte[] result = null;
        try {
            result = encode();
        } catch (InvalidKeyException e) {
        }
        return result;
    }

    /**
     * Returns the format for this key: "PKCS#8"
     */
    public String getFormat() {
        return "PKCS#8";
    }

    /**
     * Returns the DER-encoded form of the key as a byte array.
     *
     * @exception InvalidKeyException if an encoding error occurs.
     */
    public byte[] encode() throws InvalidKeyException {
        if (encodedKey == null) {
            try {
                DerOutputStream out;

                out = new DerOutputStream ();
                encode (out);
                encodedKey = out.toByteArray();

            } catch (IOException e) {
                throw new InvalidKeyException ("IOException : " +
                                               e.getMessage());
            }
        }
        return encodedKey.clone();
    }

    /*
     * Returns a printable representation of the key
     */
    public String toString ()
    {
        HexDumpEncoder  encoder = new HexDumpEncoder ();

        return "algorithm = " + algid.toString ()
            + ", unparsed keybits = \n" + encoder.encodeBuffer (key);
    }

    /**
     * Initialize an PKCS8Key object from an input stream.  The data
     * on that input stream must be encoded using DER, obeying the
     * PKCS#8 format: a sequence consisting of a version, an algorithm
     * ID and a bit string which holds the key.  (That bit string is
     * often used to encapsulate another DER encoded sequence.)
     *
     * <P>Subclasses should not normally redefine this method; they should
     * instead provide a <code>parseKeyBits</code> method to parse any
     * fields inside the <code>key</code> member.
     *
     * @param in an input stream with a DER-encoded PKCS#8
     * SubjectPublicKeyInfo value
     *
     * @exception InvalidKeyException if a parsing error occurs.
     */
    public void decode(InputStream in) throws InvalidKeyException
    {
        DerValue        val;

        try {
            val = new DerValue (in);
            if (val.tag != DerValue.tag_Sequence)
                throw new InvalidKeyException ("invalid key format");


            BigInteger version = val.data.getBigInteger();
            if (!version.equals(this.version)) {
                throw new IOException("version mismatch: (supported: " +
                                      Debug.toHexString(this.version) +
                                      ", parsed: " +
                                      Debug.toHexString(version));
            }
            algid = AlgorithmId.parse (val.data.getDerValue ());
            key = val.data.getOctetString ();
            parseKeyBits ();

            if (val.data.available () != 0)  {
                // OPTIONAL attributes not supported yet
            }

        } catch (IOException e) {
            // e.printStackTrace ();
            throw new InvalidKeyException("IOException : " +
                                          e.getMessage());
        }
    }

    public void decode(byte[] encodedKey) throws InvalidKeyException {
        decode(new ByteArrayInputStream(encodedKey));
    }

    protected Object writeReplace() throws java.io.ObjectStreamException {
        return new KeyRep(KeyRep.Type.PRIVATE,
                        getAlgorithm(),
                        getFormat(),
                        getEncoded());
    }

    /**
     * Serialization read ... PKCS#8 keys serialize as
     * themselves, and they're parsed when they get read back.
     */
    private void readObject (ObjectInputStream stream)
    throws IOException {

        try {
            decode(stream);

        } catch (InvalidKeyException e) {
            e.printStackTrace();
            throw new IOException("deserialized key is invalid: " +
                                  e.getMessage());
        }
    }

    /*
     * Produce PKCS#8 encoding from algorithm id and key material.
     */
    static void encode(DerOutputStream out, AlgorithmId algid, byte[] key)
        throws IOException {
            DerOutputStream tmp = new DerOutputStream();
            tmp.putInteger(version);
            algid.encode(tmp);
            tmp.putOctetString(key);
            out.write(DerValue.tag_Sequence, tmp);
    }

    /**
     * Compares two private keys. This returns false if the object with which
     * to compare is not of type <code>Key</code>.
     * Otherwise, the encoding of this key object is compared with the
     * encoding of the given key object.
     *
     * @param object the object with which to compare
     * @return <code>true</code> if this key has the same encoding as the
     * object argument; <code>false</code> otherwise.
     */
    public boolean equals(Object object) {
        if (this == object) {
            return true;
        }

        if (object instanceof Key) {

            // this encoding
            byte[] b1;
            if (encodedKey != null) {
                b1 = encodedKey;
            } else {
                b1 = getEncoded();
            }

            // that encoding
            byte[] b2 = ((Key)object).getEncoded();

            // do the comparison
            int i;
            if (b1.length != b2.length)
                return false;
            for (i = 0; i < b1.length; i++) {
                if (b1[i] != b2[i]) {
                    return false;
                }
            }
            return true;
        }

        return false;
    }

    /**
     * Calculates a hash code value for this object. Objects
     * which are equal will also have the same hashcode.
     */
    public int hashCode() {
        int retval = 0;
        byte[] b1 = getEncoded();

        for (int i = 1; i < b1.length; i++) {
            retval += b1[i] * i;
        }
        return(retval);
    }
}
