1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17
18package javax.crypto;
19
20import java.security.InvalidAlgorithmParameterException;
21import java.security.NoSuchAlgorithmException;
22import java.security.NoSuchProviderException;
23import java.security.Provider;
24import java.security.SecureRandom;
25import java.security.Security;
26import java.security.spec.AlgorithmParameterSpec;
27
28import org.apache.harmony.crypto.internal.nls.Messages;
29import org.apache.harmony.security.fortress.Engine;
30
31
32/**
33 * This class provides the public API for generating symmetric cryptographic
34 * keys.
35 */
36public class KeyGenerator {
37
38    // Used to access common engine functionality
39    private static final Engine engine = new Engine("KeyGenerator"); //$NON-NLS-1$
40
41    // Store SecureRandom
42    private static final SecureRandom rndm = new SecureRandom();
43
44    // Store used provider
45    private final Provider provider;
46
47    // Store used spi implementation
48    private final KeyGeneratorSpi spiImpl;
49
50    // Store used algorithm name
51    private final String algorithm;
52
53    /**
54     * Creates a new {@code KeyGenerator} instance.
55     *
56     * @param keyGenSpi
57     *            the implementation delegate.
58     * @param provider
59     *            the implementation provider.
60     * @param algorithm
61     *            the name of the algorithm.
62     */
63    protected KeyGenerator(KeyGeneratorSpi keyGenSpi, Provider provider,
64            String algorithm) {
65        this.provider = provider;
66        this.algorithm = algorithm;
67        this.spiImpl = keyGenSpi;
68    }
69
70    /**
71     * Returns the name of the key generation algorithm.
72     *
73     * @return the name of the key generation algorithm.
74     */
75    public final String getAlgorithm() {
76        return algorithm;
77    }
78
79    /**
80     * Returns the provider of this {@code KeyGenerator} instance.
81     *
82     * @return the provider of this {@code KeyGenerator} instance.
83     */
84    public final Provider getProvider() {
85        return provider;
86    }
87
88    /**
89     * Creates a new {@code KeyGenerator} instance that provides the specified
90     * key algorithm,
91     *
92     * @param algorithm
93     *            the name of the requested key algorithm
94     * @return the new {@code KeyGenerator} instance.
95     * @throws NoSuchAlgorithmException
96     *             if the specified algorithm is not available by any provider.
97     * @throws NullPointerException
98     *             if {@code algorithm} is {@code null}.
99     */
100    public static final KeyGenerator getInstance(String algorithm)
101            throws NoSuchAlgorithmException {
102        if (algorithm == null) {
103            throw new NullPointerException(Messages.getString("crypto.02")); //$NON-NLS-1$
104        }
105        synchronized (engine) {
106            engine.getInstance(algorithm, null);
107            return new KeyGenerator((KeyGeneratorSpi) engine.spi, engine.provider,
108                    algorithm);
109        }
110    }
111
112    /**
113     * Creates a new {@code KeyGenerator} instance that provides the specified
114     * key algorithm from the specified provider.
115     *
116     * @param algorithm
117     *            the name of the requested key algorithm.
118     * @param provider
119     *            the name of the provider that is providing the algorithm.
120     * @return the new {@code KeyGenerator} instance.
121     * @throws NoSuchAlgorithmException
122     *             if the specified algorithm is not provided by the specified
123     *             provider.
124     * @throws NoSuchProviderException
125     *             if the specified provider is not available.
126     * @throws IllegalArgumentException
127     *             if the specified provider is name is {@code null} or empty.
128     * @throws NullPointerException
129     *             if the specified algorithm name is {@code null}.
130     */
131    public static final KeyGenerator getInstance(String algorithm,
132            String provider) throws NoSuchAlgorithmException,
133            NoSuchProviderException {
134        if ((provider == null) || (provider.length() == 0)) {
135            throw new IllegalArgumentException(Messages.getString("crypto.03")); //$NON-NLS-1$
136        }
137        Provider impProvider = Security.getProvider(provider);
138        if (impProvider == null) {
139            throw new NoSuchProviderException(provider);
140        }
141        return getInstance(algorithm, impProvider);
142    }
143
144    /**
145     * Creates a new {@code KeyGenerator} instance that provides the specified
146     * key algorithm from the specified provider.
147     *
148     * @param algorithm
149     *            the name of the requested key algorithm.
150     * @param provider
151     *            the provider that is providing the algorithm
152     * @return the new {@code KeyGenerator} instance.
153     * @throws NoSuchAlgorithmException
154     *             if the specified algorithm is not provided by the specified
155     *             provider.
156     * @throws IllegalArgumentException
157     *             if the specified provider is {@code null}.
158     * @throws NullPointerException
159     *             if the specified algorithm name is {@code null}.
160     */
161    public static final KeyGenerator getInstance(String algorithm,
162            Provider provider) throws NoSuchAlgorithmException {
163        if (provider == null) {
164            throw new IllegalArgumentException(Messages.getString("crypto.04")); //$NON-NLS-1$
165        }
166        if (algorithm == null) {
167            throw new NullPointerException(Messages.getString("crypto.02")); //$NON-NLS-1$
168        }
169        synchronized (engine) {
170            engine.getInstance(algorithm, provider, null);
171            return new KeyGenerator((KeyGeneratorSpi) engine.spi, provider,
172                    algorithm);
173        }
174    }
175
176    /**
177     * Generates a secret key.
178     *
179     * @return the generated secret key.
180     */
181    public final SecretKey generateKey() {
182        return spiImpl.engineGenerateKey();
183    }
184
185    /**
186     * Initializes this {@code KeyGenerator} instance with the specified
187     * algorithm parameters.
188     *
189     * @param params
190     *            the parameters for the key generation algorithm.
191     * @throws InvalidAlgorithmParameterException
192     *             if the parameters cannot be used to initialize this key
193     *             generator algorithm.
194     */
195    public final void init(AlgorithmParameterSpec params)
196            throws InvalidAlgorithmParameterException {
197        spiImpl.engineInit(params, rndm);//new SecureRandom());
198    }
199
200    /**
201     * Initializes this {@code KeyGenerator} instance with the specified
202     * algorithm parameters and randomness source.
203     *
204     * @param params
205     *            the parameters for the key generation algorithm.
206     * @param random
207     *            the randomness source for any random bytes.
208     * @throws InvalidAlgorithmParameterException
209     *             if the parameters cannot be uses to initialize this key
210     *             generator algorithm.
211     */
212    public final void init(AlgorithmParameterSpec params, SecureRandom random)
213            throws InvalidAlgorithmParameterException {
214        spiImpl.engineInit(params, random);
215    }
216
217    /**
218     * Initializes this {@code KeyGenerator} instance for the specified key size
219     * (in bits).
220     *
221     * @param keysize
222     *            the size of the key (in bits).
223     */
224    public final void init(int keysize) {
225        spiImpl.engineInit(keysize, rndm);//new SecureRandom());
226    }
227
228    /**
229     * Initializes this {@code KeyGenerator} instance for the specified key size
230     * (in bits) using the specified randomness source.
231     *
232     * @param keysize
233     *            the size of the key (in bits).
234     * @param random
235     *            the randomness source for any random bytes.
236     */
237    public final void init(int keysize, SecureRandom random) {
238        spiImpl.engineInit(keysize, random);
239    }
240
241    /**
242     * Initializes this {@code KeyGenerator} with the specified randomness
243     * source.
244     *
245     * @param random
246     *            the randomness source for any random bytes.
247     */
248    public final void init(SecureRandom random) {
249        spiImpl.engineInit(random);
250    }
251}