PyCrypto密码学库源码解析(二)RSA参数生成
Python Crypto库源码解析(二) RSA参数生成
* 版权声明 *
引用请注明出处,转载请联系: h0.1c@foxmail.com
本文主要讲解pycrypto库中RSA参数生成的实现方法。主要涉及的模块是PublicKey.RSA 和其继承模块PublicKey._RSA。
- Python Crypto库源码解析(二) RSA参数生成
- 0 本文需要的背景知识
- 0.1 RSA算法的参数
- 0.2 RSA参数的要求
- 1 RSAImplementation类
- 2 generate函数
- 3 _RSA.generate_py函数
- 附录 库中给出的另一种计算参数方法
- 0 本文需要的背景知识
0 本文需要的背景知识
0.1 RSA算法的参数
在上一篇文章PyCrypto密码学库源码解析(一)随机数和大素数生成的0.5 RSA算法描述 中已经提到RSA的参数生成相关的内容,这里重申一次:
选择两个大的质数p和q,p不等于q,计算N=pq
选择一个整数e与(p-1)(q-1)互质,并且e小于(p-1)(q-1)。
计算d:d× e ≡ 1 (mod (p-1)(q-1))。
将p和q的记录销毁。
(N,e)是公钥,(N,d)是私钥。
0.2 RSA参数的要求
根据上文所述,可以根据参数生成过程来逐一解释参数的要求。
选择两个大的质数p和q,p不等于q
现如今主流的RSA密钥要求达到的位数是1024比特,例如在浏览器的公钥证书中存放的公钥就是1024比特的,而推荐使用的安全性较高的则是2048比特,也就是要求p*q的结果应该达到1024比特。
选择一个整数e与(p-1)(q-1)互质,并且e小于(p-1)(q-1)
这一点是数论要求的,否则会造成算法被攻击,要保障gcd(e,(p-1)(q-1))=1也就是要保证gcd(e,p-1) = gcd(e,q-1) = 1,这一点实际上在上一篇文章中(2.6 获取一个满足RSA要求的强素数)已经讲解过:
if e and is_possible_prime:if e & 1:if GCD (e, X-1) != 1:is_possible_prime = 0else:if GCD (e, divmod((X-1),2)[0]) != 1:is_possible_prime = 0
getStrongPrime函数在生成素数的时候,就已经将e和p-1的关系做过判断,才进行的输出。
所以目前的问题只剩下如何选择参数e,对于参数e,在库的文档中有这样一段说明:
Public RSA exponent. It must be an odd positive integer.
It is typically a small number with very few ones in its binary representation.
The default value 65537 (=0b10000000000000001
) is a safe choice: other common values are 5, 7, 17, and 257.
也就是说一般会选择65537,当然也可以选择其他给出的供选项,但是要保证一条就是一定要是奇数。
计算d:d× e ≡ 1 (mod (p-1)(q-1))
这一步只需要使用欧几里得方法求逆就可以。
最后,为了算法的安全需要将p和q的记录销毁,即使不销毁也绝对不可以泄露。
1 RSAImplementation类
在PublicKey.RSA模块中,包含RSA实现类,按照说明文档所说,该类是一个与RSA密钥相关的类,
class RSAImplementation(object):
包含有函数 _ init _, generate, construct, importKey,分别是构建函数、生成新的RSA密钥、从RSA组件构造密钥、从外部导入密钥。
值得一提的是外部导入密钥函数支持包括X.509、PKCS#1、OpenSSH等多种格式。
由于本文主要关注参数的生成模块,所以研究的重点放在generate函数上。
2 generate函数
generate(self, bits, randfunc=None, progress_func=None, e=65537)
这是函数的声明,可以见得需要输入的是bit位数,也就是生成密钥的位数,randfunc和上篇文章中讲的一样,如果不指定就会使用Crypto.Random.new(),而progress_func用于等待密钥生成时与用户交互的用途。
接下来一步一步解析该函数:
if bits < 1024 or (bits & 0xff) != 0:raise ValueError("RSA modulus length must be a multiple of 256 and >= 1024")
在上篇文章中提到,getStrongPrime函数对于输入的位数是有限制的,这里则是再次判断,要求密钥位数位 256的倍数而且不小于1024。
if e%2==0 or e<3:raise ValueError("RSA public exponent must be a positive, odd integer larger than 2.")
如果不使用默认的e=65537,那么就一定要满足非偶正奇数的条件。
rf = self._get_randfunc(randfunc)
obj = _RSA.generate_py(bits, rf, progress_func, e) # TODO: Don't use legacy _RSA module
key = self._math.rsa_construct(obj.n, obj.e, obj.d, obj.p, obj.q, obj.u)
可以看到,在generate的部分,使用的是_RSA模块的generate_py函数,后面作者还留下了注释,将会在之后的库中不在此处使用legacy 的_RSA模块。
接下来,就来看看_RSA.generate_py里是什么样的。
3 _RSA.generate_py函数
函数声明如下:
def generate_py(bits, randfunc, progress_func=None, e=65537)
首先除开progress_func不说,其他部分的代码逻辑是这样的:
obj=RSAobj()obj.e = int(e)# Generate the prime factors of np = q = 1while number.size(p*q) < bits:p = pubkey.getStrongPrime(bits>>1, obj.e, 1e-12, randfunc)q = pubkey.getStrongPrime(bits - (bits>>1), obj.e, 1e-12, randfunc)# It's OK for p to be larger than q, but let's be# kind to the function that will invert it for# the calculation of u.if p > q:(p, q)=(q, p)obj.p = pobj.q = qobj.u = pubkey.inverse(obj.p, obj.q)obj.n = obj.p*obj.qobj.d=pubkey.inverse(obj.e, (obj.p-1)*(obj.q-1))assert bits <= 1+obj.size(), "Generated key is too small"return obj
首先是转化e参数为int型,然后使用循环生成大素数p和q,生成所使用的函数便是getStrongPrime,关于该函数的解析可以参见这里,由于极其复杂的getStrongPrime考虑到了很多有关参数要求的限制,才让这个部分较为简洁。
生成了p和q之后,按照p小q大的顺序交换位置,至此e、p和q这几个最重要的参数已经确定,接下来就是
计算N=p*q
计算d:d× e ≡ 1 (mod (p-1)(q-1))。
至于这里出现的u = p−1modqp−1modqp^{-1}mod q参看_RSAobj的说明可以知道,意义是:
- u, the CRT coefficient (1/p) mod q
至此,所有RSA算法所需要的参数已经生成完毕。
下一篇文章((三)PublicKey模块概览)将讲解该库中RSA算法的实现过程。
附录 库中给出的另一种计算参数方法
在库的PublicKey._slowmath模块中,还给出了另一种RSA参数的构造过程,z这个函数通过部分参数计算余下的参数并且返回一个完整实例。这里贴上全部的源代码,不作解释,有兴趣的读者可以自行了解。
def rsa_construct(n, e, d=None, p=None, q=None, u=None):"""Construct an RSAKey object"""assert isinstance(n, int)assert isinstance(e, int)assert isinstance(d, (int, type(None)))assert isinstance(p, (int, type(None)))assert isinstance(q, (int, type(None)))assert isinstance(u, (int, type(None)))obj = _RSAKey()obj.n = nobj.e = eif d is None:return objobj.d = dif p is not None and q is not None:obj.p = pobj.q = qelse:# Compute factors p and q from the private exponent d.# We assume that n has no more than two factors.# See 8.2.2(i) in Handbook of Applied Cryptography.ktot = d*e-1# The quantity d*e-1 is a multiple of phi(n), even,# and can be represented as t*2^s.t = ktotwhile t%2==0:t=divmod(t,2)[0]# Cycle through all multiplicative inverses in Zn.# The algorithm is non-deterministic, but there is a 50% chance# any candidate a leads to successful factoring.# See "Digitalized Signatures and Public Key Functions as Intractable# as Factorization", M. Rabin, 1979spotted = 0a = 2while not spotted and a<100:k = t# Cycle through all values a^{t*2^i}=a^kwhile k<ktot:cand = pow(a,k,n)# Check if a^k is a non-trivial root of unity (mod n)if cand!=1 and cand!=(n-1) and pow(cand,2,n)==1:# We have found a number such that (cand-1)(cand+1)=0 (mod n).# Either of the terms divides n.obj.p = GCD(cand+1,n)spotted = 1breakk = k*2# This value was not any good... let's try another!a = a+2if not spotted:raise ValueError("Unable to compute factors p and q from exponent d.")# Found !assert ((n % obj.p)==0)obj.q = divmod(n,obj.p)[0]if u is not None:obj.u = uelse:obj.u = inverse(obj.p, obj.q)return obj
PyCrypto密码学库源码解析(二)RSA参数生成相关推荐
- 【深度学习模型】智云视图中文车牌识别源码解析(二)
[深度学习模型]智云视图中文车牌识别源码解析(二) 感受 HyperLPR可以识别多种中文车牌包括白牌,新能源车牌,使馆车牌,教练车牌,武警车牌等. 代码不可谓不混乱(别忘了这是职业公司的准产品级代码 ...
- Spring源码解析 -- SpringWeb请求参数获取解析
Spring源码解析 – SpringWeb请求参数获取解析 简介 在文章:Spring Web 请求初探中,我们看到最后方法反射调用的相关代码,本篇文章就探索其中的参数是如何从请求中获取的 概览 方 ...
- 【移动开发】Checkout开源库源码解析
Checkout开源库的源码解析 1.功能介绍 1.1Checkout是什么 Checkout是Android In-App Billing API(v3 +)的一个封装库.In-App Billin ...
- erlang下lists模块sort(排序)方法源码解析(二)
上接erlang下lists模块sort(排序)方法源码解析(一),到目前为止,list列表已经被分割成N个列表,而且每个列表的元素是有序的(从大到小) 下面我们重点来看看mergel和rmergel ...
- Kubernetes学习笔记之Calico CNI Plugin源码解析(二)
女主宣言 今天小编继续为大家分享Kubernetes Calico CNI Plugin学习笔记,希望能对大家有所帮助. PS:丰富的一线技术.多元化的表现形式,尽在"360云计算" ...
- hox 状态管理库源码解析
文章目录 hox是什么 hox实现状态共享的方式 基本使用 全局状态共享 局部状态共享 源码解析 index.js 入口文件 coantainer.tsx 管理每个hook 全局状态共享的实现 Hox ...
- Mobx 源码解析 二(autorun)
前言 我们在Mobx 源码解析 一(observable)已经知道了observable 做的事情了, 但是我们的还是没有讲解明白在我们的Demo中,我们在Button 的Click 事件中只是对ba ...
- android网络框架retrofit源码解析二
注:源码解析文章参考了该博客:http://www.2cto.com/kf/201405/305248.html 前一篇文章讲解了retrofit的annotation,既然定义了,那么就应该有解析的 ...
- Thrift源码解析(二)序列化协议
概述 对于一个RPC框架,定义好网络数据的序列化协议是最基本的工作,thrift的序列化协议主要包含如下几种: TBinaryProtocol TCompactProtocol TJSONProtoc ...
最新文章
- php libev pthreads,libuv 与 libev 的对比
- Android源码分析-全面理解Context
- 学习LOAM笔记——特征点提取与匹配
- birt报表数据只有一条_企业构建大数据分析体系的4个层级
- 03_MySQL多表事务课堂笔记
- idea 安装php插件_免费版的 IDEA 为啥不能使用 Tomcat ?
- 都啥年代了,求你别再说Redis是单线程了!
- 解决python2.7.9以下版本requests访问https的问题
- Missing artifact com.oracle:ojdbc6:jar:11.2.0.1.0问题解决 ojdbc包pom.xml出错
- 【Mysql】利用Mybatis3连接mysql获取datetime类型数据错误
- Thinkphp5 接口中直接返回数组提示variable type error: array
- 让 Flutter 在鸿蒙系统上跑起来
- 北京的“狗不理”包子与傻X
- 响应国家十四五规划,ABeam(德硕)科技赋能可靠股份数智化转型
- 申请CVE的姿势总结
- 无法通过windows功能控制面板自动安装或卸载windows server角色和功能
- 国内小程序生态服务平台即速应用完成5000万元A+轮融资...
- 华科计算机博导刘云生论文,华科论文式要求.doc
- 量子力学的诡异现象—朱清时教授
- TinyXML-2 读 XML 文件
热门文章
- 当代年轻人的生活仪式感有哪些。
- 无线路由器密码安全设置
- group by 两个字段
- 5. 邵婷 区送教下乡展示课三年级上册《数学广角-集合》照片
- 在Ubuntu上的Virtualbox中使用招行网银专业版
- 1941年电子计算机的英文名,Borden[伯顿,博登,波顿]的中文翻译及英文名意思
- 探索者STM32F407-ST_Link程序下载
- 主成份分析(PCA)
- Opencv学习笔记 各向异性滤波/均值滤波/高斯滤波/中值滤波/加权中值滤波/高斯低通滤波
- rtx2070怎么样 rtx2070是什么级别显卡