密码第十周

题目

NSSctf ez_enc

得到一个文件,打开可以看到一串A和B,
可以考虑培根密码,
https://www.qqxiuzi.cn/bianma/peigenmima.php
结果不对劲
也可以转二进制
A—>0
B—>1

def binary_to_text(binary_str):#二进制转字符串
    binary_str = binary_str.replace(' ', '').replace('0x', '').replace('\t', '').replace('\n', '')
    return ''.join(chr(int(binary_str[i * 8:i * 8 + 8], 2)) for i in range(len(binary_str) // 8))

file = open("D:\桌面\ez_enc", "rb").read().decode()
binaryValue = file.replace('A', '0').replace('B', '1')
hexValue = binary_to_text(binaryValue)
print(hexValue)

CTFshow_愚人杯 easybase

一串十六进制数
base16—>base32—>base64

CTFshow_愚人杯 大牛的密码

题目

from Crypto.Util.number import *
from flag import flag
from Crypto.Util.Padding import pad
from random import *
def s_box(a):
    box=[i for i in range(a)]
    shuffle(box) # 随机打乱box
    return box
BLOCK=16 #分块时的块长度
flag=pad(flag,BLOCK) #填充
S_BOX=s_box(len(flag)) #盒子长度=flag长度,flag中的每一个字符对应盒子中的每一个元素
m=[i for i in flag]
def swap(a,b): #交换
    tmp = a
    a = b
    b = tmp
def encrypt1(m):
    enc=[m[i:i+BLOCK] for i in range(0,len(m),BLOCK)]
    for i in enc:
        for j in range(BLOCK):
            aa=j*7%BLOCK
            swap(i[j],i[aa])
def encrypt2(m): #将明文列表中的元素按照S_BOX中的顺序重新排列
    for i in range(16):
        m=[m[i] for i in S_BOX]
    return m
encrypt1(m) # encrypto1没用
c=encrypt2(m)
print(S_BOX)
print(c)
'''
[9, 31, 32, 38, 20, 1, 22, 4, 8, 2, 11, 21, 7, 18, 46, 23, 34, 3, 19, 12, 45, 30, 27, 37, 5, 47, 28, 36, 0, 43, 39, 10, 29, 14, 40, 24, 33, 16, 17, 6, 42, 15, 26, 41, 44, 25, 35, 13]
[99, 111, 102, 11, 107, 49, 11, 53, 121, 48, 114, 117, 11, 95, 112, 95, 109, 115, 11, 95, 101, 95, 119, 117, 79, 123, 111, 48, 110, 95, 121, 116, 121, 125, 116, 11, 119, 11, 97, 67, 11, 11, 11, 11, 11, 99, 110, 104]
'''

主要是通过s_box查表进行了一次加密,解密也就是逆着查表回来。

exp

s_box = [9, 31, 32, 38, 20, 1, 22, 4, 8, 2, 11, 21, 7, 18, 46, 23, 34, 3, 19, 12, 45, 30, 27, 37, 5, 47, 28, 36, 0, 43, 39, 10, 29, 14, 40, 24, 33, 16, 17, 6, 42, 15, 26, 41, 44, 25, 35, 13]
c = [99, 111, 102, 11, 107, 49, 11, 53, 121, 48, 114, 117, 11, 95, 112, 95, 109, 115, 11, 95, 101, 95, 119, 117, 79, 123, 111, 48, 110, 95, 121, 116, 121, 125, 116, 11, 119, 11, 97, 67, 11, 11, 11, 11, 11, 99, 110, 104]

# enumerate()函数遍历c列表中的所有元素,并将其赋值给m列表中s_box[j]位置上
for i in range(16):
    m = [0] * len(s_box)
    for j, v in enumerate(c): 
        m[s_box[j]] = v
    c = m

print(bytes(m))

CTFshow_愚人杯 Comedy

import gmpy2, libnum
from secret import flag1, flag2

m = libnum.s2n(flag1)
assert m.bit_length() < 200  # 确保m<200
B = gmpy2.next_prime(libnum.s2n(flag2)) #B是比m大的下一个素数
A = (2022 - 2023 * m) % B
leak = pow(2, 2023, B)
print(A)
print(leak)
# 493275281479560936332761096886786925792234184811353209227551802099268192839677496844153534128991899414803550843408607188612593757622064753867565869035222715177143938385039508273050267347710495512806264863554858016145161165422812554800693811328453743229819656381224407015421235005940088439590887928051969351426291843586132741521121351667152673680122929827805479163871436776753859965413192837591532468372
# 238829196127128263156194898141748280130190920343265228257398802867203846004703877952990524473329125233083096275276064071930416561616135910190674099345267027039386328203653489152769309498199556401574021633071022874689081585677578010276529507102304828451681000682208089162940529052283763507244593173690786957816545746540436261888398732172965945762569416702401859253725696471593023885944262561159982327952

由题可得
A = ( 2022 − 2023 ∗ m ) m o d B A=(2022-2023*m) mod B A=(20222023m)modB
l e a k = 2 2023 m o d B leak=2^{2023} mod B leak=22023modB

Coppersmith算法

密码第十周_第1张图片
已知p高位,低位缺失,则采用coppersmith攻击。

截图源自
这道题的官方wp
密码第十周_第2张图片

exp

#sage
from Crypto.Util.number import *

A=493275281479560936332761096886786925792234184811353209227551802099268192839677496844153534128991899414803550843408607188612593757622064753867565869035222715177143938385039508273050267347710495512806264863554858016145161165422812554800693811328453743229819656381224407015421235005940088439590887928051969351426291843586132741521121351667152673680122929827805479163871436776753859965413192837591532468372
leak=238829196127128263156194898141748280130190920343265228257398802867203846004703877952990524473329125233083096275276064071930416561616135910190674099345267027039386328203653489152769309498199556401574021633071022874689081585677578010276529507102304828451681000682208089162940529052283763507244593173690786957816545746540436261888398732172965945762569416702401859253725696471593023885944262561159982327952

# A+2023*m-2022 = 0 % B
KB = pow(2,2023)-leak

PR. = PolynomialRing(Zmod(KB))    #构建了一个模KB下的一元多项式环
f = A+2023*m-2022    #定义一元多项式f
f = f.monic()    #将f化为首项系数为1的最高次项的单项式,这样才能在多项式环中使用LLL算法找小根。
m = int(f.small_roots(X=2^200, beta=0.4)[0])
flag1 = long_to_bytes(m)

flag2 = gcd(A+2023*m-2022, KB)
flag2 = long_to_bytes(flag2)
flag=flag1+flag2
print(flag) 

关于small_roots函数(找多项式方程的小根)

X:一个整数,表示多项式的未知数 m 的最大位数,也就是说 m 的二进制位数不超过 X。
beta:一个浮点数,用于控制搜索多项式的根的范围。这个值越小,搜索的范围就越小,但可能会错过正确的解;这个值越大,搜索的范围就越大,但可能会找到多个解。

多项式环(PolynomialRing)中的小根算法(small_roots):

小根:绝对值最小的根

假设有一个模数为n的多项式f(x),且知道其次数为d,小根算法的目标就是在范围[0, B]中查找满足 f ( x ) ≡ 0 m o d n f(x)≡{0} mod n f(x)0modn的整数x,并返回最小的满足条件的x。

一个基于Coppersmith攻击的Sage脚本,用于解决小指数RSA加密的问题:

def coppersmith_attack(n, e, c, beta):
    """
    使用Coppersmith攻击来解决小指数RSA加密的问题
    """
    # 定义多项式环
    R. = PolynomialRing(Zmod(n))

    # 定义多项式f(x),确保首项系数为1
    f = x**e - c

    # 计算多项式f(x)在x = 0时的值
    alpha = int(f(0))

    # 计算多项式f(x)在x = 0时的导数
    df = f.derivative()

    # 计算多项式g(x)
    g = df.monic()

    # 使用LLL算法找到g(x)的小根
    X = g.small_roots(beta)

    # 检查根是否存在
    if len(X) == 0:
        raise ValueError("没有找到小根")

    # 计算解密后的明文m
    m = pow(alpha, -1, n)
    for x in X:
        # 求解x + alpha * m的e次方模n的余数
        candidate = pow(x + alpha * m, e, n)

        # 检查是否解密成功
        if candidate == c:
            return x + alpha * m

    raise ValueError("解密失败")

CTFshow_愚人杯 easy_xor

题目

from Crypto.Util.number import *
from secret import flag

assert len(flag[8:-1])==23 # 根据这个断言可得flag长度,flag{......},(23+9)*8=256bit
m = bytes_to_long(flag)
p = getPrime(1024)
q = getPrime(1024)
n = p*q
e = 65537
c1 = m^p # 异或
c2 = pow(m,e,n)
print(f'c1 = {c1}')
print(f'c2 = {c2}')
print(f'n = {n}')
'''
c1 = 151198307301713399973545627808177783191262282577048906899567665485020342464366268384613589477129150406859219553325982275344405383612415523342568367197935454935162234419239807109194526080836070453102172720442102673200212658553214847476648456720629906051324248179394810385918370092764118401652990951968387233220
c2 = 7894512574379281106340582833782408137686355961537832816105517328532111343730615739255485918919146012721446905489729048235088965936700563973759759039693443386542070451737445467143517377017890468837697907596398070608179281207203217576205857817411996178441661371846647602166663752324880657668362355493701482869858528298247422875427747085642627978367348931707497113936723122393282697211257939351221141536029828744507560524637999804394951722319070365576391442828074457050403771353328835153787572457070779602728359333021922987279454923820866436212282592764768470608545881718922440010751845730974331917142224339664090863915
n = 20873587976264698212013861921447267548758723109929620330136081844796427967720295581580927324390713931549639540337285515365487607593546367886570408812338077846317206794057714877394609181224434104303259411081376607299962306250984285173463537669954845497211859940191392861121877814873939865829555350848523691546006073264112091406848179785659505299775196062799482197712761744192962658799557108701192680225134300686608396391566674966897700511638643429161735764600752699251493599533703928135311599575989253347234975026924804433742500175666009324057320386262109587593814197687132304704244158862263859846356497849518103755981
'''

从出题脚本中我们已经得到了flag的长度,c1的加密是一个异或操作,所以可以得知最后的结果只影响了低位,p的高位不变。那么这个问题就变成了已知p高位的低位缺失问题(p高位泄露)。恢复p,利用XOR的可逆性,得到flag

XOR—>p高位泄露

exp

#sage
from Crypto.Util.number import *
c1 =151198307301713399973545627808177783191262282577048906899567665485020342464366268384613589477129150406859219553325982275344405383612415523342568367197935454935162234419239807109194526080836070453102172720442102673200212658553214847476648456720629906051324248179394810385918370092764118401652990951968387233220
c2 =7894512574379281106340582833782408137686355961537832816105517328532111343730615739255485918919146012721446905489729048235088965936700563973759759039693443386542070451737445467143517377017890468837697907596398070608179281207203217576205857817411996178441661371846647602166663752324880657668362355493701482869858528298247422875427747085642627978367348931707497113936723122393282697211257939351221141536029828744507560524637999804394951722319070365576391442828074457050403771353328835153787572457070779602728359333021922987279454923820866436212282592764768470608545881718922440010751845730974331917142224339664090863915
n =20873587976264698212013861921447267548758723109929620330136081844796427967720295581580927324390713931549639540337285515365487607593546367886570408812338077846317206794057714877394609181224434104303259411081376607299962306250984285173463537669954845497211859940191392861121877814873939865829555350848523691546006073264112091406848179785659505299775196062799482197712761744192962658799557108701192680225134300686608396391566674966897700511638643429161735764600752699251493599533703928135311599575989253347234975026924804433742500175666009324057320386262109587593814197687132304704244158862263859846356497849518103755981

#分离出p的高位
kbits = 256 
c3 = c1>>kbits # 右移,舍去低位
pbits = 1024 
c4 = c3<

[HZNUCTF 2023 final]一步到喂

from Crypto.Util.number import *
from secret import flag,x,y
p=getPrime(512)
q=getPrime(512)
n=p*q
e=x
assert 1293023064232431070902426583269468463*pow(x,2)==105279230912868770223946474836383391725923*pow(y,2)+1293023064232431070902426583269468463
m=bytes_to_long(flag)
c=pow(m,e,n)
print(p,q)
print(c)
#9850212100620338486478343799784951721581757936621772924971218807300819701941457605399099898870264241518769370682330612103782092302148525012450902351701339
#10749429992014823019923966246896511618886613763258781706004694804949547801668777655988055847885755337127548775758133804022361510427909703124161450470578543
#66847321508502017574023222490247591875197038421108556106531660421662626233521063441647157067220450229816184622038471812597874582613385516838920632450015292570673816423432903604941781889308906893966588610214614726388822851471695742453496232748358301888465563812947038856742838097152549971517159475947566599664

满足等式
1293023064232431070902426583269468463 ∗ x 2 = 105279230912868770223946474836383391725923 ∗ y 2 + 1293023064232431070902426583269468463 1293023064232431070902426583269468463*x^2 = 105279230912868770223946474836383391725923*y^2 + 1293023064232431070902426583269468463 1293023064232431070902426583269468463x2=105279230912868770223946474836383391725923y2+1293023064232431070902426583269468463

pell(佩尔)方程

exp
求解佩尔方程

#判断b是否为a的整数倍,如果不是,会影响计算精度
a = 1293023064232431070902426583269468463
b = 105279230912868770223946474836383391725923
print(b//a*a == b)

import gmpy2
from math import ceil,floor,sqrt

#求解Pell方程中的最小整数解
def pell_minimum_solution(n):
    a = []
    m = floor(sqrt(n))
    sq = sqrt(n)
    a.append(m)
    b = m
    c = 1
    i = 1
    while a[i-1] != 2 * a[0]:
        c = (n - b * b) / c
        tmp = (sq + b) / c
        a.append(floor(tmp))
        i += 1
        b = a[i-1] * c - b
    p = 1
    q = 0
    for j in range(i-2,-1,-1):
        t = p
        p = q + p * a[j]
        q = t
    if (i-1) % 2 == 0:
        x0 = p
        y0 = q
    else:
        x0 = 2 * p ** 2 + 1
        y0 = 2 * p * q
    return x0,y0

print(pell_minimum_solution(b//a))

让聪明的gpt解释一下这个算法
密码第十周_第3张图片

普通RSA解密

from gmpy2 import *
from Crypto.Util.number import *

x,y = 706458746417678962043621845971467865659328419354757470370053791959400836343459667183452696881749102272803495561977766862981211957547107314899837090421877848369768126470488899783907413049018564965473411482320934865623338739674557285559179500448017722749519381238449907463225595410791751764554609076679816077991393296019025846726102143252917723127850421484059625048891687413514675773883846965460650321320194376953023128886680992904874680874592398084000621265936352579085146973168432725924933271736161246147210167219273151533549827720768127049, 2475817283208353655376575253824978610318795084158266693908795228437881838494879684898106300899685369783448887135772502375256424485378197701618246093404377305042144695942832777562138071372439272074221303824090898475856064751103068366460943484199764781203337540043797645872932430695841756685875430274803587032466826238694472049259595749567628655789857218392048459841779867350496912185026568130525427572795745011809179300697763422087575586151631990884275732162078972870311906763206309891911795517651173639547353468670434655436993030736217980
c = 66847321508502017574023222490247591875197038421108556106531660421662626233521063441647157067220450229816184622038471812597874582613385516838920632450015292570673816423432903604941781889308906893966588610214614726388822851471695742453496232748358301888465563812947038856742838097152549971517159475947566599664
p = 10749429992014823019923966246896511618886613763258781706004694804949547801668777655988055847885755337127548775758133804022361510427909703124161450470578543
q = 9850212100620338486478343799784951721581757936621772924971218807300819701941457605399099898870264241518769370682330612103782092302148525012450902351701339
d = gmpy2.invert(x,(p-1)*(q-1))

m = long_to_bytes(gmpy2.powmod(c,d,p*q))
print(m)

HD CTF2023_爬过小山去看云

题目

密文:ymyvzjtxswwktetpyvpfmvcdgywktetpyvpfuedfnzdjsiujvpwktetpyvnzdjpfkjssvacdgywktetpyvnzdjqtincduedfpfkjssne
在山的那头,有3个人,4只鸟,19只羊,11朵云

希尔Hill密码

基于矩阵的乘法,多表替换密码
加密:

  1. 有一个nxn的密钥矩阵
  2. 明文替换(A->0 B->1 …)明文分组(n个字母组成一个n维向量)
  3. 每组向量与密钥矩阵相乘,mod 26
  4. 将得到的每组数字再替换成字母,拼接起来

注意:用作加密的 n×n密钥矩阵必须是可逆的,否则无法解码。只有矩阵的行列式和26互质,才是可逆的。

解密:

  1. 得到密钥矩阵的逆矩阵
  2. 密文替换成数字,分组
  3. 每组向量与密钥逆矩阵相乘,mod 26
  4. 数字转字母,拼接

希尔密码特点:
1.密文为纯字母
2.有密钥(几个数组成,一串数字是无法判断的)

在线网站:希尔密码解密
本题得到

yourpiniseightfourtwozeroeightfourtwoonezeroeighteightfourzerotwofourzeroeightfourzeroonezeroonetwofourx

842084210884024084010124

云影密码(01248密码)

用0.1.2.4.8可以相加得到1-9中任意一个数字,用1-26代表对应的英文字母,密文中0为间隔符。

a = "842084210884024084010124"
a = a.split("0") # 根据0进行分割
flag = ''
for i in range(0, len(a)):
 	str = a[i]
 	sum = 0
 	for i in str:
 		sum += int(i)
 	flag += chr(sum + 64)
print(flag)

得到flag NOTFLAG

HD CTF2023_normal rsa

题目

from Crypto.Util.number import *
#from shin import flag

m=bytes_to_long(b'HDCTF{0b3663ed-67e4-44e2-aee7-7c2d8665b63c}') #原题flag泄露
e=65537
p=getPrime(256)
#q=getPrime(512)
q=6704006258427795304220450411280948926213189680360135534636452074716135019217911134480777251273836898349926894302122011679095979445240343891749741039976761
r=getPrime(512)
n=p*q*r
P=pow(p,2,n)  #P = p^2 mod n 
Q=pow(q,2,n)  #Q = q^2 mod n
c=pow(m,e,n)
print(f"P = {P}")
print(f"Q = {Q}")
print(f"n = {n}")
print(f"c = {c}")
'''
P = 6773247693445539441213578786581644136043035242620265251725630106817272212428325283262417364786451280269516220237289567904055371962564710888510272312707201
Q = 44943699913039047357456835559925378512493523252980366265686899925123157887149890185055864945749408514100461655676474535153113631214288057465776668291975220848776401405531599573114898492452990847774628035552581539370236080368457643523158920565504112005843410442573511095306233906498204203659537135943420051121
n = 4785613888465991171479248142015453309149548888755453367991501772592797686075465426815591528773123474962122102667475893532087343900904799831474817826058951265607078893487357878501280782935653048309499430170214015422492927323961394806106719569168457890040223027119115392961801582406287167644266319898276785787730947633037300317098453409851410936140488150390919951503767522517809035474567
c = 2247027561636791381460194811205520085150851211795956750955965051548230844233212462525163107917067768507367576366327035846089534916090521357212722275045521111077106695721780943857231570836500588468487620819893688830570842176795906808347617421353983094639290979158413935035603633331786978227439155042365130799647385116773171906670409535157184391352888875130028955334874727206292146950544
'''

因为 P = p 2 m o d n P=p^2 mod n P=p2modn Q = q 2 m o d n Q=q^2modn Q=q2modn,而 n = p ∗ q ∗ r n=p*q*r n=pqr从题中给出的数据可以看出 n > P n>P n>P n > Q n>Q n>Q,所以我们可以直接得出 P = p 2 P=p^2 P=p2 Q = q 2 Q=q^2 Q=q2
原来看到了 n = p ∗ q ∗ r n=p*q*r n=pqr 想到了ctfshow的funny rsa2,但是尝试之后发现这道题用funny rsa2的方法是解不出来的。在两道题的题解中放入

t = gmpy2.gcd(e, phi)
print(t)

就发现了在funny rsa2中e与phi是互素的,而在这道题中e与phi不互素,在这种情况下逆元d无解,得到的t=65537,说明了phi % e=0。密码第十周_第4张图片
截图来源

exp

from Crypto.Util.number import *
from gmpy2 import *
P = 6773247693445539441213578786581644136043035242620265251725630106817272212428325283262417364786451280269516220237289567904055371962564710888510272312707201
Q = 44943699913039047357456835559925378512493523252980366265686899925123157887149890185055864945749408514100461655676474535153113631214288057465776668291975220848776401405531599573114898492452990847774628035552581539370236080368457643523158920565504112005843410442573511095306233906498204203659537135943420051121
n = 4785613888465991171479248142015453309149548888755453367991501772592797686075465426815591528773123474962122102667475893532087343900904799831474817826058951265607078893487357878501280782935653048309499430170214015422492927323961394806106719569168457890040223027119115392961801582406287167644266319898276785787730947633037300317098453409851410936140488150390919951503767522517809035474567
c = 2247027561636791381460194811205520085150851211795956750955965051548230844233212462525163107917067768507367576366327035846089534916090521357212722275045521111077106695721780943857231570836500588468487620819893688830570842176795906808347617421353983094639290979158413935035603633331786978227439155042365130799647385116773171906670409535157184391352888875130028955334874727206292146950544
e = 65537
p = int(iroot(P,2)[0])
q = int(iroot(Q,2)[0])
# print(p)
#print(q)
r = n//(p*q)
d = inverse(e,(p-1)*(r-1))
print(long_to_bytes(pow(c,d,p*r)))

只需要用p和r去求e的逆元

HD CTF2023_normal rsa (revenge)

题目

from Crypto.Util.number import *
#from shin import flag

m=bytes_to_long(b'HDCTF{******}')
e=65537
p=getPrime(256)
q=getPrime(512)
r=getPrime(512)
n=p*q*r
P=pow(p,2,n)
Q=pow(q,2,n)
c=pow(m,e,n)
print(f"P = {P}")
print(f"Q = {Q}")
print(f"n = {n}")
print(f"c = {c}")
'''
P = 8760210374362848654680470219309962250697808334943036049450523139299289451311563307524647192830909610600414977679146980314602124963105772780782771611415961
Q = 112922164039059900199889201785103245191294292153751065719557417134111270255457254419542226991791126571932603494783040069250074265447784962930254787907978286600866688977261723388531394128477338117384319760669476853506179783674957791710109694089037373611516089267817074863685247440204926676748540110584172821401
n = 12260605124589736699896772236316146708681543140877060257859757789407603137409427771651536724218984023652680193208019939451539427781667333168267801603484921516526297136507792965087544395912271944257535087877112172195116066600141520444466165090654943192437314974202605817650874838887065260835145310202223862370942385079960284761150198033810408432423049423155161537072427702512211122538749
c = 7072137651389218220368861685871400051412849006784353415843217734634414633151439071501997728907026771187082554241548140511778339825678295970901188560688120351732774013575439738988314665372544333857252548895896968938603508567509519521067106462947341820462381584577074292318137318996958312889307024181925808817792124688476198837079551204388055776209441429996815747449815546163371300963785
'''

与上一题类似
在这道题中n被分解成了三个数p,q,r,并且e和phi是互素的,所以这道题和 funny rsa2 是一样的。
exp

from Crypto.Util.number import *
from gmpy2 import *
P = 8760210374362848654680470219309962250697808334943036049450523139299289451311563307524647192830909610600414977679146980314602124963105772780782771611415961
Q = 112922164039059900199889201785103245191294292153751065719557417134111270255457254419542226991791126571932603494783040069250074265447784962930254787907978286600866688977261723388531394128477338117384319760669476853506179783674957791710109694089037373611516089267817074863685247440204926676748540110584172821401
n = 12260605124589736699896772236316146708681543140877060257859757789407603137409427771651536724218984023652680193208019939451539427781667333168267801603484921516526297136507792965087544395912271944257535087877112172195116066600141520444466165090654943192437314974202605817650874838887065260835145310202223862370942385079960284761150198033810408432423049423155161537072427702512211122538749
c = 7072137651389218220368861685871400051412849006784353415843217734634414633151439071501997728907026771187082554241548140511778339825678295970901188560688120351732774013575439738988314665372544333857252548895896968938603508567509519521067106462947341820462381584577074292318137318996958312889307024181925808817792124688476198837079551204388055776209441429996815747449815546163371300963785
e = 65537
p = int(iroot(P,2)[0])
q = int(iroot(Q,2)[0])
# print(p)
#print(q)
r = n//(p*q)
# 解的时候,也可以不⽤三个,⽤两个(p和q、q和r、p和r)或⼀个(q或r)都⾏
d = inverse(e,(p-1)*(q-1)*(r-1))
print(long_to_bytes(pow(c,d,p*q*r)))

在使用欧拉函数时,只需要保证求得的数是逆元即可,而不需要知道每个质因数,因此可以只使用两个或一个质数来计算逆元。

密码第十周_第5张图片

HD CTF2023_math rsa

题目

from Crypto.Util.number import *
from shin import flag

m=bytes_to_long(flag)
r=getPrime(1024)
assert r%4==3
p=getPrime(1024)
assert pow(p,(r-1)//2,r)==1
q=getPrime(1024)
e=65537
n=p*q
a=pow(p,2,r)
c=pow(m,e,n)
print(f"n = {n}")
print(f"r = {r}")
print(f"a = {a}")
print(f"c = {c}")
'''
n = 14859096721972571275113983218934367817755893152876205380485481243331724183921836088288081702352994668073737901001999266644597320501510110156000004121260529706467596723314403262665291609405901413014268847623323618322794733633701355018297180967414569196496398340411723555826597629318524966741762029358820546567319749619243298957600716201084388836601266780686983787343862081546627427588380349419143512429889606408316907950943872684371787773262968532322073585449855893701828146080616188277162144464353498105939650706920663343245426376506714689749161228876988380824497513873436735960950355105802057279581583149036118078489
r = 145491538843334216714386412684012043545621410855800637571278502175614814648745218194962227539529331856802087217944496965842507972546292280972112841086902373612910345469921148426463042254195665018427080500677258981687116985855921771781242636077989465778056018747012467840003841693555272437071000936268768887299
a = 55964525692779548127584763434439890529728374088765597880759713360575037841170692647451851107865577004136603179246290669488558901413896713187831298964947047118465139235438896930729550228171700578741565927677764309135314910544565108363708736408337172674125506890098872891915897539306377840936658277631020650625
c = 12162333845365222333317364738458290101496436746496440837075952494841057738832092422679700884737328562151621948812616422038905426346860411550178061478808128855882459082137077477841624706988356642870940724988156263550796637806555269282505420720558849717265491643392140727605508756229066139493821648882251876933345101043468528015921111395602873356915520599085461538265894970248065772191748271175288506787110428723281590819815819036931155215189564342305674107662339977581410206210870725691314524812137801739246685784657364132180368529788767503223017329025740936590291109954677092128550252945936759891497673970553062223608
'''

整理题目给出的信息,
r ≡ 3 ( m o d 4 ) r ≡ 3 (mod 4 ) r3(mod4)
p ( r − 1 ) / / 2 ≡ 1 m o d ( r ) p^{(r-1)//2} ≡1 mod(r) p(r1)//21mod(r)
a ≡ p 2 m o d ( r ) a≡p^2mod(r) ap2mod(r)

密码第十周_第6张图片
二次剩余问题

Tonelli-Shanks算法

Tonelli –Shanks 算法(被 Shanks 称为 RESSOL 算法)用于模块化算术,以 r 2 ≡ n ( m o d p ) r^2 ≡ n (mod p ) r2n(modp)形式的同余求解r,其中p是素数:即,求n模p的平方根。

参考博客

exp

from Crypto.Util.number import isPrime, inverse, long_to_bytes
n = 14859096721972571275113983218934367817755893152876205380485481243331724183921836088288081702352994668073737901001999266644597320501510110156000004121260529706467596723314403262665291609405901413014268847623323618322794733633701355018297180967414569196496398340411723555826597629318524966741762029358820546567319749619243298957600716201084388836601266780686983787343862081546627427588380349419143512429889606408316907950943872684371787773262968532322073585449855893701828146080616188277162144464353498105939650706920663343245426376506714689749161228876988380824497513873436735960950355105802057279581583149036118078489
r = 145491538843334216714386412684012043545621410855800637571278502175614814648745218194962227539529331856802087217944496965842507972546292280972112841086902373612910345469921148426463042254195665018427080500677258981687116985855921771781242636077989465778056018747012467840003841693555272437071000936268768887299
a = 55964525692779548127584763434439890529728374088765597880759713360575037841170692647451851107865577004136603179246290669488558901413896713187831298964947047118465139235438896930729550228171700578741565927677764309135314910544565108363708736408337172674125506890098872891915897539306377840936658277631020650625
c = 12162333845365222333317364738458290101496436746496440837075952494841057738832092422679700884737328562151621948812616422038905426346860411550178061478808128855882459082137077477841624706988356642870940724988156263550796637806555269282505420720558849717265491643392140727605508756229066139493821648882251876933345101043468528015921111395602873356915520599085461538265894970248065772191748271175288506787110428723281590819815819036931155215189564342305674107662339977581410206210870725691314524812137801739246685784657364132180368529788767503223017329025740936590291109954677092128550252945936759891497673970553062223608
e = 65537
p = pow(a, (r+1) // 4, r)# p≡3(mod4) ===> p=pow(a,(r+1)//4,r)
if not isPrime(p):
 p = r - p
q = n//p
d = inverse(e, (p-1)*(q-1))
print(long_to_bytes(pow(c, d, n)))

你可能感兴趣的:(网络安全)