密钥交换算法 - Java加密与安全
生活随笔
收集整理的這篇文章主要介紹了
密钥交换算法 - Java加密与安全
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
密鑰交換算法我們在使用對稱加密算法的時候,我們用的是同一個密鑰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加密与安全的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 口令加密算法 - Java加密与安全
- 下一篇: 非对称加密算法 - Java加密与安全