问题
I'm trying to execute code to perform the Diffie-Hellman key exchange. I sourced the code from an example online (forget where now). I had to import the bouncycastle.jar, which I assumed worked up until execution.
my code:
package testproject;
import java.math.BigInteger;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.MessageDigest;
import java.security.SecureRandom;
import java.security.Security;
import javax.crypto.KeyAgreement;
import javax.crypto.spec.DHParameterSpec;
public class KeyGen {
private static BigInteger g512 = new BigInteger("1234567890", 16);
//generates a random, non-negative integer for Base
private static BigInteger p512 = new BigInteger("1234567890", 16);
//generates a random, non-negative integer for Prime
public static void main(String[] args) throws Exception {
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
DHParameterSpec dhParams = new DHParameterSpec(p512, g512);
//Specify parameters to use for the algorithm
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DH", "BC");
//Define specific algorithm to use "diffie-hellman", with provider "bc"
keyGen.initialize(dhParams, new SecureRandom());
//initialize with parameters & secure random seed
KeyAgreement aKeyAgree = KeyAgreement.getInstance("DH", "BC");
//define algorithm for A's key agreement
KeyPair aPair = keyGen.generateKeyPair();
//generate keyPair for A
KeyAgreement bKeyAgree = KeyAgreement.getInstance("DH", "BC");
//define algorithm for B's key agreement
KeyPair bPair = keyGen.generateKeyPair();
//generate keyPair for B
aKeyAgree.init(aPair.getPrivate());
//initialize A's keyAgreement with A's private key
bKeyAgree.init(bPair.getPrivate());
//initialize B's keyAgreement with B's private key
aKeyAgree.doPhase(bPair.getPublic(), true);
//do last phase of A's keyAgreement with B's public key
bKeyAgree.doPhase(aPair.getPublic(), true);
//do last phase of B's keyAgreement with A's public key
MessageDigest hash = MessageDigest.getInstance("SHA1", "BC");
System.out.println(new String(hash.digest(aKeyAgree.generateSecret())));
//generate secret key for A, hash it.
System.out.println(new String(hash.digest(bKeyAgree.generateSecret())));
//generate secret key for B, hash it.
}
}
This is the line causing the problem:
KeyPair aPair = keyGen.generateKeyPair();
I'm confused as to what the error is, as I've found each of the methods it's returning 'unknown source' for.
Any light shed on this would be much appreciated.
Continued(Edit): Java - Diffie-Hellman Encryption - Wrong Output
回答1:
You already preferred bouncycastle version. But I implemented a little helloworld version of it for learning purposes. Maybe it can be helpful for those who simply wants to use Diffie-Hellman in pure Java without dependencies:
// 1. ------------------------------------------------------------------
// This is Alice and Bob
// Alice and Bob want to chat securely. But how?
final Person alice = new Person();
final Person bob = new Person();
// ? ?
//
// O O
// /|\ /|\
// / \ / \
//
// ALICE BOB
// 2. ------------------------------------------------------------------
// Alice and Bob generate public and private keys.
alice.generateKeys();
bob.generateKeys();
//
// O O
// /|\ /|\
// / \ / \
//
// ALICE BOB
// _ PUBLIC KEY _ PUBLIC KEY
// _ PRIVATE KEY _ PRIVATE KEY
// 3. ------------------------------------------------------------------
// Alice and Bob exchange public keys with each other.
alice.receivePublicKeyFrom(bob);
bob.receivePublicKeyFrom(alice);
//
// O O
// /|\ /|\
// / \ / \
//
// ALICE BOB
// + public key + public key
// + private key + private key
// _ PUBLIC KEY <-------------------------> _ PUBLIC KEY
// 4. ------------------------------------------------------------------
// Alice generates common secret key via using her private key and Bob's public key.
// Bob generates common secret key via using his private key and Alice's public key.
// Both secret keys are equal without TRANSFERRING. This is the magic of Diffie-Helman algorithm.
alice.generateCommonSecretKey();
bob.generateCommonSecretKey();
//
// O O
// /|\ /|\
// / \ / \
//
// ALICE BOB
// + public key + public key
// + private key + private key
// + public key + public key
// _ SECRET KEY _ SECRET KEY
// 5. ------------------------------------------------------------------
// Alice encrypts message using the secret key and sends to Bob
alice.encryptAndSendMessage("Bob! Guess Who I am.", bob);
//
// O O
// /|\ []--------------------------------> /|\
// / \ / \
//
// ALICE BOB
// + public key + public key
// + private key + private key
// + public key + public key
// + secret key + secret key
// + message _ MESSAGE
// 6. ------------------------------------------------------------------
// Bob receives the important message and decrypts with secret key.
bob.whisperTheSecretMessage();
//
// O ((( ((( ((( \O/ )))
// /|\ |
// / \ / \
//
// ALICE BOB
// + public key + public key
// + private key + private key
// + public key + public key
// + secret key + secret key
// + message + message
https://github.com/firatkucuk/diffie-hellman-helloworld
回答2:
This comment is simply wrong:
private static BigInteger g512 = new BigInteger("1234567890", 16);
//generates a random, non-negative integer for Base
All you are doing there is creating the number 0x1234567890
every time. There is nothing random about it.
It looks like you copied from http://www.java2s.com/Tutorial/Java/0490__Security/DiffieHellmanKeyAgreement.htm. As this answer agrees, the code there does not make sense.
You could try the actual key exchange example on that site.
回答3:
Instead of the code:
private static BigInteger g512 = new BigInteger("1234567890", 16);
//generates a random, non-negative integer for Base
private static BigInteger p512 = new BigInteger("1234567890", 16);
//generates a random, non-negative integer for Prime
you need to use:
// The base used with the SKIP 1024 bit modulus
private static final BigInteger g512 = BigInteger.valueOf(2);
// The 1024 bit Diffie-Hellman modulus values used by SKIP
private static final byte skip1024ModulusBytes[] = { (byte) 0xF4,
(byte) 0x88, (byte) 0xFD, (byte) 0x58, (byte) 0x4E, (byte) 0x49,
(byte) 0xDB, (byte) 0xCD, (byte) 0x20, (byte) 0xB4, (byte) 0x9D,
(byte) 0xE4, (byte) 0x91, (byte) 0x07, (byte) 0x36, (byte) 0x6B,
(byte) 0x33, (byte) 0x6C, (byte) 0x38, (byte) 0x0D, (byte) 0x45,
(byte) 0x1D, (byte) 0x0F, (byte) 0x7C, (byte) 0x88, (byte) 0xB3,
(byte) 0x1C, (byte) 0x7C, (byte) 0x5B, (byte) 0x2D, (byte) 0x8E,
(byte) 0xF6, (byte) 0xF3, (byte) 0xC9, (byte) 0x23, (byte) 0xC0,
(byte) 0x43, (byte) 0xF0, (byte) 0xA5, (byte) 0x5B, (byte) 0x18,
(byte) 0x8D, (byte) 0x8E, (byte) 0xBB, (byte) 0x55, (byte) 0x8C,
(byte) 0xB8, (byte) 0x5D, (byte) 0x38, (byte) 0xD3, (byte) 0x34,
(byte) 0xFD, (byte) 0x7C, (byte) 0x17, (byte) 0x57, (byte) 0x43,
(byte) 0xA3, (byte) 0x1D, (byte) 0x18, (byte) 0x6C, (byte) 0xDE,
(byte) 0x33, (byte) 0x21, (byte) 0x2C, (byte) 0xB5, (byte) 0x2A,
(byte) 0xFF, (byte) 0x3C, (byte) 0xE1, (byte) 0xB1, (byte) 0x29,
(byte) 0x40, (byte) 0x18, (byte) 0x11, (byte) 0x8D, (byte) 0x7C,
(byte) 0x84, (byte) 0xA7, (byte) 0x0A, (byte) 0x72, (byte) 0xD6,
(byte) 0x86, (byte) 0xC4, (byte) 0x03, (byte) 0x19, (byte) 0xC8,
(byte) 0x07, (byte) 0x29, (byte) 0x7A, (byte) 0xCA, (byte) 0x95,
(byte) 0x0C, (byte) 0xD9, (byte) 0x96, (byte) 0x9F, (byte) 0xAB,
(byte) 0xD0, (byte) 0x0A, (byte) 0x50, (byte) 0x9B, (byte) 0x02,
(byte) 0x46, (byte) 0xD3, (byte) 0x08, (byte) 0x3D, (byte) 0x66,
(byte) 0xA4, (byte) 0x5D, (byte) 0x41, (byte) 0x9F, (byte) 0x9C,
(byte) 0x7C, (byte) 0xBD, (byte) 0x89, (byte) 0x4B, (byte) 0x22,
(byte) 0x19, (byte) 0x26, (byte) 0xBA, (byte) 0xAB, (byte) 0xA2,
(byte) 0x5E, (byte) 0xC3, (byte) 0x55, (byte) 0xE9, (byte) 0x2F,
(byte) 0x78, (byte) 0xC7 };
// The SKIP 1024 bit modulus
private static final BigInteger p512 = new BigInteger(1, skip1024ModulusBytes);
来源:https://stackoverflow.com/questions/22479508/java-diffie-hellman-key-exchange