NewStarCTF Crypto

Week1

除了那个babyencoding第三个没看出uuencode外其余都没什么问题
这里只写非简单题

Vigenère

这里有个注意点 解密语言要选西班牙语(好像是) 反正要试一试就行了

babyencoding

前两个用 cyberchef秒解 第三个是uuencode 用https://ctf.bugku.com/tool/uuencode

Small d

维纳攻击 脚本:

点击查看代码
# 维纳攻击
import gmpy2
import primefac
from Crypto.Util.number import *

def transform(x,y):       #使用辗转相处将分数 x/y 转为连分数的形式
    res=[]
    while y:
        res.append(x//y)
        x,y=y,x%y
    return res
    
def continued_fraction(sub_res):
    numerator,denominator=1,0
    for i in sub_res[::-1]:      #从sublist的后面往前循环
        denominator,numerator=numerator,i*numerator+denominator
    return denominator,numerator   #得到渐进分数的分母和分子,并返回

    
#求解每个渐进分数
def sub_fraction(x,y):
    res=transform(x,y)
    res=list(map(continued_fraction,(res[0:i] for i in range(1,len(res)))))  #将连分数的结果逐一截取以求渐进分数
    return res

def get_pq(a,b,c):      #由p+q和pq的值通过维达定理来求解p和q
    par=gmpy2.isqrt(b*b-4*a*c)   #由上述可得,开根号一定是整数,因为有解
    x1,x2=(-b+par)//(2*a),(-b-par)//(2*a)
    return x1,x2

def wienerAttack(e,n):
    for (d,k) in sub_fraction(e,n):  #用一个for循环来注意试探e/n的连续函数的渐进分数,直到找到一个满足条件的渐进分数
        if k==0:                     #可能会出现连分数的第一个为0的情况,排除
            continue
        if (e*d-1)%k!=0:             #ed=1 (mod φ(n)) 因此如果找到了d的话,(ed-1)会整除φ(n),也就是存在k使得(e*d-1)//k=φ(n)
            continue
        
        phi=(e*d-1)//k               #这个结果就是 φ(n)
        px,qy=get_pq(1,n-phi+1,n)
        if px*qy==n:
            p,q=abs(int(px)),abs(int(qy))     #可能会得到两个负数,负负得正未尝不会出现
            d=gmpy2.invert(e,(p-1)*(q-1))     #求ed=1 (mod  φ(n))的结果,也就是e关于 φ(n)的乘法逆元d
            return d
    print("该方法不适用")
    
c = 6755916696778185952300108824880341673727005249517850628424982499865744864158808968764135637141068930913626093598728925195859592078242679206690525678584698906782028671968557701271591419982370839581872779561897896707128815668722609285484978303216863236997021197576337940204757331749701872808443246927772977500576853559531421931943600185923610329322219591977644573509755483679059951426686170296018798771243136530651597181988040668586240449099412301454312937065604961224359235038190145852108473520413909014198600434679037524165523422401364208450631557380207996597981309168360160658308982745545442756884931141501387954248
e = 8614531087131806536072176126608505396485998912193090420094510792595101158240453985055053653848556325011409922394711124558383619830290017950912353027270400567568622816245822324422993074690183971093882640779808546479195604743230137113293752897968332220989640710311998150108315298333817030634179487075421403617790823560886688860928133117536724977888683732478708628314857313700596522339509581915323452695136877802816003353853220986492007970183551041303875958750496892867954477510966708935358534322867404860267180294538231734184176727805289746004999969923736528783436876728104351783351879340959568183101515294393048651825
n = 19873634983456087520110552277450497529248494581902299327237268030756398057752510103012336452522030173329321726779935832106030157682672262548076895370443461558851584951681093787821035488952691034250115440441807557595256984719995983158595843451037546929918777883675020571945533922321514120075488490479009468943286990002735169371404973284096869826357659027627815888558391520276866122370551115223282637855894202170474955274129276356625364663165723431215981184996513023372433862053624792195361271141451880123090158644095287045862204954829998614717677163841391272754122687961264723993880239407106030370047794145123292991433 
d=wienerAttack(e,n)
print("d=",d)
m = pow(c,d,n)
print("flag = ",long_to_bytes(m))

Affine

枚举key[0] key[1] 暴力求解

babyaes

脚本(修改一下即可):

点击查看代码
from Crypto.Cipher import AES
import os
import gmpy2
from Crypto.Util.number import *

def main():
    encryped_flag = b'\x8c-\xcd\xde\xa7\xe9\x7f.b\x8aKs\xf1\xba\xc75\xc4d\x13\x07\xac\xa4&\xd6\x91\xfe\xf3\x14\x10|\xf8p'
    xor = 91144196586662942563895769614300232343026691029427747065707381728622849079757
    xor_2 = long_to_bytes(xor)
    key = xor_2[:16]*2
    iv = bytes_to_long(key[16:])^bytes_to_long(xor_2[16:])
    iv = long_to_bytes(iv)
    aes = AES.new(key,AES.MODE_CBC,iv)
    flag = aes.decrypt(encryped_flag)
    print(flag)

    pass
if __name__ == '__main__':
    main()

Week2

滴啤

典型的dp泄露
原理
exp:

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

def modinv(a,n):
    return primefac.modinv(a,n) % n

e = 65537
n = 93172788492926438327710592564562854206438712390394636149385608321800134934361353794206624031396988124455847768883785503795521389178814791213054124361007887496351504099772757164211666778414800698976335767027868761735533195880182982358937211282541379697714874313863354097646233575265223978310932841461535936931
dp = 307467153394842898333761625034462907680907310539113349710634557900919735848784017007186630645110812431448648273172817619775466967145608769260573615221635
c = 52777705692327501332528487168340175436832109866218597778822262268417075157567880409483079452903528883040715097136293765188858187142103081639134055997552543213589467751037524482578093572244313928030341356359989531451789166815462417484822009937089058352982739611755717666799278271494933382716633553199739292089
for x in range(1,e):
    dpe1 = dp*e-1
    if dpe1%x == 0:
        if(primefac.isprime((dpe1//x)+1)):
            p = dpe1//x + 1
            q = n//p
            phi = (p-1)*(q-1)
            d = modinv(e,phi)
            m = pow(c,d,n)
            print(m)
            print(long_to_bytes(m))

不止一个pi

题目代码

from flag import flag
from Crypto.Util.number import *
import gmpy2
p = getPrime(1024)
q = getPrime(1024)
n = p**3*q**2
print("q = ",q)
print("p = ",p)
m = bytes_to_long(flag.encode())
c = pow(m,65537,n)
print("c = ",c)

这里只是将phi由(p-1)x(q-1)换成了(p ^ 3 - p ^ 2)x(q ^ 2 - q)罢了
exp:

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

q =  115478867870347527660680329271012852043845868401928361076102779938370270670897498759391844282137149013845956612257534640259997979275610235395706473965973203544920469416283181677660262509481282536465796731401967694683575843183509430017972506752901270887444490905891490955975762524187534052478173966117471143713
p =  171790960371317244087615913047696670778115765201883835525456016207966048658582417842936925149582378305610304505530997833147251832289276125084339614808085356814202236463900384335878760177630501950384919794386619363394169016560485152083893183420911295712446925318391793822371390439655160077212739260871923935217
c =  4459183928324369762397671605317600157512712503694330767938490496225669985050002776253470841193156951087663107866714426230222002399666306287642591077990897883174134404896800482234781531592939043551832049756571987010173667074168282355520711905659013076509353523088583347373358980842707686611157050425584598825151399870268083867269912139634929397957514376826145870752116583185351576051776627208882377413433140577461314504762388617595282085102271510792305560608934353515552201553674287954987323321512852114353266359364282603487098916608302944694600227628787791876600901537888110093703612414836676571562487005330299996908873589228072982641114844761980143047920770114535924959765518365614709272297666231481655857243004072049094078525569460293381479558148506346966064906164209362147313371962567040047084516510135054571080612077333228195608109065475260832580192321853906138811139036658485688320161530131239854003996457871663456850196483520239675981391047452381998620386899101820782421605287708727667663038905378115235163773867508258208867367314108701855709002634592329976912239956212490788262396106230191754680813790425433763427315230330459349320412354189010684525105318610102936715203529222491642807382215023468936755584632849348996666528981269240867612068382243822300418856599418223875522408986596925018975565057696218423036459144392625166761522424721268971676010427096379610266649911939139451989246194525553533699831110568146220347603627745407449761792135898110139743498767543521297525802809254842518002190381508964357001211353997061417710783337
n = p**3*q**2
e = 65537
phi = (p**3-p**2)*(q**2-q)
d = primefac.modinv(e,phi)
m = pow(c,d,n)
print(long_to_bytes(m))

halfcandecode

题目代码:

from Crypto.Util.number import *
import gmpy2
from flag import flag
import os
from hashlib import md5

def gen_prime(number):
    p = getPrime(number // 2)
    q = gmpy2.next_prime(p)
    return p * q

def md5_hash(m):
    return md5(m.encode()).hexdigest()
e = 65537
n = gen_prime(1024)
m1 = bytes_to_long(flag[:len(flag) // 2].encode() + os.urandom(8))
c1 = pow(m1, e, n)
m2 = flag[len(flag) // 2:]
with open("out.txt","w") as f:
    f.write(str(n) + '\n')
    f.write(str(c1) + '\n')
    for t in m2:
        f.write(str(md5_hash(t))+'\n')

md5的部分可以用在线网站也可以直接枚举a~z A~Z 0~9 _来算
前面的还是一个基础的RSA 最后添加的8bit随机数没有多大影响 这里就不给exp了

Rotate Xor

题目代码:

from secret import flag
from os import urandom
from pwn import xor
from Cryptodome.Util.number import *
k1 = getPrime(64)
k2 = getPrime(64)
ROUND = 12
ciphertext = xor(flag, long_to_bytes(k1))
def round_rotate_left(num, step):
    return ((num) << step | num >> (64-step)) & 0xffffffffffffffff
def encrypt_key(key):
    
    for _ in range(ROUND):
        key = round_rotate_left(key, 3) ^ k2
    
    return key
print('ciphertext =', ciphertext)
print('enc_k1 =', encrypt_key(k1))
print('k2 =', k2)

# ciphertext = b'\x8dSyy\xd2\xce\xe2\xd2\x98\x0fth\x9a\xc6\x8e\xbc\xde`zl\xc0\x85\xe0\xe4\xdfQlc'
# enc_k1 = 7318833940520128665
# k2 = 9982833494309156947

这是一个简单的类似lfsr的循环补位 直接逆着rotate_right即可
exp:

from pwn import xor
from Crypto.Util.number import *

ciphertext = b'\x8dSyy\xd2\xce\xe2\xd2\x98\x0fth\x9a\xc6\x8e\xbc\xde`zl\xc0\x85\xe0\xe4\xdfQlc'
enc_k1 = 7318833940520128665
k2 = 9982833494309156947

def round_rotate_right(num, step):
    return ((num) >> step | num << (64-step)) & 0xffffffffffffffff

for _ in range(12):
    enc_k1 ^= k2
    enc_k1 = round_rotate_right(enc_k1,3)
print(xor(long_to_bytes(enc_k1),ciphertext))
# flag{z3_s0lv3r_15_bri11i4nt}

broadcast

低加密指数广播攻击
这里更新一下以前的CRT脚本(这题好像要用十几组才行)
首先 手动nc 获取20组n,c
CRT求出m^e mod(N1N2N3...)后开e次方即可
exp:

def CRT(mi, ai):
    M = reduce(lambda x, y: x * y, mi)
    ai_ti_Mi = [a * (M // m) * gmpy2.invert(M // m, m) for (m, a) in zip(mi, ai)]
    return reduce(lambda x, y: x + y, ai_ti_Mi) % M
e = 17

n=[n0,n1,n2,n3,n4,n5,n6,n7,n8,n9,n10,n11,n12,n13,n14,n15,n16,n17,n18,n19]
c=[c0,c1,c2,c3,c4,c5,c6,c7,c8,c9,c10,c11,c12,c13,c14,c15,c16,c17,c18,c19]


m_e = CRT(n,c)
print(m_e)
m = gmpy2.iroot(m_e,e)[0]
print(m)
print(long_to_bytes(m))

最后flag:
image

partial decrypt

题目代码:

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

m = bytes_to_long(flag)
e = 65537
p = getPrime(512)
q = getPrime(512)

n = p*q 

c = pow(m,e,n)

dp = inverse(e, (p-1))
dq = inverse(e, (q-1))
m1 = pow(c,dp, p)
m2 = pow(c,dq, q)
q_inv = inverse(q, p)
h = (q_inv*(m1-m2)) % p
print('m2 =', m2)
print('h =', h)
print('q =', q)

# m2 = 4816725107096625408335954912986735584642230604517017890897348901815741632668751378729851753037917164989698483856004115922538576470127778342121497852554884
# h = 4180720137090447835816240697100630525624574275
# q = 7325294399829061614283539157853382831627804571792179477843187097003503398904074108324900986946175657737035770512213530293277111992799331251231223710406931

推一推式子
得到 c^d ≡ q*h+m2(mod p)
稍微枚举一下p(...根本不用枚举)
exp:

from Crypto.Util.number import *

m2 = 4816725107096625408335954912986735584642230604517017890897348901815741632668751378729851753037917164989698483856004115922538576470127778342121497852554884
h = 4180720137090447835816240697100630525624574275
q = 7325294399829061614283539157853382831627804571792179477843187097003503398904074108324900986946175657737035770512213530293277111992799331251231223710406931
# print(len(bin(q*h+m2)))
print(long_to_bytes(q*h+m2))

image

Week3

Rabin's RSA

题目

from Crypto.Util.number import *
from secret import flag
p = getPrime(64)
q = getPrime(64)
assert p % 4 == 3
assert q % 4 == 3

n = p * q

e = 2
m = bytes_to_long(flag)

c = pow(m,e,n)

print('n =', n)
print('c =', c)

# n = 201354090531918389422241515534761536573
# c = 20442989381348880630046435751193745753

由于e=2直接开根即可 注意要开all_roots
exp:

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

e = 2
n = 201354090531918389422241515534761536573
p = 13934102561950901579
q = n // p
c =20442989381348880630046435751193745753
ms = nthroot_mod(c,e,n,all_roots=True)
for m in ms:
    print(long_to_bytes(m))

小明的密码题

明文高位泄露攻击 cooperSmith
这里可以用sage中自带的small_roots解
在这之前还要解决一个问题 题目给的高位是一个b''我们自己写一个看看byte_to_long怎么转的

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

m = b'sm4ll_r00ts_is_brilliant#'
print(bin(bytes_to_long(m)))
m = b'sm4ll_r00ts_is_brilliant#abcdef11'
print(bin(bytes_to_long(m)))

image
发现不同的恰好是末64位
exp:

N = 131889193322687215946601811511407251196213571687093913054335139712633125177496800529685285401802802683116451016274353008428347997732857844896393358010946452397522017632024075459908859131965234835870443110233375074265933004741459359128684375786221535003839961829770182916778717973782408036072622166388614214899
e = 5
c = 11188201757361363141578235564807411583085091933389381887827791551369738717117549969067660372214366275040055647621817803877495473068767571465521881010707873686036336475554105314475193676388608812872218943728455841652208711802376453034141883236142677345880594246879967378770573385522326039206400578260353074379
m = 0b1110011011011010011010001101100011011000101111101110010001100000011000001110100011100110101111101101001011100110101111101100010011100100110100101101100011011000110100101100001011011100111010000100011
m = (m<<64)
ZmodN = Zmod(N)
P.<x> = PolynomialRing(ZmodN)
f = (m + x)^e - c
x0 = f.small_roots(X=2^64, beta=1)[0]  # 这里的X选取不像上文用的是临界值,而是选了一个我们未知的x的最大可能值。X的选取并非严格,但至少得保证比临界值小。
print("m:", m + x0)

sage秒出mimage
最后long_to_byte即可
image

knapsack

背包加密
学习
这里了解原理后用Git上的脚本修改一下即可
image
sage跑出
image
这里直接unhexfi的话由于位数是奇数 所以要枚举最后一位的情况

'''
255 [1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0]   ---   666c61677b4c6174746963655f726564756374696f6e2363333636323534317
'''
import binascii
from Crypto.Util.number import *
flag = '666c61677b4c6174746963655f726564756374696f6e2363333636323534317'
lst = '0123456789abcdef'
# flag = '415349535f3962643364356664323432323638326331393536383830366130373036316365'
# 415349535f3962643364356664323432323638326331393536383830366130373036316365
# 415349535f3962643364356664323432323638326331393536383830366130373036316365
for c in lst:
    fflag = flag + c
    print(binascii.unhexlify(fflag))

# print(long_to_bytes(flag))

image

babyrandom

推推式子
image
exp:

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

x1 = 12237514397472333652372078471141394089398703096615619384528520579893044503154
x2 = 37432408689751793777365062467818023081896697763737797195412253183472118989474
x3 = 33863903225262985844958383123415913586438827627942393693805450163840109911629
p =  64999433139797068147576269731948390094958654326970231465808792590598519729077
inv_x1 = modinv(x1,p)
inv_x2 = modinv(x2,p)
inv_x3 = modinv(x3,p)
xx = (x2*inv_x1-x3*inv_x2)%p
yy = (inv_x1-inv_x2)%p
b = (xx*modinv(yy,p))%p
print(b)
a = ((x2-b)*inv_x1)%p
print(a)
# b = 49669923087224127429737140938959417171295400860353416579940773763365163492628
# a = 64999433139797068147576269731948390094958654326970231465808792590598519729076
inv_a = modinv(a,p)
x = ((x1-b)*inv_a)%p
print(long_to_bytes(x))

ez_crt

这。。。有文献研究过链接
image
这个算法的原理找半天也找不着 就当结论记着吧
(也就是说后面给的一大堆全是无效信息。。。)
solution.py

p = GCD(pow(S_, e, n) - m, n)
q = n // p

...

Door

CBC翻转攻击
chall.py

from secret import flag
import string
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
from os import urandom
import re

key = urandom(16)

menu = '''
[+] WatchDog Security System
[+] Copyright (c) 1010 by School of Natural Philosophy 

please select your option:
1. Unlock Secret Entry
2. Help
3. Exit
'''

valid_code = [1033,3329,4431,5052]

auth_context_pattern = re.compile(r'^SoNP#[0-9]{4}$')

def auth_context_checker(ctx : bytes):
    for c in ctx:
        if chr(c) not in string.printable:
            return False
    if auth_context_pattern.match(ctx.decode()) : return True

    return False

def unlock():
    token = bytes.fromhex(input('Enter your token > '))
    auth_code = bytes.fromhex(input('Enter your authentication code > '))

    cipher = AES.new(key, AES.MODE_CBC,token)
    
    check = cipher.decrypt(auth_code)
    try:
        
        msg = unpad(check, 16)
        if auth_context_checker(msg) and int(msg[5:].decode()) in valid_code:
            print('door unlocked, here is your reward')
            print(flag)
        else:
            print('get out')

    except Exception as e:
        print('oops, something wrong')
        print(e)
def help():
    print('To unlock the door, please enter your token and authentication code.')
while True:
    print(menu)
    opt = input('> ')
    try:
        opt = int(opt)
        if opt == 1:
            unlock()
        elif opt == 2:
            help()
        elif opt == 3:
            break
        else:
            print('invalid option')
    except:
        print('oh no, something wrong!')

我们要想办法控制iv使得decrypt后得到我们想要的数据
服务端会把密文解密之后的填充状态返回, 那么我们只要控制iv, 使得解密之后的明文产生"...\x01", "...\x02\x02" ...的状态,获得明文为"\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10"对应的IV, 然后利用xor把我们想要输入的内容合并到这个IV里面。
solution.py

from pwn import *
from Crypto.Cipher import *
from Crypto.Util.Padding import *
from os import urandom
from tqdm import tqdm

r = remote('node4.buuoj.cn',28224)

auth_code = urandom(16)
token = urandom(16)

diff = [0]*16
for i in reversed(range(16)):
    for b in (range(256)):
        diff[i] = b
        tmp_tk = xor(token,bytes(diff))

        r.sendlineafter(b'> ',b'1')
        r.sendlineafter(b'> ',tmp_tk.hex().encode())
        r.sendlineafter(b'> ',auth_code.hex().encode())
        res = r.recvline()
        if b'out' in res:
            if i!=0:
                for j in range(i,16):
                    diff[j] = diff[j] ^ (16-i) ^ (16-i+1)
            break

forged_token = xor(token,bytes(diff))
forged_token = xor(forged_token,b'\x10'*16)
forged_token = xor(forged_token,pad(b'SoNP#3329',16))

r.sendlineafter(b'> ',b'1')
r.sendlineafter(b'> ', forged_token.hex().encode())
r.sendlineafter(b'> ', auth_code.hex().encode())

r.interactive()

image

Week5

School of CRC32

chall.py

import secrets
from secret import flag
import zlib

ROUND = 100

LENGTH = 20

print('Extreme hard CRC32 challenge')
print('ARE YOU READY')

for i in range(ROUND):
    print('ROUND', i, '!'*int(i/75 + 1))

    target = secrets.randbits(32)

    print('Here is my CRC32 value: ', hex(target))

    dat = input('Show me some data > ')
    raw = bytes.fromhex(dat)

    if zlib.crc32(raw) == target and len(raw) == LENGTH:
        print("GREAT")
    else:
        print("OH NO")
        exit()

print("Congratulation! Here is your flag")
print(flag)

这里直接运用crcsolver求解
有几个注意点 :

  • 对题目所给target的数据提取
  • crcsolver得到后要填充为40位hex (这样转成byte才是20位)

solution.py

from pwn import *
import secrets
import zlib
import crcsolver
from libnum import *

p = remote("node4.buuoj.cn",29670)
ROUND = 100
LENGTH = 20

for i in range(ROUND):
    p.recvuntil('Here is my CRC32 value: ')
    target = (p.recvline())
    # print(target)
    target = eval(target)
    m = crcsolver.solve(b'_'*LENGTH, range(8*20), target, zlib.crc32)
    # print(hex(s2n(m))[2:])
    # print(len(bytes.fromhex(hex(s2n(m))[2:])))
    msg = hex(s2n(m))[2:].zfill(40)
    p.sendlineafter('data >',msg)

p.interactive()

last_signin

chall.py

from Crypto.Util.number import *
flag = b'?'

e = 65537
p, q = getPrime(1024), getPrime(1024)
N = p * q
gift = p&(2**923-2**101)
m = bytes_to_long(flag)
c = pow(m, e, N)

print("N = ",N)
print("gift = ",gift)
print("c = ",c)

"""
N =  12055968471523053394851394038007091122809367392467691213651520944038861796011063965460456285088011754895260428814358599592032865236006733879843493164411907032292051539754520574395252298997379020268868972160297893871261713263196092380416876697472160104980015554834798949155917292189278888914003846758687215559958506116359394743135211950575060201887025032694825084104792059271584351889134811543088404952977137809673880602946974798597506721906751835019855063462460686036567578835477249909061675845157443679947730585880392110482301750827802213877643649659069945187353987713717145709188790427572582689339643628659515017749
p0 =  70561167908564543355630347620333350122607189772353278860674786406663564556557177660954135010748189302104288155939269204559421198595262277064601483770331017282701354382190472661583444774920297367889959312517009682740631673940840597651219956142053575328811350770919852725338374144
c =  2475592349689790551418951263467994503430959303317734266333382586608208775837696436139830443942890900333873206031844146782184712381952753718848109663188245101226538043101790881285270927795075893680615586053680077455901334861085349972222680322067952811365366282026756737185263105621695146050695385626656638309577087933457566501579308954739543321367741463532413790712419879733217017821099916866490928476372772542254929459218259301608413811969763001504245717637231198848196348656878611788843380115493744125520080930068318479606464623896240289381601711908759450672519228864487153103141218567551083147171385920693325876018
"""

以前p的高位泄露都是告诉了高位或低位 而这题给的是中间位
参考 https://www.anquanke.com/post/id/193939#h3-28
solution.py

N =  12055968471523053394851394038007091122809367392467691213651520944038861796011063965460456285088011754895260428814358599592032865236006733879843493164411907032292051539754520574395252298997379020268868972160297893871261713263196092380416876697472160104980015554834798949155917292189278888914003846758687215559958506116359394743135211950575060201887025032694825084104792059271584351889134811543088404952977137809673880602946974798597506721906751835019855063462460686036567578835477249909061675845157443679947730585880392110482301750827802213877643649659069945187353987713717145709188790427572582689339643628659515017749
p0 =  70561167908564543355630347620333350122607189772353278860674786406663564556557177660954135010748189302104288155939269204559421198595262277064601483770331017282701354382190472661583444774920297367889959312517009682740631673940840597651219956142053575328811350770919852725338374144
c =  2475592349689790551418951263467994503430959303317734266333382586608208775837696436139830443942890900333873206031844146782184712381952753718848109663188245101226538043101790881285270927795075893680615586053680077455901334861085349972222680322067952811365366282026756737185263105621695146050695385626656638309577087933457566501579308954739543321367741463532413790712419879733217017821099916866490928476372772542254929459218259301608413811969763001504245717637231198848196348656878611788843380115493744125520080930068318479606464623896240289381601711908759450672519228864487153103141218567551083147171385920693325876018

PR = PolynomialRing(Zmod(N), names='x,y')
x, y = PR.gens()

def bivariate(pol, XX, YY, kk=4):
    N = pol.parent().characteristic()

    f = pol.change_ring(ZZ)
    PR, (x, y) = f.parent().objgens()

    idx = [(k - i, i) for k in range(kk + 1) for i in range(k + 1)]
    monomials = list(map(lambda t: PR(x ** t[0] * y ** t[1]), idx))
    # collect the shift-polynomials
    g = []
    for h, i in idx:
        if h == 0:
            g.append(y ** h * x ** i * N)
        else:
            g.append(y ** (h - 1) * x ** i * f)

    # construct lattice basis
    M = Matrix(ZZ, len(g))
    for row in range(M.nrows()):
        for col in range(M.ncols()):
            h, i = idx[col]
            M[row, col] = g[row][h, i] * XX ** h * YY ** i

    # LLL
    B = M.LLL()

    PX = PolynomialRing(ZZ, 'xs')
    xs = PX.gen()
    PY = PolynomialRing(ZZ, 'ys')
    ys = PY.gen()

    # Transform LLL-reduced vectors to polynomials
    H = [(i, PR(0)) for i in range(B.nrows())]
    H = dict(H)
    for i in range(B.nrows()):
        for j in range(B.ncols()):
            H[i] += PR((monomials[j] * B[i, j]) / monomials[j](XX, YY))

    # Find the root
    poly1 = H[0].resultant(H[1], y).subs(x=xs)
    poly2 = H[0].resultant(H[2], y).subs(x=xs)
    poly = gcd(poly1, poly2)
    x_root = poly.roots()[0][0]

    poly1 = H[0].resultant(H[1], x).subs(y=ys)
    poly2 = H[0].resultant(H[2], x).subs(y=ys)
    poly = gcd(poly1, poly2)
    y_root = poly.roots()[0][0]

    return x_root, y_root


pol = 2 ** 923 * x + y + p0

x, y = bivariate(pol, 2 ** 101, 2 ** 101)
p = 2 ** 923 * x + y + p0
q = N // p
print(p,q,sep='   ,   ')
# from Crypto.Util.number import *
# from primefac import *

# p,q = 128316995030969915324601380638393686940451314028029847288048482890311391444850912731036515693294185876094548175445535907681477441597112946116144447110741965169166242532652418536974280062421433117597771884350348782061336417186073214602745554392782563801452571827824278044551188124531752043347553290530270395447          ,            93954572959047928343011750832384121004425708514797352779274995744988621009506935222019019171047965401245311260375453924225343494879356560534244565490966730992944825873075214193169703861204568164588812686254102717072093288624081316906954278209584119401170082334613277995260895181460040974631476760070669352467
# e = 65537
# d = modinv(e,(p-1)*(q-1))
# print(long_to_bytes(pow(c,d,N)))
posted @ 2023-11-27 11:43  N0zoM1z0  阅读(115)  评论(0编辑  收藏  举报