1package org.bouncycastle.crypto.generators; 2 3import org.bouncycastle.crypto.AsymmetricCipherKeyPair; 4import org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator; 5import org.bouncycastle.crypto.KeyGenerationParameters; 6import org.bouncycastle.crypto.params.RSAKeyGenerationParameters; 7import org.bouncycastle.crypto.params.RSAKeyParameters; 8import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters; 9 10import java.math.BigInteger; 11 12/** 13 * an RSA key pair generator. 14 */ 15public class RSAKeyPairGenerator 16 implements AsymmetricCipherKeyPairGenerator 17{ 18 private static final BigInteger ONE = BigInteger.valueOf(1); 19 20 private RSAKeyGenerationParameters param; 21 22 public void init( 23 KeyGenerationParameters param) 24 { 25 this.param = (RSAKeyGenerationParameters)param; 26 } 27 28 public AsymmetricCipherKeyPair generateKeyPair() 29 { 30 BigInteger p, q, n, d, e, pSub1, qSub1, phi; 31 32 // 33 // p and q values should have a length of half the strength in bits 34 // 35 int strength = param.getStrength(); 36 int pbitlength = (strength + 1) / 2; 37 int qbitlength = strength - pbitlength; 38 int mindiffbits = strength / 3; 39 40 e = param.getPublicExponent(); 41 42 // TODO Consider generating safe primes for p, q (see DHParametersHelper.generateSafePrimes) 43 // (then p-1 and q-1 will not consist of only small factors - see "Pollard's algorithm") 44 45 // 46 // generate p, prime and (p-1) relatively prime to e 47 // 48 for (;;) 49 { 50 p = new BigInteger(pbitlength, 1, param.getRandom()); 51 52 if (p.mod(e).equals(ONE)) 53 { 54 continue; 55 } 56 57 if (!p.isProbablePrime(param.getCertainty())) 58 { 59 continue; 60 } 61 62 if (e.gcd(p.subtract(ONE)).equals(ONE)) 63 { 64 break; 65 } 66 } 67 68 // 69 // generate a modulus of the required length 70 // 71 for (;;) 72 { 73 // generate q, prime and (q-1) relatively prime to e, 74 // and not equal to p 75 // 76 for (;;) 77 { 78 q = new BigInteger(qbitlength, 1, param.getRandom()); 79 80 if (q.subtract(p).abs().bitLength() < mindiffbits) 81 { 82 continue; 83 } 84 85 if (q.mod(e).equals(ONE)) 86 { 87 continue; 88 } 89 90 if (!q.isProbablePrime(param.getCertainty())) 91 { 92 continue; 93 } 94 95 if (e.gcd(q.subtract(ONE)).equals(ONE)) 96 { 97 break; 98 } 99 } 100 101 // 102 // calculate the modulus 103 // 104 n = p.multiply(q); 105 106 if (n.bitLength() == param.getStrength()) 107 { 108 break; 109 } 110 111 // 112 // if we get here our primes aren't big enough, make the largest 113 // of the two p and try again 114 // 115 p = p.max(q); 116 } 117 118 if (p.compareTo(q) < 0) 119 { 120 phi = p; 121 p = q; 122 q = phi; 123 } 124 125 pSub1 = p.subtract(ONE); 126 qSub1 = q.subtract(ONE); 127 phi = pSub1.multiply(qSub1); 128 129 // 130 // calculate the private exponent 131 // 132 d = e.modInverse(phi); 133 134 // 135 // calculate the CRT factors 136 // 137 BigInteger dP, dQ, qInv; 138 139 dP = d.remainder(pSub1); 140 dQ = d.remainder(qSub1); 141 qInv = q.modInverse(p); 142 143 return new AsymmetricCipherKeyPair( 144 new RSAKeyParameters(false, n, e), 145 new RSAPrivateCrtKeyParameters(n, e, d, p, q, dP, dQ, qInv)); 146 } 147} 148