一:简介
RSA 加密算法是一种非对称加密算法,非对称加密需要两个密钥,一个是加密密钥另一个是解密密钥,加密密钥(即公开密钥)PK是公开信息,解密密钥(即秘密密钥)SK是需要保密的,加密算法E和解密算法D也都是公开的。虽然解密密钥SK是由公开密钥PK决定的,但却不能根据PK计算出SK。
RSA是1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的。当时他们三人都在麻省理工学院工作。RSA就是他们三人姓氏开头字母拼在一起组成的。
它通常是先生成一对RSA 密钥,其中之一是保密密钥,由用户保存;另一个为公开密钥,可对外公开,甚至可在网络服务器中注册。为提高保密强度,RSA密钥至少为500位长,一般推荐使用1024位,或者2048位。这就使加密的计算量很大。为减少计算量,在传送信息时,常采用传统加密方法与公开密钥加密方法相结合的方式,即信息采用DES或AES密钥加密,然后使用RSA密钥加密对话密钥和信息摘要。对方收到信息后,用不同的密钥解密并可核对信息摘要。RSA(AES(key, msg), PK)
安全性
RSA的安全性依赖于大数分解,但是否等同于大数分解一直未能得到理论上的证明,因为没有证明破解RSA就一定需要作大数分解。假设存在一种无须分解大数的算法,那它肯定可以修改成为大数分解算法。 RSA 的一些变种算法已被证明等价于大数分解。不管怎样,分解n是最显然的攻击方法。人们已能分解多个十进制位的大素数。因此,模数n必须选大一些,因具体适用情况而定。
运算速度
由于进行的都是大数计算,使得RSA最快的情况也比DES慢上好几倍,无论是软件还是硬件实现。速度一直是RSA的缺陷。一般来说只用于少量数据加密。RSA的速度是对应同样安全级别的对称密码算法的1/1000左右。比起DES和其它对称算法来说,RSA要慢得多。
二:RSAUtil
public class RSAUtil {
/**
* 生成密钥对
* @return
* @throws Exception
*/
public static KeyPair genKeyPair() throws Exception{
KeyPairGenerator keyPairGenerator=KeyPairGenerator.getInstance("RSA");
// 一般为1024,为了更安全最好采用2048
keyPairGenerator.initialize(1024);
return keyPairGenerator.generateKeyPair();
}
/**
* 公钥加密
* @param content
* @param publicKey
* @return
* @throws Exception
*/
public static byte[] encrypt(byte[] content, PublicKey publicKey) throws Exception{
// java默认"RSA"="RSA/ECB/PKCS1Padding"
Cipher cipher=Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return cipher.doFinal(content);
}
/**
* 私钥解密
* @param content
* @param privateKey
* @return
* @throws Exception
*/
public static byte[] decrypt(byte[] content, PrivateKey privateKey) throws Exception{
Cipher cipher=Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return cipher.doFinal(content);
}
public static void main(String[] args) throws Exception {
String data = "123456";
KeyPair keyPair= genKeyPair();
//获取公钥,并以base64格式打印出来
PublicKey publicKey=keyPair.getPublic();
System.out.println("公钥:"+new String(Base64.getEncoder().encode(publicKey.getEncoded())));
//获取私钥,并以base64格式打印出来
PrivateKey privateKey=keyPair.getPrivate();
System.out.println("私钥:"+new String(Base64.getEncoder().encode(privateKey.getEncoded())));
//公钥加密
byte[] encryptedBytes=encrypt(data.getBytes(), publicKey);
System.out.println("加密后:"+new String(encryptedBytes));
//私钥解密
byte[] decryptedBytes=decrypt(encryptedBytes, privateKey);
System.out.println("解密后:"+new String(decryptedBytes));
}
}