2013-06-22 60 views
1

我目前正在尝试使用java crypto libray来做一个diffie hellman密钥交换,我已经成功地找到了一个安全素数,并且还为它生成了一个生成器。然而,我似乎无法创建一个DH键与我发现的值。这使我有以下异常在线程“主要” java.security.InvalidAlgorithmParameterExceptionDiffie Hellman密钥交换

例外:总理大小必须倍数64,只能从512到1024 com.sun.crypto(含) 。在DH.createSpecificKey处使用java.security.KeyPairGenerator.initialize(未知源) (DH.java :.DHKeyPairGenerator.initialize(DHKeyPairGenerator.java:120) at java.security.KeyPairGenerator $ Delegate.initialize(Unknown Source) 35) at DH.main(DH.java:166)

大家都知道,在密码学中我们不能让我们的素数很小。我如何满足我的安全素数和发生器以符合DH库的标准。

下面是我的源代码

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); 


} 

希望你们能帮助我与此有关。提前致谢!

回答

2

你的目标去512位长度: kpg.initialize(512);

可以生成p和这样长度的克这样的:

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

probablePrime可能使用拉宾 - 米勒或Solovay-Strassen的测试这只给出2^-100的机会(几乎没有机会),结果整数不是素数。自2002年以来,有一种称为AKS(Agrawal-Kayal-Saxena)的多项式时间算法来测试100%确定性的素数(但迄今为止我还没有看到它,可能2^-100对任何人都有好处)。

+0

您是否有理由在较低范围内搜索特定的素数?例外说:“素数大小必须是64的倍数,并且只能在512到1024之间(包含)” –

+0

看起来SSH(等)使用g = 2然后选择一个特殊素数为p使得q mod 12 = 5,然后2q + 1是素数。使用已知算法的某些子组进行高效攻击。 所以这个p和g的选择可能不安全。 – jettero

+0

@jettero我必须阅读这些内容,但是从我的RSA研究中,我认为g = 2是为了加速计算。然而,由于它是如此小的素数,需要非常小心地选择真正的q(和p)以维持该方案的安全性。这是我的两分钱。没有什么比两个长*素数更安全。与g = 2相比,计算将会更长。所以我想说,也许我们应该研究一些常见的实现方式,它们是如何实现的,可能与SSH相似。 –

0

我假设你的问题是为什么你只能创建从512到1024位的素数,而建议2048位?!答案很简单:2048位与素数不相关,但与模数的大小相关,后者是两个素数的乘积。每个1024位的两个素数会给你一个2048位的模数。这就是为什么使用1024位的DH素数是安全的。

关于你的例外情况:Csaba Toth是正确的:你的素数太小,产生它们的方式并不理想。只需使用你的createKey()方法,你很好。

相关问题