I'm working on implementing a library that uses DH for symmetric key agreement. The specification requires that the Second Oakley Group - http://www.ietf.org/rfc/rfc2409.txt (Section 6.2) and the 14th Oakley Group - http://www.ietf.org/rfc/rfc3526.txt (Section 3.0) be available. Using JDK1.7.0_03 with the SunJCE provider I am able to work with the the Second Oakley Group but using the 14th Oakley Group I get the exception
Exception in thread "main" java.security.InvalidAlgorithmParameterException: Prime size must be multiple of 64, and can only range from 512 to 1024 (inclusive)
at com.sun.crypto.provider.DHKeyPairGenerator.initialize(DHKeyPairGenerator.java:120)
at java.security.KeyPairGenerator$Delegate.initialize(KeyPairGenerator.java:651)
at java.security.KeyPairGenerator.initialize(KeyPairGenerator.java:400)
at me.grm.projects.ssj.common.DHExample.main(DHExample.java:64)
The test code -
import java.math.BigInteger;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import javax.crypto.KeyAgreement;
import javax.crypto.spec.DHParameterSpec;
public class DHExample
{
static
{
// Second Oakley Group - http://www.ietf.org/rfc/rfc2409.txt )(Section 6.2)
final String pHexString = "FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1"
+ "29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD"
+ "EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245"
+ "E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED"
+ "EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE65381"
+ "FFFFFFFF FFFFFFFF";
final BigInteger p = new BigInteger(pHexString.replaceAll(" ", ""), 16);
final BigInteger g = new BigInteger("2");
group2ParameterSpec = new DHParameterSpec(p, g, 1024);
}
static
{
// 14th Oakley Group - http://www.ietf.org/rfc/rfc3526.txt (Section 3.0)
final String pHexString = "FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1"
+ "29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD"
+ "EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245"
+ "E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED"
+ "EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D"
+ "C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F"
+ "83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D"
+ "670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B"
+ "E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9"
+ "DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510"
+ "15728E5A 8AACAA68 FFFFFFFF FFFFFFFF";
final BigInteger p = new BigInteger(
pHexString.replaceAll(" ", ""), 16);
final BigInteger g = new BigInteger("2");
group14ParameterSpec = new DHParameterSpec(p, g, 2048);
}
private static final DHParameterSpec group2ParameterSpec;
private static final DHParameterSpec group14ParameterSpec;
//
public static void main(String[] args) throws Exception
{
final String PROVIDER = "SunJCE";
final DHParameterSpec[] dhParameterSpecs =
{
group2ParameterSpec, group14ParameterSpec
};
for (DHParameterSpec dhParameterSpec : dhParameterSpecs)
{
System.out.println("p : " + dhParameterSpec.getP().toString(16));
System.out.println("g : " + dhParameterSpec.getG().toString(16));
System.out.println("l : " + dhParameterSpec.getL());
// Alice
KeyPairGenerator aliceDHKeyPairGenerator = KeyPairGenerator.getInstance("DH", PROVIDER);
aliceDHKeyPairGenerator.initialize(dhParameterSpec); // Exception thrown here!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
KeyPair aliceDHKeyPair = aliceDHKeyPairGenerator.generateKeyPair();
// Bob
KeyPairGenerator bobDHKeyPairGenerator = KeyPairGenerator.getInstance("DH", PROVIDER);
bobDHKeyPairGenerator.initialize(dhParameterSpec);
KeyPair bobDHKeyPair = bobDHKeyPairGenerator.generateKeyPair();
// Alice
{
final KeyAgreement ka = KeyAgreement.getInstance("DH", PROVIDER);
ka.init(aliceDHKeyPair.getPrivate());
ka.doPhase(bobDHKeyPair.getPublic(), true);
final byte[] sharedSecret = ka.generateSecret();
System.out.println("Alice's shared secret : " + new BigInteger(sharedSecret).toString(16));
}
// Bob
{
final KeyAgreement ka = KeyAgreement.getInstance("DH", PROVIDER);
ka.init(bobDHKeyPair.getPrivate());
ka.doPhase(aliceDHKeyPair.getPublic(), true);
final byte[] sharedSecret = ka.generateSecret();
System.out.println("Bob's shared secret : " + new BigInteger(sharedSecret).toString(16));
}
}
}
}
If I switch to using BouncyCastle ( crypto-145 ) provider I get a totally different exception -
Exception in thread "main" java.lang.IllegalArgumentException: when l value specified, it must be less than bitlength(p)
at org.bouncycastle.crypto.params.DHParameters.<init>(Unknown Source)
at org.bouncycastle.crypto.params.DHParameters.<init>(Unknown Source)
at org.bouncycastle.jce.provider.JDKKeyPairGenerator$DH.initialize(Unknown Source)
at java.security.KeyPairGenerator.initialize(KeyPairGenerator.java:400)
at me.grm.projects.ssj.common.DHExample.main(DHExample.java:64)
for the first DH key.
So what am I missing? I definitely do have the "Unlimited strength" files installed and I get exactly the same problem with 1.7.0_01 and 1.6.0_31 .
Any thoughts?
Edited by: sabre150 on Mar 12, 2012 9:58 PM
I can get rid of the exception when using BC by not specifying the number of bits (specifying 0 does this). I don't really want to use BC - I'm trying to minimise the number of external libraries.