1 非对称加密简介
https://www.cnblogs.com/jthr/p/15137222.html
公开密钥加密(public-key cryptography),也成为非对称加密,是密码学的一种算法,他需要两个密钥,一个是公开密钥,另一个是私有密钥,一个用作加密的时候,另一个则用作解密。
- 明文:需要加密的内容,成为明文。
- 密文:使用密钥把明文加密后的内容。只能用相应的另一个密钥才能解密得到原来的明文。甚至连最初用来加密的密钥也不能用作解密。
对称加密&&非对称加密
- 对称加密:加密和解密都是用同一个密钥的算法,称作对称加密。
- 非对称加密:加密和解密需要不同的密钥。
因为公钥加密的信息只用私钥才能解的开,所以只要私钥不泄露,通信就是安全的
2 RSA工具类
下面是一个RSA工具类,包含了一下方法
1)initKey() 用于生成一对密匙对(一个公钥和一个私钥,它们是一一对应的)
2)sign() 用私钥对数据进行数字签名
3)verify()用公钥校验数据签名,对应方法sign()
4)encryptByPublicKey()使用公钥对数据进行加密
5) decryptByPrivateKey()使用私钥对加密数据解密,对应方法encryptByPublicKey()
package com.example.springboottest.common.util;
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;
/**
* RSA安全编码组件
*
* @version 1.0
* @desc 公钥和私钥存放在properties文件的时候每行的末尾加上“\r\n\” <br/>
* “\r\n” 起到换行的作用,最后的“\”在properties在里表示连接
*
* @author Neo
* @date 2018-4-15 22:23:19
* @since 1.0
*/
public class RSAUtils extends Base64Utils {
public static final String KEY_ALGORITHM = "RSA";
public static final String SIGNATURE_ALGORITHM = "MD5withRSA";
private static final String PUBLIC_KEY = "RSAPublicKey";
private static final String PRIVATE_KEY = "RSAPrivateKey";
/**
* 用私钥对信息生成数字签名
*
* @param data 加密数据
* @param privateKey 私钥
* @return
* @throws Exception
*/
public static String sign(String data, String privateKey) throws Exception {
return sign(data.getBytes(), privateKey);
}
/**
* 用私钥对信息生成数字签名
*
* @param data 加密数据
* @param privateKey 私钥
* @return
* @throws Exception
*/
public static String sign(byte[] data, String privateKey) throws Exception {
// 解密由base64编码的私钥
byte[] keyBytes = decryptBASE64(privateKey);
// 构造PKCS8EncodedKeySpec对象
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
// KEY_ALGORITHM 指定的加密算法
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
// 取私钥匙对象
PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);
// 用私钥对信息生成数字签名
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initSign(priKey);
signature.update(data);
return encryptBASE64(signature.sign());
}
/**
* 校验数字签名
*
* @param data 加密数据
* @param publicKey 公钥
* @param sign 数字签名
* @return 校验成功返回true 失败返回false
* @throws Exception
*/
public static boolean verify(String data, String publicKey, String sign) throws Exception {
return verify(data.getBytes(), publicKey, sign);
}
/**
* 校验数字签名
*
* @param data 加密数据
* @param publicKey 公钥
* @param sign 数字签名
* @return 校验成功返回true 失败返回false
* @throws Exception
*/
public static boolean verify(byte[] data, String publicKey, String sign) throws Exception {
// 解密由base64编码的公钥
byte[] keyBytes = decryptBASE64(publicKey);
// 构造X509EncodedKeySpec对象
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
// KEY_ALGORITHM 指定的加密算法
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
// 取公钥匙对象
PublicKey pubKey = keyFactory.generatePublic(keySpec);
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initVerify(pubKey);
signature.update(data);
// 验证签名是否正常
return signature.verify(decryptBASE64(sign));
}
/**
* 解密<br>
* 用私钥解密
*
* @param data
* @param key
* @return
* @throws Exception
*/
public static String decryptByPrivateKey(String data, String key) throws Exception {
return new String(decryptByPrivateKey(Base64Utils.decryptBASE64(data), key));
}
/**
* 解密<br>
* 用私钥解密
*
* @param data
* @param key
* @return
* @throws Exception
*/
public static byte[] decryptByPrivateKey(byte[] data, String key) throws Exception {
// 对密钥解密
byte[] keyBytes = decryptBASE64(key);
// 取得私钥
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
// 对数据解密
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return cipher.doFinal(data);
}
/**
* 解密<br>
* 用公钥解密
*
* @param data
* @param key
* @return
* @throws Exception
*/
public static String decryptByPublicKey(String data, String key) throws Exception {
return new String(decryptByPublicKey(Base64Utils.decryptBASE64(data), key));
}
/**
* 解密<br>
* 用公钥解密
*
* @param data
* @param key
* @return
* @throws Exception
*/
public static byte[] decryptByPublicKey(byte[] data, String key) throws Exception {
// 对密钥解密
byte[] keyBytes = decryptBASE64(key);
// 取得公钥
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key publicKey = keyFactory.generatePublic(x509KeySpec);
// 对数据解密
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, publicKey);
return cipher.doFinal(data);
}
/**
* 加密<br>
* 用公钥加密
*
* @param data
* @param key
* @return
* @throws Exception
*/
public static String encryptByPublicKey(String data, String key) throws Exception {
return Base64Utils.encryptBASE64(encryptByPublicKey(data.getBytes(), key));
}
/**
* 加密<br>
* 用公钥加密
*
* @param data
* @param key
* @return
* @throws Exception
*/
public static byte[] encryptByPublicKey(byte[] data, String key) throws Exception {
// 对公钥解密
byte[] keyBytes = decryptBASE64(key);
// 取得公钥
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key publicKey = keyFactory.generatePublic(x509KeySpec);
// 对数据加密
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return cipher.doFinal(data);
}
/**
* 加密<br>
* 用私钥加密
*
* @param data
* @param key
* @return
* @throws Exception
*/
public static String encryptByPrivateKey(String data, String key) throws Exception {
return Base64Utils.encryptBASE64(encryptByPrivateKey(data.getBytes(), key));
}
/**
* 加密<br>
* 用私钥加密
*
* @param data
* @param key
* @return
* @throws Exception
*/
public static byte[] encryptByPrivateKey(byte[] data, String key) throws Exception {
// 对密钥解密
byte[] keyBytes = decryptBASE64(key);
// 取得私钥
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
// 对数据加密
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
return cipher.doFinal(data);
}
/**
* 取得私钥
*
* @param keyMap
* @return
* @throws Exception
*/
public static String getPrivateKey(Map<String, Object> keyMap) throws Exception {
Key key = (Key) keyMap.get(PRIVATE_KEY);
return encryptBASE64(key.getEncoded());
}
/**
* 取得公钥
*
* @param keyMap
* @return
* @throws Exception
*/
public static String getPublicKey(Map<String, Object> keyMap) throws Exception {
Key key = (Key) keyMap.get(PUBLIC_KEY);
return encryptBASE64(key.getEncoded());
}
/**
* 初始化密钥
*
* @return
* @throws Exception
*/
public static Map<String, Object> initKey() throws Exception {
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
keyPairGen.initialize(1024);
KeyPair keyPair = keyPairGen.generateKeyPair();
// 公钥
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
// 私钥
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
Map<String, Object> keyMap = new HashMap<String, Object>(2);
keyMap.put(PUBLIC_KEY, publicKey);
keyMap.put(PRIVATE_KEY, privateKey);
return keyMap;
}
}
3 Base64Utils
package com.example.springboottest.common.util;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
import java.security.MessageDigest;
/**
* BASE64的加解密
* @author Neo
* @date 2018-4-15 22:21:51
*
*/
@SuppressWarnings("restriction")
public class Base64Utils {
public static final String KEY_SHA = "SHA";
public static final String KEY_MD5 = "MD5";
/**
* 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);
}
/**
* MD5加密
*
* @param data
* @return
* @throws Exception
*/
public static byte[] encryptMD5(byte[] data) throws Exception {
MessageDigest md5 = MessageDigest.getInstance(KEY_MD5);
md5.update(data);
return md5.digest();
}
/**
* SHA加密
*
* @param data
* @return
* @throws Exception
*/
public static byte[] encryptSHA(byte[] data) throws Exception {
MessageDigest sha = MessageDigest.getInstance(KEY_SHA);
sha.update(data);
return sha.digest();
}
}
4 测试
public static void main(String[] args) { try { //创建密匙对 Map<String, Object> map = RSAUtils.initKey(); String publicKey = RSAUtils.getPublicKey(map); String privateKey = RSAUtils.getPrivateKey(map); System.out.println("公钥:" + publicKey); System.out.println("私钥:" + privateKey); String data = "Java是世界上最好的编程语言"; //加密 String encryptData = RSAUtils.encryptByPublicKey(data, publicKey); System.out.println("加密后:" + encryptData); //解密 String decryptData = RSAUtils.decryptByPrivateKey(encryptData, privateKey); System.out.println("解密后:" + decryptData); //加签和验签的操作是为了防止传输的数据被篡改 // 私钥加签 String sign = sign(data, privateKey); //公钥验签,true boolean verify = verify(data, publicKey, sign); System.out.println("没有被篡改验签:" + verify); //对数据进行篡改后,验签失败false boolean verify2 = verify((data + "a"), publicKey, sign); System.out.println("被篡改验签:" +verify2); } catch (Exception e) { e.printStackTrace(); } }
执行结果
公钥:MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDjdUX0gzZ9KBx60shWov8KL5ep2feQnNbjZmVP uCReneNlmUIF2LcljWq+WJ/6IVlqWlPxpu14SUPlVVJ4hqLpodBRc26kSfk2nRK81mA0T7Js/EcW pJ0uX9uf27f4qn60ihB0GplSjUHGCAmV24SKkuis4KesvPdz3xj9Hx6YEQIDAQAB 私钥:MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAON1RfSDNn0oHHrSyFai/wovl6nZ 95Cc1uNmZU+4JF6d42WZQgXYtyWNar5Yn/ohWWpaU/Gm7XhJQ+VVUniGoumh0FFzbqRJ+TadErzW YDRPsmz8RxaknS5f25/bt/iqfrSKEHQamVKNQcYICZXbhIqS6Kzgp6y893PfGP0fHpgRAgMBAAEC gYBXn9L+OhogpvYpvs/cyFgV9XWowkZj2HfUDJtU1ax1Ir/6YMsVc4JCnjMT9xJSCszmcrvJ6TOs VhUo4PCva7aQLnngOfb0wemAj2DW3mw67EQmJEfmOrZc+zgrYlk5z2QQUmpZineM2WXL/ER2hgFQ ST2H2ihRHldff50+OWjsAQJBAPj1QedWzBZDYeQm/L0LcqhnntfcB3PqNzqk/S/Pm4T6V2TxzMv+ ezF3H88aA2Y6EkmXbz+6SPRQjXQZo869WdECQQDp5FTf8pVhxdjZuBsUtNFN6LLH2fQPXQ3IG6rj wGlO3lZd4sIRYTQME3BuFY7X+SfcpABBZfrXE3A1ROjghqpBAkEA0CIKtONFwB8ZSeqmRU26z7vB emmC+Y+IGMkyurPwKt44DjZwpuLcD2CuATCYQvCttUSbR0XwFAD8IWIGJqL64QJAJWXkCFbyecq3 zMA6XEo5OVre00PPWXGIlZmO7pHChODaMHLkkwDW4KNvE7sQtwnYzNfQTqSuwhsSkwHstpHxwQJB AKEafzIQ8o13+FWNG9rBdQjUv4J3TB/lkfo2OCyUdI5HIJPekSfoj43Q/BMMAXXFXs/GMfL59ji1 pvZ4wEnCbMs= 加密后:r4THPubDkZRUQn4j3Lo/5LXaNtM4Y1cFQMBSFxTSt5n5f0HN/xnWYmDShpJd2ycxas/p/RJvYXOL OclFfJWEgetga4DHUFsqYLSPyXCYvWiIu/ydKsMCD/eLYAIUOQdQT904DGRIeHL0oiBuI/EX5R/W kow7T9uBc+pghIU28Hw= 解密后:Java是世界上最好的编程语言 没有被篡改验签:true 被篡改验签:false
分类:
其它
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?