1545N/A/*
4111N/A * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
1545N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
1545N/A *
1545N/A * This code is free software; you can redistribute it and/or modify it
1545N/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
1545N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
1545N/A *
1545N/A * This code is distributed in the hope that it will be useful, but WITHOUT
1545N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1545N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1545N/A * version 2 for more details (a copy is included in the LICENSE file that
1545N/A * accompanied this code).
1545N/A *
1545N/A * You should have received a copy of the GNU General Public License version
1545N/A * 2 along with this work; if not, write to the Free Software Foundation,
1545N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
1545N/A *
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
2362N/A * questions.
1545N/A */
1545N/A
1545N/Apackage sun.security.ec;
1545N/A
1545N/Aimport java.math.BigInteger;
1545N/Aimport java.security.*;
1545N/Aimport java.security.spec.AlgorithmParameterSpec;
1545N/Aimport java.security.spec.ECGenParameterSpec;
1545N/Aimport java.security.spec.ECParameterSpec;
1545N/Aimport java.security.spec.ECPoint;
1545N/A
1545N/Aimport sun.security.ec.NamedCurve;
1545N/Aimport sun.security.ec.ECParameters;
1545N/Aimport sun.security.ec.ECPrivateKeyImpl;
1545N/Aimport sun.security.ec.ECPublicKeyImpl;
1545N/Aimport sun.security.jca.JCAUtil;
1545N/A
1545N/A/**
1545N/A * EC keypair generator.
1545N/A * Standard algorithm, minimum key length is 112 bits, maximum is 571 bits.
1545N/A *
1545N/A * @since 1.7
1545N/A */
1545N/Apublic final class ECKeyPairGenerator extends KeyPairGeneratorSpi {
1545N/A
1545N/A private static final int KEY_SIZE_MIN = 112; // min bits (see ecc_impl.h)
1545N/A private static final int KEY_SIZE_MAX = 571; // max bits (see ecc_impl.h)
1545N/A private static final int KEY_SIZE_DEFAULT = 256;
1545N/A
1545N/A // used to seed the keypair generator
1545N/A private SecureRandom random;
1545N/A
1545N/A // size of the key to generate, KEY_SIZE_MIN <= keySize <= KEY_SIZE_MAX
1545N/A private int keySize;
1545N/A
1545N/A // parameters specified via init, if any
1545N/A private AlgorithmParameterSpec params = null;
1545N/A
1545N/A /**
1545N/A * Constructs a new ECKeyPairGenerator.
1545N/A */
1545N/A public ECKeyPairGenerator() {
1545N/A // initialize to default in case the app does not call initialize()
1545N/A initialize(KEY_SIZE_DEFAULT, null);
1545N/A }
1545N/A
1545N/A // initialize the generator. See JCA doc
1545N/A @Override
1545N/A public void initialize(int keySize, SecureRandom random) {
1545N/A
1545N/A checkKeySize(keySize);
1545N/A this.params = NamedCurve.getECParameterSpec(keySize);
1545N/A if (params == null) {
1545N/A throw new InvalidParameterException(
1545N/A "No EC parameters available for key size " + keySize + " bits");
1545N/A }
1545N/A this.random = random;
1545N/A }
1545N/A
1545N/A // second initialize method. See JCA doc
1545N/A @Override
1545N/A public void initialize(AlgorithmParameterSpec params, SecureRandom random)
1545N/A throws InvalidAlgorithmParameterException {
1545N/A
1545N/A if (params instanceof ECParameterSpec) {
1545N/A this.params = ECParameters.getNamedCurve((ECParameterSpec)params);
1545N/A if (this.params == null) {
1545N/A throw new InvalidAlgorithmParameterException(
1545N/A "Unsupported curve: " + params);
1545N/A }
1545N/A } else if (params instanceof ECGenParameterSpec) {
1545N/A String name = ((ECGenParameterSpec)params).getName();
1545N/A this.params = NamedCurve.getECParameterSpec(name);
1545N/A if (this.params == null) {
1545N/A throw new InvalidAlgorithmParameterException(
1545N/A "Unknown curve name: " + name);
1545N/A }
1545N/A } else {
1545N/A throw new InvalidAlgorithmParameterException(
1545N/A "ECParameterSpec or ECGenParameterSpec required for EC");
1545N/A }
1545N/A this.keySize =
1545N/A ((ECParameterSpec)this.params).getCurve().getField().getFieldSize();
1545N/A this.random = random;
1545N/A }
1545N/A
1545N/A // generate the keypair. See JCA doc
1545N/A @Override
1545N/A public KeyPair generateKeyPair() {
1545N/A
1545N/A byte[] encodedParams =
1545N/A ECParameters.encodeParameters((ECParameterSpec)params);
1545N/A
1674N/A // seed is twice the key size (in bytes) plus 1
1674N/A byte[] seed = new byte[(((keySize + 7) >> 3) + 1) * 2];
1545N/A if (random == null) {
1545N/A random = JCAUtil.getSecureRandom();
1545N/A }
1545N/A random.nextBytes(seed);
1545N/A
4111N/A try {
1545N/A
4111N/A long[] handles = generateECKeyPair(keySize, encodedParams, seed);
1545N/A
4111N/A // The 'params' object supplied above is equivalent to the native
4111N/A // one so there is no need to fetch it.
1545N/A
4111N/A // handles[0] points to the native private key
4111N/A BigInteger s = new BigInteger(1, getEncodedBytes(handles[0]));
4111N/A
1545N/A PrivateKey privateKey =
1545N/A new ECPrivateKeyImpl(s, (ECParameterSpec)params);
1545N/A
1545N/A // handles[1] points to the native public key
1545N/A ECPoint w = ECParameters.decodePoint(getEncodedBytes(handles[1]),
1545N/A ((ECParameterSpec)params).getCurve());
1545N/A PublicKey publicKey =
1545N/A new ECPublicKeyImpl(w, (ECParameterSpec)params);
1545N/A
1545N/A return new KeyPair(publicKey, privateKey);
1545N/A
1545N/A } catch (Exception e) {
1545N/A throw new ProviderException(e);
1545N/A }
1545N/A }
1545N/A
1545N/A private void checkKeySize(int keySize) throws InvalidParameterException {
1545N/A if (keySize < KEY_SIZE_MIN) {
1545N/A throw new InvalidParameterException
1545N/A ("Key size must be at least " + KEY_SIZE_MIN + " bits");
1545N/A }
1545N/A if (keySize > KEY_SIZE_MAX) {
1545N/A throw new InvalidParameterException
1545N/A ("Key size must be at most " + KEY_SIZE_MAX + " bits");
1545N/A }
1545N/A this.keySize = keySize;
1545N/A }
1545N/A
1545N/A /*
1545N/A * Generates the keypair and returns a 2-element array of handles.
1545N/A * The first handle points to the private key, the second to the public key.
1545N/A */
1545N/A private static native long[] generateECKeyPair(int keySize,
4111N/A byte[] encodedParams, byte[] seed) throws GeneralSecurityException;
1545N/A
1545N/A /*
1545N/A * Extracts the encoded key data using the supplied handle.
1545N/A */
1545N/A private static native byte[] getEncodedBytes(long handle);
1545N/A}