非对称密码概念
发送者使用接收者的公钥加密,接收者使用自己的私钥解密。
需要两个密钥进行加密或解密,分为公钥和私钥
特点:安全性高,速度慢
常用算法
DH密钥交换算法
RSA算法
ElGamal算法那
用途
密钥交换(DH)
双方在没有确定共同密钥的情况下,生成密钥,不提供加密工作,加解密还需要其他对称加密算法实现
加密/解密(RSA)
数字签名(RSA)
DH算法示例
import javax.crypto.KeyAgreement;
import javax.crypto.interfaces.DHPrivateKey;
import javax.crypto.interfaces.DHPublicKey;
import javax.crypto.spec.DHParameterSpec;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
//1 生成源密钥
//2 把源公钥交给目标,目标通过源公钥,生成目标公钥和私钥
//3 把目标公钥交给源
//4 双方使用对方的公钥和和自己的私钥,生成本地密钥
//5 如果双方生成本地密钥相同则完成密钥交换
public class DHUtil {
public static final String PUBLIC_KEY = "DH_Public_Key";
public static final String PRIVATE_KEY = "DH_Private_key";
/**
* 生成源密钥对
* @return
* @throws Exception
*/
public static Map<String,Object> initSourceKey() throws Exception{
//创建KeyPairGenerator的实例,选用DH算法
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("DH");
//初始化密钥长度,默认1024,可选范围512-65536 & 64的倍数
keyPairGenerator.initialize(1024);
//生成密钥对
KeyPair keyPair = keyPairGenerator.generateKeyPair();
DHPublicKey dhPublicKey = (DHPublicKey) keyPair.getPublic();
DHPrivateKey dhPrivateKey = (DHPrivateKey) keyPair.getPrivate();
//将密钥对放入Map
Map<String,Object> keyMap = new HashMap<String, Object>();
keyMap.put(PUBLIC_KEY, dhPublicKey);
keyMap.put(PRIVATE_KEY, dhPrivateKey);
return keyMap;
}
/**
* 通过源公钥 生成 目标密钥对
* @param sourcePublicKey
* @return
* @throws Exception
*/
public static Map<String,Object> initTargetKey(byte[] sourcePublicKey) throws Exception {
KeyFactory keyFactory = KeyFactory.getInstance("DH");
//通过源公钥,生成keySpec,使用KeyFactory生成源PublicKey相关信息
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(sourcePublicKey);
DHPublicKey sourcePublic = (DHPublicKey) keyFactory.generatePublic(keySpec);
DHParameterSpec dhPublicKeyParams = sourcePublic.getParams();
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("DH");
keyPairGenerator.initialize(dhPublicKeyParams);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
DHPublicKey dhPublicKey = (DHPublicKey) keyPair.getPublic();
DHPrivateKey dhPrivateKey = (DHPrivateKey) keyPair.getPrivate();
//将密钥对放入Map
Map<String,Object> keyMap = new HashMap<String, Object>();
keyMap.put(PUBLIC_KEY, dhPublicKey);
keyMap.put(PRIVATE_KEY, dhPrivateKey);
return keyMap;
}
/**
* 使用一方的公钥和另一方的私钥,生成本地密钥
* @return
*/
public static byte[] generateLocalSecretKey(byte[] aPublicKey, byte[] bPrivateKey) throws Exception{
KeyFactory keyFactory = KeyFactory.getInstance("DH");
//通过A公钥,生成keySpec,使用KeyFactory生成A PublicKey相关信息
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(aPublicKey);
PublicKey publicKey = keyFactory.generatePublic(keySpec);
//通过B私钥,生成B PrivateKey相关信息
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(bPrivateKey);
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
//通过KeyAgreement对A的PublicKey和B的PrivateKey进行加密
KeyAgreement keyAgreement = KeyAgreement.getInstance("DH");
keyAgreement.init(privateKey);
keyAgreement.doPhase(publicKey,true);
return keyAgreement.generateSecret("AES").getEncoded();//算法使用对称加密算法(DES,DESede,AES)
//return keyAgreement.generateSecret(); // 也可以不选择算法,使用默认方法计算
}
//获取公钥字节数组
public static byte[] getPublicKey(Map<String,Object> map){
return ((DHPublicKey) map.get(PUBLIC_KEY)).getEncoded();
}
//获取私钥字节数组
public static byte[] getPrivateKey(Map<String,Object> map){
return ((DHPrivateKey) map.get(PRIVATE_KEY)).getEncoded();
}
public static void main(String[] args) throws Exception {
byte[] source_public_key;
byte[] source_private_key;
byte[] source_local_key;
byte[] target_public_key;
byte[] target_private_key;
byte[] target_local_key;
Map<String, Object> sourceKey = initSourceKey();
source_public_key = getPublicKey(sourceKey);
source_private_key = getPrivateKey(sourceKey);
System.out.println("源公钥:"+BytesToHex.fromBytesToHex(source_public_key));
System.out.println("源私钥:"+BytesToHex.fromBytesToHex(source_private_key));
Map<String, Object> targetKey = initTargetKey(getPublicKey(sourceKey));
target_public_key = getPublicKey(targetKey);
target_private_key = getPrivateKey(targetKey);
System.out.println("目标公钥:"+BytesToHex.fromBytesToHex(target_public_key));
System.out.println("目标私钥:"+BytesToHex.fromBytesToHex(target_private_key));
source_local_key = generateLocalSecretKey(target_public_key, source_private_key);
target_local_key = generateLocalSecretKey(source_public_key, target_private_key);
System.out.println("源本地密钥:"+BytesToHex.fromBytesToHex(source_local_key));
System.out.println("目标本地密钥:"+BytesToHex.fromBytesToHex(target_local_key));
}
}
RSA 加密/解密 示例
公钥加密,私钥解密
import javax.crypto.Cipher;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PublicKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.HashMap;
import java.util.Map;
/**
* RSA加密工具
*/
public class RSAUtil {
public static final String PUBLIC_KEY = "RSA_Public_Key";
public static final String PRIVATE_KEY = "RSA_Private_Key";
/**
* 初始化密钥
* @return
* @throws Exception
*/
public static Map<String,Object> initKey() throws Exception{
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(1024);//512-65536 & 64的倍数
KeyPair keyPair = keyPairGenerator.generateKeyPair();
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
Map<String,Object> keyMap = new HashMap<String, Object>();
keyMap.put(PUBLIC_KEY, publicKey);
keyMap.put(PRIVATE_KEY, privateKey);
return keyMap;
}
public static RSAPublicKey getPublicKey(Map<String,Object> keyMap) {
return (RSAPublicKey) keyMap.get(PUBLIC_KEY);
}
public static RSAPrivateKey getPrivateKey(Map<String,Object> keyMap){
return (RSAPrivateKey) keyMap.get(PRIVATE_KEY);
}
/**
* 使用公钥对数据进行加密
* @param data
* @param publicKey
* @return
* @throws Exception
*/
public static byte[] encrypt(byte[] data, RSAPublicKey publicKey) throws Exception{
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE,publicKey);
return cipher.doFinal(data);
}
/**
* 使用私钥解密
* @param data
* @param privateKey
* @return
* @throws Exception
*/
public static byte[] decrypt(byte[] data, RSAPrivateKey privateKey) throws Exception{
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE,privateKey);
return cipher.doFinal(data);
}
public static void main(String[] args) throws Exception {
String data = "周杰伦-东风破";
Map<String, Object> keyMap = initKey();
byte[] miwen = encrypt(data.getBytes(),getPublicKey(keyMap));
System.out.println("加密后的内容:"+BytesToHex.fromBytesToHex(miwen));
byte[] plain = decrypt(miwen, getPrivateKey(keyMap));
System.out.println("解密后的内容:"+new String(plain));
}
}