RSA原理

  在RSA原理之前,我想还是有必要了解一下非对称加密算法的加密跟解密过程。下面就是一幅非称加密算法的流程图。

  RSA加密算法原理

  在此可以看到,非对称加密是通过两个**(公钥-私钥)来实现对数据的加密和解密的。公钥用于加密,私钥用于解密。对于非对称的加密和解密为什么可以使用不同的**来进行,这些都是数学上的问题了。不同的非对称加密算法也会应用到不同的数学知识。上面也对RSA中使用的数学问题做了一个小小的介绍。现在就来看看RSA算法是怎么来对数据进行加密的吧,如下是一幅RSA加密算法流程及加密过程图。

  RSA加密算法原理


RSA应用

1. 实例模型

  就以上图中的Bob和Alice来举例吧。

  现在Alice通过**生成器生成了一对**(公钥-私钥)。只把公钥对外公开了。并说,你有什么要跟我说的,就用模幂运算和公钥加密后发给我吧。

  此时,Bob已经获得了Alice发布的公钥。使用模幂运算对明文进行了加密,就把加密后的密文发送给了Alice。

  Alice获得Bob发来的密文并没有使用公钥对密文进行解密,并获得了明文。因为解密过程需要使用的**是私钥。


2. RSA算法实现

  下面的代码只是根据RSA算法的定义,使用Java开发语言实现。且这里只是展示了一些关键步骤,完整过程可以参见下面的源码下载文档。

[java] view plain copy
  1. public class RSA {      
  2.     /** 
  3.      * 获得(公/私)** 
  4.      */  
  5.     public final Map<String, RSAKey> getCipherKeys() {  
  6.         ...  
  7.         int[] primes = getRandomPrimes(2);  
  8.         int modulus = modulus(primes[0], primes[1]);  
  9.         int euler = euler(primes[0], primes[1]);  
  10.         int e = cipherExponent(euler);  
  11.         int inverse = inverse(euler, e);  
  12.         publicKey.setExponent(e);  
  13.         publicKey.setModulus(modulus);  
  14.         privateKey.setExponent(inverse);  
  15.         privateKey.setModulus(modulus);  
  16.         ...  
  17.     }  
  18.       
  19.     /** 
  20.      * 加密 
  21.      */  
  22.     public int encode(int plaintext, RSAPublicKey key) {  
  23.         return modularPower2(plaintext, key.getExponent(), key.getModulus());  
  24.     }  
  25.       
  26.     /** 
  27.      * 解密 
  28.      */  
  29.     public int decode(int chipertext, RSAPrivateKey key) {  
  30.         return modularPower2(chipertext, key.getExponent(), key.getModulus());  
  31.     }  
  32.   
  33.     // 随机生成count个素数  
  34.     private final int[] getRandomPrimes(int count) {  
  35.         ...  
  36.         try {  
  37.             primeLabels = FileReadUtils.readLines("./data/prime_table");  
  38.         } catch (IOException e) {  
  39.             e.printStackTrace();  
  40.         }  
  41.         for (int i = 0; i < primes.length; i++) {  
  42.             primes[i] = Integer.parseInt(primeLabels.get(indexs.get(i)));  
  43.         }  
  44.   
  45.         return primes;  
  46.     }  
  47.   
  48.     // 计算公共模数  
  49.     private final int modulus(int p, int q) {  
  50.         return p * q;  
  51.     }  
  52.   
  53.     // 计算欧拉数  
  54.     private final int euler(int p, int q) {  
  55.         return (p - 1) * (q - 1);  
  56.     }  
  57.   
  58.     // 计算加密指数  
  59.     private final int cipherExponent(int euler) {  
  60.         Random random = new Random();  
  61.   
  62.         int e = 7;  
  63.         do {  
  64.             e = random.nextInt(euler - 1);  
  65.         } while (!isCoprime(e, euler) || e <= 1);  
  66.   
  67.         return e;  
  68.     }  
  69.   
  70.     // 判断两个数互素  
  71.     private final boolean isCoprime(int number1, int number2) {  
  72.   
  73.         int sqrt = (int) Math.sqrt(Math.max(number1, number2));  
  74.         for (int i = 2; i <= sqrt; i++) {  
  75.             if (number1 % i == 0 && number2 % 2 == 0) {  
  76.                 return false;  
  77.             }  
  78.         }  
  79.   
  80.         return true;  
  81.     }  
  82.   
  83.     // 计算“模的逆元”  
  84.     // (d * e) ≡ 1 mod euler  
  85.     private final int inverse(int euler, int e) {  
  86.         ...  
  87.         while (flag) {  
  88.             q = m[2] / n[2];  
  89.             for (int i = 0; i < 3; i++) {  
  90.                 temp[i] = m[i] - q * n[i];  
  91.                 m[i] = n[i];  
  92.                 n[i] = temp[i];  
  93.             }  
  94.             if (n[2] == 1) {  
  95.                 if (n[1] < 0) {  
  96.                     n[1] = n[1] + euler;  
  97.                 }  
  98.                 return n[1];  
  99.             }  
  100.             if (n[2] == 0) {  
  101.                 flag = false;  
  102.             }  
  103.         }  
  104.         return 0;  
  105.     }  
  106.       
  107.     // 模幂运算  
  108.     private final int modularPower(int base, int e, int modular) {  
  109.         int result = 1;  
  110.         do {  
  111.             if (isOdd(e)) {  
  112.                 result = (result * (base % modular)) % modular;  
  113.                 e -= 1;  
  114.             } else {  
  115.                 base = (base * base) % modular;  
  116.                 e /= 2;  
  117.             }  
  118.         } while (e > 0);  
  119.           
  120.         result %= modular;  
  121.           
  122.         return result;  
  123.     }  
  124. }


RSA加密:非对称**,公开**算法

RSA加密利用了单向函数正向求解很简单,反向求解很复杂的特性。
具体是利用了:
1.对两个质数相乘容易,而将其合数分解很难的这个特点进行的加密算法。 n=p1*p2,已知p1、p2求n简单,已知n求p1、p2困难。
2.(m^e) mod n=c,已知m、e、n求c简单,已知e、n、c求m很难。
RSA加密,实现了公开**,就是A可以给所有人发送锁,其他人把要加密的信息用这把锁加密后发送给A,A用自己的钥匙开锁就可以获得加密的信息了。反过来,A要发送加密信息给B,只要知道B的锁就可以了,而这个锁是公开的。

公开**n、e的生成:随机选取两个质数p1、p2,n=p1*p2,再随机选取一个整数e,e与φ(n)互质。
加密过程:(m^e) mod n=c,其中m为原信息,c为加密信息,n、e为公开**。
解密过程:(c^d) mod n=m,其中d为解***。
解***d的求解:
(c^d) mod n=(((m^e) mod n)^d) mod n=((m^e)^d) mod n=(m^ed) mod n=m ①
根据费马定理(m^φ(n)) mod n≡1,又1^k≡1,所以(m^k*φ(n)) mod n≡1,两边同乘以m得m*((m^k*φ(n)) mod n)≡1*m,化简(m^(k*φ(n)+1)) mod n≡m ②
由①、②得ed=(k*φ(n)+1),解得d=(k*φ(n)+1)/e。
费马定理:若p是素数,a与p互素,则a^(p-1)≡1 (mod p)

过程如下:
A:有一个公钥n、e。例如:3127、3。
B:有一个信息m。例如:89。
C:偷听者

A:
第一步:随机找两个质数p1、p2,一个奇数e。例如:53、59、3。
第二步:计算n=p1*p2得到n,计算欧拉函数φ(n)=(p1-1)*(p2-1)得到φ(n),计算钥匙d=(k*φ(n)+1)/e得到d。例如:53*59=3127、(53-1)*(59-1)=3016、(k*φ(n)+1)/e=(2*3016+1)/3=2011。
第三步:发送n、e给大家知道    //n、e就是公钥也做锁,d就是n、e的钥匙。

C:获得n、e

B:
第一步:获得n、e
第二步:加密信息m,(m^e) mod n=c,获得加密信息c。例如:(89^3) mod 3127=1394。
第三步:发送c给A

C:
第一步:截获加密信息c
第二步:**信息c,此时C只有n、e、c,只有把n分解质因数才能**,而此分解很困难特别是当n很大的时候。

A:
第一步:收到加密信息c
第二步:解密信息c,(c^d) mod n=m,获得信息m。例如:(1394^2011) mod 3127=89。

完成


2.。。。。。。。。。。。。。。



们来回顾一下RSA的加密算法。我们从公钥加密算法和签名算法的定义出发,用比较规范的语言来描述这一算法。

RSA公钥加密体制包含如下3个算法:******(**生成算法),Encrypt(加密算法)以及Decrypt(解密算法)。

  • RSA加密算法原理。**生成算法以安全常数RSA加密算法原理作为输入,输出一个公钥PK,和一个私钥SK。安全常数用于确定这个加密算法的安全性有多高,一般以加密算法使用的质数p的大小有关。RSA加密算法原理越大,质数p一般越大,保证体制有更高的安全性。在RSA中,**生成算法如下:算法首先随机产生两个不同大质数p和q,计算N=pq。随后,算法计算欧拉函数RSA加密算法原理。接下来,算法随机选择一个小于RSA加密算法原理的整数e,并计算e关于RSA加密算法原理的模反元素d。最后,公钥为PK=(N, e),私钥为SK=(N, d)。
  • RSA加密算法原理。加密算法以公钥PK和待加密的消息M作为输入,输出密文CT。在RSA中,加密算法如下:算法直接输出密文为RSA加密算法原理
  • RSA加密算法原理。解密算法以私钥SK和密文CT作为输入,输出消息M。在RSA中,解密算法如下:算法直接输出明文为RSA加密算法原理。由于e和d在RSA加密算法原理下互逆,因此我们有:RSA加密算法原理

所以,从算法描述中我们也可以看出:公钥用于对数据进行加密,私钥用于对数据进行解密。当然了,这个也可以很直观的理解:公钥就是公开的**,其公开了大家才能用它来加密数据。私钥是私有的**,谁有这个**才能够解密密文。否则大家都能看到私钥,就都能解密,那不就乱套了。


=================分割线=================

我们再来回顾一下RSA签名体制。签名体制同样包含3个算法:******(**生成算法),Sign(签名算法),Verify(验证算法)。

  • RSA加密算法原理。**生成算法同样以安全常数RSA加密算法原理作为输入,输出一个公钥PK和一个私钥SK。在RSA签名中,**生成算法与加密算法完全相同。
  • RSA加密算法原理。签名算法以私钥SK和待签名的消息M作为输入,输出签名RSA加密算法原理。在RSA签名中,签名算法直接输出签名为RSA加密算法原理。注意,签名算法和RSA加密体制中的解密算法非常像
  • RSA加密算法原理。验证算法以公钥PK,签名RSA加密算法原理以及消息M作为输入,输出一个比特值b。b=1意味着验证通过。b=0意味着验证不通过。在RSA签名中,验证算法首先计算RSA加密算法原理,随后对比M'与M,如果相等,则输出b=1,否则输出b=0。注意:验证算法和RSA加密体制中的加密算法非常像

所以,在签名算法中,私钥用于对数据进行签名,公钥用于对签名进行验证。这也可以直观地进行理解:对一个文件签名,当然要用私钥,因为我们希望只有自己才能完成签字。验证过程当然希望所有人都能够执行,大家看到签名都能通过验证证明确实是我自己签的。


相关文章: