zer0ptsCTF 2023

easy_factoring

参考CCTF2022的SOT,先分解再调用sagemath的two_squares打即可。

from Crypto.Util.number import *
from pwn import *
def sot(s):
    ps = factor(s)
    n,n0 = [(1,1)], []
    for i in range(1, len(ps)):
        for k in range(ps[i][1]):
            for j in n:
                a, b = j
                c, d = two_squares(ps[i][0])
                if (a * c + b * d, a * d - b * c) not in n0:
                    n0.append((a * c + b * d, a * d - b * c))
                d, c = two_squares(ps[i][0])
                if (a * c + b * d, a * d - b * c) not in n0:
                    n0.append((a * c + b * d, a * d - b * c))
            n,n0=n0,[]
    for p,q in n:
        if isPrime(p) and isPrime(q):
            return p ,q

io = remote('crypto.2023.zer0pts.com',10333)
io.recvuntil(b'N:')
N = int(io.recvline()[:-1])
p,q = sot(N)
print(p,q)
io.sendlineafter(b'p: ',str(p).encode())
io.sendlineafter(b'q: ',str(q).encode())
io.interactive()

但更好的算法是在高斯整环对N进行分解,参考博客

p = random_prime(1 << 128)
q = random_prime(1 << 128)
n = p * q
N = pow(p, 2) + pow(q, 2)
zn = ZZ[i](N)
for d in divisors(ZZ[i](N)):
    pp, qq = map(int, d)
    if is_prime(pp) and is_prime(qq):
        print("yes", pp, qq)

SquareRNG

exp非常简单,但思路很有意思:

from pwn import *
context(log_level = "debug")
io = remote("crypto.2023.zer0pts.com", 10666)

io.sendlineafter("Bob's seed 1: ", '-1')
io.sendlineafter("Bob's seed 2: ", '1')


for round in range(77):
    io.recvuntil("Random 1: ")
    s1 = int(bin(int(io.recvline(), 16))[2:].rjust(32, '0')[0])
    io.recvuntil("Random 2: ")
    s2 = int(bin(int(io.recvline(), 16))[2:].rjust(32, '0')[-1])
    if s1 == s2:
        io.sendlineafter("Guess next bool [0 or 1]: ", '1')
    else:
        io.sendlineafter("Guess next bool [0 or 1]: ", '0')

io.interactive()

首先选取sb1=-1,sb2=1,r1 = SquareRNG(p, sa, sb1),r2 = SquareRNG(p, sa, sb2)。r1.int(32)的第一个比特为x=isSquare(1-sa),r2.int(32)的最后一个比特为y=isSquare(1+sa+sa^2+...+sa^32),而\(\small r1.bool() = sa^{33}-1=(sa-1)(1+sa+sa^2+...+sa^{32})\)。有一个前提条件为若p是4k+1形式的素数,那么1-sa和sa-1同为二次剩余或非剩余,那么要猜的值就是x==y。当p是4k+3形式的素数,1-sa和sa-1的二次剩余性质相反。要猜的值为x=-y

Elliptic Ring RSA

主要就是做个和商环的同构:

image

from sage.all import *

p = 211
a = 201
b = 102
e = 13
Fp = GF(p)
E = EllipticCurve(Fp, [a, b])

C = '182*(91, 45) + 147*(3, 164) + 85*(62, 60) + 53*(77, 59) + 99*(77, 152) + 18*(137, 59) + 106*(169, 101) + 147*(127, 127) + 154*(152, 163) + 121*(43, 73) + 155*(110, 160) + 202*(116, 45) + 195*(1, 84) + 106*(71, 162) + 33*(209, 122) + 112*(134, 164) + 186*(1, 127) + 72*(183, 116) + 141*(141, 39) + 72*(83, 127) + 157*(197, 175) + 6*(178, 24) + 106*(71, 49) + 114*(57, 201) + 95*(181, 58) + 1*(174, 44) + 193*(202, 27) + 182*(121, 95) + 52*(167, 179) + 109*(184, 177) + 110*(21, 162) + 101*(126, 170) + 208*(47, 102) + 168*(129, 105) + 209*(179, 123) + 210*(160, 70) + 10*(13, 103) + 159*(76, 55) + 165*(31, 26) + 31*(44, 119) + 47*(6, 70) + 150*(74, 47) + 117*(30, 65) + 3*(108, 69) + 61*(43, 138) + 151*(72, 209) + 122*(110, 51) + 127*(44, 92) + 64*(191, 113) + 61*(45, 70) + 155*(91, 166) + 175*(95, 194) + 97*(21, 49) + 210*(66, 191) + 129*(129, 106) + 210*(80, 7) + 157*(174, 167) + 45*(141, 172) + 189*(155, 78) + 160*(194, 1) + 209*(82, 28) + 142*(164, 136) + 135*(199, 155) + 166*(118, 95) + 100*(123, 14) + 203*(121, 116) + 22*(36, 20) + 33*(65, 58) + 196*(189, 60) + 75*(137, 152) + 22*(125, 4) + 45*(119, 162) + 59*(47, 109) + 102*(177, 157) + 196*(109, 20) + 112*(192, 94) + 97*(209, 89) + 67*(95, 17) + 129*(75, 55) + 34*(134, 47) + 156*(60, 156) + 135*(127, 84) + 11*(148, 147) + 194*(202, 184) + 27*(45, 141) + 131*(4, 166) + 166*(148, 64) + 183*(164, 75) + 177*(130, 145) + 128*(107, 8) + 204*(156, 40) + 131*(17, 25) + 99*(177, 54) + 122*(82, 183) + 52*(178, 187) + 130*(168, 19) + 14*(150, 150) + 173*(167, 32) + 82*(184, 34) + 172*(72, 2) + 144*(169, 110) + 7*(118, 116) + 96*(181, 153) + 34*(133, 5) + 97*(207, 17) + 24*(78, 161) + 54*(57, 10) + 90*(143, 188) + 172*(130, 66) + 179*(146, 65) + 38*(55, 202) + 170*(63, 31) + 99*(35, 65) + 162*(150, 61) + 56*(74, 164) + 146*(144, 85) + 196*(133, 206) + 164*(152, 48) + 139*(176, 153) + 92*(125, 207) + 124*(31, 185) + 136*(0, 1) + 118*(107, 203) + 28*(24, 56) + 66*(171, 151) + 127*(76, 156) + 63*(208, 59) + 187*(146, 146) + 138*(85, 0) + 195*(19, 190) + 115*(60, 55) + 87*(171, 60) + 194*(17, 186) + 79*(75, 156) + 181*(27, 37) + 38*(192, 117) + 168*(13, 108) + 41*(143, 23) + 167*(199, 56) + 177*(86, 71) + 160*(35, 146) + 165*(189, 151) + 130*(32, 30) + 39*(108, 142) + 197*(36, 191) + 176*(120, 17) + 180*(194, 210) + 204*(19, 21) + 160*(6, 141) + 195*(109, 191) + 194*(155, 133) + 62*(65, 153) + 6*(138, 107) + 12*(201, 62) + 43*(180, 43) + 178*(208, 152) + 86*(180, 168) + 135*(55, 9) + 5*(138, 104) + 118*(207, 194) + 58*(160, 141) + 173*(66, 20) + 16*(179, 88) + 181*(61, 131) + 3*(80, 204) + 137*(119, 49) + 106*(126, 41) + 127*(176, 58) + 64*(144, 126) + 96*(30, 146) + 165*(168, 192) + 104*(27, 174) + 64*(63, 180) + 35*(123, 197) + 111*(86, 140) + 141*(197, 36) + 83*(116, 166) + 159*(4, 45) + 165*(62, 151) + 94*(183, 95) + 133*(3, 47) + 58*(83, 84) + 149*(201, 149) + 96*(20, 112) + 141*(191, 98) + 113*(24, 155) + 139*(61, 80) + 73*(120, 194) + 116*(78, 50) + 68*(156, 171) + 31*(32, 181)'
C = C.split(' + ')
coe = []
base = []


for _ in C:
    two = _.split('*')
    if two[1] != '(0, 1)':
        coe.append(int(two[0]))
        base.append(E(eval(two[1])))
    else:
        coe.append(int(two[0]))
        base.append(E(0))
        
poly = dict()
for coef, pt in zip(coe, base):
    poly[pt] = Fp(coef)
    
o = E.order()
print('order:',o)
G = E.gens()[0]
PR.<x> = PolynomialRing(Fp)
PR = PR.quotient(x^192-1)

f = 0
for _ in range(192):
    try:
        f += poly[_*G]*x^_
    except:
        pass

f = PR(f)
fi = (p^o - 1)//13

d = inverse_mod(13, fi)
m = list(f^d)

t = {}
for _ in range(len(m)):
    t[_*G] = m[_]
    
gg = [_*G for _ in range(192)]
print(gg)
gg = sorted(gg)
print(gg)
for i in gg:
    print(chr(t[i]), end='')

moduhash && Unlimited Braid Works

两个题目都是偏代数的考点,参考官方wpMaple学习思路即可。

posted @ 2023-07-19 22:02  ZimaB1ue  阅读(208)  评论(0编辑  收藏  举报