JAVA中实现非对称加密DH算法类

1:项目需要数据加密,故学习研究了下DH算法,在这里做点记录
2:DH算法原理: 请求端被请求端 使用同样的密钥生成方法,请求端初始化一对密钥分为公钥和私钥,将公钥作为参数去请求被请求端.被请求端接受请求端公钥,通过此公钥初始化生成一对密钥.同时将公钥返回给请求端.与此同时两端都要以对方回传的公钥与己方生成的私钥组装本地密钥.两方生成的本地密钥应该是一样的.两方的加密解密都通过本地密钥来处理.
3:加密解密类代码:(包含:无参初始化密钥方法及有参初始化密钥方法) … 欢迎留言讨论指正
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
import javax.crypto.Cipher;
import javax.crypto.KeyAgreement;
import javax.crypto.SecretKey;
import javax.crypto.interfaces.DHPrivateKey;
import javax.crypto.interfaces.DHPublicKey;
import javax.crypto.spec.DHParameterSpec;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import net.sf.json.JSONObject;
import org.apache.commons.net.util.Base64;

/**

  • 非对称加密算法DH算法组件

  • 非对称算法一般是用来传送对称加密算法的密钥来使用的,所以这里我们用DH算法模拟密钥传送

  • 对称加密AES算法继续做我们的数据加解密

  • @author

  • */
    public class DHUtilXM {
    //非对称密钥算法
    public static final String KEY_ALGORITHM=“DH”;

    //本地密钥算法,即对称加密算法。可选des,aes,desede
    public static final String SECRET_ALGORITHM=“AES”;

    /**

    • 密钥长度,DH算法的默认密钥长度是1024
    • 密钥长度必须是64的倍数,在512到1024位之间
    • */
      private static final int KEY_SIZE=512;
      //公钥
      private static final String PUBLIC_KEY=“DHPublicKey”;

    //私钥
    private static final String PRIVATE_KEY=“DHPrivateKey”;

    /**

    • 初始化甲方密钥
    • @return Map 甲方密钥的Map
    • */
      public static Map initKey() throws Exception{
      //实例化密钥生成器
      KeyPairGenerator keyPairGenerator=KeyPairGenerator.getInstance(KEY_ALGORITHM);
      //初始化密钥生成器
      keyPairGenerator.initialize(KEY_SIZE);
      //生成密钥对
      KeyPair keyPair=keyPairGenerator.generateKeyPair();
      //甲方公钥
      DHPublicKey publicKey=(DHPublicKey) keyPair.getPublic();
      //甲方私钥
      DHPrivateKey privateKey=(DHPrivateKey) keyPair.getPrivate();
      //将密钥存储在map中
      Map keyMap=new HashMap();
      keyMap.put(PUBLIC_KEY, publicKey);
      keyMap.put(PRIVATE_KEY, privateKey);
      return keyMap;

    }

    /**

    • 初始化乙方密钥

    • @param key 甲方密钥(这个密钥是通过第三方途径传递的)

    • @return Map 乙方密钥的Map

    • /
      public static Map initKey(byte[] key) throws Exception{
      //解析甲方的公钥
      //转换公钥的材料
      X509EncodedKeySpec x509KeySpec=new X509EncodedKeySpec(key);
      //实例化密钥工厂
      KeyFactory keyFactory=KeyFactory.getInstance(KEY_ALGORITHM);
      //产生公钥
      PublicKey pubKey=keyFactory.generatePublic(x509KeySpec);
      //由甲方的公钥构造乙方密钥
      DHParameterSpec dhParamSpec=((DHPublicKey)pubKey).getParams();
      //实例化密钥生成器
      KeyPairGenerator keyPairGenerator=KeyPairGenerator.getInstance(keyFactory.getAlgorithm());
      //初始化密钥生成器
      keyPairGenerator.initialize(dhParamSpec);
      //产生密钥对
      KeyPair keyPair=keyPairGenerator.genKeyPair();
      //乙方公钥
      DHPublicKey publicKey=(DHPublicKey)keyPair.getPublic();
      //乙方私钥
      DHPrivateKey privateKey=(DHPrivateKey)keyPair.getPrivate();
      //将密钥存储在Map中
      Map keyMap=new HashMap();
      keyMap.put(PUBLIC_KEY, publicKey);
      keyMap.put(PRIVATE_KEY, privateKey);
      return keyMap;
      }
      /
      *

    • 加密

    • @param data

    •        待加密数据
      
    • @param key

    •        密钥
      
    • @return byte[] 加密数据

    • @throws Exception
      */
      public static byte[] encrypt(byte[] data, byte[] key) throws Exception {
      byte[] keyBytes = new byte[16];
      byte[] ivBytes = new byte[16];
      System.arraycopy(key, 0, keyBytes, 0, 16);
      System.arraycopy(key, 16, ivBytes, 0, 16);

      AlgorithmParameters params = AlgorithmParameters.getInstance(SECRET_ALGORITHM);
      params.init(new IvParameterSpec(ivBytes));

      //转化为密钥
      Key keyInfo = new SecretKeySpec(keyBytes,SECRET_ALGORITHM);
      //Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
      Cipher cipher = Cipher.getInstance(“AES/CBC/PKCS5Padding”);
      //设置为加密模式
      cipher.init(Cipher.ENCRYPT_MODE, keyInfo,params);
      return cipher.doFinal(data);
      }

    /**

    • 解密

    • @param data

    •        待解密数据
      
    • @param

    • @return byte[] 解密数据

    • @throws Exception
      */
      public static byte[] decrypt(byte[] data, byte[] keyInfo) throws Exception {
      byte[] keyBytes = new byte[16];
      byte[] ivBytes = new byte[16];
      System.arraycopy(keyInfo, 0, keyBytes, 0, 16);
      System.arraycopy(keyInfo, 16, ivBytes, 0, 16);

      AlgorithmParameters params = AlgorithmParameters.getInstance(SECRET_ALGORITHM);
      params.init(new IvParameterSpec(ivBytes));

      Key key = new SecretKeySpec(keyBytes,SECRET_ALGORITHM);
      Cipher cipher = Cipher.getInstance(“AES/CBC/PKCS5Padding”);
      //设置为解密模式
      cipher.init(Cipher.DECRYPT_MODE, key,params);
      return cipher.doFinal(data);
      }

    /**

    • 构建密钥
    • @param publicKey 公钥
    • @param privateKey 私钥
    • @return byte[] 本地密钥
    • /
      public static byte[] getSecretKey(byte[] publicKey,byte[] privateKey) throws Exception{
      //实例化密钥工厂
      KeyFactory keyFactory=KeyFactory.getInstance(KEY_ALGORITHM);
      //初始化公钥
      //密钥材料转换
      X509EncodedKeySpec x509KeySpec=new X509EncodedKeySpec(publicKey);
      //产生公钥
      PublicKey pubKey=keyFactory.generatePublic(x509KeySpec);
      //初始化私钥
      //密钥材料转换
      PKCS8EncodedKeySpec pkcs8KeySpec=new PKCS8EncodedKeySpec(privateKey);
      //产生私钥
      PrivateKey priKey=keyFactory.generatePrivate(pkcs8KeySpec);
      //实例化
      KeyAgreement keyAgree=KeyAgreement.getInstance(keyFactory.getAlgorithm());
      //初始化
      keyAgree.init(priKey);
      keyAgree.doPhase(pubKey, true);
      //生成本地密钥
      SecretKey secretKey=keyAgree.generateSecret(SECRET_ALGORITHM);
      return secretKey.getEncoded();
      }
      /
      *
    • 取得私钥
    • @param keyMap 密钥map
    • @return byte[] 私钥
    • /
      public static byte[] getPrivateKey(Map keyMap){
      Key key=(Key)keyMap.get(PRIVATE_KEY);
      return key.getEncoded();
      }
      /
      *
    • 取得公钥
    • @param keyMap 密钥map
    • @return byte[] 公钥
    • */
      public static byte[] getPublicKey(Map keyMap) throws Exception{
      Key key=(Key) keyMap.get(PUBLIC_KEY);
      return key.getEncoded();
      }

    public static String parseByte2HexStr(byte[] buf) {
    if (buf == null) {
    return null;
    }
    StringBuffer sbf = new StringBuffer();
    for (int i = 0; i < buf.length; i++) {
    String hex = Integer.toHexString(buf[i] & 0xFF);
    if (hex.length() == 1) {
    hex = “0” + hex;
    }
    sbf.append(hex.toUpperCase());
    }

     return sbf.toString();
    

    }
    /**

    • @param args

    • @throws Exception
      */
      public static void main(String[] args) throws Exception {

      //生成甲方的密钥对
      Map keyMap1=DHUtilXM.initKey();
      //甲方的公钥
      byte[] publicKey1=DHUtilXM.getPublicKey(keyMap1);
      //甲方的私钥
      byte[] privateKey1=DHUtilXM.getPrivateKey(keyMap1);
      JSONObject S = new JSONObject();
      S.put(“y”,Base64.encodeBase64String(publicKey1));
      System.out.println(S);
      System.out.println((String)S.get(“y”));

      System.out.println(“甲方公钥:”+Base64.encodeBase64String(publicKey1));
      String publicKey11=Base64.encodeBase64String(publicKey1).toString();

      System.out.println(“甲方私钥:”+Base64.encodeBase64String(privateKey1));

      //由甲方的公钥产生的密钥对

      Map keyMap2=DHUtilXM.initKey(Base64.decodeBase64(Base64.encodeBase64String(publicKey1)));//这里 小蜜传的公钥:要Base64.encodeBase64String转下
      byte[] publicKey2=DHUtilXM.getPublicKey(keyMap2);
      byte[] privateKey2=DHUtilXM.getPrivateKey(keyMap2);
      System.out.println(“乙方公钥:”+Base64.encodeBase64String(publicKey2));
      System.out.println(“乙方私钥:”+Base64.encodeBase64String(privateKey2));

      //组装甲方的本地加密密钥,由乙方的公钥和甲方的私钥组合而成
      byte[] key1=DHUtilXM.getSecretKey(publicKey2, privateKey1);

      byte[] key3=DHUtilXM.getSecretKey(Base64.decodeBase64(Base64.encodeBase64String(publicKey2)), privateKey1);
      System.out.println(“甲方的本地密钥:”+Base64.encodeBase64String(key3));

      //组装乙方的本地加密密钥,由甲方的公钥和乙方的私钥组合而成
      byte[] key2=DHUtilXM.getSecretKey(Base64.decodeBase64(Base64.encodeBase64String(publicKey1)), privateKey2); //这里 服务端传的公钥:已经Base64.encodeBase64String转了
      System.out.println("乙方的本地密钥: "+Base64.encodeBase64String(key2));

      System.out.println(“密钥对构造完毕,开始进行加密数据的传输=");
      String str="{“token” : “test”,“uid”: “168”,“pwd”: “888888”,“needdata”:false}";
      System.out.println("/n
      =甲方向乙方发送加密数据========”);
      System.out.println(“原文:”+str);
      System.out.println("=使用甲方本地密钥对进行数据加密====");
      //甲方进行数据的加密
      byte[] code1= DHUtilXM.encrypt(str.getBytes(), Base64.decodeBase64(Base64.encodeBase64String(key3)));
      System.out.println(“加密后的数据:”+Base64.encodeBase64String(code1));
      System.out.println(“加密后的数据:”+ Base64.encodeBase64String(Base64.decodeBase64(Base64.encodeBase64String(code1))));

      System.out.println("=使用乙方本地密钥对数据进行解密====");
      //乙方进行数据的解密
      byte[] decode1=DHUtilXM.decrypt(code1, Base64.decodeBase64(Base64.encodeBase64String(key2)));
      System.out.println(“乙方解密后的数据:”+new String(decode1));

      System.out.println("=反向进行操作,乙方向甲方发送数据====/n/n");

      str="{token:test,data:wudi,msg:test下中文}";

      System.out.println(“原文:”+str);

      //使用乙方本地密钥对数据进行加密
      byte[] code2= DHUtilXM.encrypt(str.getBytes(), Base64.decodeBase64(Base64.encodeBase64String(key2)));
      System.out.println("=使用乙方本地密钥对进行数据加密====");
      System.out.println(“加密后的数据:”+Base64.encodeBase64String(code2));

      System.out.println("=乙方将数据传送给甲方==========");
      System.out.println("=使用甲方本地密钥对数据进行解密====");

      //甲方使用本地密钥对数据进行解密
      byte[] decode2=DHUtilXM.decrypt(code2, Base64.decodeBase64(Base64.encodeBase64String(key1)));

      System.out.println(“甲方解密后的数据:”+new String(decode2));

    }
    }
    4:应用注意事项
    两方传递的公有密钥应注意处理换行符之类的,否则很可能造成生成的本地密钥不一致…
    5:结果展示
    JAVA中实现非对称加密DH算法类_第1张图片

你可能感兴趣的:(JAVA中实现非对称加密DH算法类)