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.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参数生成相关推荐

  1. 【深度学习模型】智云视图中文车牌识别源码解析(二)

    [深度学习模型]智云视图中文车牌识别源码解析(二) 感受 HyperLPR可以识别多种中文车牌包括白牌,新能源车牌,使馆车牌,教练车牌,武警车牌等. 代码不可谓不混乱(别忘了这是职业公司的准产品级代码 ...

  2. Spring源码解析 -- SpringWeb请求参数获取解析

    Spring源码解析 – SpringWeb请求参数获取解析 简介 在文章:Spring Web 请求初探中,我们看到最后方法反射调用的相关代码,本篇文章就探索其中的参数是如何从请求中获取的 概览 方 ...

  3. 【移动开发】Checkout开源库源码解析

    Checkout开源库的源码解析 1.功能介绍 1.1Checkout是什么 Checkout是Android In-App Billing API(v3 +)的一个封装库.In-App Billin ...

  4. erlang下lists模块sort(排序)方法源码解析(二)

    上接erlang下lists模块sort(排序)方法源码解析(一),到目前为止,list列表已经被分割成N个列表,而且每个列表的元素是有序的(从大到小) 下面我们重点来看看mergel和rmergel ...

  5. Kubernetes学习笔记之Calico CNI Plugin源码解析(二)

    女主宣言 今天小编继续为大家分享Kubernetes Calico CNI Plugin学习笔记,希望能对大家有所帮助. PS:丰富的一线技术.多元化的表现形式,尽在"360云计算" ...

  6. hox 状态管理库源码解析

    文章目录 hox是什么 hox实现状态共享的方式 基本使用 全局状态共享 局部状态共享 源码解析 index.js 入口文件 coantainer.tsx 管理每个hook 全局状态共享的实现 Hox ...

  7. Mobx 源码解析 二(autorun)

    前言 我们在Mobx 源码解析 一(observable)已经知道了observable 做的事情了, 但是我们的还是没有讲解明白在我们的Demo中,我们在Button 的Click 事件中只是对ba ...

  8. android网络框架retrofit源码解析二

    注:源码解析文章参考了该博客:http://www.2cto.com/kf/201405/305248.html 前一篇文章讲解了retrofit的annotation,既然定义了,那么就应该有解析的 ...

  9. Thrift源码解析(二)序列化协议

    概述 对于一个RPC框架,定义好网络数据的序列化协议是最基本的工作,thrift的序列化协议主要包含如下几种: TBinaryProtocol TCompactProtocol TJSONProtoc ...

最新文章

  1. php libev pthreads,libuv 与 libev 的对比
  2. Android源码分析-全面理解Context
  3. 学习LOAM笔记——特征点提取与匹配
  4. birt报表数据只有一条_企业构建大数据分析体系的4个层级
  5. 03_MySQL多表事务课堂笔记
  6. idea 安装php插件_免费版的 IDEA 为啥不能使用 Tomcat ?
  7. 都啥年代了,求你别再说Redis是单线程了!
  8. 解决python2.7.9以下版本requests访问https的问题
  9. Missing artifact com.oracle:ojdbc6:jar:11.2.0.1.0问题解决 ojdbc包pom.xml出错
  10. 【Mysql】利用Mybatis3连接mysql获取datetime类型数据错误
  11. Thinkphp5 接口中直接返回数组提示variable type error: array
  12. 让 Flutter 在鸿蒙系统上跑起来
  13. 北京的“狗不理”包子与傻X
  14. 响应国家十四五规划,ABeam(德硕)科技赋能可靠股份数智化转型
  15. 申请CVE的姿势总结
  16. 无法通过windows功能控制面板自动安装或卸载windows server角色和功能
  17. 国内小程序生态服务平台即速应用完成5000万元A+轮融资...
  18. 华科计算机博导刘云生论文,华科论文式要求.doc
  19. 量子力学的诡异现象—朱清时教授
  20. TinyXML-2 读 XML 文件

热门文章

  1. 当代年轻人的生活仪式感有哪些。
  2. 无线路由器密码安全设置
  3. group by 两个字段
  4. 5. 邵婷 区送教下乡展示课三年级上册《数学广角-集合》照片
  5. 在Ubuntu上的Virtualbox中使用招行网银专业版
  6. 1941年电子计算机的英文名,Borden[伯顿,博登,波顿]的中文翻译及英文名意思
  7. 探索者STM32F407-ST_Link程序下载
  8. 主成份分析(PCA)
  9. Opencv学习笔记 各向异性滤波/均值滤波/高斯滤波/中值滤波/加权中值滤波/高斯低通滤波
  10. rtx2070怎么样 rtx2070是什么级别显卡