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读取浮点数和读取文本文件示例
May 06 Python
python计算书页码的统计数字问题实例
Sep 26 Python
简单的编程0基础下Python入门指引
Apr 01 Python
详解使用python的logging模块在stdout输出的两种方法
May 17 Python
python执行使用shell命令方法分享
Nov 08 Python
Python利用itchat对微信中好友数据实现简单分析的方法
Nov 21 Python
Django数据库表反向生成实例解析
Feb 06 Python
Python玩转Excel的读写改实例
Feb 22 Python
python list数据等间隔抽取并新建list存储的例子
Nov 27 Python
python GUI计算器的实现
Oct 09 Python
python引入其他文件夹下的py文件具体方法
May 23 Python
你需要掌握的20个Python常用技巧
Feb 28 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
DOTA2 探索永无止境 玩家自创强悍插眼攻略
2020/04/20 DOTA
php微信开发接入
2016/08/27 PHP
php 基础函数
2017/02/10 PHP
JavaScript 学习笔记(四)
2009/12/31 Javascript
JS面向对象编程浅析
2011/08/28 Javascript
Javascript创建自定义对象 创建Object实例添加属性和方法
2012/06/04 Javascript
深入了解javascript中的prototype与继承
2013/04/14 Javascript
javascript操作css属性
2013/12/30 Javascript
基于javascript html5实现3D翻书特效
2016/03/14 Javascript
JavaScript中const、var和let区别浅析
2016/10/11 Javascript
AngularJS指令与指令之间的交互功能示例
2016/12/14 Javascript
vue项目中v-model父子组件通信的实现详解
2017/12/10 Javascript
vue element table 表格请求后台排序的方法
2018/09/28 Javascript
iview通过Dropdown(下拉菜单)实现的右键菜单
2018/10/26 Javascript
Node.js创建一个Express服务的方法详解
2020/01/06 Javascript
vue实现页面切换滑动效果
2020/06/29 Javascript
vue 使用localstorage实现面包屑的操作
2020/11/16 Javascript
[05:07]DOTA2英雄梦之声_第14期_暗影恶魔
2014/06/20 DOTA
[11:27]《一刀刀一天》之DOTA全时刻20:TI4总奖金突破920W TS赛事分析
2014/06/18 DOTA
[49:41]NB vs NAVI Supermajor小组赛A组 BO3 第一场 6.2
2018/06/03 DOTA
[49:35]LGD vs OG 2018国际邀请赛淘汰赛BO3 第二场 8.25
2018/08/29 DOTA
[15:20]DOTA2-DPC中国联赛 正赛 Elephant vs Aster 选手采访
2021/03/11 DOTA
python爬虫框架scrapy实战之爬取京东商城进阶篇
2017/04/24 Python
Python使用pandas处理CSV文件的实例讲解
2018/06/22 Python
python用列表生成式写嵌套循环的方法
2018/11/08 Python
Python装饰器语法糖
2019/01/02 Python
如何分离django中的媒体、静态文件和网页
2019/11/12 Python
python excel和yaml文件的读取封装
2021/01/12 Python
简单介绍HTML5中的文件导入
2015/05/08 HTML / CSS
英国女性时尚精品店:THE DRESSING ROOM
2018/05/23 全球购物
生产内勤岗位职责
2013/12/07 职场文书
土木建筑学生自我评价
2014/01/14 职场文书
小学五年级学生评语
2014/04/22 职场文书
教师节宣传方案
2014/05/23 职场文书
中学音乐课教学反思
2016/02/18 职场文书
汉语拼音教学反思
2016/02/22 职场文书