[UIUCTF 2022] crypto ASR,WringingRing

crypto-2 ASR

基本上ASR就是RSA的代称了。

原题

from secret import flag
from Crypto.Util.number import bytes_to_long, getPrime, isPrime
from math import prod

small_primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37]
def gen_prime(bits, lim = 7, sz = 64):
    while True:
        p = prod([getPrime(sz) for _ in range(bits//sz)])
        for i in range(lim):
            if isPrime(p+1):
                return p+1
            p *= small_primes[i]

p = gen_prime(512)
q = gen_prime(512)
n = p*q
phi = (p-1)*(q-1)
e = 0x10001
d = pow(e, -1, phi)

msg = bytes_to_long(flag)
ct = pow(msg, e, n)

print("e = ", e)
print("d = ", d)
print("ct = ", ct)
'''
e = 65537
d = 195285722677343056731308789302965842898515630705905989253864700147610471486140197351850817673117692460241696816114531352324651403853171392804745693538688912545296861525940847905313261324431856121426611991563634798757309882637947424059539232910352573618475579466190912888605860293465441434324139634261315613929473
ct = 212118183964533878687650903337696329626088379125296944148034924018434446792800531043981892206180946802424273758169180391641372690881250694674772100520951338387690486150086059888545223362117314871848416041394861399201900469160864641377209190150270559789319354306267000948644929585048244599181272990506465820030285
'''

这里只给了e,d,c没有给n也就没法直接用ed来分解n了。

不过p,q生成的方式比较特殊,先生成8个64位素数然后相乘,再乘以2,3,5,...(最多7个) 最后+1得到p,q

由于  e\cdot d\equiv 1(mod phi) 所以有 k*phi = e*d -1 这时候对k*phi进行分解质因数可以得到

2^12 * 3^3 * 5^3 * 7^2 * 11 * ...

后边是16个64位的素数,显然将这16个素数分两组然后再乘2,3,5,7,(11)再加1就得到p,q

from Crypto.Util.number import bytes_to_long, long_to_bytes, getPrime, isPrime

e = 65537
d = 195285722677343056731308789302965842898515630705905989253864700147610471486140197351850817673117692460241696816114531352324651403853171392804745693538688912545296861525940847905313261324431856121426611991563634798757309882637947424059539232910352573618475579466190912888605860293465441434324139634261315613929473
ct = 212118183964533878687650903337696329626088379125296944148034924018434446792800531043981892206180946802424273758169180391641372690881250694674772100520951338387690486150086059888545223362117314871848416041394861399201900469160864641377209190150270559789319354306267000948644929585048244599181272990506465820030285

k_phi = e*d -1 
k_phi = 12798440407105031908999784124548472446040018889572960817730530853573947469787170113848247037843114210766860084237698041237300679054325293570244618517445055261481120413825585349170515207419290554629935870091105933806157817778443160330590022707245776617234034051475753857980562266052844635281301139210583841390095872000

# 2^12 * 3^3 * 5^3 * 7^2 * 11 * ...
'''
P20 = 13923226921736843531
P20 = 15789155524315171763
P20 = 11157595634841645959
P20 = 16303174734043925501
P20 = 10476183267045952117
P20 = 10441209995968076929
P20 = 10357495682248249393
P20 = 11865228112172030291
P20 = 12775011866496218557
P20 = 16070004423296465647
P20 = 14695627525823270231
P20 = 13403263815706423849
P20 = 14497899396819662177
P20 = 18318015934220252801
P20 = 16755840154173074063
P20 = 17757525673663327889
'''
pa = [13923226921736843531,15789155524315171763,11157595634841645959,16303174734043925501,10476183267045952117,10441209995968076929,10357495682248249393,11865228112172030291,12775011866496218557,16070004423296465647,14695627525823270231,13403263815706423849,14497899396819662177,18318015934220252801,16755840154173074063,17757525673663327889]
#p,q分别为pa取8个再乘2,3,5,7,(11) +1得到
for i in [2,2,3,3,5,5,7,7,11]:
    k_phi //=i 

def get_pq(idx, tp,tq, np,nq):
    if np==8:
        if not isPrime(tp+1):
            return 
    if nq==8:
        if not isPrime(tq+1):
            return 
    if idx >= 16:
        print(tp+1, tq+1)
        p = tp+1 
        q = tq+1
        n = p*q 
        m = pow(ct, d, n)
        print(m)
        print(long_to_bytes(m))
        return 
    if np<8:
        get_pq(idx+1, tp*pa[idx], tq, np+1, nq)
    if nq<8:
        get_pq(idx+1, tp, tq*pa[idx], np, nq+1)


get_pq(0, 2*3*5*7, 2*3*5*7*11,0,0)

#uiuctf{bru4e_f0rc3_1s_FUn_fuN_Fun_f0r_The_whOLe_F4miLY!}

虽然有16层,但爆破题不大

crypto-3 WringingRing

这个由于没有远端只能测下程序

import sympy as sp
import random
import signal
#from secret import FLAG
FLAG = 'flag{testxxxxxx}'
secret = random.SystemRandom().randint(1, 500_000)   #19位数
print("secret:", secret)
_MAX = 10 ** (len(str(secret)) - 1)   # 10**5

# generating a polynomial
def _f(secret, minimum=3):
    coeffs = [secret] + [
        random.SystemRandom().randint(1, _MAX) for _ in range(minimum - 1)
    ]
    # print("Secret Polynomial:")
    # f_str = str(secret)
    # for i, coeff in enumerate(coeffs[1:]):
    #     f_str += " + " + str(coeff) + "*x^" + str(i + 1)
    # print(f_str)

    def f(x):
        res = 0
        for i, coeff in enumerate(coeffs):
            res += coeff * x ** (i)

        return res

    return f


def gen_shares(secret, minimum=3):
    f = _f(secret, minimum)
    shares = [(i + 1, f(i + 1)) for i in range(minimum)]
    return shares


def challenge(secret, minimum=3):
    shares = gen_shares(secret, minimum)
    print(shares)
    points = random.sample(shares, minimum - 1)
    print(points)
    points.sort()
    return points


def main():
    minimum = 10
    points = challenge(secret, minimum)

    print("[SSSS] Known shares of the secret polynomial: ")
    for point in points:
        print(f"       {point}")
    print()
    
    #signal.alarm(60)
    guess = int(input("[SSSS] Enter my secret: "))
    if guess == secret:
        print(f"[SSSS] Correct! {FLAG}")
    else:
        print("[SSSS] Incorrect...")
    
if __name__ == "__main__":
    main()

'''
Wringing Rings - 139 points
"comic book style person at a chalkboard drawing a curve"

crypto

Everyone says we should use finite fields, but I loved sharing secrets this way so much that I put a ring on it!

$ nc ring.chal.uiuc.tf 1337

author: Spamakin
'''

先成生10个数,第1个是secret这个数小于500000(500_000中间的下划线是分隔符直接去掉就行),后9个比它小一位(10进制),然后这些数作10次运算生成10个数会显示出9个。

这10次运算的\sum c*x^{i},虽然只给了9个但是影响不大,直接用z3

from z3 import *
from pwn import *
'''
context.log_level = 'debug'
p = remote("ring.chal.uiuc.tf", 1337)
p.recvuntil(b'[SSSS] Known shares of the secret polynomial:\n')
points = []

for i in range(9):
    p.append(eval(p.recvline()))

print(points)
'''
data = '''
       (1, 104137)
       (3, 73506441)
       (4, 879095644)
       (5, 6249646673)
       (6, 31430072352)
       (7, 123848462689)
       (8, 407425874756)
       (9, 1166688459129)
       (10, 2993217169048)
'''
data = data.strip().split("\n")
points = []
for v in data:
    points.append(eval(v))

print(points)

c = [Int(f'c{i}') for i in range(10)]
s = Solver()

s.add(c[0]>0)
s.add(c[0]<500000)

for i in range(1,10):
    s.add(c[i]>0)
    s.add(c[i]<100000)

for (i,n) in points:
    r = 0
    for j in range(10):
        r += c[j]*i**j
    s.add(r == n)

s.check()
d = s.model()
d = d[c[0]].as_long()
print(d)
#p.sendline(str(d).encode())

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值