由于RSA算法是不对称加密算法,所以每次加密得到的数据都不相同,同理加签得到的数据每次也不一样。
简单的说下不对称算法,就是两把不同,但是完全匹配的秘钥,去进行加解密,公钥对外提供进行数据加密,私钥自己保存,对加密的数据进行解密。所以私钥不要泄露。
RSA算法原理:
1、任意互质的两个质数p,q。
2、得到连个质数的乘积n。
3、得到两个质数的欧元函数f(n)=(p-1) * (q-1)。
4、任取一个小于f(n)并与其互质的质数e。
5、存在一个数d,使得e^d % f(n) = 1。
6、则(n,e)为公钥,(n,d)为私钥。
加密:待加密数据t:
t^te% n = m(m为加密后的数据);
解密:m^d % n = t(t为原数据)
Java实现RSA算法加密解密,加签以及验签代码如下:
1、Base64工具类:
//Base64加密
public static String encryptBase64(byte[] key){
return new String(Base64.encodeBase64(key));
}
//Base64解密
public static byte[] decryptBase64(String key) throws IOException {
return new BASE64Decoder().decodeBuffer(key);
}
2、获取RSA秘钥对:
public static Map<String, Object> keyMap()throws Exception{
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(1024);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
PublicKey publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate();
Map<String, Object> keyMap = new HashMap<>(2);
keyMap.put(PUBLIC_KEY, publicKey);
keyMap.put(PRIVATE_KEY, privateKey);
return keyMap;
}
3、获取RSA公钥以及私钥分别保存到文件中:
public static void keyToFile(Map keymap)throws Exception{
PublicKey publicKey = (PublicKey) keymap.get(PUBLIC_KEY);
PrivateKey privateKey = (PrivateKey)keymap.get(PRIVATE_KEY);
String encryptBase64PublicKey = encryptBase64(publicKey.getEncoded());
String encryptBase64PrivateKey = encryptBase64(privateKey.getEncoded());
FileWriter fw = new FileWriter("src/main/resources/pubKey.txt");//按需要保存路径,下同
FileWriter fw1 = new FileWriter("src/main/resources/priKey.txt");
fw.write(encryptBase64PublicKey);
fw.flush();
fw.close();
fw1.write(encryptBase64PrivateKey);
fw1.flush();
fw1.close();
}
4、从文件中获取公钥:
public static RSAPublicKey getPublicKeyForFile() throws Exception {
File file = new File("src/main/resources/pubKey.txt");
FileInputStream fis = new FileInputStream(file);
BufferedReader br = new BufferedReader(new InputStreamReader(fis));
String readLine = null;
StringBuffer sb = new StringBuffer();
while ((readLine = br.readLine()) != null) {
sb.append(readLine);
}
String publicKeyStr = sb.toString();
System.out.println("从文件获取到的公钥:" + publicKeyStr);
//Base64解密
byte[] decryptBase64 = GetKey.decryptBase64(publicKeyStr);
//选取密钥编码规则
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(decryptBase64);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
RSAPublicKey rsaPublicKey = (RSAPublicKey) keyFactory.generatePublic(keySpec);
return rsaPublicKey;
}
5、从文件中获取私钥:
//从文件中获取私钥
public static RSAPrivateKey getPrivateKeyForFile() throws Exception {
FileInputStream fis = new FileInputStream("src/main/resources/priKey.keyStore");
BufferedReader br = new BufferedReader(new InputStreamReader(fis));
String readLine = null;
StringBuffer sb = new StringBuffer();
while ((readLine = br.readLine()) != null) {
sb.append(readLine);
}
String privateKey = sb.toString();
System.out.println("从文件获取到的私钥:" + privateKey);
//Base64解密
byte[] bytes = GetKey.decryptBase64(privateKey);
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(bytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyFactory.generatePrivate(pkcs8EncodedKeySpec);
return rsaPrivateKey;
}
6.公钥加密/私钥解密:
public static byte[] encryptOrDecrypt(Key key, byte[] data, int mode) throws Exception {
//加密算法:RSA/ECB/PKCS1Padding
ByteArrayOutputStream out = new ByteArrayOutputStream();
//提供者
Provider provider = new BouncyCastleProvider();
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", provider);
cipher.init(mode, key);
int blockSize = cipher.getBlockSize();
int length = data.length;
int num = length / blockSize + 1;
int cache = blockSize;
byte[] bytes = null;
for (int i = 0; i < num; i++) {
if (i == num - 1) {
cache = length % blockSize;
if (cache == 0) {
return out.toByteArray();
}
}
bytes = cipher.doFinal(data, i * blockSize, cache);
out.write(bytes);
}
return out.toByteArray();
}
7.RSA私钥加签:
public static String addSign(PrivateKey privateKey, String context)throws Exception{
//加签算法:SHA1WithRSA
Signature signature = Signature.getInstance("SHA1WithRSA");
signature.initSign(privateKey);
signature.update(context.getBytes("utf-8"));
byte[] sign = signature.sign();
return encryptBase64(sign);
}
8.RSA公钥验签:
public static boolean verifySign(PublicKey publicKey, String context, String signData)throws Exception{
Signature signature = Signature.getInstance("SHA1WithRSA");
signature.initVerify(publicKey);
byte[] bytes = decryptBase64(signData);
signature.update(context.getBytes("utf-8"));
boolean verify = signature.verify(bytes);
return verify;
}
9.主测试类:
public class Sign {
private final static String PUBLIC_KEY = "PUBLIC_KEY";
private final static String PRIVATE_KEY = "PRIVATE_KEY";
public static void main(String[] args) { try {
Map<String, Object> map = keyMap();
keyToFile(map);
RSAPublicKey rsaPublicKey = getPublicKeyForFile();
System.out.println("rsaPublicKey公钥是:" + rsaPublicKey);
RSAPrivateKey rsaPrivateKey = getPrivateKeyForFile();
System.out.println("rsaPublicKey私钥是:" + rsaPrivateKey);
String data = "这是一个加密字符串"
//加密
byte[] encrypt = encryptOrDecrypt(rsaPublicKey, data.getBytes("utf-8"), Cipher.ENCRYPT_MODE);
String s = encryptBase64(encrypt);
System.out.println("加密后的数据:" + s);
//解密 byte[] decrypt = encryptOrDecrypt(rsaPrivateKey, decryptBase64(s), Cipher.DECRYPT_MODE);
System.out.println("解密后的数据" + new String(decrypt));
//加签
String signData = addSign(rsaPrivateKey, data);
System.out.println("加签后的数据:" + signData);
//验签
boolean b = verifySign(rsaPublicKey, data, signData);
System.out.println("验签得到的布尔值为:" + b);
} catch (Exception e) {
e.printStackTrace();
}
}
最后要说明的是要导入这个包:
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk16</artifactId>
<version>1.46</version>
</dependency>
---------------------
原文:https://blog.csdn.net/s_first/article/details/78658366