RSA详解

RSA加密是比较常用的加密算法(并不会自己写到),本文尝试使用最基础的方式解释RSA中的每一步的计算步骤、理论依据及证明;即使是忘记了此前学过的所有密码学知识,跟随本文的思路也能完全理解RSA,不用死记硬背一些没有完全理解的东西。整个篇幅会有点长,如果遇到了某个已经理解了的公式或定理,可以直接跳过。

RSA加密流程

首先会介绍一下RSA的加密流程,其中有【】标注的内容会在后文做出解释:

  • 找两个大质数:p、q;算出乘积n;可以保证任何人不能通过n,拆出p、q。

  • 算出另一个数字fn = (p - 1) * (q - 1);这个fn的意思是:在1到n之间,与n互质的数的数量【1】(该注释解释为什么fn能表示这个个数),因为n没有办法被拆开,所以攻击者也计算不出fn。

  • 然后选择一个质数e = 65537作为公钥(也可以选别的),e是质数。

  • 找到私钥d,满足 e * d mod f == 1【2】(该注释介绍如何找到d)。

以上为准备工作;准备这些数据并保存私钥的我们称为接收方,通过明文获得公钥并使用使用公钥加密的称为发送方。

发送方获取到公钥[e, n]后,通过如下方式加密:

  • 现假设有需要加密的数字m,保证m<n; (如果比较长,可以分段加,接收方分段解,始终保证m<n);

  • 发送方计算出密文c = m ^ e mod n ,发送给接收方。

  • 接收方获取到密文c和自己保存的私钥[d,n]后,通过如下方式解密:

  • 接收方计算m' = c ^ d mod n。

  • m' == m 必成立,解密完成【3】(该注释解释为什么 m' == m成立,即RSA的理论基础)

【1】为什么fn = (p-1) * (q-1)表示[1, n]中与n互质的数的个数

  • 因为p为质数,所以在[1, p]中,除p以外的数字,均与p互质,故fp = (p - 1)
  • 因为q为质数,所以在[1, q]中,除q以外的数字,均与q互质,故fq = (q - 1)
  • 因为n = p * q,所以n不是质数,故不能套用以上规则:但是可以通过排除法算出与n互质的数字的个数
  • 在[1, n]中除n外共有数字 p * q - 1个;其中与n不互质的数字包括:A.所有比p小的数字,与q的乘积,共p-1个;B.所有比q小的数字与p的乘积,共q-1个;故有[1,n]中与n互质的数字个数:fn = p * q - 1 - (p - 1) - (q - 1) = p * q - p - q + 1 = (p - 1) * (q - 1)。
  • 综上:在p、q为质数,n = p * q的情况下, fn = (p - 1) * (q - 1) 可以表示[1, n]之间与n互质的数字个数。

【2】在已知质数e、数字fn的情况下,如何找到d,使得e * d mod fn = 1

为了更清晰地阐明这个过程,这里先举一个简单的例子:

假设:p = 3;q = 13;则有n = 39;fn = 2 * 12 = 24;现在,我可以任意指定任意质数为公钥e,假设我指定e = 11,需要寻找一个数字d,满足 e * d mod fn = 1。

按照最直观的操作方式,暴力遍历d = 1、2、3、4...直到找到一个d,满足d * e mod fn = 1:

11 mod 24 = 11

22 mod 24 = 22

33 mod 24 = 9

44 mod 24 = 20

55 mod 24 = 7

66 mod 24 = 18

77 mod 24 = 5

88 mod 24 = 16

99 mod 24 = 3

110 mod 24 = 14

121 mod 24 = 1

结束;事实上,这个过程就是在寻找:

x * 11 - y * 24 = 1;x依次增加,y在总是保证结果为正的前提下尽量大,最终找到了x是11;

所以问题就变成了:我要得到1,至少需要用多少个11(公钥),这个"多少个"就是私钥。因为是私钥*公钥 mod n = 1。

然后,我们演示一下求解11和24最大公约数的过程,我们需要的并不是这个最大公约数,因为你要求的最大公约数一定是1,我们只是需要求解最大公约数过程中使用到的e的个数。

注意:事实上,因为RSA只规定了私钥p、q均为大质数,这里如果(p - 1) * (q - 1)恰好是e的倍数怎么办?在此种情况下,最大公约数是e而不是1,因此,如果遇到此种情况,需要重新换个e:你只需要计算一次(p - 1)*(q - 1)/e是否为整数即可:如果不为整数,则可以使用,如果为整数,重新挑选e,只要保证fn = (p - 1) * (q - 1)不为e的整数倍,那么,fn与e一定互质,在fn与e互质的情况下,最大公约数一定是1,这一点是在挑选e的时候需要保证的。

然后我们列出最大公约数求解过程(辗转相减):

24 - 11 = 13

13 - 11 = 2

11 - 2 = 9

9 - 2 = 7

7 - 2 = 5

5 - 2 = 3

3 - 2 = 1

这个过程有了,那么我们要的是什么值呢,要每一步使用到的11的个数,尾标注一下:

24 - 11 = 13 用到几个11? 1个 ,因为24不用11,11用1个11,所以一共是1个

13 - 11 = 2 用到几个11?2个 ,因为根据上一步:13用了1个11; 本步11用了1个11,所以一共2个

11 - 2 = 9 用到了几个11?3个,因为根据上一步:2用了2个11;本步11用了1个11,所以一共是3个

9 - 2 = 7 用到了几个11?5个,因为根据上一步:9用了3个11;上上步2用2个11,所以一共是5个

7 - 2 = 5 用到了几个11?7个,因为根据上一步:7用了5个;第二步2用了2个,一共7个

5 - 2 = 3 用到了几个11?9个,因为上一步:5用了7个;第二步2用了2个,一共9个

3 - 2 = 1 用到了几个11? 11个,因为上一步:3用了9个;第二步2用了2个;一共11个

结束,得1的时候,用到的11个11,前面的11就是d,后面的11就是e。(Emmm,这个例子不太好了,e和d相等了,但是我已经写到这了,就不重新找别的例子了,可以自行算其他的例子验证,e、d正常来说不都是一样的,这里恰好相等)

那为什么两种方法求出的使用11的个数是一致。如果你已经理解了,可以跳过下面的例子,如果还没理解可以读完这个例子:

【2.1】上下台阶例子

根据上边求解最大公约数的步骤,是不是很像是一个动态规划:列表记录每一步的结果,后一步的结果依赖前面的结果;提到动态规划,就不得不提上下台阶,如果我把题改成:一个小人上下台阶,每次只能从:A.向上走11个台阶 或 B.向下走24个台阶中选择一个方式走,起始位置是0,问:最少走多少次A才能走到1阶。

第一种方法:只要没超过24,就一直往上走11,超过24了,向下走24,直到走到1,记录向上走11的次数。

第二种方法,智能一点:

  1. 只要没超过24,我一直向上走11,超过了减24:上3次,下一次,到9;我记录一下:向上走9步需要3个11;那么下次当我快要抵达24的时候,是不是可以优先考虑9,直接用9步3次的结果。
  2. 从9开始,向上11到20,没超过;接着向上11,到31,超过了,此时,我可以看看,如果不用11,而是用最小的可以满足超过24的步数9,20 + 9 = 29,也超过了;那么我就直接用9;所以在原来3的基础上加1再加3得7;最终走到了5;记录:我向上走5阶,用7个11,下次可以用。
  3. 从5开始,向上11,到16,没超过;接着向上11,超过了,此时,我可以选一个小的值替代11:5行不行?不行,因为16 + 5 = 21 < 24; 9行不行?行,因为16 + 9 = 25 > 24;所以选9,那么也就是在原来7个11的基础上加1个11,再加3个11:7 + 1 +3 = 11,然后看到当前在25 - 24 = 1了,说明满足结果要求,故一共需要11个11能走到1阶。

第三种方法,再智能一点:

记录两个数,向上的最小阶数m,向下的最小阶数n,初始值m = 11,n = 24; 记录另外两个值stepM、stepN,表示走到向上/向下的当前最小阶数,用到11的个数,那么初始值:mNeed11 = 1、nNeed11 = 0。开始循环:

  1. 我先看看向上和向下哪个大?向下大:那么我可以用24减去尽可能多的11,得到一个向下的距离1最近的阶数:是不是24 - 2 * 11 = 2;然后用这个2替换之前的最小阶数24:m = 11, n = 2, 更新 nNeed11 = 2,因为减了两个11。
  2. 我再看看m、n哪个大?向上大:那么可以用11减去尽可能多的2,得到一个向上的距离1最近的阶数:是不是11 - 5 * 2 = 1;然后用这个1替换之前向上的最小阶数11:m = 1, n = 2, mNeed11 = mNeed11 + 5 * nNeed11 = 11,因为你用了一次向上m减去尽可能多的5个n,所以后面加了前一次的mNeed11。

此时m已经等于1了,所以退出循环。

然后看看这三个方法:方法一其实就是一个一个11向上加,超24减24的方法;方法三,其实就是辗转相除法求最大公约数,在求解e和fn的最大公约数过程中,记录使用到e的个数。

此例结束,总结:求解e * d mod fn = 1和辗转相除法求解最大公约数联系在一起时因为;前者需要的是后者中间产物,非最大公约数本身。

【3】m' == m 必成立

间隔比较远,重新描述一下问题:

m为明文,任意正整数;p、q为质数;n = p * q; fn = (p - 1) * (q - 1);

e为任取质数,d满足 e * d mod fn = 1;

c为密文,c = m ^ e mod n

m'为解密文,m' = c ^ d mod n

证明:m' == m

为了在讲述最终证明之前扫清一些障碍,首先证明三个小推论:

【3.1】模法分配率:"积的模 等于 模积模"

即:a * b mod c = (a mod c) * (b mod c) mod c ("模法分配率"我瞎编的,不知道怎么叫,这个读着顺口好记)

证明:将a、b拆成,关于c的倍数和余数之和的形式:

令: a = k * c + x; b = s * c + y;k、s为倍数,x、y为余数,x、y一定小于等于c。

那么有:a * b mod c = (k * c + x) * (s * c + y) mod c = (k * m* c^2 + k * c * y + m * c * x + x * y) mod c

前三项均包含c因子,故会被模掉,所以最终剩余:

a * b mod c = x * y mod c = (a mod c) * (b mod c) mod c

得证。

【3.2】若a与c互质 且 b与c互质,则a * b与c互质

反证法:若a * b与c不互质,则存在一个大于1的因子m,同时在a * b 和 c中;对于a * b,若想有因子m,则因子m不是在a中,就是在b中,或者是在a、b中;不论哪种情况,都与a、c互质和a、b互质矛盾,故不存在m;所以a * b 与 c互质。

得证。

【3.3】若a与b互质,则a mod b 与 b 互质

将a拆解成倍数和余数的形式 a = k * b + x;则x = a mod b;因为k * b一定与b不互质,如果x与b也不互质,那么k * b + x与b一定不互质,与a与b互质矛盾,故x与b一定互质。

得证。

【3.4】开始证明m' == m,先证此问题:对互质的两个数:a和b;在[1,a]之间,所有与a互质的数x,计算出的y = b * x mod a 均不相等。

即:所有的y与x一一映射,不存在两个不同的xi和xj能算出同一个y的情况。

反证法:我从[1,a]中任选与a互质的两个数字,xi和xj;若存在:b * xi mod a == b * xj mod a;则: (b * xj - b * xi) 一定是a的整数倍,相当于把相同的余数都减掉了,剩下的都是a的倍数,这个很好理解;也就意味着:b * (xj - xi) 是a的整数倍。

因为|xj - xi|必定比a小,所以,若想从b * (xj - xi)中提取出a因子,那么必须从b中提取出一个大于1的因子,乘上(xj - xi),才有可能凑出一个a因子;假设从b中提取出了一个大于1的因子m,凑出了a;那么该因子m也必定是a的因子;而a、b存在大于1的因子m,与a、b互质相矛盾,故不存在;所以b * (xj - xi) 不可能是a的整数倍。也就是说任意一对: b * xi mod a 和 b * xj mod a 均不相等。

得证。

【3.5】对于【3.4】中所有的y = b * x mod a,均与a互质。

显然,根据【3.2】:因为b与a互质、x与a互质,故b * x 与a 互质;又根据【3.3】因为b * x 与 a互质,故b * x mod a 与 a互质。

得证。

【3.6】综合【3.4】和【3.5】进行推论:

因为【3.4】中所有的y均比a小;且所有的y都是与x一一对应,没有重复,所以数量相等;且所有的y都与a互质。如果我将所有的x放入集合X,所有的y放入集合Y,那么X与Y必等价,表示的都是:所有【1,a】之间与a互质的正整数。

接着推:因为集合X和集合Y等价,所以两集合里面所有元素乘积必相等:

x1 * x2 * x3 ... x(f(a)) == y1 * y2 * y3 ... y(f(a))

肯定的,里面元素都一样,只是乘的顺序可能不相等,所以一个也不能漏。

然后将y侧都替换为:y = b * x mod a 的形式

x1 * x2 * ... == (b * x1 mod a) * (b * x2 mod a) ...

两边mod依然相等:

x1 * x2 * ... mod a == (b * x1 mod a) * (b * x2 mod a) ... mod a

根据【3.1】"模积模 等于 积的模":

x1 * x2 * ... mod a = (b * x1 mod a) * (b * x2 mod a) ... mod a = (b * x1) * (b * x2) ... mod a = b ^ f(a) * (x1*x2...) mod a

f(a)就是集合X中元素个数,也就是[1,a]中所有与a互质的数字个数。

两边mod相等 的条件等价于两边相减余下k个a,k任意;

所以有右-左有:

(b ^ fa - 1) * (x1 * x2 * ...) = k * a

因为 x1、x2 ... 均与a互质根据【3.2】(x1 * x2 *....)与a互质,所以 b ^ fa - 1 必为a的整数倍。

故:b ^ fa mod a = 1成立。【定理A】

根据这个推论,我们套入RSA中,上式 a 即为 RSA中的n, b即为RSA中的m;

那么:

c = m ^ e mod n;e * d mod fn = 1;

有:m' = m ^ (e * d) mod n = m ^ (k * fn + 1) mod n = m * (m^fn * m^ fn ... *m^fn) mod n

根据【3.1】"积的模 等于 模积模":

m' ={ m mod n * [ (m^fn mod n) *...] } mod n

根据前面的【定理A】,m ^ fn mod n = 1,所以上式中括号中是一堆1相乘,故:

m' = {m mod n * (1 * 1 * 1 ...)} mod n = m mod n

因为RSA在截取密文m时,始终保证m < n,故 m mod n = m,即m' = m。

得证:解密文 m' == 原文m;RSA加解密成立。

上述【定理A】即为:欧拉定理,其核心就是证明所有x凑成的集合X 与 所有y = b * x mod a 组成的集合Y,完全等价,所以元素相乘值相等,再将y中所有的b,单独提出,凑出b^fa形式,最后数学变换验证了:b^(fa - 1) mod a = 1成立得出。

【3.7】m与n不互质的情况

在上文【3.6】中,我们单纯套用了【定理A】,【定理A】中对a、b的要求是:a、b互质;然而,在RSA中,我们对原文m的要求仅为:m < n,并未保证互质;实际情况下:m可能出现比n小的任何数字;n = p * q;n必不是质数,因此没法保证m、n互质;但在此种情况下,RSA依然成立,以下给出证明:

考虑为数不多的几种m、n不互质的情况:由于m < n; n = p * q;p、q均为质数;那么仅有以下情况m、n不互质:

  1. m = k * p; k < q;

  2. m = k * q; k < p;

由于p、q等价,因此我们只需证明其中一种情况RSA仍成立,另一种情况完全对称。

取m = k * p; k < q;的情况进行讨论:

目标:计算出 c = (k * p) ^ e mod n,验证:m' = c ^ d mod n 与 m相等。

由于p、q为质数 且 k、q互质,根据【3.2】k * p 与 q互质;所以,k * p 与 q满足欧拉定理:

(k * p) ^ fq mod q = 1

那么:[ (k * p) ^ fq ] * [(k * p) ^ fq] mod q = ?

显然还是1,根据【3.1】"积的模 等于 模积模":

原式 = { [ (k * p) ^ fq mod q] * [ (k * p) ^ fq mod q] } mod q = (1 * 1) mod q

那是不是我任意个 (k * p) ^ fq 相乘 mod q都是1,所以fp个相乘也是1,故有:

(k * p) ^(fp * fq) mod q = 1

fp = p - 1; fq = q -1; fn = (p - 1) * (q - 1);所以:

(k * p) ^ fn mod q = 1;意味着:

(k * p) ^ fn = s * q + 1 ; s任意,不知道多少。

两边同时乘 k * p:

(k * p) ^ (fn + 1) = s * q * k * p + k * p

两边 mod n:

(k * p) ^ (fn + 1) mod n = k * p

根据RSA,e * d mod fn = 1;故:e * d = s * fn + 1 ; s任意;

结合上式:我现在需要根据 :

(k * p) ^ (fn + 1) mod n = k * p

推出:

(k * p) ^ (s * fn + 1) mod n = k * p

怎么办,如果我说我能根据:

(k * p) ^ (fn + 1) mod n = k * p

推出:

(k * p) ^ (2 * fn + 1) mod n = k * p;

是不是意味着我把2换成s;s >= 1;是成立的:

那就拆:

(k * p) ^ (2 * fn + 1) mod n = [ (k * p) ^ fn * (k * p)^(fn + 1)] mod n = [ (k * p) ^ fn mod n ] * {[(k * p)^(fn + 1)] mod n} mod n

后面那个fn + 1的项是不是就等于 k * p:

原式 = [ (k * p) ^ fn mod n ] * (k * p) mod n

因为k * p 一定比 n 小,所以k * p = k * p mod n

原式 = [ (k * p) ^ fn mod n ] * (k * p mod n) mod n

再把它合进去:

原式 = [ (k * p) ^ fn * (k * p) mod n ] mod n = (k * p) ^ (fn + 1) mod n = k * p

是不是前面不论再乘多少个 (k * p) ^ fn,我都能这样把它吃掉,故:

m' = (k * p) ^ (s * fn + 1) mod n = (k * p) ^ (fn + 1) mod n = k * p = m

所以,RSA在m与n不互质的情况下,依然成立。

【4】总结

通过重新叙述RSA加解密流程,进行总结:

  • 通过寻找两个大质数p、q,保证fn = fp * fq;fp、fq表示[0,p/q]之间与p/q互质的数字个数,由于p、q为质数,保证了:fp = (p - 1) ; fq = (q - 1);fn = (p - 1) * (q - 1)成立(f函数叫欧拉函数,这个函数有一些特殊性质,本文【1】证明的是其中一个:p、q为质数情况下的性质,f(p * q) = fp * fq)。
  • 取质数e作为公钥,并根据e、n使用辗转相除求解私钥d,【2】阶段证明,并列举了上下台阶的例子便于理解为什么使用辗转相除,其本质并非求解最大公约数。
  • 对原文m进行加密,c = m ^ e mod n
  • 对密文c进行解密, m' = c ^ d mod n = m;包含两种情况:1.m与n互质,套用欧拉定理得证;2.m与n不互质,【3.7】阶段给出证明。两种情况下:m' = m 均成立,故仅保证m < n 即可。

结束,以上就是RSA所依赖理论基础的全部证明过程;本文的所有论证均从最基础的理论出发,是为了保证在不了解欧拉函数、欧拉定理、辗转相除用意的前提下依然能理解RSA加解密成立的原因。同时,也填补实际使用时对产生的:e、n不互质,m、n不互质情况下的处理办法,不失为一篇全面理解RSA的好文章啊,哈哈哈;当然,对于一些已经比较了解RSA的工程师来说,本文的部分讨论着实显得拖沓了。

相关推荐
极客先躯2 分钟前
高级java每日一道面试题-2024年9月16日-框架篇-Spring MVC和Struts的区别是什么?
java·spring·面试·mvc·struts2·框架篇·高级java
dreamer2921 小时前
21、Tomato
linux·安全·web安全·网络安全·系统安全
newxtc3 小时前
【爱给网-注册安全分析报告-无验证方式导致安全隐患】
前端·chrome·windows·安全·媒体
2407-2 shw4 小时前
weblogic CVE-2018-2894 靶场攻略
java·运维·服务器·安全·weblogic
GISer_Jing4 小时前
前端面试CSS常见题目
前端·css·面试
八了个戒5 小时前
【TypeScript入坑】什么是TypeScript?
开发语言·前端·javascript·面试·typescript
xiaojiesec6 小时前
第159天:安全开发-Python-协议库爆破&FTP&SSH&Redis&SMTP&MYSQL等
运维·安全·ssh
世界尽头与你6 小时前
安全热点问题
安全·网络安全
小小工匠7 小时前
加密与安全_HTTPS TLS 1.2 连接(RSA 握手)的整个过程解读
安全·https·tls
xilu07 小时前
英语: "简历" 的两种表达,CV 和 Resume 探讨
面试