Home | History | Annotate | Download | only in dsa
      1 package org.bouncycastle.jcajce.provider.asymmetric.dsa;
      2 
      3 import java.security.InvalidAlgorithmParameterException;
      4 import java.security.InvalidParameterException;
      5 import java.security.KeyPair;
      6 import java.security.SecureRandom;
      7 import java.security.spec.AlgorithmParameterSpec;
      8 import java.security.spec.DSAParameterSpec;
      9 import java.util.Hashtable;
     10 
     11 import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
     12 import org.bouncycastle.crypto.digests.SHA256Digest;
     13 import org.bouncycastle.crypto.generators.DSAKeyPairGenerator;
     14 import org.bouncycastle.crypto.generators.DSAParametersGenerator;
     15 import org.bouncycastle.crypto.params.DSAKeyGenerationParameters;
     16 import org.bouncycastle.crypto.params.DSAParameterGenerationParameters;
     17 import org.bouncycastle.crypto.params.DSAParameters;
     18 import org.bouncycastle.crypto.params.DSAPrivateKeyParameters;
     19 import org.bouncycastle.crypto.params.DSAPublicKeyParameters;
     20 import org.bouncycastle.jcajce.provider.asymmetric.util.PrimeCertaintyCalculator;
     21 import org.bouncycastle.util.Integers;
     22 import org.bouncycastle.util.Properties;
     23 
     24 public class KeyPairGeneratorSpi
     25     extends java.security.KeyPairGenerator
     26 {
     27     private static Hashtable params = new Hashtable();
     28     private static Object    lock = new Object();
     29 
     30     DSAKeyGenerationParameters param;
     31     DSAKeyPairGenerator engine = new DSAKeyPairGenerator();
     32     // Android-changed: Change default strength to 1024
     33     // In 1.57, the default strength was changed to 2048.  We keep it at 1024 for app
     34     // compatibility, particularly because the default digest (SHA-1) doesn't have
     35     // a sufficiently long digest to work with 2048-bit keys.
     36     int strength = 1024;
     37 
     38     SecureRandom random = new SecureRandom();
     39     boolean initialised = false;
     40 
     41     public KeyPairGeneratorSpi()
     42     {
     43         super("DSA");
     44     }
     45 
     46     public void initialize(
     47         int strength,
     48         SecureRandom random)
     49     {
     50         if (strength < 512 || strength > 4096 || ((strength < 1024) && strength % 64 != 0) || (strength >= 1024 && strength % 1024 != 0))
     51         {
     52             throw new InvalidParameterException("strength must be from 512 - 4096 and a multiple of 1024 above 1024");
     53         }
     54 
     55         this.strength = strength;
     56         this.random = random;
     57         this.initialised = false;
     58     }
     59 
     60     public void initialize(
     61         AlgorithmParameterSpec params,
     62         SecureRandom random)
     63         throws InvalidAlgorithmParameterException
     64     {
     65         if (!(params instanceof DSAParameterSpec))
     66         {
     67             throw new InvalidAlgorithmParameterException("parameter object not a DSAParameterSpec");
     68         }
     69         DSAParameterSpec dsaParams = (DSAParameterSpec)params;
     70 
     71         param = new DSAKeyGenerationParameters(random, new DSAParameters(dsaParams.getP(), dsaParams.getQ(), dsaParams.getG()));
     72 
     73         engine.init(param);
     74         initialised = true;
     75     }
     76 
     77     public KeyPair generateKeyPair()
     78     {
     79         if (!initialised)
     80         {
     81             Integer paramStrength = Integers.valueOf(strength);
     82 
     83             if (params.containsKey(paramStrength))
     84             {
     85                 param = (DSAKeyGenerationParameters)params.get(paramStrength);
     86             }
     87             else
     88             {
     89                 synchronized (lock)
     90                 {
     91                     // we do the check again in case we were blocked by a generator for
     92                     // our key size.
     93                     if (params.containsKey(paramStrength))
     94                     {
     95                         param = (DSAKeyGenerationParameters)params.get(paramStrength);
     96                     }
     97                     else
     98                     {
     99                         DSAParametersGenerator pGen;
    100                         DSAParameterGenerationParameters dsaParams;
    101 
    102                         int certainty = PrimeCertaintyCalculator.getDefaultCertainty(strength);
    103 
    104                         // Typical combination of keysize and size of q.
    105                         //     keysize = 1024, q's size = 160
    106                         //     keysize = 2048, q's size = 224
    107                         //     keysize = 2048, q's size = 256
    108                         //     keysize = 3072, q's size = 256
    109                         // For simplicity if keysize is greater than 1024 then we choose q's size to be 256.
    110                         // For legacy keysize that is less than 1024-bit, we just use the 186-2 style parameters
    111                         if (strength == 1024)
    112                         {
    113                             pGen = new DSAParametersGenerator();
    114                             if (Properties.isOverrideSet("org.bouncycastle.dsa.FIPS186-2for1024bits"))
    115                             {
    116                                 pGen.init(strength, certainty, random);
    117                             }
    118                             else
    119                             {
    120                                 dsaParams = new DSAParameterGenerationParameters(1024, 160, certainty, random);
    121                                 pGen.init(dsaParams);
    122                             }
    123                         }
    124                         else if (strength > 1024)
    125                         {
    126                             dsaParams = new DSAParameterGenerationParameters(strength, 256, certainty, random);
    127                             pGen = new DSAParametersGenerator(new SHA256Digest());
    128                             pGen.init(dsaParams);
    129                         }
    130                         else
    131                         {
    132                             pGen = new DSAParametersGenerator();
    133                             pGen.init(strength, certainty, random);
    134                         }
    135                         param = new DSAKeyGenerationParameters(random, pGen.generateParameters());
    136 
    137                         params.put(paramStrength, param);
    138                     }
    139                 }
    140             }
    141 
    142             engine.init(param);
    143             initialised = true;
    144         }
    145 
    146         AsymmetricCipherKeyPair pair = engine.generateKeyPair();
    147         DSAPublicKeyParameters pub = (DSAPublicKeyParameters)pair.getPublic();
    148         DSAPrivateKeyParameters priv = (DSAPrivateKeyParameters)pair.getPrivate();
    149 
    150         return new KeyPair(new BCDSAPublicKey(pub), new BCDSAPrivateKey(priv));
    151     }
    152 }
    153