版权申明:本文为博主窗户(Colin Cai)原创,欢迎转帖。如要转贴,必须注明原文网址

  http://www.cnblogs.com/Colin-Cai/p/7290010.html 

  作者:窗户

  QQ:6679072

  E-mail:6679072@qq.com

  RSA最终加密、解密都要用到模乘的幂运算,简称模幂运算。

  回忆一下RSA,从明文A到密文B

  B=Ae1%N

  对B解密回到明文A,就是

  A=Be2%N

  其中,一般来说,加密公钥中的e1一般会比较小,取65537居多,但解密的时候,这个e2是一个非常非常大的数,显然,直接通过e2次模乘来解密是不现实的。

  为了让RSA的加密、解密成为现实,我们必须要找一个好的算法来做模幂运算。

  借上一节我设定的符号,以区别于传统上的幂的数学表示,

  定义a#b为a和b的模乘,

  定义a##n为n个a的模乘,或称a的n阶模乘。

  a = a##1,

  a##2 = a#a,

  a##4 = (a##2) # (a##2),

  ...

  a##2n = (a##2n-1) # (a##2n-1),

  从而,进行了n次模乘,分别获得了1、21 、22 ...2n 个a的模乘结果,

  而1、21 、22 ...2n 取其中任意一部分的和可以覆盖1~2n-1的所有整数。

  从而我们得到了一个算法来计算a##b:

  先不断通过每次得到的新结果自己同自己模乘,得到

  a、a##2、a##4...a##2n,使得满足2n≤b<2n+1

  再将b化为二进制表示,实际上也就是表示为2的各次幂相加形式,

  然后找到对应每个2的幂次a模乘结果,

  然后再把这些结果依次模乘,得到最终结果。

  打个比方,如果想求a##21,

  21用二进制表示为10101,所以21 = 16+4+1,

  第一步,求得a##2,a##4,a##8,a##16,

  第二步,取a,a##4,a##16,三者模乘就是最终需要的结果。

  

  当然,可以把第一步求a的2n阶模乘和第二步取需要的模乘融合在一起,这样就不需要存储每一个a的2n阶模乘结果,从而存储空间可以为常数级,而之前存储空间为线性级。

  该算法用bc描述如下:

  

#!/usr/bin/bc -q
define mod_mul(a1,a2,n)// a1*a2%n
{
return a1*a2%n;
}
define mod_exp(a,b,n)// a^b%n
{
while(b%==) {
a = mod_mul(a,a,n);
b /= ;
}
ret = a;
b /= ;
while(b!=) {
a = mod_mul(a,a,n);
if(b% == )
ret = mod_mul(a,ret,n);
b /= ;
}
return ret;
}
a=read();
b=read();
n=read();
print mod_exp(a,b,n),"\n"
quit

  该算法求a##b所做模乘次数:

  求各个a的2n阶模乘,所做模乘次数为log2b取整,也就是b的二进制的位数减1;

  取相应的2的正整数次幂的模乘结果再做模乘,所做模乘次数为b的二进制中1的个数减1。

  两者加一起为模乘次数。

  比如上面想求a##21,21用二进制表示为10101,所以该算法所需要模乘次数为(5-1)+(3-1)=6次。

  

  但此算法未必是最优的,我们来看看如下例子:

  想求a##441,

  441用二进制展开为110111001,于是模乘次数应该是(9-1)+(6-1)=13次。

  但我们可以用另外一种方式来求a##441,

  441 = 21 * 21,

  a##441 = (a##21) ## 21,

  我们求b = a##21需要6次模乘,

  再求b##21需要6次模乘,总共只需要12次模乘,比刚才少了1次。

  

  441是合数,我们再取个质数,239。

  239写成二进制是11101111,那么根据我们的算法应该做的模乘次数为(8-1)+(7-1)=13次。

  239 = 14*17+1,

  a##239 = ((a##14) ## 17) # a,

  先求b = a##14,需要5次模乘,

  再求c = b##1,需要5次模乘,

  最后再与a模乘,需要1次模乘,

  总共11次模乘,比13次要少。

  但是,即便是合数分解了,也未必得到更好的结果。

  例如49 = 7*7,

  分解前,49表示为二进制为110001,要做(6-1)+(3-1)=7次模乘,

  可是分解后,7表示为二进制制为111,

  总共要做(3-1)+(3-1)+(3-1)+(3-1)=8次模乘了。

  从而我们可以知道,我们给出的算法虽然是一个线性时间算法,但未必是最优算法,不过做到线性时间算法,从运算时间复杂度上来说,的确没有时间复杂度是这个算法的低阶无穷大级的算法了,从这个意义上,此算法已经“最优”了。

  如何做到最少次模乘?

  本问题为以下问题:

  (1)集合A初始为{1}

  (2)每一步从集合A中取两个数a和b,ab可相同,让c = a+b,再把c并入集合A,

    A = A∪{c}

  (3)输入正整数e,求A里面有元素e的最小步骤的过程。

  

  可惜此问题获得最优解似乎没有很好的算法,甚至远高于RSA可能基于的安全性——大数分解,但存在相对好的算法,从而可以用来改进我们的模幂算法。

  

  模幂算法是RSA的核心,不仅仅加密解密的时候需要,寻找密钥的时候也是需要的。

RSA简介(二)——模幂算法的更多相关文章

  1. RSA算法的C++string实现(模幂算法和欧几里得算法的使用)后附思路

    void resetNumA(string numAStr); //使用string重置numB void resetNumB(string numBStr); //将数组转换为字符串,用于输出 st ...

  2. RSA简介(四)——求逆算法

    此处所谓求逆运算,是指在模乘群里求逆. 第一节里提到互质的两个定义: (1)p,q两整数互质指p,q的最大公约数为1. (2)p.q两整数互质指存在整数a,b,使得ap+bq=1. 只要明白了欧几里得 ...

  3. RSA简介(三)——寻找质数

    要生成RSA的密钥,第一步就是要寻找质数,本节专讲如何寻找质数. 我们的质数(又称素数).合数一般是对正整数来讲,质数就是只有1和本身两个的正整数,合数至少有3个约数,而1既不是合数也不是质数. 质数 ...

  4. RSA算法原理——(2)RSA简介及基础数论知识

    上期为大家介绍了目前常见加密算法,相信阅读过的同学们对目前的加密算法也算是有了一个大概的了解.如果你对这些解密算法概念及特点还不是很清晰的话,昌昌非常推荐大家可以看看HTTPS的加密通信原理,因为HT ...

  5. Modular_exponentiation模幂运算

    https://en.wikipedia.org/wiki/Modular_exponentiation 蒙哥马利(Montgomery)幂模运算是快速计算a^b%k的一种算法,是RSA加密算法的核心 ...

  6. 二模13day1解题报告

    二模13day1解题报告 T1.发射站(station) N个发射站,每个发射站有高度hi,发射信号强度vi,每个发射站的信号只会被左和右第一个比他高的收到.现在求收到信号最强的发射站. 我用了时间复 ...

  7. 二模 (8) day2

    第一题: 题目描述: 有 n 个炸弹,有些炸弹牵了一根单向引线(也就是说引线只有在这一端能被炸弹点燃),只要引爆了这个炸弹,用引线连接的下一个炸弹也会爆炸.每个炸弹还有个得分,当这个炸弹被引爆后就能得 ...

  8. 非对称加密RSA、Elgamal、背包算法、Rabin、D-H、ECC(椭圆曲线加密算法)等。使用最广泛的是RSA算法

          非对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥(privatekey).公开密钥与私有密钥是一对,如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密:如果用私 ...

  9. 银行卡号码校验算法(Luhn算法,又叫模10算法)

    有时候在网上办理一些业务时有些需要填写银行卡号码,当胡乱填写时会立即报错,但是并没有发现向后端发送请求,那么这个效果是怎么实现的呢. 对于银行卡号有一个校验算法,叫做Luhn算法. 一.银行卡号码的校 ...

随机推荐

  1. Qlik报表开发见解

    因为项目需要,最近去做了Qlik Sense报表开发,学习了Qlik报表的开发方法和一些基础的开发模式,以下是我对Qlik报表开发的一些见解,个人水平有限,欢迎大神指导. 1.Qlik Sense的函 ...

  2. java递归算法实现 数字人民币大写转换

    最近穷死了 ,没钱吃饭ing 写点钱给自己吧!public class Test{ public static String getChar(long a){ int b = (int)a; Map ...

  3. Entity Framework入门教程:什么是Entity Framework

    Entity Framework简介 Entity Framework是微软提供的一个O/RM(对象关系映射)框架.它基于ADO.NET,为开发人员提供了一种自动化的机制来访问和存储数据库中的数据. ...

  4. RabbitMQ系列教程之四:路由(Routing)

    (使用Net客户端)在上一个教程中,我们构建了一个简单的日志系统,我们能够向许多消息接受者广播发送日志消息.在本教程中,我们将为其添加一项功能 ,这个功能是我们将只订阅消息的一个子集成为可能. 例如, ...

  5. 使用juggle简化网络编程

    常规的网络编程,在消息处理上大概会采用如下方式 struct msg{ int msg_id; int msg_len; //...msg_info }; 定义如上的消息结构 接收方接收后,按如上的消 ...

  6. 轻量级高性能ORM框架:Dapper高级玩法

    Dapper高级玩法1: 数据库中带下划线的表字段自动匹配无下划线的Model字段. Dapper.DefaultTypeMap.MatchNamesWithUnderscores = true; 备 ...

  7. Cordova(PhoneGap) 环境搭建与基础

    Cordova(PhoneGap) 创建步骤:官方Guide 环境准备 安装 Node.js nodejs.org 安装 git git-scm.com (bin目录添加到path) 安装 cordo ...

  8. accp8.0转换教材第3章MySQL高级查询(一)理解与练习

    一.单词部分 ①constraint约束②foreign外键③references参考 ④subquery子查询⑤inner内部的⑥join连接 二.预习部分 1.修改表SQL语句的关键字是什么 RE ...

  9. (转载)JProfiler试用手记

    JProfiler是一款Java的性能监控工具.可以查看当前应用的对象.对象引用.内存.CPU使用情况.线程.线程运行情况(阻塞.等待等),同时可以查找应用内存使用得热点,这里提供有几篇文章供参考:获 ...

  10. Css绘制形状

    前言:终于我的大一生活结束了,迎来了愉快的暑假,大家都开始了各自的忙碌.一直忙着一些项目的事情,终于决定今天要更新一篇博客了,对上一阶段的学习做简单的总结. 这次我主要总结一下用Css绘制各种形状的技 ...