密钥交换算法 - Java加密与安全
生活随笔
收集整理的這篇文章主要介紹了
密钥交换算法 - Java加密与安全
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
密鑰交換算法我們?cè)谑褂脤?duì)稱加密算法的時(shí)候,我們用的是同一個(gè)密鑰key
我們以AES加密為例,當(dāng)我們需要加密明文,我們需要一個(gè)隨機(jī)生成的key,作為密鑰進(jìn)行加解密,最后我們的問題是如何傳遞密鑰
因?yàn)椴唤o對(duì)方密鑰,對(duì)方就不能解密,而直接傳遞密鑰,就會(huì)被黑客監(jiān)聽,所以問題就變成了如何在不安全的信道上如何安全的傳輸密鑰
密鑰算法也就是Diffie-Hellman算法,簡稱DH算法,他就是為了解決這個(gè)問題的,p=509,g=5,A=215,你收到以后,他也選擇一個(gè)隨機(jī)數(shù)b,例如456,然后得到g的b次方,然后對(duì)p取余數(shù),結(jié)果是181,然后計(jì)算S等于A的b次方,除以p的余數(shù),結(jié)果是121,乙把計(jì)算的B發(fā)給甲,甲計(jì)算S等于B的a次方,除以p的余數(shù),結(jié)果計(jì)算的s相同,也是121,所以最后雙方協(xié)商的密鑰,是121,要注意這個(gè)密鑰并沒有在網(wǎng)絡(luò)上傳輸,通過網(wǎng)絡(luò)傳輸?shù)氖莗,g,A,B,但是通過這4個(gè)數(shù),黑客是無法推算出S的,所以更確切的說,DH算法是密鑰協(xié)商算法,雙方最終協(xié)商一個(gè)共同的密鑰
我們把小a看成是甲的密鑰,大A看成是甲的公鑰,小b看成是乙的私鑰,大b看成是公鑰,DH的算法本質(zhì)是各自生成自己的公鑰和私鑰,然后交換公鑰,并且根據(jù)自己的私鑰和對(duì)方的公鑰,生成最終的私鑰,DH算法通過數(shù)學(xué)
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 {/*** 我們寫一個(gè)main方法來測試DH協(xié)商協(xié)議* @param args*/public static void main(String[] args) {// Bob 和 Alice/*** 首先我們創(chuàng)建兩個(gè)Person對(duì)象* 一個(gè)是Bob,一個(gè)是Alice*/Person bob = new Person("Bob");Person alice = new Person("Alice");// 各自生成KeyPair:/*** 然后Bob和Alice各自生成自己的KeyPair*/bob.generateKeyPair();alice.generateKeyPair();// 雙方交換各自的PublicKey:// Bob根據(jù)Alice的PublicKey生成自己的本地密鑰:/*** 緊接著各自交換publicKey* 由于Bob需要Alice的publicKey生成自己的本地密鑰* 所以我們對(duì)Bob調(diào)用generateSecretKey的時(shí)候* 我們需要傳入alice.publicKey.getEncoded()*/bob.generateSecretKey(alice.publicKey.getEncoded());// Alice根據(jù)Bob的PublicKey生成自己的本地密鑰:/*** 同樣的Alice是通過bob的publicKey來生成自己的本地密鑰*/alice.generateSecretKey(bob.publicKey.getEncoded());// 檢查雙方本地密鑰是否相同/*** 我們來看一下他們的本地密鑰是否相同* 如果雙方的SecretKey是相同的* 那么后序的通信就可以使用這個(gè)SecretKey* AES加解密* 我們看到Bob的privateKey和publicKey以及Bob生成的secretKey* 我們?cè)賮砜碅lice的privateKey和publicKey以及Alice生成的secretKey* 我們注意到Alice的SecretKey和Bob的SecretKey他們是相同的* 所以在后序的通訊中,* Bob和Alice可以使用這兩個(gè)相同的key以及AES的加解密*/bob.printKeys();alice.printKeys();// 雙方的SecretKey相同,后續(xù)通信將使用SecretKey作為密鑰進(jìn)行AES加密String msgBobToAlice = bob.sendMessage("Hello, Alice!");System.out.println("Bob -> Alice: " + msgBobToAlice);String aliceDecrypted = alice.receiveMessage(msgBobToAlice);System.out.println("Alice decrypted: " + aliceDecrypted);}
}/*** 我們首先定義了一個(gè)Person類* @author Leon.Sun**/
class Person {/*** 我們定義了一個(gè)name字段,表示Person名字*/public final String name;/*** publicKey表示public Key*/public PublicKey publicKey;/*** privateKey表示private Key*/private PrivateKey privateKey;/*** 這個(gè)把表示最后生成的secretKey*/private SecretKey secretKey;/*** 我們定義個(gè)方法來初始化Person的名字* @param name*/public Person(String name) {this.name = name;}/*** 生成本地KeyPair* * 緊接著我們定義一個(gè)generateKeyPair*/public void generateKeyPair() {try {/*** 我們通過KeyPairGenerator.getInstance傳入DH表示我們要生成KeyPairGenerator* 用于DH算法*/KeyPairGenerator kpGen = KeyPairGenerator.getInstance("DH");/*** 表示我們要生成512位的keyPair*/kpGen.initialize(512);/*** 我們通過generateKeyPair所獲得一個(gè)KeyPair對(duì)象*/KeyPair kp = kpGen.generateKeyPair();/*** 緊接著我們通過getPrivate和getPublic分別獲得了privateKey和publicKey*/this.privateKey = kp.getPrivate();this.publicKey = kp.getPublic();} catch (GeneralSecurityException e) {throw new RuntimeException(e);}}/*** 生成密鑰* * 當(dāng)通信的雙方把publicKey交給雙方的時(shí)候,* 我們都可以從對(duì)方接收到public key這個(gè)字節(jié)中回復(fù)public key對(duì)象* * @param receivedPubKeyBytes*/public void generateSecretKey(byte[] receivedPubKeyBytes) {try {// 從byte[]恢復(fù)PublicKey/*** 我們通過X509EncodedKeySpec這個(gè)類傳入收到的字節(jié)數(shù)組* 就可以恢復(fù)公鑰*/X509EncodedKeySpec keySpec = new X509EncodedKeySpec(receivedPubKeyBytes);KeyFactory kf = KeyFactory.getInstance("DH");/*** 我們可以通過generatePublic*/PublicKey receivedPublicKey = kf.generatePublic(keySpec);// 生成本地密鑰:/*** 我們通過KeyAgreement.getInstance傳入DH得到一個(gè)KeyAgreement對(duì)象*/KeyAgreement keyAgreement = KeyAgreement.getInstance("DH");/*** 然后我們通過init方法傳入自己的private key*/keyAgreement.init(this.privateKey); // 自己的PrivateKey/*** 然后我們通過doPhase傳入對(duì)方的publicKey,*/keyAgreement.doPhase(receivedPublicKey, true);// 對(duì)方的PublicKey// 生成AES密鑰:/*** 這個(gè)時(shí)候我們通過generateSecret傳入AES表示我們要生成一個(gè)AES的密鑰* 這個(gè)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()));}/*** 發(fā)送加密消息* * 我們用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算法不能避免中間人攻擊,如果黑客假冒乙和甲交互密鑰,同時(shí)又假冒乙和甲交互密鑰,他就可以成功的進(jìn)行攻擊最后我們總結(jié)一下:1. DH算法是一種密鑰交換協(xié)議,通信雙方通過一個(gè)不安全的信道協(xié)商密鑰,然后進(jìn)行對(duì)稱加密傳輸2. DH算法并沒有解決中間人攻擊的問題
?
總結(jié)
以上是生活随笔為你收集整理的密钥交换算法 - Java加密与安全的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 口令加密算法 - Java加密与安全
- 下一篇: 非对称加密算法 - Java加密与安全