또 뭐하지

[Dreamhack] uncommon e 본문

Write-up/Crypto

[Dreamhack] uncommon e

mameul 2024. 11. 15. 21:12
728x90

풀이 

from Crypto.Util.number import getPrime, GCD, bytes_to_long

FLAG = b"DH{????????????????????????}"
FLAG = bytes_to_long(FLAG)

while True:
    p = getPrime(1024)
    q = getPrime(1024)
    N = p * q

    # e = 0x10001 
    # assert GCD((p - 1)*(q - 1), e) == 1... Oh, COME ON.. Stop generating that stupid COMMON e.
    for e1 in range(0x100, 0x10001):
        if GCD(p - 1, e1) >= 0x100: # much better!
            break

    for e2 in range(0x100, 0x10001):
        if GCD(q - 1, e2) >= 0x100: # This is nice!!
            break

    if GCD(e1, e2) == 1: # UN-UN common == common :P
        break

print(f"{N = }")
print(f"{e1 = }")
print(f"{e2 = }")

FLAG_enc1 = pow(FLAG, e1, N)
FLAG_enc2 = pow(FLAG, e2, N)

print(f"{FLAG_enc1 = }")
print(f"{FLAG_enc2 = }")

제공된 코드를 살펴보면 새로운 방식으로 공개키 e1과 e2를 설정하여 암호화를 하고 있다. 이 때, e1과 e2가 서로소 관계이기 때문에 확장 유클리드 알고리즘에 따라서 e1*d1 + e2*d2 = 1 (d1, d2는 각각 e1,e2의 역원)이라는 공식이 성립한다. 

e1*d1 + e2*d2 = 1이라는 공식을 활용하면, 복호화 과정에서 위와 같은 관계가 성립된다. e1과 e2는 output.txt 파일에서 주어져있으므로 간단히 역원을 구하는 과정을 통해서 flag를 얻을 수 있을 것이다. 

exec(open('./uncommon_e/output.txt', 'r').read())

from Crypto.Util.number import long_to_bytes, inverse

d1 = inverse(e1, e2)
d2 = -(d1*e1 - 1) // e2

m = pow(FLAG_enc1, d1, N) * pow(FLAG_enc2, d2, N) % N


res = long_to_bytes(m)
print(res)

이렇게 복호화 코드를 작성하고 실행해보면 아래와 같이 플래그를 얻을 수 있다. 

 

'Write-up > Crypto' 카테고리의 다른 글

[Dreamhack] X-Time Pad  (0) 2024.11.18
[Dreamhack] 40 Birthdays  (0) 2024.11.08
[Dreamhack] No sub please!  (1) 2024.11.08
[Dreamhack] Insecure Seed  (0) 2024.10.31
[Dreamhack] Easy Linguistics  (0) 2024.10.24