2021 Chang'an Cup - College Group - crypto easyrsa WP

Keywords: Python CTF


The game was terrible. After all, it was too bad for me. No password was given. esayrsa was not easy at all. This problem was given an hour and a half after the game.

1, Title

from Crypto.Util.number import *

def add(a,b):
    if(a<b):
        a0 = str(b).encode()
        b0 = str(a).encode()
    else:
        a0 = str(a).encode()
        b0 = str(b).encode()
    ans = 0
    for i in range(len(a0)-len(b0)):
        ans = ans*10+a0[i]-48
    for i in range(len(b0)):
        ans = ans*10+(a0[i+len(a0)-len(b0)]+b0[i]+4)%10
    return ans

def mul(a,b):
    if(a<b):
        a0 = str(b).encode()
        b0 = str(a).encode()
    else:
        a0 = str(a).encode()
        b0 = str(b).encode()
    ans = 0
    for i in range(len(b0)):
        ans = ans*10+((a0[i+len(a0)-len(b0)]+2)*(b0[i]+2))%10
    return ans

m = bytes_to_long(flag)
e = 65537
p = getPrime(512)
q = getPrime(512)
n = p*q
c = pow(m,e,n)
print(add(p,q))
print(mul(p,q))
print(n)
print(c)
''' 10399034381787849923326924881454040531711492204619924608227265350044149907274051734345037676383421545973249148286183660679683016947030357640361405556516408
6004903250672248020273453078045186428048881010508070095760634049430058892705564009054400328070528434060550830050010084328522605000400260581038846465000861
100457237809578238448997689590363740025639066957321554834356116114019566855447194466985968666777662995007348443263561295712530012665535942780881309520544097928921920784417859632308854225762469971326925931642031846400402355926637518199130760304347996335637140724757568332604740023000379088112644537238901495181
49042009464540753864186870038605696433949255281829439530955555557471951265762643642510403828448619593655860548966001304965902133517879714352191832895783859451396658166132732818620715968231113019681486494621363269268257297512939412717227009564539512793374347236183475339558666141579267673676878540943373877937
'''

2, Analysis

1.add() function

The function of add() is to add a and b without carry. It should be regarded as semi addition

I know everything~

2.mul() function

The function of mul() is similar to that of add(). The corresponding two digits are multiplied but not carried

Well, I know everything!

3. Problem solving ideas

In fact, this question is similar to the XOR question of the previous Zhonghai university competition and the fifth space.

The XOR problem tells us p^q, and then violent search, relying on n to verify.

The same is true for this problem. We know that add and mul can decompose the possible numbers in each bit, and then multiply them by n.

Then I took the script of the XOR problem and changed it.

I. decomposition

Find satisfaction in 0 ~ 9 ( x + y ) % 10 = = a (x+y)\%10==a (x+y)%10==a, ( x ∗ y ) % 10 = = b (x*y)\%10==b (x * y)%10==b (x,y)

II. Verification

Add X and y to (p,q), multiply p and Q, and judge p ∗ q p*q Whether the low order of p * q is equal to the low order of n (the low order length is the length of p or q)

If equal, then p and Q are possible values.

Why is this verification? I understand, but I don't understand. It's still too delicious after all

III. storage

Create a list pq0 to save all possible (p,q) in the current step

3, Problem solution

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

a = 10399034381787849923326924881454040531711492204619924608227265350044149907274051734345037676383421545973249148286183660679683016947030357640361405556516408
b = 6004903250672248020273453078045186428048881010508070095760634049430058892705564009054400328070528434060550830050010084328522605000400260581038846465000861
n = 100457237809578238448997689590363740025639066957321554834356116114019566855447194466985968666777662995007348443263561295712530012665535942780881309520544097928921920784417859632308854225762469971326925931642031846400402355926637518199130760304347996335637140724757568332604740023000379088112644537238901495181
c = 49042009464540753864186870038605696433949255281829439530955555557471951265762643642510403828448619593655860548966001304965902133517879714352191832895783859451396658166132732818620715968231113019681486494621363269268257297512939412717227009564539512793374347236183475339558666141579267673676878540943373877937

def adddddddd(k, p0, q0):
    if (p0 * q0) % (10 ** (k + 1)) == n % (10 ** (k + 1)):
        pq0.append((p0, q0))

a0 = str(a)
b0 = str(b)
pq0 = [(0, 0)]
for k in range(len(b0)):
    pq, pq0 = pq0, [(0, 0)]
    for i in range(10):
        for j in range(10):
            if (i + j) % 10 == int(a0[-k - 1]) and (i * j) % 10 == int(b0[-k - 1]):
                for (p, q) in pq:
                    p = (p + i * 10 ** k)
                    q = (q + j * 10 ** k)
                    adddddddd(k, p, q)
#print(pq0)
p = int('1' + str(pq0[1][0]))
q = pq0[1][1]
#p=12092931636613623040737253079065768977037831274116990695362696899634198318309588587556607732878944639910799730236593646983127255905400637167879667181506829
#q=8307103755174226983699771812499382664784661030503034013965679561410051699975573257899430944515587916063550418050690024796566861042630720583592848475010689
#print(isPrime(p))
phi = (p - 1) * (q - 1)
d = inverse(65537, phi)
print(long_to_bytes(pow(c, d, n)))

I think the most classic thing in exp is

pq, pq0 = pq0, [(0, 0)]

This thing is true. Unexpectedly, put all the possibilities into pq0, then copy pq0 into PQ for the next step, and reset pq0 to store all the new possibilities.

4, Summary

I thought of a method for this problem, but I couldn't realize it. I got stuck in backtracking, but I don't need backtracking( 🤡 It's actually me). It's too delicious. I've read other people's ready-made scripts and need to work harder.

Posted by mverrier on Tue, 28 Sep 2021 13:17:07 -0700