1 /*
   2  * Copyright (c) 2005, 2011, Oracle and/or its affiliates. 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.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package sun.security.mscapi;
  27 
  28 import java.util.UUID;
  29 import java.security.*;
  30 import java.security.spec.AlgorithmParameterSpec;
  31 import java.security.spec.RSAKeyGenParameterSpec;
  32 
  33 import sun.security.jca.JCAUtil;
  34 import sun.security.rsa.RSAKeyFactory;
  35 
  36 /**
  37  * RSA keypair generator.
  38  *
  39  * Standard algorithm, minimum key length is 512 bit, maximum is 16,384.
  40  * Generates a private key that is exportable.
  41  *
  42  * @since 1.6
  43  */
  44 public final class RSAKeyPairGenerator extends KeyPairGeneratorSpi {
  45 
  46     // Supported by Microsoft Base, Strong and Enhanced Cryptographic Providers
  47     static final int KEY_SIZE_MIN = 512; // disallow MSCAPI min. of 384
  48     static final int KEY_SIZE_MAX = 16384;
  49     private static final int KEY_SIZE_DEFAULT = 1024;
  50 
  51     // size of the key to generate, KEY_SIZE_MIN <= keySize <= KEY_SIZE_MAX
  52     private int keySize;
  53 
  54     public RSAKeyPairGenerator() {
  55         // initialize to default in case the app does not call initialize()
  56         initialize(KEY_SIZE_DEFAULT, null);
  57     }
  58 
  59     // initialize the generator. See JCA doc
  60     // random is always ignored
  61     public void initialize(int keySize, SecureRandom random) {
  62 
  63         try {
  64             RSAKeyFactory.checkKeyLengths(keySize, null,
  65                 KEY_SIZE_MIN, KEY_SIZE_MAX);
  66         } catch (InvalidKeyException e) {
  67             throw new InvalidParameterException(e.getMessage());
  68         }
  69 
  70         this.keySize = keySize;
  71     }
  72 
  73     // second initialize method. See JCA doc
  74     // random and exponent are always ignored
  75     public void initialize(AlgorithmParameterSpec params, SecureRandom random)
  76             throws InvalidAlgorithmParameterException {
  77 
  78         int tmpSize;
  79         if (params == null) {
  80             tmpSize = KEY_SIZE_DEFAULT;
  81         } else if (params instanceof RSAKeyGenParameterSpec) {
  82 
  83             if (((RSAKeyGenParameterSpec) params).getPublicExponent() != null) {
  84                 throw new InvalidAlgorithmParameterException
  85                     ("Exponent parameter is not supported");
  86             }
  87             tmpSize = ((RSAKeyGenParameterSpec) params).getKeysize();
  88 
  89         } else {
  90             throw new InvalidAlgorithmParameterException
  91                 ("Params must be an instance of RSAKeyGenParameterSpec");
  92         }
  93 
  94         try {
  95             RSAKeyFactory.checkKeyLengths(tmpSize, null,
  96                 KEY_SIZE_MIN, KEY_SIZE_MAX);
  97         } catch (InvalidKeyException e) {
  98             throw new InvalidAlgorithmParameterException(
  99                 "Invalid Key sizes", e);
 100         }
 101 
 102         this.keySize = tmpSize;
 103     }
 104 
 105     // generate the keypair. See JCA doc
 106     public KeyPair generateKeyPair() {
 107 
 108         try {
 109 
 110             // Generate each keypair in a unique key container
 111             RSAKeyPair keys =
 112                 generateRSAKeyPair(keySize,
 113                     "{" + UUID.randomUUID().toString() + "}");
 114 
 115             return new KeyPair(keys.getPublic(), keys.getPrivate());
 116 
 117         } catch (KeyException e) {
 118             throw new ProviderException(e);
 119         }
 120     }
 121 
 122     private static native RSAKeyPair generateRSAKeyPair(int keySize,
 123         String keyContainerName) throws KeyException;
 124 }