Python 25行代码实现的RSA算法详解


Posted in Python onApril 10, 2018

本文实例讲述了Python 25行代码实现的RSA算法。分享给大家供大家参考,具体如下:

网络上很多关于RSA算法的原理介绍,但是翻来翻去就是没有一个靠谱的算法实现,即使有代码介绍,也都是直接调用JDK或者Python代码包中的API实现,或者即使有代码也都写得特别烂。无形中让人感觉RSA加密算法竟然这么高深,然后就看不下去了。还有我发现对于“大整数的幂次乘方取模”竟然采用直接计算的幂次的值,再取模,类似于(2 ^ 1024) ^ (2 ^ 1024),这样的计算就直接去计算了,我不知道各位博主有没有运行他们的代码???知道这个数字有多大吗?这么说吧,把全宇宙中的物质都做成硬盘都放不下,更何况你的512内存的电脑。所以我说他们的代码只可远观而不可亵玩已。

于是我用了2天时间,没有去参考网上的代码重新开始把RSA算法的代码完全实现了一遍以后发现代码竟然这么少,25行就全部搞定。为了方便整数的计算,我使用了Python语言。为什么用Python?因为Python在数值计算上比较直观,而Java语言需要用到BigInteger类,数值的计算都是用方法调用,所以使用起来比较麻烦。如果有同学对我得代码感兴趣的话,先二话不说,不管3X7=22,把代码粘贴进pydev中运行一遍,是驴是马拉出来溜溜。看不懂可以私信我,我就把代码具体讲讲,如果本文章没有人感兴趣,我就不做讲解了。

RSA算法的步骤主要有以下几个步骤:

①、选择 p、q两个超级大的质数
②、令n = p * q。取 φ(n) =(p-1) * (q-1)。
③、取 e ∈ 1 < e < φ(n) ,( n , e )为公钥对
④、令 ed mod φ(n) = 1,取得d,( n , d ) 为私钥对。 利用扩展欧几里的算法进行计算。
⑤、销毁 p、q。密文 = 明文 ^ e mod n , 明文 = 密文 ^ d mod n。利用蒙哥马利方法进行计算

代码主要涉及到三个Python可执行文件:计算最大公约数、大整数幂取模算法、公钥私钥生成及加解密。这三个文件构成了RSA算法的核心。

前方高能,我要开始装逼了。看不懂的童鞋请绕道,先去看看理论,具体内容如下:

1. 计算最大公约数
2. 超大整数的超大整数次幂取超大整数模算法(好拗口,哈哈,不拗口一点就显示不出这个算法的超级牛逼之处)
3. 公钥私钥生成

1、计算最大公约数与扩展欧几里得算法

gcd.py文件,gcd方法用来计算两个整数的最大公约数。ext_gcd是扩展欧几里得方法的计算公式。

# -*- coding: utf-8 -*-
# 求两个数字的最大公约数(欧几里得算法)
def gcd(a, b):
  if b == 0:
    return a
  else:
    return gcd(b, a % b)
'''
扩展欧几里的算法
计算 ax + by = 1中的x与y的整数解(a与b互质)
'''
def ext_gcd(a, b):
  if b == 0:
    x1 = 1
    y1 = 0
    x = x1
    y = y1
    r = a
    return r, x, y
  else:
    r, x1, y1 = ext_gcd(b, a % b)
    x = y1
    y = x1 - a / b * y1
    return r, x, y

2、大整数幂取模算法

exponentiation.py文件,主要用于计算超大整数超大次幂然后对超大的整数取模。我在网上查询到这个算法叫做“蒙哥马利算法”。

# -*- coding: utf-8 -*-
'''
超大整数超大次幂然后对超大的整数取模
(base ^ exponent) mod n
'''
def exp_mode(base, exponent, n):
  bin_array = bin(exponent)[2:][::-1]
  r = len(bin_array)
  base_array = []
  pre_base = base
  base_array.append(pre_base)
  for _ in range(r - 1):
    next_base = (pre_base * pre_base) % n
    base_array.append(next_base)
    pre_base = next_base
  a_w_b = __multi(base_array, bin_array)
  return a_w_b % n
def __multi(array, bin_array):
  result = 1
  for index in range(len(array)):
    a = array[index]
    if not int(bin_array[index]):
      continue
    result *= a
  return result

有同学就不服了,说是我为啥不把这个幂次的数字计算出来,再取模。我说这样做,理论上是对的,但是实际上行不通。因为:一个2048位的数字的2048位次的幂,计算出来了以后,这个数字很可能把全宇宙的物质都做成硬盘也放不下。不懂的童鞋请私信我。所以需要用“蒙哥马利算法”进行优化。

3、公钥私钥生成

rsa.py,生成公钥、私钥、并对信息加密解密。

# -*- coding: utf-8 -*-
from gcd import ext_gcd
from exponentiation import exp_mode
# 生成公钥私钥,p、q为两个超大质数
def gen_key(p, q):
  n = p * q
  fy = (p - 1) * (q - 1)   # 计算与n互质的整数个数 欧拉函数
  e = 3889          # 选取e  一般选取65537
  # generate d
  a = e
  b = fy
  r, x, y = ext_gcd(a, b)
  print x  # 计算出的x不能是负数,如果是负数,说明p、q、e选取失败,一般情况下e选取65537
  d = x
  # 返回:  公钥   私钥
  return  (n, e), (n, d)
# 加密 m是被加密的信息 加密成为c
def encrypt(m, pubkey):
  n = pubkey[0]
  e = pubkey[1]
  c = exp_mode(m, e, n)
  return c
# 解密 c是密文,解密为明文m
def decrypt(c, selfkey):
  n = selfkey[0]
  d = selfkey[1]
  m = exp_mode(c, d, n)
  return m
if __name__ == "__main__":
  '''公钥私钥中用到的两个大质数p,q'''
  p = 106697219132480173106064317148705638676529121742557567770857687729397446898790451577487723991083173010242416863238099716044775658681981821407922722052778958942891831033512463262741053961681512908218003840408526915629689432111480588966800949428079015682624591636010678691927285321708935076221951173426894836169
  q = 144819424465842307806353672547344125290716753535239658417883828941232509622838692761917211806963011168822281666033695157426515864265527046213326145174398018859056439431422867957079149967592078894410082695714160599647180947207504108618794637872261572262805565517756922288320779308895819726074229154002310375209
  '''生成公钥私钥'''
  pubkey, selfkey = gen_key(p, q)
  '''需要被加密的信息转化成数字,长度小于秘钥n的长度,如果信息长度大于n的长度,那么分段进行加密,分段解密即可。'''
  m = 1356205320457610288745198967657644166379972189839804389074591563666634066646564410685955217825048626066190866536592405966964024022236587593447122392540038493893121248948780525117822889230574978651418075403357439692743398250207060920929117606033490559159560987768768324823011579283223392964454439904542675637683985296529882973798752471233683249209762843835985174607047556306705224118165162905676610067022517682197138138621344578050034245933990790845007906416093198845798901781830868021761765904777531676765131379495584915533823288125255520904108500256867069512326595285549579378834222350197662163243932424184772115345
  '''信息加密'''
  c = encrypt(m, pubkey)
  print c
  '''信息解密'''
  d = decrypt(c, selfkey)
  print d

代码就是这么简单,RSA算法就是这么任性。代码去除掉没用的注释或者引用,总长度不会超过25行,有疑问的我们掰扯掰扯。

实测:秘钥长度在2048位的时候,我的thinkpad笔记本T440上面、python2.7环境的运行时间是4秒,1024位的时候是1秒。说明了RSA加密算法的算法复杂度应该是O(N^2),其中n是秘钥长度。不知道能不能优化到O(NlogN)

Python 相关文章推荐
Python通过poll实现异步IO的方法
Jun 04 Python
Python的IDEL增加清屏功能实例
Jun 19 Python
Python中list查询及所需时间计算操作示例
Jun 21 Python
pyqt5 从本地选择图片 并显示在label上的实例
Jun 13 Python
Python转换时间的图文方法
Jul 01 Python
Python求离散序列导数的示例
Jul 10 Python
python 魔法函数实例及解析
Sep 25 Python
Python常用模块sys,os,time,random功能与用法实例分析
Jan 07 Python
pytorch方法测试详解——归一化(BatchNorm2d)
Jan 15 Python
python numpy库np.percentile用法说明
Jun 08 Python
Django haystack实现全文搜索代码示例
Nov 28 Python
Python 微信公众号文章爬取的示例代码
Nov 30 Python
使用pandas中的DataFrame数据绘制柱状图的方法
Apr 10 #Python
Python基于socket模块实现UDP通信功能示例
Apr 10 #Python
pandas把dataframe转成Series,改变列中值的类型方法
Apr 10 #Python
在pandas中一次性删除dataframe的多个列方法
Apr 10 #Python
pandas将DataFrame的列变成行索引的方法
Apr 10 #Python
Pandas 对Dataframe结构排序的实现方法
Apr 10 #Python
python DataFrame 修改列的顺序实例
Apr 10 #Python
You might like
咖啡知识 除了喝咖啡还有那些知识点
2021/03/06 新手入门
PHP has encountered an Access Violation
2007/01/15 PHP
PHP多线程编程之管道通信实例分析
2015/03/07 PHP
php获得客户端浏览器名称及版本的方法(基于ECShop函数)
2015/12/23 PHP
PHP正则之正向预查与反向预查讲解与实例
2020/04/06 PHP
javascript编程起步(第六课)
2007/01/10 Javascript
javascript之更有效率的字符串替换
2008/08/02 Javascript
js操作textarea方法集合封装(兼容IE,firefox)
2011/02/22 Javascript
jquery html动态生成select标签出问题的解决方法
2013/11/20 Javascript
js打开windows上的可执行文件示例
2014/05/27 Javascript
javascript原型模式用法实例详解
2015/06/04 Javascript
JavaScript中Date.toSource()方法的使用教程
2015/06/12 Javascript
JQuery 在文档中查找指定name的元素并移除的实现方法
2016/05/19 Javascript
jQuery下拉菜单的实现代码
2016/11/03 Javascript
javascript容错处理代码(屏蔽js错误)
2017/01/20 Javascript
JS排序算法之希尔排序与快速排序实现方法
2017/12/12 Javascript
vue中使用rem布局代码详解
2019/10/30 Javascript
JavaScript如何使用插值实现图像渐变
2020/06/28 Javascript
angular8.5集成TinyMce5的使用和详细配置(推荐)
2020/11/16 Javascript
Python urllib、urllib2、httplib抓取网页代码实例
2015/05/09 Python
scrapy spider的几种爬取方式实例代码
2018/01/25 Python
Python+Pandas 获取数据库并加入DataFrame的实例
2018/07/25 Python
Python开发网站目录扫描器的实现
2019/02/21 Python
python判断文件夹内是否存在指定后缀文件的实例
2019/06/10 Python
Python绘制股票移动均线的实例
2019/08/24 Python
django实现日志按日期分割
2020/05/21 Python
利用Canvas模仿百度贴吧客户端loading小球的方法示例
2017/08/13 HTML / CSS
小程序canvas中文字设置居中锚点
2019/04/16 HTML / CSS
四川成都导游欢迎词
2014/01/18 职场文书
幸福家庭事迹材料
2014/02/03 职场文书
医德医风自我评价
2014/09/19 职场文书
教师四风自我剖析材料
2014/09/30 职场文书
中班下学期个人总结
2015/02/12 职场文书
2015年司法所工作总结
2015/04/27 职场文书
合作合同协议书
2016/03/21 职场文书
Python 语言实现六大查找算法
2021/06/30 Python