/* 
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.harmony.security.tests.java.security;

import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.Provider;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Security;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.Vector;

public class KeyFactory2Test extends junit.framework.TestCase {

    private static final String KEYFACTORY_ID = "KeyFactory.";

    private String[] keyfactAlgs = null;

    private String providerName = null;

    static class KeepAlive extends Thread {
        int sleepTime, iterations;

        public KeepAlive(int sleepTime, int iterations) {
            this.sleepTime = sleepTime;
            this.iterations = iterations;
        }

        public void run() {
            synchronized (this) {
                this.notify();
            }
            for (int i = 0; i < iterations; i++) {
                try {
                    Thread.sleep(sleepTime);
                    System.out.print("[KA]");
                } catch (InterruptedException e) {
                    System.out.print("[I]");
                    break;
                }
            }
        }
    }

    private KeepAlive createKeepAlive(String alg) {
        if (alg.equals("RSA")) {
            // 32 minutes
            KeepAlive keepalive = new KeepAlive(240000, 8);
            synchronized (keepalive) {
                keepalive.start();
                try {
                    keepalive.wait();
                } catch (InterruptedException e) {
                    // ignore
                }
            }
            return keepalive;
        }
        return null;
    }

    /**
     * @tests java.security.KeyFactory#generatePrivate(java.security.spec.KeySpec)
     */
    public void test_generatePrivateLjava_security_spec_KeySpec() {
        // Test for method java.security.PrivateKey
        // java.security.KeyFactory.generatePrivate(java.security.spec.KeySpec)
        for (int i = 0; i < keyfactAlgs.length; i++) {
            try {
                KeyFactory fact = KeyFactory.getInstance(keyfactAlgs[i],
                        providerName);
                KeyPairGenerator keyGen = KeyPairGenerator
                        .getInstance(keyfactAlgs[i]);
                SecureRandom random = new SecureRandom(); // We don't use
                // getInstance
                keyGen.initialize(1024, random);
                KeepAlive keepalive = createKeepAlive(keyfactAlgs[i]);
                KeyPair keys = keyGen.generateKeyPair();
                if (keepalive != null) {
                    keepalive.interrupt();
                }

                KeySpec privateKeySpec = fact.getKeySpec(keys.getPrivate(),
                        getPrivateKeySpecClass(keyfactAlgs[i]));
                PrivateKey privateKey = fact.generatePrivate(privateKeySpec);
                boolean samePrivate = Arrays.equals(keys.getPrivate()
                        .getEncoded(), privateKey.getEncoded());
                assertTrue(
                        "generatePrivate generated different key for algorithm "
                                + keyfactAlgs[i], samePrivate);
                fact.generatePrivate(new PKCS8EncodedKeySpec(keys.getPrivate()
                        .getEncoded()));
            } catch (InvalidKeySpecException e) {
                fail("invalid key spec for algorithm " + keyfactAlgs[i]);
            } catch (NoSuchAlgorithmException e) {
                fail("getInstance did not find algorithm " + keyfactAlgs[i]);
            } catch (NoSuchProviderException e) {
                fail("getInstance did not find provider " + providerName);
            }
        }
    }

    /**
     * @tests java.security.KeyFactory#generatePublic(java.security.spec.KeySpec)
     */
    public void test_generatePublicLjava_security_spec_KeySpec() {
        // Test for method java.security.PublicKey
        // java.security.KeyFactory.generatePublic(java.security.spec.KeySpec)
        for (int i = 0; i < keyfactAlgs.length; i++) {
            try {
                KeyFactory fact = KeyFactory.getInstance(keyfactAlgs[i],
                        providerName);
                KeyPairGenerator keyGen = KeyPairGenerator
                        .getInstance(keyfactAlgs[i]);
                // We don't use getInstance
                SecureRandom random = new SecureRandom();
                keyGen.initialize(1024, random);
                KeepAlive keepalive = createKeepAlive(keyfactAlgs[i]);
                KeyPair keys = keyGen.generateKeyPair();
                if (keepalive != null) {
                    keepalive.interrupt();
                }
                KeySpec publicKeySpec = fact.getKeySpec(keys.getPublic(),
                        getPublicKeySpecClass(keyfactAlgs[i]));
                PublicKey publicKey = fact.generatePublic(publicKeySpec);
                boolean samePublic = Arrays.equals(keys.getPublic()
                        .getEncoded(), publicKey.getEncoded());
                assertTrue(
                        "generatePublic generated different key for algorithm "
                                + keyfactAlgs[i], samePublic);
            } catch (NoSuchAlgorithmException e) {
                fail("getInstance did not find algorithm " + keyfactAlgs[i]);
            } catch (NoSuchProviderException e) {
                fail("getInstance did not find provider " + providerName);
            } catch (InvalidKeySpecException e) {
                fail("invalid key spec for algorithm " + keyfactAlgs[i]);
            }
        }
    }

    /**
     * @tests java.security.KeyFactory#getAlgorithm()
     */
    public void test_getAlgorithm() {
        // Test for method java.lang.String
        // java.security.KeyFactory.getAlgorithm()
        for (int i = 0; i < keyfactAlgs.length; i++) {
            try {
                KeyFactory fact = KeyFactory.getInstance(keyfactAlgs[i],
                        providerName);
                assertTrue("getAlgorithm ok for algorithm " + keyfactAlgs[i],
                        fact.getAlgorithm().equals(keyfactAlgs[i]));
            } catch (NoSuchAlgorithmException e) {
                fail("getInstance did not find algorithm " + keyfactAlgs[i]);
            } catch (NoSuchProviderException e) {
                fail("getInstance did not find provider " + providerName);
            }
        }// end for
    }

    /**
     * @tests java.security.KeyFactory#getInstance(java.lang.String)
     */
    public void test_getInstanceLjava_lang_String() {
        // Test for method java.security.KeyFactory
        // java.security.KeyFactory.getInstance(java.lang.String)
        for (int i = 0; i < keyfactAlgs.length; i++) {
            try {
                assertNotNull(KeyFactory.getInstance(keyfactAlgs[i]));
            } catch (NoSuchAlgorithmException e) {
                fail("getInstance did not find algorithm " + keyfactAlgs[i]);
            }
        }// end for
    }

    /**
     * @tests java.security.KeyFactory#getInstance(java.lang.String,
     *java.lang.String)
     */
    public void test_getInstanceLjava_lang_StringLjava_lang_String() throws Exception {

        // Test1: Test for method java.security.KeyFactory
        // java.security.KeyFactory.getInstance(java.lang.String,
        // java.lang.String)
        try {
            Provider[] providers = Security.getProviders("KeyFactory.DSA");
            if (providers != null) {
                for (int i = 0; i < providers.length; i++) {
                    KeyFactory.getInstance("DSA", providers[i].getName());
                }// end for
            } else {
                fail("No providers support KeyFactory.DSA");
            }
        } catch (NoSuchAlgorithmException e) {
            fail("getInstance did not find algorithm");
        } catch (NoSuchProviderException e) {
            fail("getInstance did not find the provider");
        }

        // Test2: Test with null provider name
        try {
            KeyFactory.getInstance("DSA", (String) null);
            fail("Expected IllegalArgumentException");
        } catch (IllegalArgumentException e) {
            // Expected
        }
    }

    /**
     * @tests java.security.KeyFactory#getKeySpec(java.security.Key,
     *java.lang.Class)
     */
    public void test_getKeySpecLjava_security_KeyLjava_lang_Class() {
        // Test for method java.security.spec.KeySpec
        // java.security.KeyFactory.getKeySpec(java.security.Key,
        // java.lang.Class)
        for (int i = 0; i < keyfactAlgs.length; i++) {
            try {
                KeyFactory fact = KeyFactory.getInstance(keyfactAlgs[i],
                        providerName);
                KeyPairGenerator keyGen = KeyPairGenerator
                        .getInstance(keyfactAlgs[i]);

                // We don't use getInstance
                SecureRandom random = new SecureRandom();
                keyGen.initialize(1024, random);
                KeepAlive keepalive = createKeepAlive(keyfactAlgs[i]);
                KeyPair keys = keyGen.generateKeyPair();
                if (keepalive != null) {
                    keepalive.interrupt();
                }
                KeySpec privateKeySpec = fact.getKeySpec(keys.getPrivate(),
                        getPrivateKeySpecClass(keyfactAlgs[i]));
                KeySpec publicKeySpec = fact.getKeySpec(keys.getPublic(),
                        getPublicKeySpecClass(keyfactAlgs[i]));
                PrivateKey privateKey = fact.generatePrivate(privateKeySpec);
                PublicKey publicKey = fact.generatePublic(publicKeySpec);
                boolean samePublic = Arrays.equals(keys.getPublic()
                        .getEncoded(), publicKey.getEncoded());
                boolean samePrivate = Arrays.equals(keys.getPrivate()
                        .getEncoded(), privateKey.getEncoded());
                assertTrue(
                        "generatePrivate generated different key for algorithm "
                                + keyfactAlgs[i], samePrivate);
                assertTrue(
                        "generatePublic generated different key for algorithm "
                                + keyfactAlgs[i], samePublic);
                KeySpec encodedSpec = fact.getKeySpec(keys.getPublic(),
                        X509EncodedKeySpec.class);
                assertTrue("improper key spec for encoded public key",
                        encodedSpec.getClass().equals(X509EncodedKeySpec.class));
                encodedSpec = fact.getKeySpec(keys.getPrivate(),
                        PKCS8EncodedKeySpec.class);
                assertTrue("improper key spec for encoded private key",
                        encodedSpec.getClass()
                                .equals(PKCS8EncodedKeySpec.class));
            } catch (NoSuchAlgorithmException e) {
                fail("getInstance did not find algorithm " + keyfactAlgs[i]);
            } catch (NoSuchProviderException e) {
                fail("getInstance did not find provider " + providerName);
            } catch (InvalidKeySpecException e) {
                fail("invalid key spec for algorithm " + keyfactAlgs[i]);
            }
        }
    }

    /**
     * @tests java.security.KeyFactory#getProvider()
     */
    public void test_getProvider() {
        // Test for method java.security.Provider
        // java.security.KeyFactory.getProvider()
        for (int i = 0; i < keyfactAlgs.length; i++) {
            try {
                KeyFactory fact = KeyFactory.getInstance(keyfactAlgs[i]);
                Provider p = fact.getProvider();
                assertNotNull("provider is null for algorithm "
                        + keyfactAlgs[i], p);
            } catch (NoSuchAlgorithmException e) {
                fail("getInstance did not find algorithm " + keyfactAlgs[i]);
            }
        }// end for
    }

    /**
     * @tests java.security.KeyFactory#translateKey(java.security.Key)
     */
    public void test_translateKeyLjava_security_Key() {
        // Test for method java.security.Key
        // java.security.KeyFactory.translateKey(java.security.Key)
        for (int i = 0; i < keyfactAlgs.length; i++) {
            try {
                KeyFactory fact = KeyFactory.getInstance(keyfactAlgs[i],
                        providerName);
                KeyPairGenerator keyGen = KeyPairGenerator
                        .getInstance(keyfactAlgs[i]);

                // We don't use getInstance
                SecureRandom random = new SecureRandom();
                keyGen.initialize(1024, random);
                KeepAlive keepalive = createKeepAlive(keyfactAlgs[i]);
                KeyPair keys = keyGen.generateKeyPair();
                if (keepalive != null) {
                    keepalive.interrupt();
                }
                fact.translateKey(keys.getPrivate());
            } catch (NoSuchAlgorithmException e) {
                fail("getInstance did not find algorithm " + keyfactAlgs[i]);
            } catch (NoSuchProviderException e) {
                fail("getInstance did not find provider " + providerName);
            } catch (InvalidKeyException e) {
                fail("generatePublic did not generate right spec for algorithm "
                        + keyfactAlgs[i]);
            }
        }
    }

    protected void setUp() {
        if (keyfactAlgs == null) {
            Provider[] providers = Security.getProviders();
            // Arbitrarily use the first provider that supports
            // KeyFactory algorithms
            for (Provider provider : providers) {
                providerName = provider.getName();
                keyfactAlgs = getKeyFactoryAlgorithms(providerName);
                if (keyfactAlgs.length != 0) {
                    break;
                }
            }
        }
    }

    /*
      * Returns the key algorithms that the given provider supports.
      */
    private String[] getKeyFactoryAlgorithms(String providerName) {
        Vector algs = new Vector();

        Provider provider = Security.getProvider(providerName);
        if (provider == null)
            return new String[0];
        Enumeration e = provider.keys();
        while (e.hasMoreElements()) {
            String algorithm = (String) e.nextElement();
            if (algorithm.startsWith(KEYFACTORY_ID) && !algorithm.contains(" ")) {
                algs.addElement(algorithm.substring(KEYFACTORY_ID.length()));
            }
        }

        return (String[]) algs.toArray(new String[algs.size()]);
    }

    /**
     * Returns the public key spec class for a given algorithm, or null if it is
     * not known.
     */
    private Class getPrivateKeySpecClass(String algName) {
        if (algName.equals("RSA")) {
            return java.security.spec.RSAPrivateCrtKeySpec.class;
        }
        if (algName.equals("DSA")) {
            return java.security.spec.DSAPrivateKeySpec.class;
        }
        return null;
    }

    /**
     * Returns the private key spec class for a given algorithm, or null if it
     * is not known.
     */
    private Class getPublicKeySpecClass(String algName) {
        if (algName.equals("RSA")) {
            return java.security.spec.RSAPublicKeySpec.class;
        }
        if (algName.equals("DSA")) {
            return java.security.spec.DSAPublicKeySpec.class;
        }
        return null;
    }
}
