Java中的Diffie-Hellman密钥交换

我正在开发一个Java项目,涉及通过不安全的渠道发送敏感数据。 我需要知道如何使用其库在Java中实现Diffie Hellman密钥交换(DHKE)。 我知道关于它的所有加密理论所以不需要详细说明,我只需要一个非常基本的实现,所以我可以让2个程序共享一个密钥。 我从java2s.com获得了示例,但它并不完整:

import java.math.BigInteger; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.SecureRandom; import javax.crypto.spec.DHParameterSpec; import javax.crypto.spec.DHPublicKeySpec; public class Main { public final static int pValue = 47; public final static int gValue = 71; public final static int XaValue = 9; public final static int XbValue = 14; public static void main(String[] args) throws Exception { BigInteger p = new BigInteger(Integer.toString(pValue)); BigInteger g = new BigInteger(Integer.toString(gValue)); BigInteger Xa = new BigInteger(Integer.toString(XaValue)); BigInteger Xb = new BigInteger(Integer.toString(XbValue)); int bitLength = 512; // 512 bits SecureRandom rnd = new SecureRandom(); p = BigInteger.probablePrime(bitLength, rnd); g = BigInteger.probablePrime(bitLength, rnd); createSpecificKey(p, g); } 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); } } 

我怎么继续这个? 任何人都可以帮我完成剩余的代码吗?

官方Oracle Docs怎么样? 它们在那里显示代码中的DH密钥交换。

这是一个工作示例:

 static void main() { DH dh = new DH(); byte[] myPublicKey = dh.generatePublicKey(); /* Send myPublicKey to other party, and get hisPublicKey in return */ byte[] sharedKey = dh.computeSharedKey(hisPublicKey) /* sharedKey is now 'shared' between both parties */ } public class DH { private static final String TAG = "DH"; private KeyPair keyPair; private KeyAgreement keyAgree; public byte[] generatePublicKey() { DHParameterSpec dhParamSpec; try { dhParamSpec = new DHParameterSpec(P, G); Log.i(TAG, "P = " + P.toString(16)); KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("DiffieHellman"); keyPairGen.initialize(dhParamSpec); keyPair = keyPairGen.generateKeyPair(); Log.i(TAG, "Y = " + ((DHPublicKey) keyPair.getPublic()).getY().toString(16)); keyAgree = KeyAgreement.getInstance("DiffieHellman"); keyAgree.init(keyPair.getPrivate()); BigInteger pubKeyBI = ((DHPublicKey) keyPair.getPublic()).getY(); byte[] pubKeyBytes = pubKeyBI.toByteArray(); Log.i(TAG, String.format(TAG, "Y [%d] = %s", pubKeyBytes.length, Utils.toHexString(pubKeyBytes))); return pubKeyBytes; } catch (Exception e) { Log.e(TAG, "generatePubKey(): " + e.getMessage()); return null; } } public byte[] computeSharedKey(byte[] pubKeyBytes) { if (keyAgree == null) { Log.e(TAG, "computeSharedKey(): keyAgree IS NULL!!"); return null; } try { KeyFactory keyFactory = KeyFactory.getInstance("DiffieHellman"); BigInteger pubKeyBI = new BigInteger(1, pubKeyBytes); Log.i(TAG, "Y = " + pubKeyBI.toString(16)); PublicKey pubKey = keyFactory.generatePublic(new DHPublicKeySpec(pubKeyBI, P, G)); keyAgree.doPhase(pubKey, true); byte[] sharedKeyBytes = keyAgree.generateSecret(); Log.i(TAG, String.format("SHARED KEY[%d] = %s", sharedKeyBytes.length, Utils.toHexString(sharedKeyBytes))); return sharedKeyBytes; } catch (Exception e) { Log.e(TAG, "computeSharedKey(): " + e.getMessage()); return null; } } private static final byte P_BYTES[] = { (byte)0xF4, (byte)0x88, (byte)0xFD, (byte)0x58, ... (byte)0xE9, (byte)0x2F, (byte)0x78, (byte)0xC7 }; private static final BigInteger P = new BigInteger(1, P_BYTES); private static final BigInteger G = BigInteger.valueOf(2); } 

以下代码使用Elliptic Curve Diffie-Hellman生成并共享128位密钥和AES进行加密。

 import sun.misc.BASE64Decoder; import sun.misc.BASE64Encoder; import javax.crypto.*; import javax.crypto.spec.SecretKeySpec; import java.io.IOException; import java.security.*; public class AESSecurityCap { private PublicKey publickey; KeyAgreement keyAgreement; byte[] sharedsecret; String ALGO = "AES"; AESSecurityCap() { makeKeyExchangeParams(); } private void makeKeyExchangeParams() { KeyPairGenerator kpg = null; try { kpg = KeyPairGenerator.getInstance("EC"); kpg.initialize(128); KeyPair kp = kpg.generateKeyPair(); publickey = kp.getPublic(); keyAgreement = KeyAgreement.getInstance("ECDH"); keyAgreement.init(kp.getPrivate()); } catch (NoSuchAlgorithmException | InvalidKeyException e) { e.printStackTrace(); } } public void setReceiverPublicKey(PublicKey publickey) { try { keyAgreement.doPhase(publickey, true); sharedsecret = keyAgreement.generateSecret(); } catch (InvalidKeyException e) { e.printStackTrace(); } } public String encrypt(String msg) { try { Key key = generateKey(); Cipher c = Cipher.getInstance(ALGO); c.init(Cipher.ENCRYPT_MODE, key); byte[] encVal = c.doFinal(msg.getBytes()); return new BASE64Encoder().encode(encVal); } catch (BadPaddingException | InvalidKeyException | NoSuchPaddingException | IllegalBlockSizeException | NoSuchAlgorithmException e) { e.printStackTrace(); } return msg; } public String decrypt(String encryptedData) { try { Key key = generateKey(); Cipher c = Cipher.getInstance(ALGO); c.init(Cipher.DECRYPT_MODE, key); byte[] decordedValue = new BASE64Decoder().decodeBuffer(encryptedData); byte[] decValue = c.doFinal(decordedValue); return new String(decValue); } catch (BadPaddingException | InvalidKeyException | NoSuchPaddingException | IllegalBlockSizeException | NoSuchAlgorithmException | IOException e) { e.printStackTrace(); } return encryptedData; } public PublicKey getPublickey() { return publickey; } protected Key generateKey() { return new SecretKeySpec(sharedsecret, ALGO); } } 

扩展您自己的类以添加AES加密function

 public class Node extends AESSecurityCap { //your class } 

最后,使用加密的方式

 public class Main { public static void main(String[] args) throws IOException { Node server = new Node(); Node client = new Node(); server.setReceiverPublicKey(client.getPublickey()); client.setReceiverPublicKey(server.getPublickey()); String data = "hello"; String enc = server.encrypt(data); System.out.println("hello is coverted to "+enc); System.out.println(enc+" is converted to "+client.decrypt(enc)); } } 

输出:

 hello is coverted to OugbNvUuylvAr9mKv//nLA== OugbNvUuylvAr9mKv//nLA== is converted to hello Process finished with exit code 0