RSA是1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的。当时他们三人都在麻省理工学院工作。RSA就是他们三人姓氏开头字母拼在一起组成的。
是最常用、安全的非对称加密算法,通常用来通信加密与签名认证,如HTTPS、SSH秘钥对连接方式以及众多商业公司的开放接口的签名认证都有其身影,公钥公开、私钥保密,使用方式为【公钥加密、私钥解密】【私钥加签、公钥解签】。
加、解密原理
加密过程
E(Encrypt)表示加密秘钥,N(Number)是一个常量,(E,N)表示公钥
解密过程
D(Decrypt)表示解密秘钥,(D,N)表示私钥
名词 | 表达式 |
---|---|
公钥 | (E,N) |
私钥 | (D,N) |
秘钥对 | (E,D,N) |
加密过程 | 明文^E%N |
解密过程 | 密文^D%N |
秘钥对生成过程
- 求N
- 求L
- 求E
- 求D
假定p、q为两质数,则上述N=p*q(为了保证安全性,通常要求p与q为大质数);
L为中间数,是p-1与q-1的最小公倍数,两数的最小公倍数可以使用公约法求得:
E满足:大于1小于L且与L互质,即与L的最大公约数为1
D由E与L计算得出,满足:1<D<L && E*D%L=1
值 | 条件 |
---|---|
N | p*q |
L | lcm(p-1,q-1) |
E | 1<E<L && gcd(E,L)=1 |
D | 1<D<L && E*D % L =1 |
简单加解密与秘钥对推导过程
对应Java代码表示:
public static void main(String[] args) {
// 公钥 E
int encrypt = 5;
// 私钥 D
int decrypt = 77;
// N p*q=13*17
int number = 221;
// 明文
int message = 123;
// 加密过程 密文=明文的E次方%N
BigDecimal encryptedMsg = encrypt(encrypt, number, message);
System.out.println("密文:"+encryptedMsg);
// 解密过程 明文=密文的D次方%N
int decryptMsg = decrypt(decrypt, number, encryptedMsg).intValue();
System.out.println("解密后:"+decryptMsg);
Assert.isTrue(decryptMsg == message);
}
/**
* RSA解密过程
* @param decrypt 私钥
* @param number 推导出密钥对的两大质数之积
* @param encryptedMsg 密文
* @return
*/
private static BigDecimal decrypt(int decrypt, int number, BigDecimal encryptedMsg) {
return encryptedMsg.pow(decrypt).divideAndRemainder(new BigDecimal(number))[1];
}
/**
* RSA加密
* @param encrypt 公钥
* @param number 推导出密钥对的两个不等质数之积
* @param message 需要加密的消息
* @return
*/
private static BigDecimal encrypt(int encrypt, int number, int message) {
BigDecimal decimal = new BigDecimal(message);
return decimal.pow(encrypt).divideAndRemainder(new BigDecimal(number))[1];
}