**交换算法DH(Java实现)

**交换算法——DH

1.简述

    1976年,W.Diffie和M.Hellman在发表的论文中提出了公钥加密算法思想,但当时并没有给出具体的实施方案,原因在于没有找到单向函数(也就是消息摘要算法),但在该论文中给出了通信双方通过信息交换协商**的算法,即Diffie-Hellman**交换算法(简称为DH算法)。该算法的目的在于让消息的收发双方可以在安全的条件下交换**,以备后续加密/解密使用。因此,DH算法是第一个**协商算法,但仅能用于**分配,不能用于加密或者解密消息。

    DH**交换算法的安全性基于有限域上的离散对数难题。基于这种安全性,通过DH算法进行**分配,使得消息的收发双方可以安全地交换一个**,再通过这个**对数据进行加密和解密处理。


2.模型分析

    我们以消息传递模型为例,甲方作为发送者,乙方作为接受者,分述甲乙双方如何构建**、交互**和加密数据。

    首先,甲乙双方需要在收发消息前构建自己的**对,如图1所示。

    **交换算法DH(Java实现)

    甲乙双方构建**需要经过以下几个步骤:

    1)由消息发送的一方构建**,这里由甲方构建**。

    2)由构建**的一方向对方公布其公钥,这里由甲方向乙方发布公钥。

    3)由消息接收的一方通过对方公钥构建自身**,这里由乙方使用甲方公钥构建乙方**。

    4)由消息接收的一方向对方公布其公钥,这里由乙方向甲方公布公钥。

    这里要注意的是,乙方构建自己**对的时候需要使用甲方公钥作为参数这是很关键的一点,如果缺少了这一环节则无法确保甲乙双方获得同一个**,消息加密更无从谈起。

    其次,假设甲乙双方事先约定好了用于数据加密的对称加密算法(如AES算法),并构建本地**(即对称加密算法中的**),如图2所示。

**交换算法DH(Java实现)

    甲方需要使用自己的私钥和乙方的公钥才能构建自己的本地**,乙方需要使用自己的私钥和甲方的公钥才能构建自己的本地**。

    虽然甲乙双方使用了不同的**来构建本地**,但是甲乙两方得到的**其实是一致的,后面的demo可以证明,也正是基于此,甲乙双方才能顺利地进行加密消息的传送。

    最后,甲乙双方构建了本地**后,可按照基于对称加密算法的消息传递模型完成消息传递。如图4所示。

**交换算法DH(Java实现)

    作为对称加密*向非对称加密*的一种过渡,DH算法仅仅比一般的对称加密算法多了**对的构建和本地**的构建这两项操作,而真正的数据加密/解密操作仍由对称加密算法完成。


3.实现

1)DH算法实现(DHCoder.java)

[java] view plain copy
  1. package dh;  
  2.   
  3. import java.security.Key;  
  4. import java.security.KeyFactory;  
  5. import java.security.KeyPair;  
  6. import java.security.KeyPairGenerator;  
  7. import java.security.PrivateKey;  
  8. import java.security.PublicKey;  
  9. import java.security.spec.PKCS8EncodedKeySpec;  
  10. import java.security.spec.X509EncodedKeySpec;  
  11. import java.util.HashMap;  
  12. import java.util.Map;  
  13. import javax.crypto.Cipher;  
  14. import javax.crypto.KeyAgreement;  
  15. import javax.crypto.SecretKey;  
  16. import javax.crypto.interfaces.DHPrivateKey;  
  17. import javax.crypto.interfaces.DHPublicKey;  
  18. import javax.crypto.spec.DHParameterSpec;  
  19. import javax.crypto.spec.SecretKeySpec;  
  20.   
  21. public abstract class DHCoder {  
  22.     /** 
  23.      * 非对称加***算法 
  24.      */  
  25.     private static final String KEY_ALGORITHM = "DH";  
  26.     /** 
  27.      * 本地**算法,即对称加***算法 
  28.      * 可选DES、DESede或者AES 
  29.      */  
  30.     private static final String SELECT_ALGORITHM = "AES";  
  31.     /** 
  32.      * **长度 
  33.      */  
  34.     private static final int KEY_SIZE = 512;  
  35.     //公钥  
  36.     private static final String PUBLIC_KEY = "DHPublicKey";  
  37.     //私钥  
  38.     private static final String PRIVATE_KEY = "DHPrivateKey";  
  39.       
  40.     /** 
  41.      * 初始化甲方** 
  42.      * @return Map 甲方**Map 
  43.      * @throws Exception 
  44.      */  
  45.     public static Map<String, Object> initKey() throws Exception{  
  46.         //实例化**对生成器  
  47.         KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORITHM);  
  48.         //初始化**对生成器  
  49.         keyPairGenerator.initialize(KEY_SIZE);  
  50.         //生成**对  
  51.         KeyPair keyPair = keyPairGenerator.generateKeyPair();  
  52.         //甲方公钥  
  53.         DHPublicKey publicKey = (DHPublicKey)keyPair.getPublic();  
  54.         //甲方私钥  
  55.         DHPrivateKey privateKey = (DHPrivateKey)keyPair.getPrivate();  
  56.         //将**对存储在Map中  
  57.         Map<String, Object> keyMap = new HashMap<String, Object>(2);  
  58.         keyMap.put(PUBLIC_KEY, publicKey);  
  59.         keyMap.put(PRIVATE_KEY, privateKey);  
  60.         return keyMap;  
  61.     }  
  62.       
  63.     /** 
  64.      * 初始化乙方** 
  65.      * @param key 甲方公钥 
  66.      * @return Map 乙方**Map 
  67.      * @throws Exception 
  68.      */  
  69.     public static Map<String, Object> initKey(byte[] key) throws Exception{  
  70.         //解析甲方公钥  
  71.         //转换公钥材料  
  72.         X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(key);  
  73.         //实例化**工厂  
  74.         KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);  
  75.         //产生公钥  
  76.         PublicKey pubKey = keyFactory.generatePublic(x509KeySpec);  
  77.         //由甲方公钥构建乙方**  
  78.         DHParameterSpec dhParameterSpec = ((DHPublicKey)pubKey).getParams();  
  79.         //实例化**对生成器  
  80.         KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORITHM);  
  81.         //初始化**对生成器  
  82.         keyPairGenerator.initialize(KEY_SIZE);  
  83.         //产生**对  
  84.         KeyPair keyPair = keyPairGenerator.generateKeyPair();  
  85.         //乙方公钥  
  86.         DHPublicKey publicKey = (DHPublicKey) keyPair.getPublic();  
  87.         //乙方私约  
  88.         DHPrivateKey privateKey = (DHPrivateKey) keyPair.getPrivate();  
  89.         //将**对存储在Map中  
  90.         Map<String, Object> keyMap = new HashMap<String, Object>(2);  
  91.         keyMap.put(PUBLIC_KEY, publicKey);  
  92.         keyMap.put(PRIVATE_KEY, privateKey);  
  93.         return keyMap;  
  94.     }  
  95.       
  96.     /** 
  97.      * 加密 
  98.      * @param data 待加密数据 
  99.      * @param key ** 
  100.      * @return byte[] 加密数据 
  101.      * @throws Exception 
  102.      */  
  103.     public static byte[] encrypt(byte[] data, byte[] key) throws Exception{  
  104.         //生成本地**  
  105.         SecretKey secretKey = new SecretKeySpec(key, SELECT_ALGORITHM);  
  106.         //数据加密  
  107.         Cipher cipher = Cipher.getInstance(secretKey.getAlgorithm());  
  108.         cipher.init(Cipher.ENCRYPT_MODE, secretKey);  
  109.         return cipher.doFinal(data);  
  110.     }  
  111.       
  112.     /** 
  113.      * 解密 
  114.      * @param data 待解密数据 
  115.      * @param key ** 
  116.      * @return byte[] 解密数据 
  117.      * @throws Exception 
  118.      */  
  119.     public static byte[] decrypt(byte[] data, byte[] key) throws Exception{  
  120.         //生成本地**  
  121.         SecretKey secretKey = new SecretKeySpec(key, SELECT_ALGORITHM);  
  122.         //数据揭秘  
  123.         Cipher cipher = Cipher.getInstance(secretKey.getAlgorithm());  
  124.         cipher.init(Cipher.DECRYPT_MODE, secretKey);  
  125.         return cipher.doFinal(data);  
  126.     }  
  127.       
  128.     /** 
  129.      * 构建** 
  130.      * @param publicKey 公钥 
  131.      * @param privateKey 私钥 
  132.      * @return byte[] 本地** 
  133.      * @throws Exception 
  134.      */  
  135.     public static byte[] getSecretKey(byte[] publicKey, byte[] privateKey) throws Exception{  
  136.         //实例化**工厂  
  137.         KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);  
  138.         //初始化公钥  
  139.         //**材料转换  
  140.         X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(publicKey);  
  141.         //产生公钥  
  142.         PublicKey pubKey = keyFactory.generatePublic(x509KeySpec);  
  143.         //初始化私钥  
  144.         //**材料转换  
  145.         PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(privateKey);  
  146.         //产生私钥  
  147.         PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);  
  148.         //实例化  
  149.         KeyAgreement keyAgree = KeyAgreement.getInstance(keyFactory.getAlgorithm());  
  150.         //初始化  
  151.         keyAgree.init(priKey);  
  152.         keyAgree.doPhase(pubKey, true);  
  153.         //生成本地**  
  154.         SecretKey secretKey = keyAgree.generateSecret(SELECT_ALGORITHM);  
  155.         return secretKey.getEncoded();  
  156.     }  
  157.       
  158.     /** 
  159.      * 取得私钥 
  160.      * @param keyMap **Map 
  161.      * @return byte[] 私钥 
  162.      * @throws Exception 
  163.      */  
  164.     public static byte[] getPrivateKey(Map<String, Object> keyMap) throws Exception{  
  165.         Key key = (Key) keyMap.get(PRIVATE_KEY);  
  166.         return key.getEncoded();  
  167.     }  
  168.       
  169.     /** 
  170.      * 取得公钥 
  171.      * @param keyMap **Map 
  172.      * @return byte[] 公钥 
  173.      * @throws Exception 
  174.      */  
  175.     public static byte[] getPublicKey(Map<String, Object> keyMap) throws Exception{  
  176.         Key key = (Key) keyMap.get(PUBLIC_KEY);  
  177.         return key.getEncoded();  
  178.     }  
  179. }  

2)DH算法测试(DHTest.java)

[java] view plain copy
  1. package dh;  
  2.   
  3. import java.util.Map;  
  4.   
  5. import org.apache.commons.codec.binary.Base64;  
  6.   
  7. public class DHTest {  
  8.     //甲方公钥  
  9.     private static byte[] publicKey1;  
  10.     //甲方私钥  
  11.     private static byte[] privateKey1;  
  12.     //甲方本地**  
  13.     private static byte[] key1;  
  14.     //乙方公钥  
  15.     private static byte[] publicKey2;  
  16.     //乙方私钥  
  17.     private static byte[] privateKey2;  
  18.     //乙方本地**  
  19.     private static byte[] key2;  
  20.   
  21.     /** 
  22.      * 初始化** 
  23.      * @throws Exception 
  24.      */  
  25.     public static final void initKey() throws Exception{  
  26.         //生成甲方**对  
  27.         Map<String, Object> keyMap1 = DHCoder.initKey();  
  28.         publicKey1 = DHCoder.getPublicKey(keyMap1);  
  29.         privateKey1 = DHCoder.getPrivateKey(keyMap1);  
  30.         System.out.println("甲方公钥:\n" + Base64.encodeBase64String(publicKey1));  
  31.         System.out.println("甲方私钥:\n" + Base64.encodeBase64String(privateKey1));  
  32.         //由甲方公钥产生本地**对  
  33.         Map<String, Object> keyMap2 = DHCoder.initKey(publicKey1);  
  34.         publicKey2 = DHCoder.getPublicKey(keyMap2);  
  35.         privateKey2 = DHCoder.getPrivateKey(keyMap2);  
  36.         System.out.println("乙方公钥:\n" + Base64.encodeBase64String(publicKey2));  
  37.         System.out.println("乙方私钥:\n" + Base64.encodeBase64String(privateKey2));  
  38.         key1 = DHCoder.getSecretKey(publicKey2, privateKey1);  
  39.         System.out.println("甲方本地**:\n" + Base64.encodeBase64String(key1));  
  40.         key2 = DHCoder.getSecretKey(publicKey1, privateKey2);  
  41.         System.out.println("乙方本地**:\n" + Base64.encodeBase64String(key2));  
  42.     }  
  43.       
  44.     /** 
  45.      * 主方法 
  46.      * @param args 
  47.      * @throws Exception 
  48.      */  
  49.     public static void main(String[] args) throws Exception {  
  50.         // TODO Auto-generated method stub  
  51.         initKey();  
  52.         System.out.println();  
  53.         System.out.println("===甲方向乙方发送加密数据===");  
  54.         String input1 = "求知若饥,虚心若愚。";  
  55.         System.out.println("原文:\n" + input1);  
  56.         System.out.println("---使用甲方本地**对数据进行加密---");  
  57.         //使用甲方本地**对数据加密  
  58.         byte[] encode1 = DHCoder.encrypt(input1.getBytes(), key1);  
  59.         System.out.println("加密:\n" + Base64.encodeBase64String(encode1));  
  60.         System.out.println("---使用乙方本地**对数据库进行解密---");  
  61.         //使用乙方本地**对数据进行解密  
  62.         byte[] decode1 = DHCoder.decrypt(encode1, key2);  
  63.         String output1 = new String(decode1);  
  64.         System.out.println("解密:\n" + output1);  
  65.           
  66.         System.out.println("/~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~..~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~/");  
  67.         initKey();  
  68.         System.out.println("===乙方向甲方发送加密数据===");  
  69.         String input2 = "好好学习,天天向上。";  
  70.         System.out.println("原文:\n" + input2);  
  71.         System.out.println("---使用乙方本地**对数据进行加密---");  
  72.         //使用乙方本地**对数据进行加密  
  73.         byte[] encode2 = DHCoder.encrypt(input2.getBytes(), key2);  
  74.         System.out.println("加密:\n" + Base64.encodeBase64String(encode2));  
  75.         System.out.println("---使用甲方本地**对数据进行解密---");  
  76.         //使用甲方本地**对数据进行解密  
  77.         byte[] decode2 = DHCoder.decrypt(encode2, key1);  
  78.         String output2 = new String(decode2);  
  79.         System.out.println("解密:\n" + output2);  
  80.     }  
  81. }  

4.测试结果

**交换算法DH(Java实现)


**交换算法DH(Java实现)


https://blog.csdn.net/ldld1717/article/details/53116048