8216012: Infinite loop in RSA KeyPairGenerator

Valerie Peng valerie.peng at oracle.com
Tue Dec 3 00:40:38 UTC 2019


Hi Masanori Yano,

I can help sponsoring this fix. However, as it's a P4, it may be  
targeted to 15 depending on the available cycles.

Are you a contributor for OpenJDK?

If not, please see http://openjdk.java.net/contribute/ for the process.

Thanks,
Valerie
On 10/8/2019 8:10 PM, yano-masanori at fujitsu.com wrote:
> Hello.
>
> I would like to contribute for JDK-8216012.
>
> The cause of this problem is RSAKeyPairGenerator that doesn't check
> the public exponent even though the algorithm of rsa key generation
> can use only odd exponent number.
>
> To generate a KeyPair, the RSAKeyPairGenerator finds two random primes
> P and Q, and calculate Phi = (P - 1) * (Q - 1). If Phi is not relative
> prime to exponent, RSAKeyPairGenerator retry from the first.
>
> The value of Phi must be an even number because P and Q are odd numbers.
> If exponent is an even number, the greatest common divisor cannot
> be 1 because one of common divisors is 2 which is bigger than 1.
> Therefore, generateKeyPair() method of RSAKeyPairGenerator cannot exit
> the retrying loop.
>
> To solve this problem, I propose to check whether the public exponent
> is even number.
>
> Please sponsor the following change.
>
> diff --git a/src/java.base/share/classes/sun/security/rsa/RSAKeyPairGenerator.java b/src/java.base/share/classes/sun/security/rsa/RSAKeyPairGenerator.java
> --- a/src/java.base/share/classes/sun/security/rsa/RSAKeyPairGenerator.java
> +++ b/src/java.base/share/classes/sun/security/rsa/RSAKeyPairGenerator.java
> @@ -96,6 +96,10 @@
>                   throw new InvalidAlgorithmParameterException
>                           ("Public exponent must be 3 or larger");
>               }
> +            if (!tmpPublicExponent.testBit(0)) {
> +                throw new InvalidAlgorithmParameterException
> +                        ("Public exponent must be an odd number");
> +            }
>               if (tmpPublicExponent.bitLength() > tmpKeySize) {
>                   throw new InvalidAlgorithmParameterException
>                           ("Public exponent must be smaller than key size");
> diff --git a/test/jdk/sun/security/rsa/TestKeyPairGeneratorExponent.java b/test/jdk/sun/security/rsa/TestKeyPairGeneratorExponent.java
> new file mode 100644
> --- /dev/null
> +++ b/test/jdk/sun/security/rsa/TestKeyPairGeneratorExponent.java
> @@ -0,0 +1,65 @@
> +import java.math.BigInteger;
> +
> +import java.security.*;
> +import java.security.interfaces.*;
> +import java.security.spec.*;
> +
> +/**
> + * @test
> + * @bug 8216012
> + * @summary Tests the RSA public key exponent for KeyPairGenerator
> + * @run main/timeout=60 TestKeyPairGeneratorExponent
> + */
> +public class TestKeyPairGeneratorExponent {
> +    private static int keyLen = 512;
> +
> +    private static BigInteger[] validExponents = new BigInteger[] {
> +        RSAKeyGenParameterSpec.F0,
> +        RSAKeyGenParameterSpec.F4,
> +        // Since 512-bit exponent is larger than  modulus, fails in RSAPublicKeyImpl.checkExponentRange().
> +        BigInteger.ONE.shiftLeft(keyLen - 1).subtract(BigInteger.ONE)
> +    };
> +
> +    private static BigInteger[] invalidExponents = new BigInteger[] {
> +        BigInteger.valueOf(-1),
> +        BigInteger.ZERO,
> +        BigInteger.ONE,
> +        // 8216012: An even number causes infinite loop.
> +        BigInteger.valueOf(4),
> +        BigInteger.ONE.shiftLeft(keyLen)
> +    };
> +
> +    public static void testValidExponents(KeyPairGenerator kpg, BigInteger exponent) {
> +        try {
> +            kpg.initialize(new RSAKeyGenParameterSpec(keyLen, exponent));
> +            kpg.generateKeyPair();
> +        } catch(InvalidAlgorithmParameterException iape){
> +            throw new RuntimeException("Unexpected Exception: " + iape);
> +        }
> +    }
> +
> +    public static void testInvalidExponents(KeyPairGenerator kpg, BigInteger exponent) {
> +        try {
> +            kpg.initialize(new RSAKeyGenParameterSpec(keyLen, exponent));
> +            kpg.generateKeyPair();
> +            throw new RuntimeException("Expected InvalidAlgorithmParameterException was not thrown.");
> +        } catch(InvalidAlgorithmParameterException iape){
> +            // Expected InvalidAlgorithmParameterException was thrown.OK
> +        }
> +    }
> +
> +    public static void main(String[] args) throws Exception {
> +        Provider provider = Security.getProvider("SunRsaSign");
> +        KeyPairGenerator kpg;
> +
> +        for(BigInteger validExponent : validExponents) {
> +            kpg = KeyPairGenerator.getInstance("RSA", provider);
> +            testValidExponents(kpg, validExponent);
> +        }
> +
> +        for(BigInteger invalidExponent : invalidExponents) {
> +            kpg = KeyPairGenerator.getInstance("RSA", provider);
> +            testInvalidExponents(kpg, invalidExponent);
> +        }
> +    }
> +}
>
> Regards,
> Masanori Yano


More information about the security-dev mailing list