使用说明
非对称加密
非对称加密算法主要有:RSA、Elgamal、背包算法、Rabin、D-H、ECC(椭圆曲线加密算法)。下面例子中使用的就是RSA算法。
特点:非对称加密算法比对称加密算法慢数千倍,但在保护通信安全方面,非对称加密算法却具有对称密码难以企及的优势。
理解:非对称加密需要两把密钥:公钥和私钥,他们是一对,如果用公钥对数据加密,那么只能用对应的私钥解密。如果用私钥对数据加密,只能用对应的公钥进行解密。因为加密和解密用的是不同的密钥,所以称为非对称加密。
私钥加密---------》公钥解密
公钥加密---------》私钥解密
案例:
为了保证安全:不允许中间第三方来截取篡改数据,生成唯一的公钥私钥。双方就需要各自生成自己的公钥私钥,并且发送给对方。
如:
客户端发请求到服务端,需要拿着自己的公钥发送过去,而服务端收到后,拿着对应的私钥进行解密,解密成功后,进行下一环节。
如果在中间被第三方拦截到,篡改内容,服务端没有对应的公钥,服务端则解析失败。
生成keystore文件
需要进入jdk的bin目录下,找到keytool.exe
.\keytool.exe
查看生成密钥对帮助说明
.\keytool.exe -genkeypair -help
输入命令生成自己的keystore文件
.\keytool.exe -genkeypair -alias fd-alias -keypass 123456 -keyalg RSA -keysize 1024 -validity 365 -keystore D:\sumscope\MyCode\cer\fd-alias.keystore -storepass 123456
查看自己的密钥库
.\keytool.exe -list -rfc -keystore D:\sumscope\MyCode\cer\fd-alias.keystore
生成文件
公钥私钥互相解密
获取fd-alias.keystore中的公钥私钥
package com.springweb.utils;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
import java.io.FileInputStream;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.PublicKey;
/**
* 从证书获取 公钥和私钥
* @author admin
* @date 2022/1/7
*/
public class ReadKeyStoreUtils {
/**
* Java密钥库(Java Key Store,JKS)KEY_STORE
*/
public static final String KEY_STORE = "JKS";
public static final String X509 = "X.509";
/**
* BASE64解密
* @param key
* @return
* @throws Exception
*/
public static byte[] decryptBASE64(String key) throws Exception {
return(new BASE64Decoder()).decodeBuffer(key);
}
/**
* BASE64加密
* @param key
* @return
* @throws Exception
*/
public static String encryptBASE64(byte[] key) throws Exception {
return(new BASE64Encoder()).encodeBuffer(key).replace("\r","").replace("\n","");
}
/**
* 获得KeyStore
*
* @param keyStorePath
* @param password
* @return
* @throws Exception
*/
private static KeyStore getKeyStore(String keyStorePath, String password)
throws Exception {
FileInputStream is = new FileInputStream(keyStorePath);
KeyStore ks = KeyStore.getInstance(KEY_STORE);
ks.load(is, password.toCharArray());
is.close();
return ks;
}
/**
* 由KeyStore获得私钥
*
* @param keyStorePath
* @param alias
* @param storePass
* @return
*/
private static PrivateKey getPrivateKey(String keyStorePath, String alias, String storePass, String keyPass) throws Exception {
KeyStore ks = getKeyStore(keyStorePath, storePass);
PrivateKey key = (PrivateKey) ks.getKey(alias, keyPass.toCharArray());
return key;
}
/**
* 由Certificate获得公钥
*
* @param keyStorePath KeyStore路径
* @param alias 别名
* @param storePass KeyStore访问密码
*/
private static PublicKey getPublicKey(String keyStorePath, String alias, String storePass) throws Exception {
KeyStore ks = getKeyStore(keyStorePath, storePass);
PublicKey key = ks.getCertificate(alias).getPublicKey();
return key;
}
/**
* 从KeyStore中获取公钥,并经BASE64编码
*
* @param keyStorePath
* @param alias
* @param storePass
*/
public static String getStrPublicKey(String keyStorePath, String alias, String storePass) throws Exception {
PublicKey key = getPublicKey(keyStorePath, alias, storePass);
String strKey = encryptBASE64(key.getEncoded());
return strKey;
}
/**
* 获取经BASE64编码后的私钥
*
* @param keyStorePath
* @param alias
* @param storePass
* @param keyPass
* @return
* @throws Exception
* @author 奔跑的蜗牛
*/
public static String getStrPrivateKey(String keyStorePath, String alias, String storePass, String keyPass) throws Exception {
PrivateKey key = getPrivateKey(keyStorePath, alias, storePass, keyPass);
String strKey = encryptBASE64(key.getEncoded());
return strKey;
}
public static void main(String[] args) throws Exception {
String keyStorePath = "D:\\sumscope\\MyCode\\cer\\fd-alias.keystore";
String strPublicKey = getStrPublicKey(keyStorePath, "fd-alias", "123456");
System.out.println("公钥:"+strPublicKey);
String strPrivateKey = getStrPrivateKey(keyStorePath, "fd-alias", "123456", "123456");
System.out.println("私钥:"+strPrivateKey);
}
}
结果:
使用生成公钥私钥进行解密
上面生成的公钥私钥需要保留,在这里需要使用到
package com.springweb.utils;
import org.apache.commons.codec.binary.Base64;
import javax.crypto.Cipher;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
public class RSAEncrypt {
public static void main(String[] args) throws Exception {
testAll();
}
public static void test() throws Exception {
//生成公钥和私钥
Map<String, String> keyMap = new HashMap<>();
keyMap.put("publicKey", "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDEXr8P0dlvpZRhcKSkKgfzSRA3TpH8RfZc7b529PeiaRQGm7cXlath5w0Nj1gs6jZWSzltcf7SIdMEkpxTX4/xbXt8v/87L7DdicGOt4+VVh6NOrqB9HhNqeEtGRMv+DAHg6zij3uA+YCNA40Oretojjf4v51QSsvfQv6W4DWhTQIDAQAB");
keyMap.put("privateKey", "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAMRevw/R2W+llGFwpKQqB/NJEDdOkfxF9lztvnb096JpFAabtxeVq2HnDQ2PWCzqNlZLOW1x/tIh0wSSnFNfj/Fte3y//zsvsN2JwY63j5VWHo06uoH0eE2p4S0ZEy/4MAeDrOKPe4D5gI0DjQ6t62iON/i/nVBKy99C/pbgNaFNAgMBAAECgYBRAjUXtZ5ZrJkVyX5iKuS0vINwDX2z8Li9hWZ5dH1kBq04PKy/kgLtlH+SBHx/qu9XkhjSyaAx17pRvJm420dpvJy7T9GHlQ9bOVxaKNxsodxokERu69+YqHmfFrRG7UjfVup4gqU1SRdBaRWmMhY7QwTCQgV5IOJG/gDICa6LkQJBAOJoCZGz3d+oKsv1GRpmtUMrACyuK20jAC0G8wkNyn80UF8eyX9C2axSFX55Ha94YSkLGC5hzxlkHvT1COaRmVsCQQDeCaQSoypYfYDaSPXi8IpXHgY2QzB2ABP0SjqDlcMV+pK/G4e5i8ptmQZOlYUgkjAGEeXX8sq5iQHJ7hNZXYh3AkEArEsB5Thcw0RFdTrK5LV+gWPq2RWeBIqbKqjcMGqnTBAyjYBvVII6BhHdO4bN2WehgMtplnpmUOtJR55lLJlmewJAEcDDlZnmMN0YCFv9DQAej4ifBoeowEaRUd79frfiuUcnpJAW8gbzUIADuRTLaCdIH7QepH2NJ/iEZBjdAzAvUQJAW0jhWNcfM+2eMuUNvjRCLlKnoJN8yhY0Sl+oPP1ImEbFoWSh/kIa4dZep8FDSrChq8FTPaK0DgUWno893QMszA==");
String publicKey = keyMap.get("publicKey");
String privateKey = keyMap.get("privateKey");
System.out.println("公钥:"+publicKey);
System.out.println("私钥:"+privateKey);
// 原始字符串
String message = "我是测试 原始内容";
System.out.println("原始数据:"+message);
long startTime = System.currentTimeMillis();
for (int i=0;i<10;i++){
String messageEn = publicKeyEncrypt(message, publicKey);
System.out.println("公钥加密后内容:" + messageEn);
String messageDe = privateKeyDecrypt(messageEn, privateKey);
System.out.println("私钥解密后内容:" + messageDe);
}
long endTime = System.currentTimeMillis();
System.out.println(endTime - startTime);
}
/**
* 公加私解
* 私加公解
* @throws Exception
*/
public static void testAll() throws Exception {
//生成公钥和私钥
Map<String, String> keyMap = new HashMap<>();
keyMap.put("publicKey", "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCmqgoIV7+9E2JI7FHFPyEiFzaCufvP0JNIqR3HoytzME9Nt1c3ykMClOpgO8drsZILfAx/rXLdsWC4jjKORWSFDJ+UEqD6y8qOyzFwK3sRR9zdS7rWxdl62IfsdQdHptlygQ/MC09a8koXjbUdiqadf0NkjMiMaZfnHoqWbWmttQIDAQAB");
keyMap.put("privateKey", "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKaqCghXv70TYkjsUcU/ISIXNoK5+8/Qk0ipHcejK3MwT023VzfKQwKU6mA7x2uxkgt8DH+tct2xYLiOMo5FZIUMn5QSoPrLyo7LMXArexFH3N1LutbF2XrYh+x1B0em2XKBD8wLT1rySheNtR2Kpp1/Q2SMyIxpl+ceipZtaa21AgMBAAECgYBuxJJ4awGXQ5vOBapvIv79blofVkbDHsfUwfl15r+JBjGe4FyKStZwj9KZ9QEcVV9QXLjd3sR6DVrQLknxfrNIGtKnw15tKrNvec+nt/TqKXlY1sQThouBGmISLl2kTe0mIdOdVfJ5bGpe8miH73/3C6eGMnCWfcT3/acLYP++vQJBAOBgIggoFqZlQi0IOQhC7tM8VeMG/D8ie8gJK2O86Q72elz/WLTs4ttIQZLDxEu3buFs5PUTpDnP9cuXRu3EF/cCQQC+J5R4ZrQZEr6yIyoal+3NzpyIE42KfOgYrOZc2E9BhaX2vVT+xyPhOARfG5TOiU0BNXiy3H9MGG24cj/e13SzAkBzEnqBqmWrYuUkiUIOrZ0kcp4tt+hoTLwk5Cb/mOQCC4DH7yFEcPULtywCJCqpFmNkc1+dHTytda0+g9AZoucTAkB59IiUb8oyCoOjXEo0pBwwUsKxw1iT6Wgx6zITeefa7gxzIxrQDIhGedbT6KyXiheJHvI6RJCgDUrRcPTlxulhAkEAjHzGzkMmzFM02WqUidyv3TQzCBaoSBeWr+69j6PeLg/i+3szERleWXiHtgPb/s+DzY0P+rZYkILHuxNRiKQU2A==");
String publicKey = keyMap.get("publicKey");
String privateKey = keyMap.get("privateKey");
System.out.println("公钥:"+publicKey);
System.out.println("私钥:"+privateKey);
// 原始字符串
String message = "我是测试原始内容";
System.out.println("原始数据:"+message);
String messageEn = publicKeyEncrypt(message, publicKey);
System.out.println("公钥加密后内容:" + messageEn);
String messageDe = privateKeyDecrypt(messageEn, privateKey);
System.out.println("私钥解密后内容:" + messageDe);
System.out.println("=====================");
//私钥加密,公钥解密
String s = privateKeyEncrypt(message, privateKey);
System.out.println("私钥加密后内容:"+s);
String s1 = publicKeyDecrypt(s, publicKey);
System.out.println("公钥解密后内容:"+s1);
}
/**
* 随机生成密钥对
*
* @throws NoSuchAlgorithmException
*/
public static Map<String, String> genKeyPair() throws NoSuchAlgorithmException {
// KeyPairGenerator类用于生成公钥和私钥对,基于RSA算法生成对象
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
// 初始化密钥对生成器,密钥大小为96-1024位
keyPairGen.initialize(1024, new SecureRandom());
// 生成一个密钥对,保存在keyPair中
KeyPair keyPair = keyPairGen.generateKeyPair();
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); // 得到私钥
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); // 得到公钥
String publicKeyString = new String(Base64.encodeBase64(publicKey.getEncoded()));
// 得到私钥字符串
String privateKeyString = new String(Base64.encodeBase64((privateKey.getEncoded())));
// 将公钥和私钥保存到Map
Map<String, String> map = new HashMap<>();
map.put("publicKey", publicKeyString);
map.put("privateKey", privateKeyString);
return map;
}
/**
* RSA公钥加密
*
* @param str 加密字符串
* @param publicKey 公钥
* @return 密文
* @throws Exception 加密过程中的异常信息
*/
public static String publicKeyEncrypt(String str, String publicKey) throws Exception {
//base64编码的公钥
byte[] decoded = Base64.decodeBase64(publicKey);
RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA").
generatePublic(new X509EncodedKeySpec(decoded));
//RSA加密
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
String outStr = Base64.encodeBase64String(cipher.doFinal(str.getBytes("UTF-8")));
return outStr;
}
/**
* RSA私钥解密
*
* @param str 加密字符串
* @param privateKey 私钥
* @return 铭文
* @throws Exception 解密过程中的异常信息
*/
public static String privateKeyDecrypt(String str, String privateKey) throws Exception {
//64位解码加密后的字符串
byte[] inputByte = Base64.decodeBase64(str.getBytes("UTF-8"));
//base64编码的私钥
byte[] decoded = Base64.decodeBase64(privateKey);
RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA")
.generatePrivate(new PKCS8EncodedKeySpec(decoded));
//RSA解密
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, priKey);
String outStr = new String(cipher.doFinal(inputByte));
return outStr;
}
/**
* RSA私钥加密
*
* @param str
* @param privateKey
* @return
* @throws Exception
*/
public static String privateKeyEncrypt(String str, String privateKey) throws Exception {
//base64编码的公钥
byte[] decoded = Base64.decodeBase64(privateKey);
PrivateKey priKey = KeyFactory.getInstance("RSA").
generatePrivate(new PKCS8EncodedKeySpec(decoded));
//RSA加密
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, priKey);
String outStr = Base64.encodeBase64String(cipher.doFinal(str.getBytes()));
return outStr;
}
/**
* RSA公钥解密
*
* @param str
* @param publicKey
* @return
* @throws Exception
*/
public static String publicKeyDecrypt(String str, String publicKey) throws Exception {
//64位解码加密后的字符串
byte[] inputByte = Base64.decodeBase64(str.getBytes("UTF-8"));
//base64编码的私钥
byte[] decoded = Base64.decodeBase64(publicKey);
PublicKey pubKey = KeyFactory.getInstance("RSA")
.generatePublic(new X509EncodedKeySpec(decoded));
//RSA解密
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, pubKey);
String outStr = new String(cipher.doFinal(inputByte));
return outStr;
}
}
传入公钥私钥,进行解密,执行testAll方法,解密结果为: