IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> RSA中coppersmith定理的应用条件 -> 正文阅读

[数据结构与算法]RSA中coppersmith定理的应用条件


k e y w o r d s : keywords: keywords: coppersmithRSAsmall_roots()

I n t r o d u c t i o n Introduction Introduction

一般来说,coppersmithRSA中应用最多的就是,高位攻击一类的已知部分二进制位,通过coppersmith定理(里面应用了LLL算法)求得剩余的二进制位

大家有没有想过,究竟在已知多少二进制位数的情况下,coppersmith定理能够生效?

D e d u c t i o n Deduction Deduction

(本文提到的coppersmith定理均只针对单变量)

先来看看coppersmith定理本身的应用场景是:

现有一个 e e e阶的多项式 f f f,那么可以:

  • 给定 β \beta β,快速求出模某个 n n n的因数 b b b意义下较小的根,其中 b ≥ n β b\geq n^{\beta} bnβ,( 0 < β ≤ 1 0< \beta \leq 1 0<β1
  • 在模 n n n意义下,快速求出 n β 2 e n^{\frac{\beta^2}{e}} neβ2?以内的根

而前面提到的高位攻击显然是应用了第二条性质,此时构造的多项式 f = p h i g h + p u n k n o w n f=p_{high}+p_{unknown} f=phigh?+punknown?,阶数 e = 1 e=1 e=1

应用coppersmith定理求解 p u n k n o w n p_{unknown} punknown?,前提条件是 p u n k n o w n ≤ n β 2 e p_{unknown}\leq n^{\frac{\beta^2}{e}} punknown?neβ2?

那么 n β 2 e n^{\frac{\beta^2}{e}} neβ2?究竟有多大呢?在高位攻击的情况下 e = 1 e=1 e=1,所以转换为是求 n β 2 n^{\beta^2} nβ2

β \beta β的定义是

n n n的某个因数 b b b使得 b ≥ n β b\geq n^{\beta} bnβ,( 0 < β ≤ 1 0< \beta \leq 1 0<β1

当然,在RSA n n n的因数也就是组成 n n n的大素数,一般来说, n = p ? q n=p\cdot q n=p?q,其中 p , q p,q p,q均为大素数

python中的实现代码(这里以 1024 b i t s 1024bits 1024bits为例)

from Crypto.Util.number import getPrime
p = getPrime(1024)
q = getPrime(1024)
n = p * q

那么就意味着 n n n的大小为 2048 b i t s 2048bits 2048bits或者 2047 b i t s 2047bits 2047bits(大小涉及到乘法对二进制位数的关系,这里就不过多讲述了)

很显然 n 0.5 n^{0.5} n0.5就是 1024 b i t s 1024bits 1024bits左右的数,与 p , q p,q p,q很接近,但是仍有可能不满足 p , q ≥ n 0.5 p,q\geq n^{0.5} p,qn0.5

检验一下

import gmpy2
assert gmpy2.iroot(n,2)[0] <= p
assert gmpy2.iroot(n,2)[0] <= q
'''
>>> assert gmpy2.iroot(n,2)[0] <= p
>>> assert gmpy2.iroot(n,2)[0] <= q
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AssertionError
'''

此时不满足条件

回到问题的开头,我们想要知道的是在已知多少 p p p或者 q q q的二进制位数下,我们能够通过coppersmith定理求得剩下的二进制位(所需构造的多项式前面已经构造好了)

所以我们可以来看看如果此时满足条件,那么我们至少需要已知多少二进制位数(这里假设求 p p p

计算此时 n β 2 n^{\beta ^2} nβ2 e = 1 e=1 e=1,所以就忽略不代入运算了)的二进制位数,我们未知的二进制位数需要小于 n β 2 n^{\beta ^2} nβ2的二进制位数

gmpy2.iroot(n,2**2)[0].bit_length()
'''
>>> gmpy2.iroot(n,2**2)[0].bit_length()
512
'''

这里我们看到如果 p , q ≥ n β p,q\geq n^{\beta} p,qnβ,那么我们未知 p p p或者 q q q(任意一个均可)的二进制位数必须小于 512 512 512

以上都是假设的,我们来看看真实地满足 p , q ≥ n β p,q\geq n^{\beta} p,qnβ情况下,我们未知的二进制位数必须小于多少?

既然 n 0.5 n^{0.5} n0.5(即是 β = 0.5 \beta=0.5 β=0.5情况下)不满足条件,那么与之最接近的 β = 0.49 \beta=0.49 β=0.49的情况(也就是 β < 0.5 \beta < 0.5 β<0.5时)一定能满足条件(这里又涉及到指数运算对二进制位数的影响,也不过多讲述了,可以自己计算试一试)

还是刚才那套检验过程以及计算 n β 2 n^{\beta ^2} nβ2的过程

assert gmpy2.iroot(n**49,100)[0] <= p
assert gmpy2.iroot(n**49,100)[0] <= q
gmpy2.iroot(n**(49**2),100**2)[0].bit_length()
gmpy2.iroot(n**(48**2),100**2)[0].bit_length()
gmpy2.iroot(n**(47**2),100**2)[0].bit_length()
'''
>>> assert gmpy2.iroot(n**49,100)[0] <= p
>>> assert gmpy2.iroot(n**49,100)[0] <= q
>>> gmpy2.iroot(n**(49**2),100**2)[0].bit_length()
492
>>> gmpy2.iroot(n**(48**2),100**2)[0].bit_length()
472
>>> gmpy2.iroot(n**(47**2),100**2)[0].bit_length()
453
'''

本来按照定理条件的推导,只要未知二进制位数少于 492 492 492均可应用coppersmith定理求解


sagemath中应用coppersmith定理的函数有两个:small_rootscoppersmith_howgrave_univariate

后者的使用方法可以参考 Coppersmith 相关攻击 - CTF Wiki (ctf-wiki.org)

对RSA-Factoring with High Bits Known理解 - 简书 (jianshu.com)

这里求解coppersmith我们统一使用sagemathsmall_roots()函数;该函数导入的 β \beta β 起作用的只有一位小数(如果是两位小数,其求解范围还是相当于一位小数的求解范围),这就意味着一般形如p = getPrime(bits),q = geyPrime(bits)的RSA应用coppersmith求解p的低位时, β \beta β只能是最接近 0.5 0.5 0.5 0.4 0.4 0.4

关于small_roots的使用方法:

small_roots(X = ,beta = ) 有两个参数

X代表所需要求解根的上限;虽然是根的上限,并不是说上限越高越好,当上限超过某个值的时候就会计算失效,即使已知二进制位数满足条件,也无法用此函数求得结果;所以一般来说X取在给定情况下的最大求解上限

beta即是前面提到的 β \beta β ,当p,q二进制位数相同时一般只能取 0.4 0.4 0.4;如果p,q二进制位数不同,就按照之前的方法具体问题具体分析

那么实际操作下,使用small_roots()我们至少需要已知多少二进制位数呢?(以下是sagemath环境)

from Crypto.Util.number import getPrime
p = getPrime(int(1024))
q = getPrime(int(1024))
n = p * q
test_bits = 454
p_h = p >> test_bits
R.<x> = PolynomialRing(Zmod(n))
f = (p_h << test_bits) + x
f.small_roots(2**test_bits,0.4)

经过测试得到,当未知量小于等于 454 b i t s 454bits 454bits时(p,q 1024 b i t s 1024bits 1024bits),coppersmith定理可以求解

之后改变了p,q的大小,经过测试发现,当p,q同二进制位数时,要使用small_roots()应用coppersmith定理求解 n n n的某个因数的低位,需要满足未知的二进制位数与因数之间的二进制位数的关系是
u n k n o w n _ b i t s ÷ p _ b i t s ≤ 0.44 unknown\_bits \div p\_bits \leq 0.44 unknown_bits÷p_bits0.44
下面来以例题为标准应用一下small_roots的灵活应用

P r o b l e m Problem Problem

问题来自鹤城杯2021,babyrsa

D e s c r i p t i o n Description Description

from Crypto.Util.number import getPrime, bytes_to_long
from secret import flag

p = getPrime(1024)
q = getPrime(1024)
n = p * q
e = 65537
hint1 = p >> 724
hint2 = q % (2 ** 265)
ct = pow(bytes_to_long(flag), e, n)
print(hint1)
print(hint2)
print(n)
print(ct)

A n a l y s i s Analysis Analysis

显然是应用高位攻击

但是由于之前测试的结果,未知的二进制位数需要小于 454 454 454,而这里p未知的二进制位数达到了 724 724 724,而q则更多;

但是这里既然给出了p,q两者分别的高位,低位;按照高位攻击的思路,需要是某一个因数的多个二进制位数,所以找方法能不呢把q的低位转换为p的低位,或者相反
{ q l o w ≡ q ( m o d 2 265 ) q h i g h = k ? 2 265 n = p ? ( q h i g h + q l o w ) ? n = p ? k ? 2 265 + p ? q ( m o d 2 265 ) \begin{cases} q_{low} \equiv q\pmod {2^{265}}\\ q_{high} = k\cdot 2^{265}\\ n = p\cdot (q_{high} + q_{low}) \end{cases} \Rightarrow n =p\cdot k\cdot 2^{265} + p\cdot q\pmod {2^{265}} ??????qlow?q(mod2265)qhigh?=k?2265n=p?(qhigh?+qlow?)??n=p?k?2265+p?q(mod2265)
等式两边同时求余 2 265 2^{265} 2265
n l o w ≡ p ? k ? 2 265 + p ? q l o w ( m o d 2 265 ) ? p l o w ≡ n l o w ? q l o w ? 1 ( m o d 2 265 ) n_{low}\equiv p\cdot k\cdot 2^{265} + p\cdot q_{low}\pmod {2^{265}}\\ \Rightarrow p_{low}\equiv n_{low} \cdot q^{-1}_{low} \pmod{2^{265}} nlow?p?k?2265+p?qlow?(mod2265)?plow?nlow??qlow?1?(mod2265)
这样一来我们就知道了 p p p的低 265 265 265位,此时未知的二进制位数仍然有 459 459 459位,而我们需要的是未知二进制位要在 454 454 454之下

只剩下 5 5 5位了,那么直接就可以爆破剩余的 5 5 5位二进制

S o l v i n g ? c o d e Solving~code Solving?code

from Crypto.Util.number import *
import gmpy2
p_high = 1514296530850131082973956029074258536069144071110652176122006763622293335057110441067910479
q_low = 40812438243894343296354573724131194431453023461572200856406939246297219541329623
n = 21815431662065695412834116602474344081782093119269423403335882867255834302242945742413692949886248581138784199165404321893594820375775454774521554409598568793217997859258282700084148322905405227238617443766062207618899209593375881728671746850745598576485323702483634599597393910908142659231071532803602701147251570567032402848145462183405098097523810358199597631612616833723150146418889589492395974359466777040500971885443881359700735149623177757865032984744576285054725506299888069904106805731600019058631951255795316571242969336763938805465676269140733371287244624066632153110685509892188900004952700111937292221969
enc = 19073695285772829730103928222962723784199491145730661021332365516942301513989932980896145664842527253998170902799883262567366661277268801440634319694884564820420852947935710798269700777126717746701065483129644585829522353341718916661536894041337878440111845645200627940640539279744348235772441988748977191513786620459922039153862250137904894008551515928486867493608757307981955335488977402307933930592035163126858060189156114410872337004784951228340994743202032248681976932591575016798640429231399974090325134545852080425047146251781339862753527319093938929691759486362536986249207187765947926921267520150073408188188
e = 65537

mod = pow(2,265)
p0 = n * inverse_mod(q_low,mod) % mod
PR.<x> = PolynomialRing(Zmod(n))
for i in range(2**5):
    f = p_high * (2^724) + p0 + (x * 32 + i) * mod
    f = f.monic()
    out_p = f.small_roots(2^454,0.4)
    if len(out_p) != 0:
        print(out_p[0])
        break
p = out_p[0] * 32 + i * mod + p_high * (2^724) + p0
# print(p)
p = 133637329398256221348922087205912367118213472434713498908220867690672019569057789598459580146410501473689139466275052698529257254973211963162087316149628000798221014338373126500646873612341158676084318494058522014519669302359038980726479317742766438142835169562422371156257894374341629012755597863752154328407
assert n % p == 0
q = n // p
fai_n = (p-1) * (q-1)
d = inverse_mod(e,fai_n)
m = pow(enc,d,n)
print(bytes.decode(long_to_bytes(m)))

O t h e r Other Other

关于RSA中应用coppersmith还有部分私钥泄露攻击等等

这里就不过多阐述了,可以参考 CTF中的RSA基本套路(3) - 食兔人的博客 (ycdxsb.cn)

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-03-21 21:17:10  更:2022-03-21 21:17:55 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 -2025/1/9 1:27:38-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码