RSA加密算法是一种非对称加密算法
RSA是一对密钥。分别是公钥和私钥,这个公钥和私钥其实就是一组数字!
其二进制位长度可以是1024位或者2048位.长度越长其加密强度越大,
目前为止公之于众的能破解的最大长度为768位密钥,只要高于768位,相对就比较安全.
RSA加密的方式
- 使用公钥加密的数据,利用私钥进行解密
- 使用私钥加密的数据,利用公钥进行解密
算法优缺点
优点
- 不需要进行密钥传递,提高了安全性
- 可以进行数字签名认证
缺点
- 加密解密效率不高,一般只适用于处理小量数据(如:密钥)
- 容易遭受小指数攻击
代码 demo
import javax.crypto.Cipher;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
public class RSAUtils {
/**
* 512、1024、2048
*/
private static final int DEFAULT_KEY_SIZE = 2048;
public static String RSA_ALGORITHM = "RSA";
/**
* 从文件中读取公钥
*
* @param file 公钥保存路径,获取的file
* @return PublicKey 公钥对象
* @throws Exception
*/
public static PublicKey getPublicKey(File file) throws Exception {
return getPublicKey(readFile(file));
}
/**
* 从文件中读取密钥
*
* @param file 私钥保存路径,获取的file
* @return PrivateKey 私钥对象
* @throws Exception
*/
public static PrivateKey getPrivateKey(File file) throws Exception {
return getPrivateKey(readFile(file));
}
/**
* 获取公钥
* 公钥的字节形式。
*
* @param bytes 公钥的字节形式
* @return
* @throws Exception
*/
private static PublicKey getPublicKey(byte[] bytes) throws Exception {
//todo 打印调试
System.out.println("公钥:" + new String(bytes));
bytes = Base64.getDecoder().decode(bytes);
X509EncodedKeySpec spec = new X509EncodedKeySpec(bytes);
KeyFactory factory = KeyFactory.getInstance(RSA_ALGORITHM);
return factory.generatePublic(spec);
}
/**
* 获取密钥
*
* @param bytes 私钥的字节形式
* @return
* @throws Exception
*/
private static PrivateKey getPrivateKey(byte[] bytes) throws NoSuchAlgorithmException, InvalidKeySpecException {
//todo 打印调试
System.out.println("私钥:" + new String(bytes));
bytes = Base64.getDecoder().decode(bytes);
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(bytes);
KeyFactory factory = KeyFactory.getInstance(RSA_ALGORITHM);
return factory.generatePrivate(spec);
}
/**
* 根据密文,生存rsa公钥和私钥,并写入指定文件
* ⚠️: 该方法是生成本地的 rsa 文件
*
* @param publicKeyFilename 公钥文件路径
* @param privateKeyFilename 私钥文件路径
* @param secret 生成密钥的密文
*/
public static void generateKey(String publicKeyFilename, String privateKeyFilename, String secret, int keySize) throws Exception {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
SecureRandom secureRandom = new SecureRandom(secret.getBytes());
keyPairGenerator.initialize(Math.max(keySize, DEFAULT_KEY_SIZE), secureRandom);
KeyPair keyPair = keyPairGenerator.genKeyPair();
// 获取公钥并写出
byte[] publicKeyBytes = keyPair.getPublic().getEncoded();
publicKeyBytes = Base64.getEncoder().encode(publicKeyBytes);
writeFile(new File(publicKeyFilename), publicKeyBytes);
// 获取私钥并写出
byte[] privateKeyBytes = keyPair.getPrivate().getEncoded();
privateKeyBytes = Base64.getEncoder().encode(privateKeyBytes);
writeFile(new File(privateKeyFilename), privateKeyBytes);
}
private static byte[] readFile(File file) throws Exception {
return Files.readAllBytes(file.toPath());
}
private static void writeFile(File dest, byte[] bytes) throws IOException {
if (!dest.exists()) {
dest.createNewFile();
}
Files.write(dest.toPath(), bytes);
}
/**
* 私钥加密
*
* @param data 待加密数据
* @param privateKey 密钥
* @return byte[] 加密数据
*/
public static byte[] encryptByPrivateKey(byte[] data, PrivateKey privateKey) throws Exception {
Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
return cipher.doFinal(data);
}
/**
* 私钥解密
*
* @param data 待解密数据
* @param privateKey 密钥
* @return byte[] 解密数据
*/
public static byte[] decryptByPrivateKey(byte[] data, PrivateKey privateKey) throws Exception {
//数据解密
Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return cipher.doFinal(data);
}
/**
* 公钥加密
*
* @param data
* @param publicKey
* @return
* @throws Exception
*/
private static byte[] encryptByPublicKey(byte[] data, PublicKey publicKey) throws Exception {
Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return cipher.doFinal(data);
}
/**
* 公钥解密
*
* @param data 待解密数据
* @param pubKey 密钥
* @return byte[] 解密数据
*/
public static byte[] decryptByPublicKey(byte[] data, PublicKey pubKey) throws Exception {
Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, pubKey);
return cipher.doFinal(data);
}
public static void main(String[] args) throws Exception {
//1. 生成本次测试的公钥私钥。(文件已经存在则可以跳过此步骤)
// generateKey("./test_pub",
// "./test_private",
// "yourSecret",
// 2048);
//获取 publicKey;
PublicKey publicKey = getPublicKey(new File("./test_pub"));
//如果密钥文件放在 resource目录下.(文件已经存在)参考 https://mylomen.com/archives/141
//PublicKey publicKey = getPublicKey(ResourceFileUtils.getConfigLocation("classpath:test_pub").getFile());
//获取 privateKey
PrivateKey privateKey = getPrivateKey(new File("./test_private"));
String password = "123456";
//加密
byte[] encryptByPublicKey = encryptByPublicKey(password.getBytes(), publicKey);
System.out.println("使用公钥加密后的数据:" + new String(Base64.getEncoder().encode(encryptByPublicKey)));
//解密
byte[] decryptByPrivateKey2 = decryptByPrivateKey(encryptByPublicKey, privateKey);
System.out.println("使用私钥解密后的数据:" + new String(decryptByPrivateKey2));
}
}
文章评论