分解因子算法——Pollard rho算法
分解因子算法——Pollard ρ\rhoρ 算法
攻击RSA密码体制最明显的方法就是分解大整数。关于大整数分解的算法有许多,常见的有试除法、p±1p\pm1p±1算法、Pollard ρ\rhoρ算法、数域筛法、二次筛法等等。这篇分享的就是其中之一的Pollard ρ\rhoρ算法。
我们说因子分解,很多时候并不一定要把大整数nnn彻底分解成素数乘积,而是求出nnn的某个非平凡因子即可。求大整数的一个因子固然困难,但是Euclidean算法告诉我们求两个数的最大公因子是可以在O(logn)O(\log n)O(logn)的时间得到的。Pollard ρ\rhoρ算法利用的就是这个思想。
问题描述
设大整数为nnn,我们要找到nnn的一个因子ppp。
Pollard ρ\rhoρ 算法
为了利用Euclidean算法找到ppp,我们设想存在两个整数x,x′∈Znx,x'\in \mathbb{Z}_{n}x,x′∈Zn,满足x≡x′(modp)x\equiv x'\pmod{p}x≡x′(modp),这样的话就有p∣(x−x′)p|(x-x')p∣(x−x′),又因为p∣np|np∣n,所以有p≤gcd(x−x′,n)<np\le gcd(x-x',n)<np≤gcd(x−x′,n)<n——这句话的意思是:gcd(x−x′,n)gcd(x-x',n)gcd(x−x′,n)一定是nnn的非平凡因子。这就完成了因子分解。问题归结为:如何找到满足条件的xxx和x′x'x′。
一个朴素的想法就是:随机选择一个子集X⊂ZnX\subset \mathbb{Z}_{n}X⊂Zn,然后对所有不同的x,x′∈Xx,x'\in Xx,x′∈X,判断gcd(x−x′,n)gcd(x-x',n)gcd(x−x′,n)是否为1。这个方法能够成功当且仅当映射x→x(modp)x \rarr x\pmod{p}x→x(modp)在XXX中至少存在一个碰撞。根据生日攻击可以分析:如果∣X∣≈1.71p|X| \approx 1.71\sqrt{p}∣X∣≈1.71p时,至少存在一个碰撞的概率是50%,为了找到XXX中存在的这个碰撞,我们需要求(∣X∣2)\begin{pmatrix}|X|\\2 \end{pmatrix}(∣X∣2)次gcd。
Pollard ρ\rhoρ算法减少了求解gcd的次数。它并不是随机产生一个子集XXX,而是事先确定一个整系数多项式fff,并取x1∈Znx_{1}\in \mathbb{Z}_{n}x1∈Zn,令
xi+1=f(xi)modn,i=1,2,3⋯x_{i+1}=f(x_{i})\mod{n},i=1,2,3\cdots xi+1=f(xi)modn,i=1,2,3⋯
这就产生了集合X={x1,x2,⋯,xm}X=\lbrace x_{1},x_{2},\cdots,x_{m} \rbraceX={x1,x2,⋯,xm}。下面描述这个集合是如何减少gcd计算次数的。
核心思想:如果xi≡xj(modp)x_{i}\equiv x_{j} \pmod{p}xi≡xj(modp),由于fff是整系数多项式,所以f(xi)≡f(xj)(modp)f(x_{i})\equiv f(x_{j}) \pmod{p}f(xi)≡f(xj)(modp) 。又因为p∣np|np∣n,所以
xi+1modp=(f(xi)modn)modp=f(xi)modpx_{i+1}\mod{p}=(f(x_{i})\mod{n})\mod{p}=f(x_{i})\mod{p} xi+1modp=(f(xi)modn)modp=f(xi)modp
同理有xj+1modp=f(xj)modpx_{j+1}\mod{p}=f(x_{j})\mod{p}xj+1modp=f(xj)modp。因此xi+1≡xj+1(modp)x_{i+1} \equiv x_{j+1}\pmod{p}xi+1≡xj+1(modp)。进一步有:如果xi≡xj(modp)x_{i}\equiv x_{j} \pmod{p}xi≡xj(modp),则对∀δ≥0\forall \delta \ge0∀δ≥0 ,有xi+δ≡xj+δ(modp)x_{i+\delta}\equiv x_{j+\delta} \pmod{p}xi+δ≡xj+δ(modp)。
记l=j−il=j-il=j−i,可知xi′≡xj′(modp)x_{i'} \equiv x_{j'} \pmod{p}xi′≡xj′(modp)如果j′≥i′≥ij'\ge i'\ge ij′≥i′≥i且j′−i′≡0(modl)j'-i'\equiv0\pmod{l}j′−i′≡0(modl)。
这样序列X就可以看成带有一个“尾巴”
x1→x2→⋯→xi(modp)x_{1}\rarr x_{2} \rarr \cdots \rarr x_{i} \pmod{p} x1→x2→⋯→xi(modp)
和一个“环”
xi→xi+1→⋯→xj=xi(modp)x_{i} \rarr x_{i+1} \rarr \cdots \rarr x_{j}=x_{i} \pmod{p} xi→xi+1→⋯→xj=xi(modp)
看成图的话就像希腊字母ρ\rhoρ,这正是算法名字的由来。对这个算法,我们需要计算(j−12)+i\begin{pmatrix}j-1\\2 \end{pmatrix}+i(j−12)+i次gcd才能得到第一个碰撞xi,xjx_{i},x_{j}xi,xj。
进一步改进:我们只要求得一个碰撞即可,不一定是xix_{i}xi和xjx_{j}xj,也可以是xi+δx_{i+\delta}xi+δ和xj+δx_{j+\delta}xj+δ。所以在找碰撞的时候,不必逐个逐个求gcd,可以跳跃着求。我们断言:在第一个“环”xi→xi+1→⋯→xj=xi(modp)x_{i} \rarr x_{i+1} \rarr \cdots \rarr x_{j}=x_{i} \pmod{p}xi→xi+1→⋯→xj=xi(modp)中,一定存在i′i'i′满足x2i′≡xi′(modp)x_{2i'} \equiv x_{i'}\pmod{p}x2i′≡xi′(modp)。事实上,只要2i′−i′=i′=kl2i'-i'=i'=kl2i′−i′=i′=kl,就有x2i′≡xi′(modp)x_{2i'} \equiv x_{i'}\pmod{p}x2i′≡xi′(modp)成立;而i≤i′=kl≤j−1i\le i'=kl\le j-1i≤i′=kl≤j−1,所以最多找jjj次就可以得到i′i'i′。
算法流程
Pollard ρ\rhoρ (n,x1x_{1}x1)
x=x1,x′=f(x)modnx=x_{1},x'=f(x)\mod{n}x=x1,x′=f(x)modn
p=gcd(x−x′,n)p=gcd(x-x',n)p=gcd(x−x′,n)
while p==1p==1p==1
//第i次迭代
x=xi,x′=x2ix=x_{i},x'=x_{2i}x=xi,x′=x2i
x=f(x)modpx=f(x)\mod{p}x=f(x)modp
x′=f(x′)modpx'=f(x')\mod{p}x′=f(x′)modp
x′=f(x′)modpx'=f(x')\mod{p}x′=f(x′)modp
p=gcd(x−x′,n)p=gcd(x-x',n)p=gcd(x−x′,n)
end
if p==n
return “failure”
else
return p
算法性能分析
假设f=x2+1f=x^{2}+1f=x2+1,则jjj的最大值为p\sqrt{p}p(因为xjx_{j}xj是第一个环中的数),所以最多需要p\sqrt{p}p次gcd计算。而p<np<\sqrt{n}p<n,所以算法的期望复杂度是O(n14)O(n^{\frac{1}{4}})O(n41)。需要强调的是,这是一个启发式算法,不是严格的数学证明。算法可能会失败,此时是因为子集XXX中没有碰撞,需要重新选择初始值x1x_{1}x1或者选择不同的函数fff产生新的集合XXX。
例子
设n=7171n=7171n=7171,f(x)=x2+1,x1=1f(x) = x^{2}+1,x_{1} = 1f(x)=x2+1,x1=1。
计算集合XXX部分元素为:
1,2,5,26,677,6557,4105,6347,4903,2218,219,4936,4210,4560,4872,375,4377,4389,2016,5471,88⋯1,2,5,26,677,6557,4105,6347,4903,2218,219,4936,4210,4560,4872,375,4377,4389,2016,5471,88\cdots 1,2,5,26,677,6557,4105,6347,4903,2218,219,4936,4210,4560,4872,375,4377,4389,2016,5471,88⋯
计算gcd(x1−x2,n),gcd(x2−x4,n),gcd(x3−x6,n)⋯gcd(x_{1}-x_{2},n),gcd(x_{2}-x_{4},n),gcd(x_{3}-x_{6},n)\cdotsgcd(x1−x2,n),gcd(x2−x4,n),gcd(x3−x6,n)⋯,发现gcd(x11−x22,n)=71gcd(x_{11}-x_{22}, n)=71gcd(x11−x22,n)=71,这就找到了nnn的一个因子71。
参考书籍:Stinson D , 斯廷森, 冯登国. 密码学原理与实践[M]. 电子工业出版社, 2009.
分解因子算法——Pollard rho算法相关推荐
- 大整数分解——Pollard Rho算法
延续上一篇,这次来讲一讲大整数分解算法的应用. 要解决的问题很简单,对一个整数进行分解质因数. 首先还是效率非常低的暴力算法,相信大家都会,不多提. 和上次一样,当数达到非常大的时候,分解将变得非常困 ...
- c语言用rho函数求复数模长,Pollard Rho 算法简介
$\text{update 2019.8.18}$ 由于本人将大部分精力花在了cnblogs上,而不是洛谷博客,评论区提出的一些问题直到今天才解决. 下面给出的Pollard Rho函数已给出散点图. ...
- 数学--数论--随机算法--Pollard Rho 大数分解算法 (带输出版本)
RhoPollard Rho是一个著名的大数质因数分解算法,它的实现基于一个神奇的算法:MillerRabinMillerRabin素数测试. 操作流程 首先,我们先用MillerRabinMille ...
- 数学--数论--随机算法--Pollard Rho 大数分解算法(纯模板带输出)
ACM常用模板合集 #include <bits/stdc++.h> using namespace std; typedef long long ll; ll pr; ll pmod(l ...
- BZOJ 5330 Luogu P4607 [SDOI2018]反回文串 (莫比乌斯反演、Pollard Rho算法)
题目链接 (BZOJ) https://www.lydsy.com/JudgeOnline/problem.php?id=5330 (Luogu) https://www.luogu.org/prob ...
- 素数判定质因数分解(数论)(Miller Rabin)(Pollard Rho)
太玄学了! 我真的被概率的魅力折服了.此前我认为1便是1,0.9999999999-便是0.9999999999-. 但实际上它们有着千丝万缕的关系. 试想,如果一件事发生的概率是0.99999999 ...
- 简述大数分解算法Pollard Rho和Pollard p-1
大数分解问题其实至今都是一个世界级难题,最常见的分解法是从2一直找到sqr(N),作为一个密码学专业的学生,每次看到别人这么做来进行因子分解,自己都控制不住想要制止他,因为这个算法的效率简直太太太太太 ...
- 因数分解 Pollard rho
因数分解 Pollard rho 算法思路 随机生成两个数a,ba,ba,b,然后求gcd(n,a−b)\gcd\pod{n,a-b}gcd(n,a−b),如果其值不为111,则这个数就是nnn的一 ...
- 【快速因数分解】Pollard's Rho 算法
算法目的 给一个数n,快速提取n的一个因数. 算法根据:生日悖论 讲生日悖论之前,先看一个东西. 给出[1-1000]的数,从中任意选出一个数为k的概率是110001\over 100010001. ...
- 4.2 Pollard p-1算法
文章目录 算法 Python实现 算法 1974年,John Pollard发明了p-1算法,其灵感来自于费马小定理.p-1算法一个重要的概念就是B-powersmooth,这个不太好翻译,pow ...
最新文章
- 网络端口的转发和重定向
- stm32入门c语言下载,STM32入门C语言详解.docx
- Unity3D-GUI初试
- Ubuntu12.04 下配置tomcat
- OpenShift 4.6 新特性 - 用 Windows MachineConfig Operator 管理 Windows Container
- 在线文本中插入符号工具
- java初学总结_Java初学总结
- APP适配安卓手机刘海屏
- Python 进阶 —— 可变参数(*args, **kw)与参数收集的逆过程
- 2015年 不可不知的五大热点话题
- 使用listen()和accept()函数
- php opendir(),PHP opendir()用法及代码示例
- qq四国军旗2.1 beat03 builde017记牌器开发思路(二)
- Premiere Pro CC 2018 经典教程
- 好看的个人网站源码_新手想建个人网站,都要注意哪些关于自助建站源码的坑?...
- android微信分享怎么自定义样式,微信更新!主题皮肤终于支持自定义了,样式超多有个性...
- 敏捷软件开发(2)--- 设计原则
- 全国中学生计算机竞赛被取消,叫停4个月,中国计算机学会发布通知,恢复信奥联赛...
- Emulator: emulator: INFO: QtLogger.cpp:68: Critical: Uncaught ReferenceError: $ is not defined (qrc:
- Python查询手机号码所在地区