jdk/src/share/classes/sun/security/ec/ECKeyPairGenerator.java
changeset 3492 e549cea58864
child 3863 8e0f58b1c072
equal deleted inserted replaced
3480:c197e38bf15a 3492:e549cea58864
       
     1 /*
       
     2  * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Sun designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Sun in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
       
    22  * CA 95054 USA or visit www.sun.com if you need additional information or
       
    23  * have any questions.
       
    24  */
       
    25 
       
    26 package sun.security.ec;
       
    27 
       
    28 import java.math.BigInteger;
       
    29 import java.security.*;
       
    30 import java.security.spec.AlgorithmParameterSpec;
       
    31 import java.security.spec.ECGenParameterSpec;
       
    32 import java.security.spec.ECParameterSpec;
       
    33 import java.security.spec.ECPoint;
       
    34 
       
    35 import sun.security.ec.NamedCurve;
       
    36 import sun.security.ec.ECParameters;
       
    37 import sun.security.ec.ECPrivateKeyImpl;
       
    38 import sun.security.ec.ECPublicKeyImpl;
       
    39 import sun.security.jca.JCAUtil;
       
    40 
       
    41 /**
       
    42  * EC keypair generator.
       
    43  * Standard algorithm, minimum key length is 112 bits, maximum is 571 bits.
       
    44  *
       
    45  * @since 1.7
       
    46  */
       
    47 public final class ECKeyPairGenerator extends KeyPairGeneratorSpi {
       
    48 
       
    49     // flag indicating whether the native ECC implementation is present
       
    50     private static boolean implementationPresent = true;
       
    51     static {
       
    52         try {
       
    53             AccessController.doPrivileged(new PrivilegedAction<Void>() {
       
    54                 public Void run() {
       
    55                     System.loadLibrary("sunecc");
       
    56                     return null;
       
    57                 }
       
    58             });
       
    59         } catch (UnsatisfiedLinkError e) {
       
    60             implementationPresent = false;
       
    61         }
       
    62     }
       
    63     private static final int KEY_SIZE_MIN = 112; // min bits (see ecc_impl.h)
       
    64     private static final int KEY_SIZE_MAX = 571; // max bits (see ecc_impl.h)
       
    65     private static final int KEY_SIZE_DEFAULT = 256;
       
    66 
       
    67     // used to seed the keypair generator
       
    68     private SecureRandom random;
       
    69 
       
    70     // size of the key to generate, KEY_SIZE_MIN <= keySize <= KEY_SIZE_MAX
       
    71     private int keySize;
       
    72 
       
    73     // parameters specified via init, if any
       
    74     private AlgorithmParameterSpec params = null;
       
    75 
       
    76     /**
       
    77      * Constructs a new ECKeyPairGenerator.
       
    78      *
       
    79      * @exception ProviderException if the native ECC library is unavailable.
       
    80      */
       
    81     public ECKeyPairGenerator() {
       
    82         if (!implementationPresent) {
       
    83             throw new ProviderException("EC implementation is not available");
       
    84         }
       
    85         // initialize to default in case the app does not call initialize()
       
    86         initialize(KEY_SIZE_DEFAULT, null);
       
    87     }
       
    88 
       
    89     // initialize the generator. See JCA doc
       
    90     @Override
       
    91     public void initialize(int keySize, SecureRandom random) {
       
    92 
       
    93         checkKeySize(keySize);
       
    94         this.params = NamedCurve.getECParameterSpec(keySize);
       
    95         if (params == null) {
       
    96             throw new InvalidParameterException(
       
    97                 "No EC parameters available for key size " + keySize + " bits");
       
    98         }
       
    99         this.random = random;
       
   100     }
       
   101 
       
   102     // second initialize method. See JCA doc
       
   103     @Override
       
   104     public void initialize(AlgorithmParameterSpec params, SecureRandom random)
       
   105             throws InvalidAlgorithmParameterException {
       
   106 
       
   107         if (params instanceof ECParameterSpec) {
       
   108             this.params = ECParameters.getNamedCurve((ECParameterSpec)params);
       
   109             if (this.params == null) {
       
   110                 throw new InvalidAlgorithmParameterException(
       
   111                     "Unsupported curve: " + params);
       
   112             }
       
   113         } else if (params instanceof ECGenParameterSpec) {
       
   114             String name = ((ECGenParameterSpec)params).getName();
       
   115             this.params = NamedCurve.getECParameterSpec(name);
       
   116             if (this.params == null) {
       
   117                 throw new InvalidAlgorithmParameterException(
       
   118                     "Unknown curve name: " + name);
       
   119             }
       
   120         } else {
       
   121             throw new InvalidAlgorithmParameterException(
       
   122                 "ECParameterSpec or ECGenParameterSpec required for EC");
       
   123         }
       
   124         this.keySize =
       
   125             ((ECParameterSpec)this.params).getCurve().getField().getFieldSize();
       
   126         this.random = random;
       
   127     }
       
   128 
       
   129     // generate the keypair. See JCA doc
       
   130     @Override
       
   131     public KeyPair generateKeyPair() {
       
   132 
       
   133         byte[] encodedParams =
       
   134             ECParameters.encodeParameters((ECParameterSpec)params);
       
   135 
       
   136         // seed is twice the key size (in bytes)
       
   137         byte[] seed = new byte[2 * ((keySize + 7) >> 3)];
       
   138         if (random == null) {
       
   139             random = JCAUtil.getSecureRandom();
       
   140         }
       
   141         random.nextBytes(seed);
       
   142 
       
   143         long[] handles = generateECKeyPair(keySize, encodedParams, seed);
       
   144 
       
   145         // The 'params' object supplied above is equivalent to the native one
       
   146         // so there is no need to fetch it.
       
   147 
       
   148         // handles[0] points to the native private key
       
   149         BigInteger s = new BigInteger(1, getEncodedBytes(handles[0]));
       
   150 
       
   151         try {
       
   152             PrivateKey privateKey =
       
   153                 new ECPrivateKeyImpl(s, (ECParameterSpec)params);
       
   154 
       
   155             // handles[1] points to the native public key
       
   156             ECPoint w = ECParameters.decodePoint(getEncodedBytes(handles[1]),
       
   157                 ((ECParameterSpec)params).getCurve());
       
   158             PublicKey publicKey =
       
   159                 new ECPublicKeyImpl(w, (ECParameterSpec)params);
       
   160 
       
   161             return new KeyPair(publicKey, privateKey);
       
   162 
       
   163         } catch (Exception e) {
       
   164             throw new ProviderException(e);
       
   165         }
       
   166     }
       
   167 
       
   168     private void checkKeySize(int keySize) throws InvalidParameterException {
       
   169         if (keySize < KEY_SIZE_MIN) {
       
   170             throw new InvalidParameterException
       
   171                 ("Key size must be at least " + KEY_SIZE_MIN + " bits");
       
   172         }
       
   173         if (keySize > KEY_SIZE_MAX) {
       
   174             throw new InvalidParameterException
       
   175                 ("Key size must be at most " + KEY_SIZE_MAX + " bits");
       
   176         }
       
   177         this.keySize = keySize;
       
   178     }
       
   179 
       
   180     /*
       
   181      * Generates the keypair and returns a 2-element array of handles.
       
   182      * The first handle points to the private key, the second to the public key.
       
   183      */
       
   184     private static native long[] generateECKeyPair(int keySize,
       
   185         byte[] encodedParams, byte[] seed);
       
   186 
       
   187     /*
       
   188      * Extracts the encoded key data using the supplied handle.
       
   189      */
       
   190     private static native byte[] getEncodedBytes(long handle);
       
   191 }