|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  */ | 
|  |  | 
|  | package sun.security.provider; | 
|  |  | 
|  | import java.math.BigInteger; | 
|  |  | 
|  | import java.security.*; | 
|  | import java.security.SecureRandom; | 
|  | import java.security.interfaces.DSAParams; | 
|  | import java.security.spec.AlgorithmParameterSpec; | 
|  | import java.security.spec.InvalidParameterSpecException; | 
|  | import java.security.spec.DSAParameterSpec; | 
|  |  | 
|  | import sun.security.jca.JCAUtil; | 
|  | import static sun.security.util.SecurityProviderConstants.DEF_DSA_KEY_SIZE; | 
|  | import static sun.security.util.SecurityProviderConstants.getDefDSASubprimeSize; | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  */ | 
|  | class DSAKeyPairGenerator extends KeyPairGenerator { | 
|  |  | 
|  |      | 
|  |     private int plen; | 
|  |     private int qlen; | 
|  |  | 
|  |      | 
|  |     boolean forceNewParameters; | 
|  |  | 
|  |      | 
|  |     private DSAParameterSpec params; | 
|  |  | 
|  |      | 
|  |     private SecureRandom random; | 
|  |  | 
|  |     DSAKeyPairGenerator(int defaultKeySize) { | 
|  |         super("DSA"); | 
|  |         initialize(defaultKeySize, null); | 
|  |     } | 
|  |  | 
|  |     private static void checkStrength(int sizeP, int sizeQ) { | 
|  |         if ((sizeP >= 512) && (sizeP <= 1024) && (sizeP % 64 == 0) | 
|  |             && sizeQ == 160) { | 
|  |             // traditional - allow for backward compatibility | 
|  |             // L=multiples of 64 and between 512 and 1024 (inclusive) | 
|  |             // N=160 | 
|  |         } else if (sizeP == 2048 && (sizeQ == 224 || sizeQ == 256)) { | 
|  |             // L=2048, N=224 or 256 | 
|  |         } else if (sizeP == 3072 && sizeQ == 256) { | 
|  |             // L=3072, N=256 | 
|  |         } else { | 
|  |             throw new InvalidParameterException | 
|  |                 ("Unsupported prime and subprime size combination: " + | 
|  |                  sizeP + ", " + sizeQ); | 
|  |         } | 
|  |     } | 
|  |  | 
|  |     public void initialize(int modlen, SecureRandom random) { | 
|  |         init(modlen, random, false); | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     public void initialize(AlgorithmParameterSpec params, SecureRandom random) | 
|  |             throws InvalidAlgorithmParameterException { | 
|  |         if (!(params instanceof DSAParameterSpec)) { | 
|  |             throw new InvalidAlgorithmParameterException | 
|  |                 ("Inappropriate parameter"); | 
|  |         } | 
|  |         init((DSAParameterSpec)params, random, false); | 
|  |     } | 
|  |  | 
|  |     void init(int modlen, SecureRandom random, boolean forceNew) { | 
|  |         int subPrimeLen = getDefDSASubprimeSize(modlen); | 
|  |         checkStrength(modlen, subPrimeLen); | 
|  |         this.plen = modlen; | 
|  |         this.qlen = subPrimeLen; | 
|  |         this.params = null; | 
|  |         this.random = random; | 
|  |         this.forceNewParameters = forceNew; | 
|  |     } | 
|  |  | 
|  |     void init(DSAParameterSpec params, SecureRandom random, | 
|  |         boolean forceNew) { | 
|  |         int sizeP = params.getP().bitLength(); | 
|  |         int sizeQ = params.getQ().bitLength(); | 
|  |         checkStrength(sizeP, sizeQ); | 
|  |         this.plen = sizeP; | 
|  |         this.qlen = sizeQ; | 
|  |         this.params = params; | 
|  |         this.random = random; | 
|  |         this.forceNewParameters = forceNew; | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     public KeyPair generateKeyPair() { | 
|  |         if (random == null) { | 
|  |             random = JCAUtil.getSecureRandom(); | 
|  |         } | 
|  |         DSAParameterSpec spec; | 
|  |         try { | 
|  |             if (forceNewParameters) { | 
|  |                  | 
|  |                 spec = ParameterCache.getNewDSAParameterSpec(plen, qlen, random); | 
|  |             } else { | 
|  |                 if (params == null) { | 
|  |                     params = | 
|  |                         ParameterCache.getDSAParameterSpec(plen, qlen, random); | 
|  |                 } | 
|  |                 spec = params; | 
|  |             } | 
|  |         } catch (GeneralSecurityException e) { | 
|  |             throw new ProviderException(e); | 
|  |         } | 
|  |         return generateKeyPair(spec.getP(), spec.getQ(), spec.getG(), random); | 
|  |     } | 
|  |  | 
|  |     private KeyPair generateKeyPair(BigInteger p, BigInteger q, BigInteger g, | 
|  |                                    SecureRandom random) { | 
|  |  | 
|  |         BigInteger x = generateX(random, q); | 
|  |         BigInteger y = generateY(x, p, g); | 
|  |  | 
|  |         try { | 
|  |  | 
|  |             // See the comments in DSAKeyFactory, 4532506, and 6232513. | 
|  |  | 
|  |             DSAPublicKey pub; | 
|  |             if (DSAKeyFactory.SERIAL_INTEROP) { | 
|  |                 pub = new DSAPublicKey(y, p, q, g); | 
|  |             } else { | 
|  |                 pub = new DSAPublicKeyImpl(y, p, q, g); | 
|  |             } | 
|  |             DSAPrivateKey priv = new DSAPrivateKey(x, p, q, g); | 
|  |  | 
|  |             KeyPair pair = new KeyPair(pub, priv); | 
|  |             return pair; | 
|  |         } catch (InvalidKeyException e) { | 
|  |             throw new ProviderException(e); | 
|  |         } | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     private BigInteger generateX(SecureRandom random, BigInteger q) { | 
|  |         BigInteger x = null; | 
|  |         byte[] temp = new byte[qlen]; | 
|  |         while (true) { | 
|  |             random.nextBytes(temp); | 
|  |             x = new BigInteger(1, temp).mod(q); | 
|  |             if (x.signum() > 0 && (x.compareTo(q) < 0)) { | 
|  |                 return x; | 
|  |             } | 
|  |         } | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     BigInteger generateY(BigInteger x, BigInteger p, BigInteger g) { | 
|  |         BigInteger y = g.modPow(x, p); | 
|  |         return y; | 
|  |     } | 
|  |  | 
|  |     public static final class Current extends DSAKeyPairGenerator { | 
|  |         public Current() { | 
|  |             super(DEF_DSA_KEY_SIZE); | 
|  |         } | 
|  |     } | 
|  |  | 
|  |     public static final class Legacy extends DSAKeyPairGenerator | 
|  |         implements java.security.interfaces.DSAKeyPairGenerator { | 
|  |  | 
|  |         public Legacy() { | 
|  |             super(1024); | 
|  |         } | 
|  |  | 
|  |          | 
|  |  | 
|  |  | 
|  |          */ | 
|  |         @Override | 
|  |         public void initialize(int modlen, boolean genParams, | 
|  |             SecureRandom random) throws InvalidParameterException { | 
|  |             if (genParams) { | 
|  |                 super.init(modlen, random, true); | 
|  |             } else { | 
|  |                 DSAParameterSpec cachedParams = | 
|  |                     ParameterCache.getCachedDSAParameterSpec(modlen, | 
|  |                         getDefDSASubprimeSize(modlen)); | 
|  |                 if (cachedParams == null) { | 
|  |                     throw new InvalidParameterException | 
|  |                         ("No precomputed parameters for requested modulus" + | 
|  |                          " size available"); | 
|  |                 } | 
|  |                 super.init(cachedParams, random, false); | 
|  |             } | 
|  |         } | 
|  |  | 
|  |          | 
|  |  | 
|  |  | 
|  |  | 
|  |          */ | 
|  |         @Override | 
|  |         public void initialize(DSAParams params, SecureRandom random) | 
|  |             throws InvalidParameterException { | 
|  |             if (params == null) { | 
|  |                 throw new InvalidParameterException("Params must not be null"); | 
|  |              } | 
|  |              DSAParameterSpec spec = new DSAParameterSpec | 
|  |                  (params.getP(), params.getQ(), params.getG()); | 
|  |              super.init(spec, random, false); | 
|  |         } | 
|  |     } | 
|  | } |