本文完成的是公钥加密,私钥解密(私钥加密公钥解密是一样的)。
注意点:
- 秘钥生成的格式不同,使用算法也不同,公钥是X509EncodedKeySpec,私钥是PKCS8EncodedKeySpec。
- 报错java.security.spec.InvalidKeySpecException就是因为密钥格式问题。
- 报错Data must not be longer than *** bytes是因为没有分段解密,密文太长。
- 分段加密解密时钥注意偏移量,256位或者128位钥看自己密钥的生成。
- 本文把公私密钥做了编码获取处理是为了方便传输,如果不需要传输,可以不做,代码稍改即可。
代码如下
package RSA;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
/**
* @version v1.0
* @ProjectName: Cryptography
* @ClassName: RSA
* @Description: TODO(RSA加密解密算法类)
* @Author: 你还年轻
* @Date: 2020/9/27 21:04
*/
public class RSA {
/**
* @Description: TODO(获取密钥对)
* @param
* @return {@link KeyPair}
* @author 你还年轻
* @throws
* @date 2020/9/27 21:48
*/
public static KeyPair generateKeyPairs() throws NoSuchAlgorithmException, UnsupportedEncodingException {
//标明算法类型
String algorithm = "RSA";
//创建秘钥对生成对象(密钥生成器)
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(algorithm);
SecureRandom secureRandom = new SecureRandom(String.valueOf(System.currentTimeMillis()).getBytes("utf-8")); // 说的一个安全的随机数
keyPairGenerator.initialize(2048, secureRandom); // 这里可以是1024、2048 初始化一个密钥对
//生成密钥对,此时公钥好私钥已经在keyPair对象中
KeyPair keyPair = keyPairGenerator.generateKeyPair();
return keyPair;
}
/**
* @Description: TODO(获取密钥对中的公钥,并对其进行Base64编码处理)
* @param keyPair
* @return {@link String}
* @author 你还年轻
* @throws
* @date 2020/9/27 21:49
*/
public static String getPublicKeyBase64(KeyPair keyPair){
//获取传进来的密钥对中的公钥
PublicKey publicKey = keyPair.getPublic();
//对公钥进行Base64编码
String publicKeyBase64 = Base64.getEncoder().encodeToString(publicKey.getEncoded());
return publicKeyBase64;
}
/**
* @Description: TODO(获取密钥对中的私钥,并对其进行Base64编码处理)
* @param keyPair
* @return {@link String}
* @author 你还年轻
* @throws
* @date 2020/9/27 22:43
*/
public static String getPrivateKeyBase64(KeyPair keyPair){
//获取传进来的密钥对中的私钥
PrivateKey privateKey = keyPair.getPrivate();
//对私钥进行Base64编码处理
String privateKeyBase64 = Base64.getEncoder().encodeToString(privateKey.getEncoded());
return privateKeyBase64;
}
/**
* @Description: TODO(使用公钥加密)
* @param publicKeyStr 经过Base64编码过的公钥字符串
* @param content
* @return {@link String}
* @author 你还年轻
* @throws
* @date 2020/9/27 23:12
*/
public static String publicKeyEncrypt(String content,String publicKeyStr)
throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, NoSuchProviderException, IOException {
// 传递进来的公钥是经过Base64编码过的字符串,要返回成字节数组形式,需要解码
byte[] decodePublicKeyByte = Base64.getDecoder().decode(publicKeyStr);
//调用X509EncodedKeySpec对象,转换格式
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(decodePublicKeyByte);
//调用密钥工厂
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey = keyFactory.generatePublic(keySpec);
//调用Java加密的Cipher对象,
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE,publicKey);//第一个参数表示这是加密模式,第二个参数表示密钥
//分段加密
byte[] bytesContent = content.getBytes();
int inputLen = bytesContent.length;
int offLen = 0;//偏移量
int i = 0;
ByteArrayOutputStream bops = new ByteArrayOutputStream();
while(inputLen - offLen > 0){
byte [] cache;
if(inputLen - offLen > 256){
cache = cipher.doFinal(bytesContent, offLen,256);
}else{
cache = cipher.doFinal(bytesContent, offLen,inputLen - offLen);
}
bops.write(cache);
i++;
offLen = 256 * i;
}
bops.close();
byte[] encryptedData = bops.toByteArray();
//使用Base64对加密结果进行编码
String encode = Base64.getEncoder().encodeToString(encryptedData);
return new String(encode);
}
/**
* @Description: TODO(私钥解密)
* @param content 秘文,base64编码过的字符串
* @param privateKeyStr 私钥,base64编码过的字符串
* @return {@link String}
* @author 你还年轻
* @throws
* @date 2020/9/27 23:15
*/
public static String privateKeyDecrypt(String content,String privateKeyStr)
throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, BadPaddingException, IllegalBlockSizeException, InvalidKeyException, IOException {
//传递进来的私钥是经过Base64编码过的字符串,要返回成字节数组形式,需要解码
byte[] decodePrivateKeyByte = Base64.getDecoder().decode(privateKeyStr);
//调用PKCS8EncodedKeySpec对象
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decodePrivateKeyByte);
//调用密钥工厂
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
//调用Java加密的Cipher对象,
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE,privateKey);//第一个参数表示这是加密模式,第二个参数表示密钥
byte[] bytesContent = Base64.getDecoder().decode(content.getBytes());
int inputLen = bytesContent.length;
int offLen = 0;
int i = 0;
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
while(inputLen - offLen > 0){
byte[] cache;
if(inputLen - offLen > 256){
cache = cipher.doFinal(bytesContent,offLen,256);
}else{
cache = cipher.doFinal(bytesContent,offLen,inputLen - offLen);
}
byteArrayOutputStream.write(cache);
i++;
offLen = 256 * i;
}
byteArrayOutputStream.close();
byte[] byteArray = byteArrayOutputStream.toByteArray();
//使用Base64对加密结果进行编码
return new String(byteArray);
}
public static void main(String[] args) throws
NoSuchAlgorithmException, IllegalBlockSizeException, InvalidKeyException, BadPaddingException, InvalidKeySpecException, NoSuchPaddingException, IOException, NoSuchProviderException {
String input = "123321";
KeyPair keyPair = generateKeyPairs();
String en = publicKeyEncrypt(input,getPublicKeyBase64(keyPair));
String de = privateKeyDecrypt(en, getPrivateKeyBase64(keyPair));
System.out.println("原文:"+input);
System.out.println("密文:"+ en);
System.out.println("解密:"+de);
}
}
测试