快速幂取模

这是一个被应用在很多加密算法中的一个小算法

比如我们熟知的RSA加密

那前面铺垫了两期

今天我们终于开始拆解这个算法了哈

其实它只解决了一个问题

也就是说我们需要对一个数

进行大数的指数运算

能大到什么程度呢

一般来说

RSA的私钥涉及的相关数据

都是几百倍的数字

我们先来看一下

在java里尝试计算123的1234次方试试哈

大家注意

Infinity

好我们再来看Js

我们用Node啊

还是Infinity

结果就已经是Infinity了

所以先不说算几百次方的效率问题

单就说找一个数据类型来参与计算

都是个问题

就更别提所消耗的内存

和CPU的算力了

所以呢我们就需要一个算法

来将这么巨大的任务拆分开

做这件事之前

我们先来了解一个基础公式哈

就是a乘以b乘以c

可以继续乘

然后最终取模m

其实它和a乘以(b%m), 乘以c

然后继续乘

或者把c取模m

最终在取模m

它们是相等的

也就说当我们计算多个数的乘积

来取模m的时候

如果我们把其中的一个或者多个数

先做了取模m

其实也不影响整体的结果

其实这个原理很简单

我们来看7 取模

结果是

那么两个7取模4呢

从这个图里我们看出

其实跟两个3取膜4的效果是一样的

就类似我们玩消消乐一样

每一行先消掉4个

这也就变成了:7取模

再乘以

再取模4了

那多个乘数也是一样的哈

大家感兴趣可以自己研究一下

我们再回到视频开始的问题

为了方便

我们先取一个特殊的指数

为什么说它特殊呢

因为它的二进制是

它每一位都是一

也就是所谓的梅森数

所以呢根据前两期视频的结论

x的15次方就等于这个

然后再拆开括号的话

就等于:x∙x²∙x⁴∙x⁸

大家注意哈

这里边的每一个指数

都是前面数的指数的二倍

然后我们继续应用

视频开始提到的基础公式啊

把所有的数都先取模一次

m对结果也没有影响

那么x的15次方取模m就可以变成这样

注意

15的二进制有几位

前半部分这个方括号里就有几个乘数

好那么我们就先看前半部分

如果我们把这第一部分的x取模m

先看作H

那么第二部分

就可以通过两个x相乘的方式

最终拆解成这样

那这两个x%m

就又可以用 H1代替了

也就等于H1乘以H1取模m了

同理

我们再把“x平方取模m”看作H2的话

那么X的4次方曲目m

就等于两个H2相乘再取模m

所以刚才的式子左半部分

我们只需要算出x%m

之后就可以依次地算出

后面各个因式的值了

非梅森数做指数

我们后面再说哈

那到这里

就已经有点代码循环的样子了哈

接下来我们还差一步取模m

因为

我们还是不能直接把这里面结果

做相乘再取模

因为它还是会很大

所以

如果我们再把这些数看成a b c d的话

就变成这个样子

如果我们把a乘b当成一个整体

就又可以把a乘b再取模m了

以此类推呢

就是这样

也就说我们可以把…

a b c d一个一个的跟结果相乘

并且每次相乘后再取模m

其实结果是一样的

包括我们最开始的a可以先跟1相乘

用代码表示呢

就是这样

这是一个快速幂取模的一个方法

我们先设result等于

最后return result

然后把中括号里每一部分取模m的值

放到这个base边量来存储

这里呢我们先取第一个

然后我们就开始循环

循环的条件就是指数还大于

中途每次循环我们都会让指数右移一位 (砍掉二进制右侧最后一位)

直到变成

终止循环

循环里,每次

我们先把base累积到result的结果中

也就说它乘以result

再取模 mod

然后我们再更新base变量的值哈

让它等于它刚才的平方取模 mod

最后每次循环结束

我们记得把指数右移一位(砍掉二进制的最右边一位)

这个也可以通过整出2来实现啊

原理我们就参考上期视频

这样看起来是OK了

但是前面说了

这只是针对梅森数做指数

那么非美森数呢

其实也简单

区别只是在二进制下并不都是

比如是

对应的二进制就是

那么相对于x的15次方

x的13次方就变成这样

只是这一位变成了

但后面的还是没有变化

跟刚刚一样

我们继续拆分

到了这里呢

因为是乘法

所以这里的“1”其实就相当于没有了

但是后面的运算规律

跟刚才梅森数做指数是一样的

所以对应的循环里

我们只要碰到二进之位是

我们就不计入result就可以了

其他的还保持不变

就变成了最终这样

到这里呢

我们三期的视频

就浓缩成了这么一个方法

我们再用JS来验证一下啊

然后呢

我们先去尝试计算一个大一点的指数哈

比如123的1234567次方

大家看:Infinity

但是我们用这快速幂取模的算法呢

大家看啊

123的1234567次方

然后取模1313(随便找个模数),大家看 514

最后更新于

这有帮助吗?