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 urlopen 使用小示例
Sep 06 Python
python 从远程服务器下载东西的代码
Feb 10 Python
Python实现的下载网页源码功能示例
Jun 13 Python
详解用python实现简单的遗传算法
Jan 02 Python
python 集合 并集、交集 Series list set 转换的实例
May 29 Python
python制作mysql数据迁移脚本
Jan 01 Python
Python按钮的响应事件详解
Mar 04 Python
Python列表与元组的异同详解
Jul 02 Python
twilio python自动拨打电话,播放自定义mp3音频的方法
Aug 08 Python
通过celery异步处理一个查询任务的完整代码
Nov 19 Python
Kears 使用:通过回调函数保存最佳准确率下的模型操作
Jun 17 Python
python rsa-oaep加密的示例代码
Sep 23 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摘要生成函数(无乱码)
2012/02/04 PHP
用javascript获取地址栏参数
2006/12/22 Javascript
Kibo 用于处理键盘事件的Javascript工具库
2011/10/28 Javascript
JavaScript自定义事件介绍
2013/08/29 Javascript
如何动态的导入js文件具体该怎么实现
2014/01/14 Javascript
json实现前后台的相互传值详解
2015/01/05 Javascript
JavaScript获取文本框内选中文本的方法
2015/02/20 Javascript
jquery实现页面关键词高亮显示的方法
2015/03/12 Javascript
原生js编写autoComplete插件
2016/04/13 Javascript
Bootstrap轮播插件简单使用方法介绍
2016/06/21 Javascript
详解Angular 4.x Injector
2017/05/04 Javascript
Javascript中将变量转换为字符串的三种方法
2017/09/19 Javascript
微信小程序 按钮滑动的实现方法
2017/09/27 Javascript
Vue.js 动态为img的src赋值方法
2018/03/14 Javascript
js 闭包深入理解与实例分析
2020/03/19 Javascript
JavaScript async/await原理及实例解析
2020/12/02 Javascript
[02:01]BBC DOTA2国际邀请赛每日综述:八强胜者组鏖战,中国队喜忧参半
2014/07/19 DOTA
[47:12]TFT vs Secret Supermajor小组赛C组 BO3 第三场 6.3
2018/06/04 DOTA
python实现登陆知乎获得个人收藏并保存为word文件
2015/03/16 Python
pyspark 读取csv文件创建DataFrame的两种方法
2018/06/07 Python
python二维列表一维列表的互相转换实例
2018/07/02 Python
正确理解Python中if __name__ == '__main__'
2019/01/24 Python
Python中numpy模块常见用法demo实例小结
2019/03/16 Python
Python reversed函数及使用方法解析
2020/03/17 Python
python实现图片转字符画
2021/02/19 Python
中国综合网上购物商城:苏宁易购
2016/08/09 全球购物
非功能性需求都包括哪些方面
2013/10/29 面试题
班组长安全职责
2014/01/05 职场文书
《春天来了》教学反思
2014/04/07 职场文书
投资意向书
2014/07/30 职场文书
民主生活会剖析材料
2014/09/30 职场文书
小学五年级语文上册教学计划
2015/01/22 职场文书
事业单位聘任报告
2015/03/02 职场文书
中国合伙人观后感
2015/06/02 职场文书
环保守法证明
2015/06/24 职场文书
Node.js实现爬取网站图片的示例代码
2022/04/04 NodeJs