非对称加密算法---加密学习笔记(四)
介紹:
非對稱加密相對與對稱加密算法來說是高級的。
舉個雙保險的例子:
銀行的保險柜,客戶往銀行的保險柜存貴重東西,這個保險柜的鑰匙會有兩把,客戶有一把,銀行有一把。如果想打開保險柜就需要銀行的鑰匙和客戶的鑰匙一塊使用才能打開保險柜。
公鑰,私鑰:客戶和銀行的鑰匙
公鑰:是通過非安全的通道發放的,也就是說是公開的方式
私鑰:自己保存的。
公鑰和私鑰一般是成對出現的,使用公鑰加密的數據只有與它對應的私鑰才能解開。
在非對稱加密算法中有一些算法是可以公鑰加密私鑰解密,私鑰加密公鑰解密都支持的,有一些算法只支持一種方式的。
非對稱加密算法種類:
DH(Diffie-Hellman):密鑰交換算法
RSA:基于因子分解,既能用于數字加密也能用于數字簽名
Elgamal:基于離散對數
ECC(Elliptical Curve Cryptography):橢圓曲線加密
DH
對稱加密算法的弊端:
對稱加密算法中公布密鑰這個步驟會有問題,發送密鑰的時候可能會出現泄露密鑰的情況。一旦密鑰被泄露,那么所有的數據就很容易被破解掉。
但是DH(密鑰交換算法)是通過構建本地密鑰來解決密鑰容易在傳遞中泄露的問題的。
初始化發送方密鑰涉及的三個類:
1. KeyPairGenerator(通過KeyPairGenerator來得到KeyPair類的對象)
2 KeyPair(得到密鑰對,包括公鑰和私鑰)
3. PublicKey:公鑰
初始化接收方密鑰涉及到的類:
1. KeyFactory:作用是生成密鑰(包括公鑰和私鑰)
generatePublic()方法用來生成公鑰
generatePrivate()方法用來生成私鑰
2 X509EncodedKeySpec:根據ASN.1標準進行密鑰編碼
3. DHPublicKey:是PublicKey的某種具體的形式
4. DHParameterSpec:隨從著DH算法來使用的參數的集合
5. KeyPairGenerator:通過KeyPairGenerator來得到KeyPair類的對象
6. PrivateKey:私鑰
密鑰構建涉及的類
2 SecretKey:生成一個分組的秘密密鑰,同時提供了相應的類型安全的操作
3. KeyFactory
4. X509EncodedKeySpec
5. PublicKey
加解密涉及到的類:
Cipher
例子
package com.timliu.security.asymmetric_encryption;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.Objects;import javax.crypto.Cipher; import javax.crypto.KeyAgreement; import javax.crypto.SecretKey; import javax.crypto.interfaces.DHPublicKey; import javax.crypto.spec.DHParameterSpec;import org.apache.commons.codec.binary.Base64;public class DHTest {public static final String src = "hello world";public static void main(String[] args) {jdkDH();}// jdk實現:public static void jdkDH() {try {/** 發送方的操作*/// 1.初始化發送方密鑰KeyPairGenerator senderKeyPairGenerator = KeyPairGenerator.getInstance("DH");senderKeyPairGenerator.initialize(512);//設置長度KeyPair senderKeyPair = senderKeyPairGenerator.generateKeyPair();//生成keypair// 保存了發送方公鑰的字節數組,發送給接收方(發送方式:網絡、文件。。。)byte[] senderPublicKeyEnc = senderKeyPair.getPublic().getEncoded();/** 接收方的操作*/// 2.初始化接收方密鑰KeyFactory receiverKeyFactory = KeyFactory.getInstance("DH");X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(senderPublicKeyEnc);PublicKey receiverPublicKey = receiverKeyFactory.generatePublic(x509EncodedKeySpec);DHParameterSpec dhParameterSpec = ((DHPublicKey) receiverPublicKey).getParams();KeyPairGenerator receiverKeyPairGenerator = KeyPairGenerator.getInstance("DH");receiverKeyPairGenerator.initialize(dhParameterSpec);KeyPair receiverKeypair = receiverKeyPairGenerator.generateKeyPair();PrivateKey receiverPrivateKey = receiverKeypair.getPrivate();//保存了接收方公鑰的字節數組,發送給發送方(發送方式:網絡,文件。。。。)byte[] receiverPublicKeyEnc = receiverKeypair.getPublic().getEncoded();// 3.密鑰構建KeyAgreement receiverKeyAgreement = KeyAgreement.getInstance("DH");receiverKeyAgreement.init(receiverPrivateKey);receiverKeyAgreement.doPhase(receiverPublicKey, true);//生成接收方的本地密鑰SecretKey receiverDesKey = receiverKeyAgreement.generateSecret("DES");/** 發送方的操作*/KeyFactory senderKeyFactory = KeyFactory.getInstance("DH");x509EncodedKeySpec = new X509EncodedKeySpec(receiverPublicKeyEnc);PublicKey senderPublicKey = senderKeyFactory.generatePublic(x509EncodedKeySpec);KeyAgreement senderKeyAgreement = KeyAgreement.getInstance("DH");senderKeyAgreement.init(senderKeyPair.getPrivate());senderKeyAgreement.doPhase(senderPublicKey, true);//生成發送方的本地密鑰SecretKey senderDesKey = senderKeyAgreement.generateSecret("DES");if(Objects.equals(receiverDesKey, senderDesKey)){System.out.println("發送方和接收方密鑰相同。");}else{System.out.println("發送方和接收方密鑰不相同");}// 4.加密Cipher cipher = Cipher.getInstance("DES");cipher.init(Cipher.ENCRYPT_MODE, senderDesKey);byte[] result = cipher.doFinal(src.getBytes());System.out.println("bc dh encrypt:"+ Base64.encodeBase64String(result));// 5.解密cipher.init(Cipher.DECRYPT_MODE, receiverDesKey);result = cipher.doFinal(result);System.out.println("bc dh decrypt:" + new String(result));} catch (Exception e) {e.printStackTrace();}}}運行結果:
DH算法的應用場景
RSA
唯一廣泛接受并實現的非對稱加密的算法。
可以實現數據加密和數字簽名。
提供了:
1. 公鑰加密,私鑰解密
2. 私鑰加密,公鑰解密
例子:
package com.timliu.security.asymmetric_encryption;import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.PrivateKey; import java.security.PublicKey; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec;import javax.crypto.Cipher;import org.apache.commons.codec.binary.Base64;public class RSATest {public static final String src = "hello world";public static void main(String[] args) {jdkRSA();}// jdk實現:public static void jdkRSA() {try {// 1.初始化發送方密鑰KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");keyPairGenerator.initialize(512);KeyPair keyPair = keyPairGenerator.generateKeyPair();RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();System.out.println("Public Key:"+ Base64.encodeBase64String(rsaPublicKey.getEncoded()));System.out.println("Private Key:"+ Base64.encodeBase64String(rsaPrivateKey.getEncoded()));// 2.私鑰加密、公鑰解密 ---- 加密PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());KeyFactory keyFactory = KeyFactory.getInstance("RSA");PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);Cipher cipher = Cipher.getInstance("RSA");cipher.init(Cipher.ENCRYPT_MODE, privateKey);byte[] result = cipher.doFinal(src.getBytes());System.out.println("私鑰加密、公鑰解密 ---- 加密:"+ Base64.encodeBase64String(result));// 3.私鑰加密、公鑰解密 ---- 解密X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(rsaPublicKey.getEncoded());keyFactory = KeyFactory.getInstance("RSA");PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);cipher = Cipher.getInstance("RSA");cipher.init(Cipher.DECRYPT_MODE, publicKey);result = cipher.doFinal(result);System.out.println("私鑰加密、公鑰解密 ---- 解密:" + new String(result));// 4.公鑰加密、私鑰解密 ---- 加密X509EncodedKeySpec x509EncodedKeySpec2 = new X509EncodedKeySpec(rsaPublicKey.getEncoded());KeyFactory keyFactory2 = KeyFactory.getInstance("RSA");PublicKey publicKey2 = keyFactory2.generatePublic(x509EncodedKeySpec2);Cipher cipher2 = Cipher.getInstance("RSA");cipher2.init(Cipher.ENCRYPT_MODE, publicKey2);byte[] result2 = cipher2.doFinal(src.getBytes());System.out.println("公鑰加密、私鑰解密 ---- 加密:"+ Base64.encodeBase64String(result2));// 5.公鑰加密、私鑰解密 ---- 解密PKCS8EncodedKeySpec pkcs8EncodedKeySpec5 = new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());KeyFactory keyFactory5 = KeyFactory.getInstance("RSA");PrivateKey privateKey5 = keyFactory5.generatePrivate(pkcs8EncodedKeySpec5);Cipher cipher5 = Cipher.getInstance("RSA");cipher5.init(Cipher.DECRYPT_MODE, privateKey5);byte[] result5 = cipher5.doFinal(result2);System.out.println("公鑰加密、私鑰解密 ---- 解密:" + new String(result5));} catch (Exception e) {e.printStackTrace();}}}運行結果:
Public Key: MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAOz8ggiZp7ly13XoE9CtW3OlXQjVbrXc8zZCdKhFagXSSFcUvGqKbdfZuvjAjET7Vec7GurqLX14w99KnxFAbD8CAwEAAQ== Private Key: MIIBVQIBADANBgkqhkiG9w0BAQEFAASCAT8wggE7AgEAAkEA7PyCCJmnuXLXdegT0K1bc6VdCNVutdzzNkJ0qEVqBdJIVxS8aopt19m6+MCMRPtV5zsa6uotfXjD30qfEUBsPwIDAQABAkAjp4nYyWVWnVSVRKlWh/5uU76/iXzyl59v1me+uVLONR7XjkQyz7Kq3uh33276FAxZtHFlabphCpZf0aqpUFuBAiEA9lAF2lMjx379oTtRJhs75iw11z7f+hpaxaUN+JMa1RECIQD2TpWxJfF20bRyDCi0U2sl2ElqdxjZe0pAAiebgr3sTwIgbEChQeHWUMBUMf9C2++ONMvrYc1FXMMmb8TpzfzBBzECIQCOB4y8JRQTHyO9bBOAwGWV4h2bneefaT/MnzF1tDOOcwIhALs3oH3XIAPBU2bFBaGqBTO//XIUoE8CfyOfPA3fvusC 私鑰加密、公鑰解密 ---- 加密: cIvL/HQH8gMBpD5qi99B4Cql/qZiNFc7eHfnua9qlQLGfQ436wNV9tzCQg+n7cR+/mDlAUSAvegwvk/0FD/Jmw== 私鑰加密、公鑰解密 ---- 解密:hello world 公鑰加密、私鑰解密 ---- 加密: rvG7tdyCbU5B4fbT2xrFPkH8tUUsepkpZwGALi56/CCpVWOyvGq/aqBS4dQJKxjwH0t0pfWzt+iw3fJe3qTwGg== 公鑰加密、私鑰解密 ---- 解密:hello worldRSA應用場景:
ElGamal
提供公鑰加密算法。
基于離散對數。
JDK沒有提供ElGamal算法的實現,是Bouncy Castle提供的。
例子:
package com.timliu.security.asymmetric_encryption;import java.security.AlgorithmParameterGenerator; import java.security.AlgorithmParameters; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.PrivateKey; import java.security.PublicKey; import java.security.SecureRandom; import java.security.Security; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec;import javax.crypto.Cipher; import javax.crypto.spec.DHParameterSpec;import org.apache.commons.codec.binary.Base64; import org.bouncycastle.jce.provider.BouncyCastleProvider;public class ElGamalTest {public static final String src = "hello world";public static void main(String[] args) {BCElgamal();}/*** * 對于:“Illegal key size or default* parameters”異常,是因為美國的出口限制,Sun通過權限文件(local_policy* .jar、US_export_policy.jar)做了相應限制。因此存在一些問題: Java 6* 無政策限制文件:http://www.oracle* .com/technetwork/java/javase/downloads/jce-6-download-429243.html Java 7* 無政策限制文件* :http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download* -432124.html 我的時java7,自己安裝的。* /Library/Java/JavaVirtualMachines/jdk1.7.0_71* .jdk/Contents/Home/jre/lib/security目錄下* ,對應覆蓋local_policy.jar和US_export_policy.jar兩個文件。* * 切換到%JDK_Home%\jre\lib\security目錄下,對應覆蓋local_policy.jar和US_export_policy.* jar兩個文件。同時,你可能有必要在%JRE_Home%\lib\security目錄下,也需要對應覆蓋這兩個文件。*/// BC實現:“私鑰解密、公鑰加密” , 對于:“私鑰加密、公鑰解密”有問題,因為Elgamal不支持public static void BCElgamal() {try {// 加入對BouncyCastle支持Security.addProvider(new BouncyCastleProvider());// 1.初始化發送方密鑰AlgorithmParameterGenerator algorithmParameterGenerator = AlgorithmParameterGenerator.getInstance("Elgamal");// 初始化參數生成器algorithmParameterGenerator.init(256);// 生成算法參數AlgorithmParameters algorithmParameters = algorithmParameterGenerator.generateParameters();// 構建參數材料DHParameterSpec dhParameterSpec = (DHParameterSpec) algorithmParameters.getParameterSpec(DHParameterSpec.class);// 實例化密鑰生成器KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("Elgamal");// 初始化密鑰對生成器keyPairGenerator.initialize(dhParameterSpec, new SecureRandom());KeyPair keyPair = keyPairGenerator.generateKeyPair();// 公鑰PublicKey elGamalPublicKey = keyPair.getPublic();// 私鑰PrivateKey elGamalPrivateKey = keyPair.getPrivate();System.out.println("Public Key:"+ Base64.encodeBase64String(elGamalPublicKey.getEncoded()));System.out.println("Private Key:"+ Base64.encodeBase64String(elGamalPrivateKey.getEncoded()));// 2.私鑰解密、公鑰加密 ---- 加密// 初始化公鑰// 密鑰材料轉換X509EncodedKeySpec x509EncodedKeySpec2 = new X509EncodedKeySpec(elGamalPublicKey.getEncoded());// 實例化密鑰工廠KeyFactory keyFactory2 = KeyFactory.getInstance("Elgamal");// 產生公鑰PublicKey publicKey2 = keyFactory2.generatePublic(x509EncodedKeySpec2);// 數據加密// Cipher cipher2 = Cipher.getInstance("Elgamal");Cipher cipher2 = Cipher.getInstance(keyFactory2.getAlgorithm());cipher2.init(Cipher.ENCRYPT_MODE, publicKey2);byte[] result2 = cipher2.doFinal(src.getBytes());System.out.println("私鑰加密、公鑰解密 ---- 加密:"+ Base64.encodeBase64String(result2));// 3.私鑰解密、公鑰加密 ---- 解密PKCS8EncodedKeySpec pkcs8EncodedKeySpec5 = new PKCS8EncodedKeySpec(elGamalPrivateKey.getEncoded());KeyFactory keyFactory5 = KeyFactory.getInstance("Elgamal");PrivateKey privateKey5 = keyFactory5.generatePrivate(pkcs8EncodedKeySpec5);// Cipher cipher5 = Cipher.getInstance("Elgamal");Cipher cipher5 = Cipher.getInstance(keyFactory5.getAlgorithm());cipher5.init(Cipher.DECRYPT_MODE, privateKey5);byte[] result5 = cipher5.doFinal(result2);System.out.println("Elgamal 私鑰加密、公鑰解密 ---- 解密:"+ new String(result5));} catch (Exception e) {e.printStackTrace();}}}運行結果:
應用場景:
總結
以上是生活随笔為你收集整理的非对称加密算法---加密学习笔记(四)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 对称加密算法---加密学习笔记(三)
- 下一篇: Eclipse中Build Path的使