Clearner88
Clearner88

Reputation: 101

Diffie Hellman Key Exchange

i am currently trying to do a diffie hellman key exchange using the java crypto libray, I have succeeded in finding a safe prime and also a generator for it. However i seem to have trouble creating a DH key with the values that i have found. It gives me the following 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(Unknown Source) at java.security.KeyPairGenerator.initialize(Unknown Source) at DH.createSpecificKey(DH.java:35) at DH.main(DH.java:166)

As you all know, in cryptography we cannot let our primes be small. How do i cater my safe primes and generator to fit the criteria of the DH library.

Below is my source code

public static void createKey()throws Exception
{
    KeyPairGenerator kpg = KeyPairGenerator.getInstance("DiffieHellman");
    kpg.initialize(512);
    KeyPair kp = kpg.generateKeyPair();
    KeyFactory kfactory = KeyFactory.getInstance("DiffieHellman");

    DHPublicKeySpec kspec = (DHPublicKeySpec) kfactory.getKeySpec(kp.getPublic(), DHPublicKeySpec.class);

}

public static void createSpecificKey(BigInteger p,BigInteger g)throws Exception
{
    KeyPairGenerator kpg = KeyPairGenerator.getInstance("DiffieHellman");
    DHParameterSpec param = new DHParameterSpec(p,g);
    kpg.initialize(param);

    KeyPair kp = kpg.generateKeyPair();

    KeyFactory kfactory = KeyFactory.getInstance("DiffieHellman");

    DHPublicKeySpec kspec = (DHPublicKeySpec) kfactory.getKeySpec(kp.getPublic(), DHPublicKeySpec.class);

}


static boolean isPrime(long n)
{
    if (n%2 == 0)
    {
        return false;
    }

    for(int i = 3 ; i*i<=n;i+=2)
    {
        if(n%i==0)
            return false;
    }
    return true;
}


public static void main(String [] args) throws Exception
{

    Random randomGenerator = new Random();

    long pValue = randomGenerator.nextInt(1000000);
    long gValue = randomGenerator.nextInt(100000);
    long correctPValue;

    boolean checkPrime = isPrime(pValue);
    System.out.println("the number generated is "+pValue);
    System.out.println(checkPrime);

    while(checkPrime == false)

    {
        long pValue2 = randomGenerator.nextInt(1000000);
        boolean checkPrimeInLoop = isPrime(pValue2);
        //System.out.println("value in loop is "+pValue2);
        if(checkPrimeInLoop == true)
        {
            pValue=pValue2;
            break;
        }
    }


    long checkSP = (pValue*2)+1;
    boolean checkSafePrime = isPrime(checkSP);
    //System.out.println(checkSafePrime);
    while(checkSafePrime==false)
    {
        long pValue3=randomGenerator.nextInt(1000000);
        boolean checkPrimeInLoop = isPrime(pValue3);
        long pValue5=(pValue3*2)+1;
        //boolean checkSafePrimeInLoop = isPrime(pValue4);
        boolean checkSafePrime2InLoop = isPrime(pValue5);

        if(checkSafePrime2InLoop == true && checkPrimeInLoop == true)
        {
            pValue=pValue3;
            break;
        }

    }

    System.out.println("the safe prime is"+pValue);//safe prime

    while(gValue>pValue)
    {
        long gValue2=randomGenerator.nextInt(100000);

        if(gValue2<pValue)
        {
            gValue=gValue2;
            break;
        }
    }

    long getDivisor = (pValue-1)/2;
    BigInteger bi1,bi2,bi3,bi4;

    bi1=BigInteger.valueOf(getDivisor);

    bi2 = BigInteger.valueOf(pValue);

    bi3 = BigInteger.valueOf(gValue);

    bi4= bi3.modPow(bi1,bi2);

    long calculatedValue = bi4.longValue();


    while(calculatedValue == 1)
    {
        long gValue3=randomGenerator.nextInt(100000);
        long getDivisorInLoop = (pValue-1)/2;
        BigInteger bi5,bi6,bi7,bi8;

        bi5=BigInteger.valueOf(getDivisorInLoop);

        bi6 = BigInteger.valueOf(pValue);

        bi7 = BigInteger.valueOf(gValue3);

        bi8= bi7.modPow(bi5,bi6);

        long calculatedValueInLoop = bi8.longValue();
        System.out.println(calculatedValueInLoop);
        if(calculatedValueInLoop!=1)
        {
            gValue=gValue3;
            break;
        }
    }

    BigInteger generatorValue,primeValue;

    generatorValue = BigInteger.valueOf(gValue);
    primeValue = BigInteger.valueOf(pValue);

    createKey();

    int bitLength=512;

    createSpecificKey(generatorValue,primeValue);


}

Hope you guys can help me with this. Thanks in advance!

Upvotes: 1

Views: 8094

Answers (2)

Kurt Huwig
Kurt Huwig

Reputation: 1023

I assume your question is why you can only create primes from 512 to 1024 bits, while 2048 bits is recommended?! The answer is simple: the 2048 bits do not relate to the primes, but to the size of the modulus which is the product of the two primes. Two primes with 1024 bit each will give you a modulus of 2048 bit. That's why it's safe to use 1024 bit for the DH primes.

Regarding your exception: Csaba Toth is right: your primes are too small and the way to generate them is suboptimal. Just use your createKey() method and you are fine.

Upvotes: 0

Csaba Toth
Csaba Toth

Reputation: 10729

You aim to go for 512 bit length: kpg.initialize(512);

You can generate p and g of such length like this:

int bitLength = 1024;
SecureRandom rnd = new SecureRandom();
BigInteger p = BigInteger.probablePrime(bitLength, rnd);
BigInteger g = BigInteger.probablePrime(bitLength, rnd);

The probablePrime probably use Rabin-Miller or Solovay-Strassen test which gives only 2^-100 chance (virtually no chance) that the resulting integer is not prime. Since 2002 a there's a polinomial-time algorithm called AKS (Agrawal–Kayal–Saxena) to test primes for 100% certainty (but I haven't seen it used so far, probably 2^-100 is good for anyone).

Upvotes: 2

Related Questions