11.一、非對稱加密算法java
特色:算法
常見算法:apache
11.二、DH(僅能用於密鑰分配,不能加解密數據)數組
實現方式:安全
幾個概念:ide
整個流程:post
1)甲乙雙方初始化各自的密鑰對測試
甲方構建出密鑰對keyPair1-->乙方使用甲方的密鑰對中的公鑰publicKey1構建出本身的密鑰對keyPair2網站
2)甲乙雙方構建各自的本地密鑰加密
甲方使用本身的私鑰privateKey1+乙方的公鑰publicKey2構建出本身的本地密鑰key1
乙方使用本身的私鑰privateKey2+甲方的公鑰publicKey1構建出本身的本地密鑰key2
最後會發現key1==key2,這兩個本地密鑰將會是接下來對對稱加密所使用的密鑰
3)發送方(甲方或乙方都可)使用本地密鑰+對稱加密算法對待加密數據進行加密,傳遞給接收方
4)接收方使用本地密鑰+對稱加密算法對待解密數據進行解密
1 package com.util.dh; 2 3 import java.io.UnsupportedEncodingException; 4 import java.security.InvalidAlgorithmParameterException; 5 import java.security.InvalidKeyException; 6 import java.security.Key; 7 import java.security.KeyFactory; 8 import java.security.KeyPair; 9 import java.security.KeyPairGenerator; 10 import java.security.NoSuchAlgorithmException; 11 import java.security.PrivateKey; 12 import java.security.PublicKey; 13 import java.security.spec.InvalidKeySpecException; 14 import java.security.spec.PKCS8EncodedKeySpec; 15 import java.security.spec.X509EncodedKeySpec; 16 17 import javax.crypto.BadPaddingException; 18 import javax.crypto.Cipher; 19 import javax.crypto.IllegalBlockSizeException; 20 import javax.crypto.KeyAgreement; 21 import javax.crypto.NoSuchPaddingException; 22 import javax.crypto.interfaces.DHPublicKey; 23 import javax.crypto.spec.DHParameterSpec; 24 import javax.crypto.spec.SecretKeySpec; 25 26 import org.apache.commons.codec.binary.Base64; 27 28 /** 29 * 基於JDK的DH算法,工做模式採用ECB 30 */ 31 public class DHJDK { 32 private static final String ENCODING = "UTF-8"; 33 private static final String FDC_KEY_ALGORITHM = "DH";//非對稱加密密鑰算法 34 private static final String DC_KEY_ALGORITHM = "AES";//產生本地密鑰的算法(對稱加密密鑰算法) 35 private static final String CIPHER_ALGORITHM = "AES/ECB/PKCS5Padding";//加解密算法 格式:算法/工做模式/填充模式 注意:ECB不使用IV參數 36 private static final int FDC_KEY_SIZE = 512;//非對稱密鑰長度(512~1024之間的64的整數倍) 37 38 /** 39 * 生成甲方密鑰對 40 */ 41 public static KeyPair initKey() throws NoSuchAlgorithmException{ 42 KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(FDC_KEY_ALGORITHM);//密鑰對生成器 43 keyPairGenerator.initialize(FDC_KEY_SIZE);//指定密鑰長度 44 KeyPair keyPair = keyPairGenerator.generateKeyPair();//生成密鑰對 45 return keyPair; 46 } 47 48 /** 49 * 生成乙方密鑰對 50 * @param key 甲方公鑰 51 */ 52 public static KeyPair initKey(byte[] key) throws NoSuchAlgorithmException, 53 InvalidKeySpecException, 54 InvalidAlgorithmParameterException{ 55 KeyFactory keyFactory = KeyFactory.getInstance(FDC_KEY_ALGORITHM);//密鑰工廠 56 PublicKey publicKey = keyFactory.generatePublic(new X509EncodedKeySpec(key));//還原甲方公鑰 57 DHParameterSpec dHParameterSpec = ((DHPublicKey)publicKey).getParams(); 58 59 KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(keyFactory.getAlgorithm());//乙方密鑰對生成器 60 keyPairGenerator.initialize(dHParameterSpec);//使用甲方公鑰參數初始化乙方密鑰對生成器 61 KeyPair keyPair = keyPairGenerator.generateKeyPair();//生成密鑰對 62 return keyPair; 63 } 64 65 /** 66 * DH加密 67 * @param data 帶加密數據 68 * @param keyByte 本地密鑰,由getSecretKey(byte[] publicKey, byte[] privateKey)產生 69 */ 70 public static byte[] encrypt(String data, byte[] keyByte) throws NoSuchAlgorithmException, 71 NoSuchPaddingException, 72 InvalidKeyException, 73 IllegalBlockSizeException, 74 BadPaddingException, 75 UnsupportedEncodingException { 76 Key key = new SecretKeySpec(keyByte, DC_KEY_ALGORITHM);//生成本地密鑰 77 78 Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM); 79 cipher.init(Cipher.ENCRYPT_MODE, key);//設置加密模式而且初始化key 80 return cipher.doFinal(data.getBytes(ENCODING)); 81 } 82 83 /** 84 * DH解密 85 * @param data 待解密數據爲字節數組 86 * @param keyByte 本地密鑰,由getSecretKey(byte[] publicKey, byte[] privateKey)產生 87 */ 88 public static byte[] decrypt(byte[] data, byte[] keyByte) throws NoSuchAlgorithmException, 89 NoSuchPaddingException, 90 InvalidKeyException, 91 IllegalBlockSizeException, 92 BadPaddingException { 93 Key key = new SecretKeySpec(keyByte, DC_KEY_ALGORITHM);//生成本地密鑰 94 Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM); 95 cipher.init(Cipher.DECRYPT_MODE, key); 96 return cipher.doFinal(data); 97 } 98 99 /** 100 * 根據本方私鑰與對方公鑰構建本地密鑰(即對稱加密的密鑰) 101 * @param publicKey 對方公鑰 102 * @param privateKey 本方私鑰 103 */ 104 public static byte[] getSecretKey(byte[] publicKey, byte[] privateKey) throws NoSuchAlgorithmException, 105 InvalidKeySpecException, 106 InvalidKeyException{ 107 KeyFactory keyFactory = KeyFactory.getInstance(FDC_KEY_ALGORITHM);//密鑰工廠 108 PublicKey pubkey = keyFactory.generatePublic(new X509EncodedKeySpec(publicKey));//還原公鑰 109 PrivateKey prikey = keyFactory.generatePrivate(new PKCS8EncodedKeySpec(privateKey));//還原私鑰 110 111 KeyAgreement keyAgreement = KeyAgreement.getInstance(keyFactory.getAlgorithm()); 112 keyAgreement.init(prikey); 113 keyAgreement.doPhase(pubkey, true); 114 return keyAgreement.generateSecret(DC_KEY_ALGORITHM).getEncoded();//生成本地密鑰(對稱加密的密鑰) 115 } 116 117 /** 118 * 獲取公鑰 119 */ 120 public static byte[] getPublicKey(KeyPair keyPair){ 121 return keyPair.getPublic().getEncoded(); 122 } 123 124 /** 125 * 獲取私鑰 126 */ 127 public static byte[] getPrivateKey(KeyPair keyPair){ 128 return keyPair.getPrivate().getEncoded(); 129 } 130 131 /** 132 * 測試 133 */ 134 public static void main(String[] args) throws NoSuchAlgorithmException, 135 InvalidKeySpecException, 136 InvalidAlgorithmParameterException, 137 InvalidKeyException, 138 NoSuchPaddingException, 139 IllegalBlockSizeException, 140 BadPaddingException, 141 UnsupportedEncodingException { 142 byte[] pubKey1;//甲方公鑰 143 byte[] priKey1;//甲方私鑰 144 byte[] key1;//甲方本地密鑰 145 byte[] pubKey2;//乙方公鑰 146 byte[] priKey2;//乙方私鑰 147 byte[] key2;//乙方本地密鑰 148 149 /*********************測試是否能夠正確生成以上6個key,以及key1與key2是否相等*********************/ 150 KeyPair keyPair1 = DHJDK.initKey();//生成甲方密鑰對 151 pubKey1 = DHJDK.getPublicKey(keyPair1); 152 priKey1 = DHJDK.getPrivateKey(keyPair1); 153 154 KeyPair keyPair2 = DHJDK.initKey(pubKey1);//根據甲方公鑰生成乙方密鑰對 155 pubKey2 = DHJDK.getPublicKey(keyPair2); 156 priKey2 = DHJDK.getPrivateKey(keyPair2); 157 158 key1 = DHJDK.getSecretKey(pubKey2, priKey1);//使用對方公鑰和本身私鑰構建本地密鑰 159 key2 = DHJDK.getSecretKey(pubKey1, priKey2);//使用對方公鑰和本身私鑰構建本地密鑰 160 161 System.out.println("甲方公鑰pubKey1-->"+Base64.encodeBase64String(pubKey1)+"@@pubKey1.length-->"+pubKey1.length); 162 System.out.println("甲方私鑰priKey1-->"+Base64.encodeBase64String(priKey1)+"@@priKey1.length-->"+priKey1.length); 163 System.out.println("乙方公鑰pubKey2-->"+Base64.encodeBase64String(pubKey2)+"@@pubKey2.length-->"+pubKey2.length); 164 System.out.println("乙方私鑰priKey2-->"+Base64.encodeBase64String(priKey2)+"@@priKey2.length-->"+priKey2.length); 165 System.out.println("甲方密鑰key1-->"+Base64.encodeBase64String(key1)); 166 System.out.println("乙方密鑰key2-->"+Base64.encodeBase64String(key2)); 167 168 /*********************測試甲方使用本地密鑰加密數據向乙方發送,乙方使用本地密鑰解密數據*********************/ 169 System.out.println("甲方-->乙方"); 170 String data = "找一個好姑娘啊!"; 171 byte[] encodeStr = DHJDK.encrypt(data, key1); 172 System.out.println("甲方加密後的數據-->"+Base64.encodeBase64String(encodeStr)); 173 byte[] decodeStr = DHJDK.decrypt(encodeStr, key2); 174 System.out.println("乙方解密後的數據-->"+new String(decodeStr,"UTF-8")); 175 176 /*********************測試乙方使用本地密鑰加密數據向甲方發送,甲方使用本地密鑰解密數據*********************/ 177 System.out.println("乙方-->甲方"); 178 String data2 = "找一個好姑娘啊!"; 179 byte[] encodeStr2 = DHJDK.encrypt(data2, key2); 180 System.out.println("乙方加密後的數據-->"+Base64.encodeBase64String(encodeStr2)); 181 byte[] decodeStr2 = DHJDK.decrypt(encodeStr, key1); 182 System.out.println("甲方解密後的數據-->"+new String(decodeStr2,"UTF-8")); 183 } 184 }