JAVA加密算法- 非对称加密算法(DH,RSA)的详细介绍

非对称密码概念

1、与对称加密算法的主要差别在于,加密和解密的密钥不相同,一个公开(公钥),一个保密(私钥)。主要解决了对称加密算法密钥分配管理的问题,提高了算法安全性。

2、非对称加密算法的加密、解密的效率比较低。在算法设计上,非对称加密算法对待加密的数据长度有着苛刻的要求。例如RSA算法要求待加密的数据不得大于53个字节。

3、非对称加密算法主要用于 交换对称加密算法的密钥,而非数据交换

4、java6提供实现了DH和RSA两种算法。Bouncy Castle提供了E1Gamal算法支持。除了上述三种算法还有一个ECC算法,目前没有相关的开源组件提供支持

需要两个密钥进行加密或解密,分为公钥和私钥

特点:安全性高,速度慢

用途

【密钥交换(DH)】

双方在没有确定共同密钥的情况下,生成密钥,不提供加密工作,加解密还需要其他对称加密算法实现

DH算法示例

import javax.crypto.KeyAgreement;
import javax.crypto.interfaces.DHPrivateKey;
import javax.crypto.interfaces.DHPublicKey;
import javax.crypto.spec.DHParameterSpec;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

//1 生成源密钥
//2 把源公钥交给目标,目标通过源公钥,生成目标公钥和私钥
//3 把目标公钥交给源
//4 双方使用对方的公钥和和自己的私钥,生成本地密钥
//5 如果双方生成本地密钥相同则完成密钥交换
public class DHUtil {

  public static final String PUBLIC_KEY = "DH_Public_Key";
  public static final String PRIVATE_KEY = "DH_Private_key";

  /**
   * 生成源密钥对
   * @return
   * @throws Exception
   */
  public static Map<String,Object> initSourceKey() throws Exception{
    //创建KeyPairGenerator的实例,选用DH算法
    KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("DH");

    //初始化密钥长度,默认1024,可选范围512-65536 & 64的倍数
    keyPairGenerator.initialize(1024);

    //生成密钥对
    KeyPair keyPair = keyPairGenerator.generateKeyPair();
    DHPublicKey dhPublicKey = (DHPublicKey) keyPair.getPublic();
    DHPrivateKey dhPrivateKey = (DHPrivateKey) keyPair.getPrivate();

    //将密钥对放入Map
    Map<String,Object> keyMap = new HashMap<String, Object>();
    keyMap.put(PUBLIC_KEY, dhPublicKey);
    keyMap.put(PRIVATE_KEY, dhPrivateKey);
    return keyMap;
  }

  /**
   * 通过源公钥 生成 目标密钥对
   * @param sourcePublicKey
   * @return
   * @throws Exception
   */
  public static Map<String,Object> initTargetKey(byte[] sourcePublicKey) throws Exception {

    KeyFactory keyFactory = KeyFactory.getInstance("DH");

    //通过源公钥,生成keySpec,使用KeyFactory生成源PublicKey相关信息
    X509EncodedKeySpec keySpec = new X509EncodedKeySpec(sourcePublicKey);
    DHPublicKey sourcePublic = (DHPublicKey) keyFactory.generatePublic(keySpec);

    DHParameterSpec dhPublicKeyParams = sourcePublic.getParams();

    KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("DH");
    keyPairGenerator.initialize(dhPublicKeyParams);

    KeyPair keyPair = keyPairGenerator.generateKeyPair();
    DHPublicKey dhPublicKey = (DHPublicKey) keyPair.getPublic();
    DHPrivateKey dhPrivateKey = (DHPrivateKey) keyPair.getPrivate();

    //将密钥对放入Map
    Map<String,Object> keyMap = new HashMap<String, Object>();
    keyMap.put(PUBLIC_KEY, dhPublicKey);
    keyMap.put(PRIVATE_KEY, dhPrivateKey);
    return keyMap;
  }

  /**
   * 使用一方的公钥和另一方的私钥,生成本地密钥
   * @return
   */
  public static byte[] generateLocalSecretKey(byte[] aPublicKey, byte[] bPrivateKey) throws Exception{
    KeyFactory keyFactory = KeyFactory.getInstance("DH");

    //通过A公钥,生成keySpec,使用KeyFactory生成A PublicKey相关信息
    X509EncodedKeySpec keySpec = new X509EncodedKeySpec(aPublicKey);
    PublicKey publicKey = keyFactory.generatePublic(keySpec);

    //通过B私钥,生成B PrivateKey相关信息
    PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(bPrivateKey);
    PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);

    //通过KeyAgreement对A的PublicKey和B的PrivateKey进行加密
    KeyAgreement keyAgreement = KeyAgreement.getInstance("DH");
    keyAgreement.init(privateKey);
    keyAgreement.doPhase(publicKey,true);

    return keyAgreement.generateSecret("AES").getEncoded();//算法使用对称加密算法(DES,DESede,AES)
    //return keyAgreement.generateSecret();        // 也可以不选择算法,使用默认方法计算
  }

  //获取公钥字节数组
  public static byte[] getPublicKey(Map<String,Object> map){
    return ((DHPublicKey) map.get(PUBLIC_KEY)).getEncoded();
  }

  //获取私钥字节数组
  public static byte[] getPrivateKey(Map<String,Object> map){
    return ((DHPrivateKey) map.get(PRIVATE_KEY)).getEncoded();
  }

  public static void main(String[] args) throws Exception {

    byte[] source_public_key;
    byte[] source_private_key;
    byte[] source_local_key;

    byte[] target_public_key;
    byte[] target_private_key;
    byte[] target_local_key;

    Map<String, Object> sourceKey = initSourceKey();
    source_public_key = getPublicKey(sourceKey);
    source_private_key = getPrivateKey(sourceKey);

    System.out.println("源公钥:"+BytesToHex.fromBytesToHex(source_public_key));
    System.out.println("源私钥:"+BytesToHex.fromBytesToHex(source_private_key));

    Map<String, Object> targetKey = initTargetKey(getPublicKey(sourceKey));
    target_public_key = getPublicKey(targetKey);
    target_private_key = getPrivateKey(targetKey);

    System.out.println("目标公钥:"+BytesToHex.fromBytesToHex(target_public_key));
    System.out.println("目标私钥:"+BytesToHex.fromBytesToHex(target_private_key));

    source_local_key = generateLocalSecretKey(target_public_key, source_private_key);
    target_local_key = generateLocalSecretKey(source_public_key, target_private_key);

    System.out.println("源本地密钥:"+BytesToHex.fromBytesToHex(source_local_key));
    System.out.println("目标本地密钥:"+BytesToHex.fromBytesToHex(target_local_key));
  }
}

【加密/解密(RSA)】【数字签名(RSA)】

RSA算法晚于DH算法,这五个字母全都是人名首字母.DH算法是第一个非对称密码体系.

RSA算法运算速度慢,不适宜加密大量数据.一种解决方案是,将RSA跟对称加密方式混合使用,将数据使用对称加密方式加密,对称加密的密钥使用RSA算法加密,因为密钥很短,所以时间费不了太多.实际上,对称加密方式唯一的弊端就是密钥不好传递,对称加密方式也很难破解.

RSA的适用情景一:

(1)服务器生成一个公钥和一个私钥,把公钥公开了.

(2)客户端使用公钥把数据进行加密,上交服务器.别人是没法理解加密后的数据的.

(3)服务器使用私钥将数据解密,查看用户提交的数据.

这种情景下,公钥像是一个信箱,每个人都可以往这个信箱里面放信,但是这个信箱里面的信只有掌握信箱钥匙的人才能开箱查看.

RSA适用情景二:

(1)皇上生成一个公钥和一个密钥,把公钥公开了.

(2)皇上发布了一封诏书,昭告天下.诏书右下角有两串数字,第一串数字是一个随机串,第二串数字是用私钥加密第一串数字所得的结果.

(3)有人不相信这诏书是皇上写的,就把第二串数字使用公钥解密,解密之后发现跟第一串数字一样,说明确实是皇上写的,因为一般人没有密钥,也就没法加密那些能够用公钥解密的数据.

这种情境下,公钥用于解密,私钥用于加密,这可以用于发布公告时,证明这个公告确实是某个人发的.相当于签名.

实际上,签名没有必要特别长,一般情况下,签名是定长的,要想定长,可以使用MessageDigest算法,如MD5和SHA系列.所以就有了多种签名算法,如MD5withRSA等.

RSA 加密/解密 示例

import javax.crypto.Cipher;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PublicKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.HashMap;
import java.util.Map;

/**
 * RSA加密工具
 */
public class RSAUtil {

  public static final String PUBLIC_KEY = "RSA_Public_Key";
  public static final String PRIVATE_KEY = "RSA_Private_Key";

  /**
   * 初始化密钥
   * @return
   * @throws Exception
   */
  public static Map<String,Object> initKey() throws Exception{
    KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
    keyPairGenerator.initialize(1024);//512-65536 & 64的倍数
    KeyPair keyPair = keyPairGenerator.generateKeyPair();
    RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
    RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();

    Map<String,Object> keyMap = new HashMap<String, Object>();
    keyMap.put(PUBLIC_KEY, publicKey);
    keyMap.put(PRIVATE_KEY, privateKey);
    return keyMap;
  }

  public static RSAPublicKey getPublicKey(Map<String,Object> keyMap) {
    return (RSAPublicKey) keyMap.get(PUBLIC_KEY);
  }

  public static RSAPrivateKey getPrivateKey(Map<String,Object> keyMap){
    return (RSAPrivateKey) keyMap.get(PRIVATE_KEY);
  }

  /**
   * 使用公钥对数据进行加密
   * @param data
   * @param publicKey
   * @return
   * @throws Exception
   */
  public static byte[] encrypt(byte[] data, RSAPublicKey publicKey) throws Exception{
    Cipher cipher = Cipher.getInstance("RSA");
    cipher.init(Cipher.ENCRYPT_MODE,publicKey);
    return cipher.doFinal(data);
  }

  /**
   * 使用私钥解密
   * @param data
   * @param privateKey
   * @return
   * @throws Exception
   */
  public static byte[] decrypt(byte[] data, RSAPrivateKey privateKey) throws Exception{
    Cipher cipher = Cipher.getInstance("RSA");
    cipher.init(Cipher.DECRYPT_MODE,privateKey);
    return cipher.doFinal(data);
  }

  public static void main(String[] args) throws Exception {
    String data = "周杰伦-东风破";
    Map<String, Object> keyMap = initKey();

    byte[] miwen = encrypt(data.getBytes(),getPublicKey(keyMap));
    System.out.println("加密后的内容:"+BytesToHex.fromBytesToHex(miwen));

    byte[] plain = decrypt(miwen, getPrivateKey(keyMap));
    System.out.println("解密后的内容:"+new String(plain));

  }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • java加密算法分享(rsa解密、对称加密、md5加密)

    复制代码 代码如下: import java.io.UnsupportedEncodingException;import java.security.InvalidKeyException;import java.security.MessageDigest;import java.security.NoSuchAlgorithmException;import java.security.PrivateKey;import java.security.PublicKey;import jav

  • Java RSA加密解密实现方法分析【附BASE64 jar包下载】

    本文实例讲述了Java RSA加密解密实现方法.分享给大家供大家参考,具体如下: 该工具类中用到了BASE64,需要借助第三方类库:javabase64-1.3.1.jar javabase64-1.3.1.jar 本站下载地址. 注意: RSA加密明文最大长度117字节,解密要求密文最大长度为128字节,所以在加密和解密的过程中需要分块进行. RSA加密对明文的长度是有限制的,如果加密数据过大会抛出如下异常: Exception in thread "main" javax.cryp

  • java使用des加密解密示例分享

    复制代码 代码如下: import java.security.Key;import java.security.SecureRandom;import java.security.spec.AlgorithmParameterSpec; import javax.crypto.Cipher;import javax.crypto.SecretKeyFactory;import javax.crypto.spec.DESKeySpec;import javax.crypto.spec.IvPar

  • java 加密之RSA算法加密与解密的实例详解

    java 加密之RSA算法加解密与解密的实例详解 前言: RSA是第一个比较完善的公开密钥算法,它既能用于加密,也能用于数字签名.RSA以它的三个发明者Ron Rivest, Adi Shamir, Leonard Adleman的名字首字母命名,这个算法经受住了多年深入的密码分析,虽然密码分析者既不能证明也不能否定RSA的安全性,但这恰恰说明该算法有一定的可信性,目前它已经成为最流行的公开密钥算法. RSA的安全基于大数分解的难度.其公钥和私钥是一对大素数(100到200位十进制数或更大)的函

  • JAVA 中解密RSA算法JS加密实例详解

    JAVA 中解密RSA算法JS加密实例详解 有这样一个需求,前端登录的用户名密码,密码必需加密,但不可使用MD5,因为后台要检测密码的复杂度,那么在保证安全的前提下将密码传到后台呢,答案就是使用RSA非对称加密算法解决 . java代码 需要依赖 commons-codec 包 RSACoder.Java import org.apache.commons.codec.binary.Base64; import javax.crypto.Cipher; import java.security.

  • java实现的RSA加密算法详解

    本文实例讲述了java实现的RSA加密算法.分享给大家供大家参考,具体如下: 一.什么是非对称加密 1.加密的密钥与加密的密钥不相同,这样的加密算法称之为非对称加密 2.密钥分为:公钥,私钥 公钥:可以对外给任何人的加密和解密的密码,是公开的 私钥:通过私钥可以生成公钥,但从公钥被认为无法生成公钥(被推导出的概率小到不考虑) 3.当将要加密的内容用公钥加密的时候,只能用私钥来解密 当将要加密的内容用私钥加密的时候,只能用公钥来解密 4.公钥与私钥的关系,利用一个简单的公式来生成公钥和私钥,即非对

  • java常用工具类之DES和Base64加密解密类

    一.DES加密和解密 package com.itjh.javaUtil; import java.io.UnsupportedEncodingException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.security.spec.InvalidKeySpecExc

  • Java中RSA加密解密的实现方法分析

    本文实例讲述了Java中RSA加密解密的实现方法.分享给大家供大家参考,具体如下: public static void main(String[] args) throws Exception { // TODO Auto-generated method stub HashMap<String, Object> map = RSAUtils.getKeys(); //生成公钥和私钥 RSAPublicKey publicKey = (RSAPublicKey) map.get("

  • RSA加密算法java简单实现方法(必看)

    简单完整的代码,通过这个代码你将对RSA加密算法在Java中的实现方法有一个初步的了解,这个类,你可以直接使用,水平高的,就自己修改完善下代码. package security; import java.security.*; import java.security.spec.*; import java.security.interfaces.*; import javax.crypto.spec.*; import javax.crypto.interfaces.*; import ja

  • java 中RSA的方式实现非对称加密的实例

    java 中RSA的方式实现非对称加密的实例 RSA通俗理解: 你只要去想:既然是加密,那肯定是不希望别人知道我的消息,所以只有我才能解密,所以可得出公钥负责加密,私钥负责解密:同理,既然是签名,那肯定是不希望有人冒充我发消息,只有我才能发布这个签名,所以可得出私钥负责签名,公钥负责验证. 实现代码: package com.sahadev; import java.security.KeyFactory; import java.security.KeyPair; import java.se

随机推荐