热门标签 | HotTags
当前位置:  开发笔记 > 运维 > 正文

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

这篇文章主要介绍了JAVA加密算法-非对称加密算法(DH,RSA),详细介绍了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 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 keyMap = new HashMap();
    keyMap.put(PUBLIC_KEY, dhPublicKey);
    keyMap.put(PRIVATE_KEY, dhPrivateKey);
    return keyMap;
  }

  /**
   * 通过源公钥 生成 目标密钥对
   * @param sourcePublicKey
   * @return
   * @throws Exception
   */
  public static Map 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 keyMap = new HashMap();
    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 map){
    return ((DHPublicKey) map.get(PUBLIC_KEY)).getEncoded();
  }

  //获取私钥字节数组
  public static byte[] getPrivateKey(Map 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 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 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 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 keyMap = new HashMap();
    keyMap.put(PUBLIC_KEY, publicKey);
    keyMap.put(PRIVATE_KEY, privateKey);
    return keyMap;
  }

  public static RSAPublicKey getPublicKey(Map keyMap) {
    return (RSAPublicKey) keyMap.get(PUBLIC_KEY);
  }

  public static RSAPrivateKey getPrivateKey(Map 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 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));

  }
}

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


推荐阅读
  • 作者:守望者1028链接:https:www.nowcoder.comdiscuss55353来源:牛客网面试高频题:校招过程中参考过牛客诸位大佬的面经,但是具体哪一块是参考谁的我 ... [详细]
  • 本文介绍如何在现有网络中部署基于Linux系统的透明防火墙(网桥模式),以实现灵活的时间段控制、流量限制等功能。通过详细的步骤和配置说明,确保内部网络的安全性和稳定性。 ... [详细]
  • 深入探讨智能布线管理系统的电子配线架应用
    本文详细介绍了电子配线架智能布线系统的核心优势,包括实时监测网络连接、提高操作准确性、图形化显示连接架构、自动识别网络拓扑、增强安全性等功能。该系统不仅提升了网络管理的效率和准确性,还为资产管理、报告生成以及与其他智能系统的集成提供了强大的支持。 ... [详细]
  • 网易严选Java开发面试:MySQL索引深度解析
    本文详细记录了网易严选Java开发岗位的面试经验,特别针对MySQL索引相关的技术问题进行了深入探讨。通过本文,读者可以了解面试官常问的索引问题及其背后的原理。 ... [详细]
  • 探讨架构师在项目中应如何平衡对产品的关注和对团队成员的关注,以实现最佳的开发成果。 ... [详细]
  • 本文深入探讨了 Redis 的两种持久化方式——RDB 快照和 AOF 日志。详细介绍了它们的工作原理、配置方法以及各自的优缺点,帮助读者根据具体需求选择合适的持久化方案。 ... [详细]
  • 本文介绍了多个关于JavaScript的书籍资源、实用工具和编程实例,涵盖从入门到进阶的各个阶段,帮助读者全面提升JavaScript编程能力。 ... [详细]
  • 本文探讨了如何在日常工作中通过优化效率和深入研究核心技术,将技术和知识转化为实际收益。文章结合个人经验,分享了提高工作效率、掌握高价值技能以及选择合适工作环境的方法,帮助读者更好地实现技术变现。 ... [详细]
  • 深入理解一致性哈希算法及其应用
    本文详细介绍了分布式系统中的一致性哈希算法,探讨其原理、优势及应用场景,帮助读者全面掌握这一关键技术。 ... [详细]
  • 深入解析TCP/IP五层协议
    本文详细介绍了TCP/IP五层协议模型,包括物理层、数据链路层、网络层、传输层和应用层。每层的功能及其相互关系将被逐一解释,帮助读者理解互联网通信的原理。此外,还特别讨论了UDP和TCP协议的特点以及三次握手、四次挥手的过程。 ... [详细]
  • 探索电路与系统的起源与发展
    本文回顾了电路与系统的发展历程,从电的早期发现到现代电子器件的应用。文章不仅涵盖了基础理论和关键发明,还探讨了这一学科对计算机、人工智能及物联网等领域的深远影响。 ... [详细]
  • 本文探讨了2012年4月期间,淘宝在技术架构上的关键数据和发展历程。涵盖了从早期PHP到Java的转型,以及在分布式计算、存储和网络流量管理方面的创新。 ... [详细]
  • 科研单位信息系统中的DevOps实践与优化
    本文探讨了某科研单位通过引入云原生平台实现DevOps开发和运维一体化,显著提升了项目交付效率和产品质量。详细介绍了如何在实际项目中应用DevOps理念,解决了传统开发模式下的诸多痛点。 ... [详细]
  • 2018年3月31日,CSDN、火星财经联合中关村区块链产业联盟等机构举办的2018区块链技术及应用峰会(BTA)核心分会场圆满举行。多位业内顶尖专家深入探讨了区块链的核心技术原理及其在实际业务中的应用。 ... [详细]
  • 本文详细介绍了网络存储技术的基本概念、分类及应用场景。通过分析直连式存储(DAS)、网络附加存储(NAS)和存储区域网络(SAN)的特点,帮助读者理解不同存储方式的优势与局限性。 ... [详细]
author-avatar
富农032884
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有