2024 强网杯 Crypto wp
1770980518794052 发表于 浙江 CTF 436浏览 · 2024-11-03 14:29

EasyRSA

题目

#encoding:utf-8
from Crypto.Util.number import long_to_bytes, bytes_to_long, getPrime
import random, gmpy2

class RSAEncryptor:
    def __init__(self):
        self.g = self.a = self.b = 0
        self.e = 65537
        self.factorGen()
        self.product()

    def factorGen(self):
        while True:
            self.g = getPrime(500)
            while not gmpy2.is_prime(2*self.g*self.a+1):
                self.a = random.randint(2**523, 2**524)
            while not gmpy2.is_prime(2*self.g*self.b+1):
                self.b = random.randint(2**523, 2**524)
            self.h = 2*self.g*self.a*self.b+self.a+self.b
            if gmpy2.is_prime(self.h):
                self.N = 2*self.h*self.g+1
                print(len(bin(self.N)))
                return

    def encrypt(self, msg):
        return gmpy2.powmod(msg, self.e, self.N)


    def product(self):
        with open('/flag', 'rb') as f:
            self.flag = f.read()
        self.enc = self.encrypt(self.flag)
        self.show()
        print(f'enc={self.enc}')

    def show(self):
        print(f"N={self.N}")
        print(f"e={self.e}")
        print(f"g={self.g}")


RSAEncryptor()

题解

common prime RSA

已知g,跑脚本,发现出不来,可能是n太大了

g<a+b l论文题

WriteUps of MRCTF2021(Crypto) - Hao Jiang (d33b4t0.com)

D=iroot(right-left,2)[0]

D=left+k*D+i

爆破k,i

from Crypto.Util.number import *
from gmpy2 import iroot
n=49772654129918657265017224959299193495254216585967338739168650086191861452300412241047407950798411859067491869373788703824137456447978969803056902795716761959456067322414974169421894154465055989257454095985468450965871903811764399815267585258819854363996386931089197996828905892681960861726159749735774108745226042906570756722357743172225643921367590629441403631522125208757797647194016249362483845335014324978898865368651612654770948881872945053238350136592858869040599417498072502578977509399218927696625823452901084714222938417072759781842694565170281682723041605537728448510423962109995153717150631738378455222143
e=65537
g=2609290269584876920945282873479122171178002733919064880382724262163153884664689961266033962348331708825468959551801467334031011446564187579427413906013
enc=8746228432198832861930372453161088485197230618631505905414017869471355572344313577427383903965789443478715003718363394360186991846873876398410009152511266623674374274283784883312995156935241021352151414458858673836877962149382867511081524115963592083483210153140792701514143301995333969969720387297837376730082792179388710037042252702035179813508558042408844638147209995246943768994171598974221817596785121808048589249601097296707973010675362719565455350535238171942291239855095128733387738770119373232485878725070488565456741677674517927469025903637807463975221698069881171348847239113426711052607025112106263748508


beta = 2*g
s = (n-1)//beta
u = s//beta
v = s% beta

left = (2*int(sqrt(n))//beta-2-v)//beta
right = (3*int(sqrt(2)*sqrt(n))//(2*beta) - 2 - v )//beta
print(left)
print(right)
print(right-left)
print(iroot(right-left,2))

D = iroot(right - left , 2)[0] + 1
b = pow(2 , beta, n)
dic = {}
base = int(pow(b , left , n))
diff = int(pow(b , D , n))
for i in range(D+1):
    temp = base & 0xfffffffffff
    if temp in dic:
        print(i)
    dic[temp] = i
    base *= diff
    base %= n
print('baby step done')
base = pow(b , u , n)
diff = inverse(b , n)

for i in range(D + 1):
    temp = int(base) & 0xfffffffffff
    if temp in dic:
        print(i , dic[temp])
        c = left + dic[temp]*D + i
        xy = u - c
        x_y = v + c * beta
        temp = iroot(x_y ** 2 - 4 * xy, 2)[0]
        x = (x_y + temp) // 2
        y = (x_y - temp) // 2
        p = x * beta + 1
        q = y * beta + 1
        d = inverse(e, (p-1)*(q-1))
        print(long_to_bytes(int(pow(enc, d, n))))
    base *= diff
    base %= n

apbq

题目

I obtained several sets of ap + bq through channel measurement. Can you solve it?

from Crypto.Util.number import *
from secrets import flag
from math import ceil
import sys

class RSA():
    def __init__(self, privatekey, publickey):
        self.p, self.q, self.d = privatekey
        self.n, self.e = publickey

    def encrypt(self, plaintext):
        if isinstance(plaintext, bytes):
            plaintext = bytes_to_long(plaintext)
        ciphertext = pow(plaintext, self.e, self.n)
        return ciphertext

    def decrypt(self, ciphertext):
        if isinstance(ciphertext, bytes):
            ciphertext = bytes_to_long(ciphertext)
        plaintext = pow(ciphertext, self.d, self.n)
        return plaintext

def get_keypair(nbits, e = 65537):
    p = getPrime(nbits//2)
    q = getPrime(nbits//2)
    n = p * q
    d = inverse(e, n - p - q + 1)
    return (p, q, d), (n, e)

if __name__ == '__main__':
    pt = './output.txt'
    fout = open(pt, 'w')
    sys.stdout = fout

    block_size = ceil(len(flag)/3)
    flag = [flag[i:i+block_size] for i in range(0, len(flag), block_size)]
    e = 65537

    print(f'[+] Welcome to my apbq game')
    # stage 1
    print(f'┃ stage 1: p + q')
    prikey1, pubkey1 = get_keypair(1024)
    RSA1 = RSA(prikey1, pubkey1)
    enc1 = RSA1.encrypt(flag[0])
    print(f'┃ hints = {prikey1[0] + prikey1[1]}')
    print(f'┃ public key = {pubkey1}')
    print(f'┃ enc1 = {enc1}')
    print(f'----------------------')

    # stage 2
    print(f'┃ stage 2: ai*p + bi*q')
    prikey2, pubkey2 = get_keypair(1024)
    RSA2 = RSA(prikey2, pubkey2)
    enc2 = RSA2.encrypt(flag[1])
    kbits = 180
    a = [getRandomNBitInteger(kbits) for i in range(100)]
    b = [getRandomNBitInteger(kbits) for i in range(100)]
    c = [a[i]*prikey2[0] + b[i]*prikey2[1] for i in range(100)]
    print(f'┃ hints = {c}')
    print(f'┃ public key = {pubkey2}')
    print(f'┃ enc2 = {enc2}')
    print(f'----------------------')

    # stage 3
    print(f'┃ stage 3: a*p + q, p + bq')
    prikey3, pubkey3 = get_keypair(1024)
    RSA3 = RSA(prikey3, pubkey3)
    enc3 = RSA2.encrypt(flag[2])
    kbits = 512
    a = getRandomNBitInteger(kbits)
    b = getRandomNBitInteger(kbits)
    c1 = a*prikey3[0] + prikey3[1]
    c2 = prikey3[0] + b*prikey3[1]
    print(f'┃ hints = {c1, c2}')
    print(f'┃ public key = {pubkey3}')
    print(f'┃ enc3 = {enc3}')

题解

stage1:p+q

hints = 18978581186415161964839647137704633944599150543420658500585655372831779670338724440572792208984183863860898382564328183868786589851370156024615630835636170
public_key = (89839084450618055007900277736741312641844770591346432583302975236097465068572445589385798822593889266430563039645335037061240101688433078717811590377686465973797658355984717210228739793741484666628342039127345855467748247485016133560729063901396973783754780048949709195334690395217112330585431653872523325589, 65537)
enc1 = 23664702267463524872340419776983638860234156620934868573173546937679196743146691156369928738109129704387312263842088573122121751421709842579634121187349747424486233111885687289480494785285701709040663052248336541918235910988178207506008430080621354232140617853327942136965075461701008744432418773880574136247
n, e = public_key
# p*(hints-p) = n
from gmpy2 import iroot
from Crypto.Util.number import *

de = hints**2 - 4*n
p = (hints + iroot(de, 2)[0]) // 2
q = n // p
print(long_to_bytes(pow(enc1, inverse(e, (p-1)*(q-1)), n)))
# b'flag{yOu_can_'

stage2: aip + biq

c = [a[i]*prikey2[0] + b[i]*prikey2[1]

hints = 
n,e = (73566307488763122580179867626252642940955298748752818919017828624963832700766915409125057515624347299603944790342215380220728964393071261454143348878369192979087090394858108255421841966688982884778999786076287493231499536762158941790933738200959195185310223268630105090119593363464568858268074382723204344819, 65537)
enc2 = 30332590230153809507216298771130058954523332140754441956121305005101434036857592445870499808003492282406658682811671092885592290410570348283122359319554197485624784590315564056341976355615543224373344781813890901916269854242660708815123152440620383035798542275833361820196294814385622613621016771854846491244

import itertools
from Crypto.Util.number import long_to_bytes

V = hints
k = 2^800
M = Matrix.column([k * v for v in V]).augment(Matrix.identity(len(V)))
B = [b[1:] for b in M.LLL()]
M = (k * Matrix(B[:len(V)-2])).T.augment(Matrix.identity(len(V)))
B = [b[-len(V):] for b in M.LLL() if set(b[:len(V)-2]) == {0}]

for s, t in itertools.product(range(4), repeat=2):
    T = s*B[0] + t*B[1]
    a1, a2, a3 = T[:3]
    kq = gcd(a1 * hints[1] - a2 * hints[0], n)
    if 1 < kq < n:
        print('find!', kq, s, t)
        break

p = 9067773077510925207378520309595658022345214442920360440202890774224295250116442048990578009377300541280465330975931465993745130297479191298485033569345231
q = n // p
print(long_to_bytes(pow(enc2, inverse(e, (p-1)*(q-1)),n)))
b's0lve_the_@pb'

stage3

第三部分他是用的第二部分的rsa进行加密的

enc3 = 17737974772490835017139672507261082238806983528533357501033270577311227414618940490226102450232473366793815933753927943027643033829459416623683596533955075569578787574561297243060958714055785089716571943663350360324047532058597960949979894090400134473940587235634842078030727691627400903239810993936770281755
print(long_to_bytes(pow(enc3, inverse(e, (p-1)*(q-1)),n)))
b'q_prob1em!!}'

21 step

题目

import re
import random
from secrets import flag
print(f'Can you weight a 128 bits number in 21 steps')
pattern = r'([AB]|\d+)=([AB]|\d+)(\+|\-|\*|//|<<|>>|&|\^|%)([AB]|\d+)'

command = input().strip()
assert command[-1] == ';'
assert all([re.fullmatch(pattern, i) for i in command[:-1].split(';')])

step = 21
for i in command[:-1].split(';'):
    t = i.translate(str.maketrans('', '', '=AB0123456789'))
    if t in ['>>', '<<', '+', '-', '&', '^']:
        step -= 1
    elif t in ['*', '/', '%']:
        step -= 3
if step < 0:exit()

success = 0
w = lambda x: sum([int(i) for i in list(bin(x)[2:])])
for _ in range(100):
    A = random.randrange(0, 2**128)
    wa = w(A)
    B = 0
    try : exec("global A; global B;" + command)
    except : exit()
    if A == wa:
        success += 1

if success == 100:
    print(flag)

题解

题目要求我们用21步求出128比特随机数的汉明重量。

找到variable-precision SWAR算法,让AI写一个128比特的实现代码。

def variable_precision_swar(A):
    # Step 1: Initialize the counter
    B = 0

    # Step 2: Parallel calculation of 4-bit Hamming weights
    A = (A & 0x55555555555555555555555555555555) + ((A >> 1) & 0x55555555555555555555555555555555)
    A = (A & 0x33333333333333333333333333333333) + ((A >> 2) & 0x33333333333333333333333333333333)

    # Step 3: Combine intermediate results
    A = (A + (A >> 4)) & 0x0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F
    A = (A + (A >> 8)) & 0x00FF00FF00FF00FF00FF00FF00FF00FF
    A = (A + (A >> 16)) & 0x0000FFFF0000FFFF0000FFFF0000FFFF
    A = (A + (A >> 32)) & 0x00000000FFFFFFFF00000000FFFFFFFF
    A = (A + (A >> 64)) & 0x0000000000000000FFFFFFFFFFFFFFFF

    # Step 4: Extract the final result
    B = A & 0x7F  # The result is in the lower 7 bits

    return B

# Test the function
import random

def test_variable_precision_swar():
    for _ in range(100):
        A = random.randrange(0, 2**128)
        expected = bin(A).count('1')
        result = variable_precision_swar(A)
        if result != expected:
            print(f"Failed for {A}: expected {expected}, got {result}")
            return False
    print("All tests passed!")
    return True

test_variable_precision_swar()

按上面代码改写成符合要求的表示是,每一行需要4步,一共七步,完全不够用。

经过尝试以后发现,以下这几步中,最后&0x??????????????????????,这一操作可以忽略, 并不影响结果,只需要最后&0x7f即可。这样以下运算只需要10+1步。

# Step 3: Combine intermediate results
A = (A + (A >> 4)) & 0x0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F
A = (A + (A >> 8)) & 0x00FF00FF00FF00FF00FF00FF00FF00FF
A = (A + (A >> 16)) & 0x0000FFFF0000FFFF0000FFFF0000FFFF
A = (A + (A >> 32)) & 0x00000000FFFFFFFF00000000FFFFFFFF
A = (A + (A >> 64)) & 0x0000000000000000FFFFFFFFFFFFFFFF

转换一下

B=A>>1;B=B&113427455640312821154458202477256070485;A=A&113427455640312821154458202477256070485;A=A+B;B=A>>2;B=B&68056473384187692692674921486353642291;A=A&68056473384187692692674921486353642291;A=A+B;B=A>>4;A=A+B;A=A&20016609818878733144904388672456953615;B=A>>8;A=A+B;B=A>>16;A=A+B;B=A>>32;A=A+B;B=A>>64;A=A+B;A=A&127;

0 条评论
某人
表情
可输入 255

没有评论