I came across a problem with GNU Crypto that causes Diffie-Hellman key
exchange to fail when running on IcedTea.  We're doing what looks to
me like an unnecessary check in DiffieHellmanImpl.engineDoPhase()
which can fail in some circumstances, and this is triggered when
running in IcedTea.  The code runs correctly on Sun's Java 1.7, not on
the IcedTea version of Java 1.7, which uses GNU Crypto.

With IcedTea and Classpath we get:

Exception in thread "main" java.security.InvalidKeyException: Incompatible key
        at 
gnu.javax.crypto.jce.DiffieHellmanImpl.engineDoPhase(DiffieHellmanImpl.java:99)
        at javax.crypto.KeyAgreement.doPhase(KeyAgreement.java:224)
        at Tt.main(Tt.java:35)

Here's my patch:

2007-08-03  Andrew Haley  <[EMAIL PROTECTED]>

        * jce/gnu/javax/crypto/jce/DiffieHellmanImpl.java (engineDoPhase):
        Don't check the length of q.

--- gnu/javax/crypto/jce/DiffieHellmanImpl.java~        2007-07-23 
14:15:36.000000000 +0100
+++ gnu/javax/crypto/jce/DiffieHellmanImpl.java 2007-08-03 17:49:09.000000000 
+0100
@@ -94,8 +94,7 @@
     DHPublicKey pub = (DHPublicKey) incoming;
     DHParameterSpec s1 = key.getParams();
     DHParameterSpec s2 = pub.getParams();
-    if (! s1.getG().equals(s2.getG()) || ! s1.getP().equals(s2.getP())
-        || s1.getL() != s2.getL())
+    if (! s1.getG().equals(s2.getG()) || ! s1.getP().equals(s2.getP()))
       throw new InvalidKeyException("Incompatible key");
     if (! lastPhase)
       throw new IllegalArgumentException(


The IcedTea test case (that will only run on IcedTea) looks like this:

package sun.security.ssl;
import java.security.*;
import java.math.*;

public class CrypTest
{
  void test()
  {
    SecureRandom random = new SecureRandom();
    DHCrypt dh = new DHCrypt(768, random);
    byte bytes[] = new byte[96];
    random.nextBytes(bytes);
    System.out.println(dh.getAgreedSecret(new BigInteger(bytes)));
  }

  public static void main(String[] argv)
  {
    new CrypTest().test();
  }
}


A generic pure Java test case is:

import java.security.*;
import java.math.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import javax.crypto.interfaces.*;

public class Tt
{

  public static void main(String[] argv)
    throws Throwable
  {
    SecureRandom random = new SecureRandom();
    byte bytes[] = new byte[96];
    random.nextBytes(bytes);
    
    KeyFactory factory = KeyFactory.getInstance("DH");
 
    KeyPairGenerator clientKpairGen = KeyPairGenerator.getInstance("DH");
    clientKpairGen.initialize(768, random);
    KeyPair clientKpair = clientKpairGen.generateKeyPair();

    DHPublicKey k1 = (DHPublicKey)clientKpair.getPublic();
    DHParameterSpec spec = (DHParameterSpec)k1.getParams();

    DHPublicKeySpec publicKeySpec
      = new DHPublicKeySpec(new BigInteger(bytes), spec.getP(), spec.getG());
    DHPublicKey k2 = (DHPublicKey)factory.generatePublic(publicKeySpec);

    KeyAgreement clientKeyAgree = KeyAgreement.getInstance("DH");
    clientKeyAgree.init(clientKpair.getPrivate());
    clientKeyAgree.doPhase(k2, true);

    System.out.println(spec);
  }
}

Andrew.




Reply via email to