密钥交换算法我们在使用对称加密算法的时候,我们用的是同一个密钥key

我们以AES加密为例,当我们需要加密明文,我们需要一个随机生成的key,作为密钥进行加解密,最后我们的问题是如何传递密钥

因为不给对方密钥,对方就不能解密,而直接传递密钥,就会被黑客监听,所以问题就变成了如何在不安全的信道上如何安全的传输密钥

密钥算法也就是Diffie-Hellman算法,简称DH算法,他就是为了解决这个问题的,p=509,g=5,A=215,你收到以后,他也选择一个随机数b,例如456,然后得到g的b次方,然后对p取余数,结果是181,然后计算S等于A的b次方,除以p的余数,结果是121,乙把计算的B发给甲,甲计算S等于B的a次方,除以p的余数,结果计算的s相同,也是121,所以最后双方协商的密钥,是121,要注意这个密钥并没有在网络上传输,通过网络传输的是p,g,A,B,但是通过这4个数,黑客是无法推算出S的,所以更确切的说,DH算法是密钥协商算法,双方最终协商一个共同的密钥

我们把小a看成是甲的密钥,大A看成是甲的公钥,小b看成是乙的私钥,大b看成是公钥,DH的算法本质是各自生成自己的公钥和私钥,然后交换公钥,并且根据自己的私钥和对方的公钥,生成最终的私钥,DH算法通过数学
package com.learn.securl;import java.io.IOException;
import java.math.BigInteger;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;import javax.crypto.Cipher;
import javax.crypto.KeyAgreement;
import javax.crypto.SecretKey;public class DH {/*** 我们写一个main方法来测试DH协商协议* @param args*/public static void main(String[] args) {// Bob 和 Alice/*** 首先我们创建两个Person对象* 一个是Bob,一个是Alice*/Person bob = new Person("Bob");Person alice = new Person("Alice");// 各自生成KeyPair:/*** 然后Bob和Alice各自生成自己的KeyPair*/bob.generateKeyPair();alice.generateKeyPair();// 双方交换各自的PublicKey:// Bob根据Alice的PublicKey生成自己的本地密钥:/*** 紧接着各自交换publicKey* 由于Bob需要Alice的publicKey生成自己的本地密钥* 所以我们对Bob调用generateSecretKey的时候* 我们需要传入alice.publicKey.getEncoded()*/bob.generateSecretKey(alice.publicKey.getEncoded());// Alice根据Bob的PublicKey生成自己的本地密钥:/*** 同样的Alice是通过bob的publicKey来生成自己的本地密钥*/alice.generateSecretKey(bob.publicKey.getEncoded());// 检查双方本地密钥是否相同/*** 我们来看一下他们的本地密钥是否相同* 如果双方的SecretKey是相同的* 那么后序的通信就可以使用这个SecretKey* AES加解密* 我们看到Bob的privateKey和publicKey以及Bob生成的secretKey* 我们再来看Alice的privateKey和publicKey以及Alice生成的secretKey* 我们注意到Alice的SecretKey和Bob的SecretKey他们是相同的* 所以在后序的通讯中,* Bob和Alice可以使用这两个相同的key以及AES的加解密*/bob.printKeys();alice.printKeys();// 双方的SecretKey相同,后续通信将使用SecretKey作为密钥进行AES加密String msgBobToAlice = bob.sendMessage("Hello, Alice!");System.out.println("Bob -> Alice: " + msgBobToAlice);String aliceDecrypted = alice.receiveMessage(msgBobToAlice);System.out.println("Alice decrypted: " + aliceDecrypted);}
}/*** 我们首先定义了一个Person类* @author Leon.Sun**/
class Person {/*** 我们定义了一个name字段,表示Person名字*/public final String name;/*** publicKey表示public Key*/public PublicKey publicKey;/*** privateKey表示private Key*/private PrivateKey privateKey;/*** 这个把表示最后生成的secretKey*/private SecretKey secretKey;/*** 我们定义个方法来初始化Person的名字* @param name*/public Person(String name) {this.name = name;}/*** 生成本地KeyPair* * 紧接着我们定义一个generateKeyPair*/public void generateKeyPair() {try {/*** 我们通过KeyPairGenerator.getInstance传入DH表示我们要生成KeyPairGenerator* 用于DH算法*/KeyPairGenerator kpGen = KeyPairGenerator.getInstance("DH");/*** 表示我们要生成512位的keyPair*/kpGen.initialize(512);/*** 我们通过generateKeyPair所获得一个KeyPair对象*/KeyPair kp = kpGen.generateKeyPair();/*** 紧接着我们通过getPrivate和getPublic分别获得了privateKey和publicKey*/this.privateKey = kp.getPrivate();this.publicKey = kp.getPublic();} catch (GeneralSecurityException e) {throw new RuntimeException(e);}}/*** 生成密钥* * 当通信的双方把publicKey交给双方的时候,* 我们都可以从对方接收到public key这个字节中回复public key对象* * @param receivedPubKeyBytes*/public void generateSecretKey(byte[] receivedPubKeyBytes) {try {// 从byte[]恢复PublicKey/*** 我们通过X509EncodedKeySpec这个类传入收到的字节数组* 就可以恢复公钥*/X509EncodedKeySpec keySpec = new X509EncodedKeySpec(receivedPubKeyBytes);KeyFactory kf = KeyFactory.getInstance("DH");/*** 我们可以通过generatePublic*/PublicKey receivedPublicKey = kf.generatePublic(keySpec);// 生成本地密钥:/*** 我们通过KeyAgreement.getInstance传入DH得到一个KeyAgreement对象*/KeyAgreement keyAgreement = KeyAgreement.getInstance("DH");/*** 然后我们通过init方法传入自己的private key*/keyAgreement.init(this.privateKey); // 自己的PrivateKey/*** 然后我们通过doPhase传入对方的publicKey,*/keyAgreement.doPhase(receivedPublicKey, true);// 对方的PublicKey// 生成AES密钥:/*** 这个时候我们通过generateSecret传入AES表示我们要生成一个AES的密钥* 这个SecretKey就是我们将来要用的密钥*/this.secretKey = keyAgreement.generateSecret("AES");} catch (GeneralSecurityException e) {throw new RuntimeException(e);}}/*** 打印密钥* * 我们用printKeys打印privateKey,publicKey,secretKey*/public void printKeys() {System.out.printf("Name: %s\n", this.name);System.out.printf("Private key: %x\n", new BigInteger(1,this.privateKey.getEncoded()));System.out.printf("Public key: %x\n",new BigInteger(1, this.publicKey.getEncoded()));System.out.printf("Secret key: %x\n",new BigInteger(1, this.secretKey.getEncoded()));}/*** 发送加密消息* * 我们用sendMessage方法用来测试AES加密* * @param message* @return*/public String sendMessage(String message) {try {Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");cipher.init(Cipher.ENCRYPT_MODE, this.secretKey);byte[] data = cipher.doFinal(message.getBytes("UTF-8"));return Base64.getEncoder().encodeToString(data);} catch (GeneralSecurityException | IOException e) {throw new RuntimeException(e);}}/*** 接收加密消息并解密* * 我们用receiveMessage来测试收到的信息,* 并且用AES解密* * @param message* @return*/public String receiveMessage(String message) {try {Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");cipher.init(Cipher.DECRYPT_MODE, this.secretKey);byte[] data = cipher.doFinal(Base64.getDecoder().decode(message));return new String(data, "UTF-8");} catch (GeneralSecurityException | IOException e) {throw new RuntimeException(e);}}
}

DH算法不能避免中间人攻击,如果黑客假冒乙和甲交互密钥,同时又假冒乙和甲交互密钥,他就可以成功的进行攻击最后我们总结一下:1. DH算法是一种密钥交换协议,通信双方通过一个不安全的信道协商密钥,然后进行对称加密传输2. DH算法并没有解决中间人攻击的问题

密钥交换算法 - Java加密与安全相关推荐

  1. java dh算法_dh密钥交换算法java

    dh密钥交换算法java 迪菲-赫尔曼密钥交换(Diffie–Hellman key exchange,简称"D–H") 是一种安全协议. 它可以让双方在完全没有对方任何预先信息的 ...

  2. 廖雪峰Java10加密与安全-4加密算法-4密钥交换算法

    1DH算法 1.1.原根公式:g^i mod P 条件:1<g<P,0<i<P 原根:介于[1, p-1]之间的任意2个数i,j(p为素数,i≠j)的结果不相等,即 g^i m ...

  3. java与php链条遇到的坑,记一次Java加密加签算法到php的坑

    写代码的经历中,总少不了与外部的程序对接,一旦有这样的事,往往周期会很长,很麻烦,因为你要考虑的事会多了很多,其中安全性的加密解密就是重要的一项.写代码,可以出Bug,但逼格不能弱.什么是逼格?和别人 ...

  4. 非对称加密——RSA算法JAVA代码实践

    文章目录 说明 RSA加解密 测试代码 打印输出 说明 1:下面代码参考自<JAVA加密解密的艺术>,有部分修改,详见原理见原书 2:下面代码是RSA在JAVA中API级别的代码实现,具体 ...

  5. 从数学角度讲解DH密钥交换算法、非对称加密、数字签名

    背景知识 数字可以分为两大部分: 不可再分的数:prime number质数 可以再分的数:composite number 和数 每个数字可以描述为一个"锁" 每个数字有且只有一 ...

  6. Java加密:六、爱德华兹曲线数字签名(EdDSA)算法

    一.EdDSA 概述 在公钥密码学中,爱德华兹曲线数字签名算法( EdDSA ) 是一种数字签名方案,它使用基于扭曲爱德华兹曲线的Schnorr 签名变体.它被设计为比现有的数字签名方案更快而不牺牲安 ...

  7. 【AES 算法】实现服务端 Java 加密,前端 JS 解密

    目录 背景 AES CBC 加解密算法 代码实现 Java 生成 key 和 iv Java 加密 & 解密 JavaScript 解密 小结 背景 我们的游戏充值平台马上要到货一批充值码,需 ...

  8. java ecdh秘钥交换_了解一下密钥交换算法ECDH

    https://www.jianshu.com/p/b26cd2bfdc28 搬一下别人的解释: 下面我们以Alice和Bob为例叙述Diffie-Hellman密钥交换的原理. 1,Diffie-H ...

  9. 国密SM9算法C++实现之八:密钥交换算法

    SM9算法C++实现系列目录: 基于JPBC的SM9算法的java实现与测试 国密SM9算法C++实现之0:源码下载地址 国密SM9算法C++实现之一:算法简介 国密SM9算法C++实现之二:测试工具 ...

最新文章

  1. 如何在github上为新问题附加新的拉取请求?
  2. 常用软件架构模式分类
  3. QT项目添加现有文件后不能运行,MFC在类视图中自动隐藏类
  4. 索引sql server_SQL Server索引与统计顾问的困境或麻烦
  5. 阅读SSM项目之scm【第一篇】
  6. PCL最小二乘法进行平面拟合原理
  7. spring boot 教程(二)模板依赖
  8. vue2.0中 怎么引用less?
  9. 快乐之道:游戏设计的黄金法则
  10. paypal 付款、支出接入文档及官方示例
  11. 有关《家》的经典歌曲_盘点《乐队的夏天》15首经典歌曲,太好听了!
  12. 访问服务器硬盘速度慢,硬盘读取速度变慢 当前传输模式pio的解决方法
  13. python企业微信回调_Python微信企业号开发之回调模式接收微信端客户端发送消息及被...
  14. 希捷和西数移动硬盘哪个好_希捷,西数哪个移动硬盘更好
  15. 教您一招解决Word不能复制粘贴问题
  16. 电脑耳机插入外放解决办法
  17. 【心情日志】ZJOI2015酱油记
  18. linux下oracle11G DG搭建(三):围绕备库搭建操作
  19. ETM黄皮书全球首发
  20. 全息生成的体光栅的严格模拟

热门文章

  1. 让图片自适应大小的方法
  2. 在Eclipse中给JRE-Library添加本地Javadoc
  3. 【大话数据结构算法】冒泡排序
  4. MySQL 配置文档
  5. 综合应用WPF/WCF/WF/LINQ之八:后台开发人员的Solution
  6. 08.self关键字
  7. shutdown,halt,reboot,init
  8. HDU 1536 求解SG函数
  9. OpenDNS,独特的免费DNS
  10. MySQL 的日语认证有了,中文呢?