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实现改变与矩形橡胶的线条的颜色代码示例
Jan 05 Python
python实现简易版计算器
Jun 22 Python
tensorflow识别自己手写数字
Mar 14 Python
python中从str中提取元素到list以及将list转换为str的方法
Jun 26 Python
Python3爬虫之urllib携带cookie爬取网页的方法
Dec 28 Python
在 Jupyter 中重新导入特定的 Python 文件(场景分析)
Oct 27 Python
opencv3/C++实现视频读取、视频写入
Dec 11 Python
简单了解Python write writelines区别
Feb 27 Python
Keras - GPU ID 和显存占用设定步骤
Jun 22 Python
Django利用elasticsearch(搜索引擎)实现搜索功能
Nov 26 Python
python opencv通过按键采集图片源码
May 20 Python
浏览器常用基本操作之python3+selenium4自动化测试(基础篇3)
May 21 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
PHP类与对象中的private访问控制的疑问
2012/11/01 PHP
PHP数据库操作之基于Mysqli的数据库操作类库
2014/04/19 PHP
php如何控制用户对图片的访问 PHP禁止图片盗链
2016/03/25 PHP
使用tp框架和SQL语句查询数据表中的某字段包含某值
2019/10/18 PHP
向当前style sheet中插入一个新的style实现方法
2013/04/01 Javascript
解析js原生方法创建表格效率测试
2013/07/08 Javascript
使用JavaScript刷新网页的方法
2015/06/04 Javascript
在JavaScript中用getMinutes()方法返回指定的分时刻
2015/06/10 Javascript
JavaScript中使用数组方法汇总
2016/02/16 Javascript
javascript验证手机号和实现星号(*)代替实例
2016/08/16 Javascript
深入理解jQuery.data() 的实现方式
2016/11/30 Javascript
JS异步函数队列功能实例分析
2017/11/28 Javascript
细说webpack源码之compile流程-rules参数处理技巧(1)
2017/12/26 Javascript
React diff算法的实现示例
2018/04/20 Javascript
解决Mac node版本升级失败的问题
2018/05/16 Javascript
js数组去重的方法总结
2019/01/18 Javascript
使用react context 实现vue插槽slot功能
2019/07/18 Javascript
分析用Python脚本关闭文件操作的机制
2015/06/28 Python
python制作爬虫并将抓取结果保存到excel中
2016/04/06 Python
Python实现找出数组中第2大数字的方法示例
2018/03/26 Python
Python 实现一行输入多个值的方法
2018/04/21 Python
python操作excel的方法(xlsxwriter包的使用)
2018/06/11 Python
Python判断是否json是否包含一个key的方法
2018/12/31 Python
python实现弹窗祝福效果
2019/04/07 Python
Tensorflow tf.dynamic_partition矩阵拆分示例(Python3)
2020/02/07 Python
Django import export实现数据库导入导出方式
2020/04/03 Python
python之语音识别speech模块
2020/09/09 Python
最便宜促销价格订机票:Airpaz(总部设在印尼,支持中文)
2018/11/13 全球购物
Vivo俄罗斯官方在线商店:中国智能手机品牌
2019/10/04 全球购物
车辆转让协议书
2014/09/24 职场文书
大学生违纪检讨书范文
2015/05/07 职场文书
金榜题名主持词
2015/07/02 职场文书
css 边框添加四个角的实现代码
2021/10/16 HTML / CSS
使用Redis实现点赞取消点赞的详细代码
2022/03/20 Redis
python 使用tkinter与messagebox写界面和弹窗
2022/03/20 Python
解决IIS7下无法绑定https主机的问题
2022/04/29 Servers