RSA 数论技巧
写在前言:持续更新中...
光滑数
定义
对于一个数 \(n\),如果它能够被唯一分解为 \(n = p_{1}^{\alpha_1}p_{2}^{\alpha_2} \dots p_{s}^{\alpha_s}(p_1 < p_2 < ... < p_s)\),如果对于所有的 \(p_i(1 \le i \le s)\) 均有 \(p_i \le B\),那么我们称这个数为 \(B - \text{光滑}\) 的。
很多算法是基于 \(B\) 较小的情况来进行解决,我们可以看下面的例题来学习,以下 \(B - \text{光滑}\) 的数若 \(B\) 较小,简称光滑数。
p - 1 光滑
Pollard's 算法
若 \(p\) 是 \(n\) 的因数,并且 \(p − 1\) 是光滑数,可以考虑使用 Pollard's 算法来分解 \(n\)。
Wiki 上的算法流程如下:

由于 \(p - 1\) 是光滑的,选取一个 \(B\) 使得 \((p - 1) \mid B!\)。
根据费马小定理,我们有:
\]
那么可以推出 \(a^{K(p-1)} \equiv 1 \pmod p\)。
由于 \(B! = K(p-1)\),所以 \(a^{B!} \equiv 1 \pmod p\)
因此 \(a^{B!} - 1 = k_{1}p\)。
同时,让 \(a^{B!}\) 模 \(n\) 有 \(a^{B!} \equiv A \pmod n\)
因此 \(a^{B!} - A = k_{2}n\)。
上述两式相减可得 \(A - 1 = k_{2}n - k_{1}p\)。
不难发现 \(p = \gcd{(A - 1, ~ n)}\)。
注意:选取恰当的 \(B\) 是必要的,如果 \(n = pq\) 中 \(p, ~ q\) 两个因子均是光滑的,且 \((p - 1) \mid B!\) 与 \((q - 1) \mid B!\) 同时成立,那么此时 \(a^{(p - 1)(q - 1)} \equiv 1 \pmod {pq}\) 此时计算 \(\gcd{(A - 1, ~ n)}\) 得到的结果为 \(n\),同理,\(B\) 较小会导致 \(\gcd{(A - 1, ~ n)} = 1\)。
由于计算阶乘的算法效率低下,所以对于非光滑数这个算法没有意义。
下面我们来看一个例题。
SHCTF 2024 魔鬼的步伐
from Crypto.Util.number import *
from random import choice
from enc import flag
m = bytes_to_long(flag)
def get_primes(limit):
primes = []
is_prime = [True] * (limit + 1)
for num in range(2, limit + 1):
if is_prime[num]:
primes.append(num)
for multiple in range(num * num, limit + 1, num):
is_prime[multiple] = False
return primes
def get_Prime(bits):
while True:
n = 2
while n.bit_length() < bits:
n *= choice(primes)
if isPrime(n + 1):
return n + 1
e = 65537
primes = get_primes(e)
p = get_Prime(512)
q = get_Prime(512)
n = p*q
c = pow(m,e,n)
print(f"n = {n}")
print(f"e = {e}")
print(f"c = {c}")
'''
n = 391005776046755596699618659246340733279513517050143630792209612493300221058346162409182143062864675702996104615097739220521431717966140002923091879824285706802681307073746160973177190517416980825268203022023401016332004335037582180267013391314432153625679364386326204808730143431891425324668120649464691460108081
e = 65537
c = 143234875923924414196836790485715958182553144290862550786433431528452602241496206240152356816911891891888596692519884126258641274109685025389569676536718006741800941833337629087306702531952775237637889020188884538158307245138965948781078007989600030230701865185135035643226997549934727114764825219500382771617775
'''
通过代码可以发现 \(p, q\) 一定是 \(e - \text{光滑}\) 的,尝试将 \(B\) 取 \(e\) 进行运算发现结果为 \(n\),因此我们在 \((1, ~ e)\) 中进行二分求得一个恰当的 \(B\),时间复杂度是 \(O(e\log{e})\) 的,所以我们可以很快求出答案。
脚本如下:
from Crypto.Util.number import *
from gmpy2 import *
from math import factorial
n = 391005776046755596699618659246340733279513517050143630792209612493300221058346162409182143062864675702996104615097739220521431717966140002923091879824285706802681307073746160973177190517416980825268203022023401016332004335037582180267013391314432153625679364386326204808730143431891425324668120649464691460108081
e = 65537
c = 143234875923924414196836790485715958182553144290862550786433431528452602241496206240152356816911891891888596692519884126258641274109685025389569676536718006741800941833337629087306702531952775237637889020188884538158307245138965948781078007989600030230701865185135035643226997549934727114764825219500382771617775
l = 1
r = e
while (l < r):
mid = l + r >> 1
a = pow(2, math.factorial(mid), n)
p = gmpy2.gcd(a - 1, n)
if p == 1:
l = mid + 1
continue
if p == n:
r = mid - 1
continue
q = n // p
d = gmpy2.invert(e, (p - 1) * (q - 1))
m = pow(c, d, n)
print(long_to_bytes(m))
break
RSA 数论技巧的更多相关文章
- 【数论+技巧】神奇的Noip模拟试题第二试 T1 素数统计
1. 素数统计 (pcount.pas/.c/.cpp) [问题描述] 小tan的老师揣谙戈给同学们布置了一道题,要求统计给定区间内素数的个数.“这不是很简单吗?”小tan忍不住说.揣谙戈冷 ...
- RSA学习档案
RSA 学习档案 基本原理 随机选择两个质数p,q模数n=p*qφ(n)=(p−1)(q−1)选择加密指数e: 1 < e < φ(n)计算机密指数d: e*d % φ(n) = 1c = ...
- Luogu P5285 [十二省联考2019]骗分过样例
Preface ZJOI一轮被麻将劝退的老年选手看到这题就两眼放光,省选也有乱搞题? 然后狂肝了3~4天终于打完了,期间还补了一堆姿势 由于我压缩技术比较菜,所以用的都是非打表算法,所以一共写了5K- ...
- 题解 loj3050 「十二省联考 2019」骗分过样例
CASE \(1\sim 3\) \(n\)组测试数据,每次输入一个数\(x\),求\(19^x\). 测试点\(1\),\(x=0,1,\dots n-1\),可以直接递推. 测试点\(2\)要开l ...
- RSA算法原理——(2)RSA简介及基础数论知识
上期为大家介绍了目前常见加密算法,相信阅读过的同学们对目前的加密算法也算是有了一个大概的了解.如果你对这些解密算法概念及特点还不是很清晰的话,昌昌非常推荐大家可以看看HTTPS的加密通信原理,因为HT ...
- RSA简介(一)——数论原理
RSA是最常用的非对称加密算法. 所谓非对称加密,就是说有两个密钥,一个密钥加密只可以用另外一个密钥解密,一般一个作为公钥,公开给所有人用来加密用,而另一个用来解密其他拥有公钥的加密结果,叫做私钥.另 ...
- python技巧总结之set、日志、rsa加密
一.日志模块logging模块调用 1.日志模块使用原理 #!/usr/bin/python # -*- coding:utf-8 -*- import logging # 方式一: "&q ...
- 项目开发中的一些注意事项以及技巧总结 基于Repository模式设计项目架构—你可以参考的项目架构设计 Asp.Net Core中使用RSA加密 EF Core中的多对多映射如何实现? asp.net core下的如何给网站做安全设置 获取服务端https证书 Js异常捕获
项目开发中的一些注意事项以及技巧总结 1.jquery采用ajax向后端请求时,MVC框架并不能返回View的数据,也就是一般我们使用View().PartialView()等,只能返回json以 ...
- UVA11752 The Super Powers —— 数论、枚举技巧
题目链接:https://vjudge.net/problem/UVA-11752 题意: 一个超级数是能够至少能表示为两个数的幂,求1~2^64-1内的超级数. 题解: 1.可知对于 n = a^b ...
- 公钥密码RSA算法记录
介绍: RSA算法是1978年由 R.Rivest.A.Shamir.L.Adleman提出的一种用数论构造的.也是迄今为止理论上最为成熟.完善的公钥密码体,该体制已得到广泛的应用. 算法描述: 1. ...
随机推荐
- 线性dp:大盗阿福(打家劫舍)
大盗阿福 本题与leetcode198题--打家劫舍的题意一模一样,阅读完本文以后可以尝试以下题目 力扣题目链接) 题目叙述: 阿福是一名经验丰富的大盗.趁着月黑风高,阿福打算今晚洗劫一条街上的店铺. ...
- JS脚本批量处理TS数据类型
在TS开发中,经常会遇到后台数据字段比较多的情况,这时候需要一个个复制字段然后给他手动配置数据类型来完成我们的TS类型定义,相当麻烦.有什么快速的方法呢,我就目前遇到的两种情况分别写了JS脚本来处理后 ...
- Docker 构建多平台镜像
构建多平台镜像的方法分为两种:一种是在不同平台的机器上分别构建并推送对应平台的镜像,然后通过 Docker Manifest 将两个镜像标签合并为一个.另一种是通过 Docker buildx 在一台 ...
- linux磁盘分区之后,lsblk没有显示
可以看出 fdisk 创建一个 sda4 的分区 并保存退出, 但是 不管是使用 fdisk -l ,还是 lsblk 都无法显示出来, 那么导致问题的原因,主要是因为新创建了分区之后,系统没有重 ...
- Excel中制作目录的3种方法,你了解几种?
点赞再看,养成习惯:言之无文,行而不远. 微信搜索[亦心Excel]关注这个不一样的自媒体人. 本文 GitHub https://github.com/hugogoos/Excel 已收录,包含Ex ...
- C# 泛型对象和DataTable之间的相互转换
应用场景 实际开发场景下会经常出现DataTable和List对象需要相互转换的时候,通过方法提取避免重复造轮子 List转换成DataTable 基本思路: 向DataTable里面添加新的数据内容 ...
- MyBatis——简介
MyBatis MyBatis 是一款优秀的持久层框架,用于简化 JDBC 开发 官网:https://mybatis.net.cn/ 持久层 负责将数据保存到数据库的那一层代码 javaEE 三层架 ...
- AD域下,普通用户环境下安装软件需要管理员权限的解决办法
原理:将AD域普通用户添加到管理组中,使其拥有管理员权限 做法: 1.切换到AD域管理员账户: 2.计算机 -> 管理 -> 用户和组 -> 组 -> Administrato ...
- 怎么理解vue的单向数据流
单向数据流是父组件传给子组件的数据,子组件没有权利修改,只能委托父组件修改,然后子组件更新
- 71.登录失效,token过期怎么处理
1. 清除用户数据,直接跳转登录页重新登录 : 2. 短token 过期,使用 长 token 重新获取短 token ,然后重新请求 : 如果长 token 也过期了,就去重新登录获取 token ...