diff options
Diffstat (limited to 'libraries/spongycastle/core/src/main/java/org/spongycastle/crypto/generators/RSAKeyPairGenerator.java')
-rw-r--r-- | libraries/spongycastle/core/src/main/java/org/spongycastle/crypto/generators/RSAKeyPairGenerator.java | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/libraries/spongycastle/core/src/main/java/org/spongycastle/crypto/generators/RSAKeyPairGenerator.java b/libraries/spongycastle/core/src/main/java/org/spongycastle/crypto/generators/RSAKeyPairGenerator.java new file mode 100644 index 000000000..0708ec729 --- /dev/null +++ b/libraries/spongycastle/core/src/main/java/org/spongycastle/crypto/generators/RSAKeyPairGenerator.java @@ -0,0 +1,147 @@ +package org.spongycastle.crypto.generators; + +import org.spongycastle.crypto.AsymmetricCipherKeyPair; +import org.spongycastle.crypto.AsymmetricCipherKeyPairGenerator; +import org.spongycastle.crypto.KeyGenerationParameters; +import org.spongycastle.crypto.params.RSAKeyGenerationParameters; +import org.spongycastle.crypto.params.RSAKeyParameters; +import org.spongycastle.crypto.params.RSAPrivateCrtKeyParameters; + +import java.math.BigInteger; + +/** + * an RSA key pair generator. + */ +public class RSAKeyPairGenerator + implements AsymmetricCipherKeyPairGenerator +{ + private static final BigInteger ONE = BigInteger.valueOf(1); + + private RSAKeyGenerationParameters param; + + public void init( + KeyGenerationParameters param) + { + this.param = (RSAKeyGenerationParameters)param; + } + + public AsymmetricCipherKeyPair generateKeyPair() + { + BigInteger p, q, n, d, e, pSub1, qSub1, phi; + + // + // p and q values should have a length of half the strength in bits + // + int strength = param.getStrength(); + int pbitlength = (strength + 1) / 2; + int qbitlength = strength - pbitlength; + int mindiffbits = strength / 3; + + e = param.getPublicExponent(); + + // TODO Consider generating safe primes for p, q (see DHParametersHelper.generateSafePrimes) + // (then p-1 and q-1 will not consist of only small factors - see "Pollard's algorithm") + + // + // generate p, prime and (p-1) relatively prime to e + // + for (;;) + { + p = new BigInteger(pbitlength, 1, param.getRandom()); + + if (p.mod(e).equals(ONE)) + { + continue; + } + + if (!p.isProbablePrime(param.getCertainty())) + { + continue; + } + + if (e.gcd(p.subtract(ONE)).equals(ONE)) + { + break; + } + } + + // + // generate a modulus of the required length + // + for (;;) + { + // generate q, prime and (q-1) relatively prime to e, + // and not equal to p + // + for (;;) + { + q = new BigInteger(qbitlength, 1, param.getRandom()); + + if (q.subtract(p).abs().bitLength() < mindiffbits) + { + continue; + } + + if (q.mod(e).equals(ONE)) + { + continue; + } + + if (!q.isProbablePrime(param.getCertainty())) + { + continue; + } + + if (e.gcd(q.subtract(ONE)).equals(ONE)) + { + break; + } + } + + // + // calculate the modulus + // + n = p.multiply(q); + + if (n.bitLength() == param.getStrength()) + { + break; + } + + // + // if we get here our primes aren't big enough, make the largest + // of the two p and try again + // + p = p.max(q); + } + + if (p.compareTo(q) < 0) + { + phi = p; + p = q; + q = phi; + } + + pSub1 = p.subtract(ONE); + qSub1 = q.subtract(ONE); + phi = pSub1.multiply(qSub1); + + // + // calculate the private exponent + // + d = e.modInverse(phi); + + // + // calculate the CRT factors + // + BigInteger dP, dQ, qInv; + + dP = d.remainder(pSub1); + dQ = d.remainder(qSub1); + qInv = q.modInverse(p); + + return new AsymmetricCipherKeyPair( + new RSAKeyParameters(false, n, e), + new RSAPrivateCrtKeyParameters(n, e, d, p, q, dP, dQ, qInv)); + } +} |