워게임/CryptoHack
[CryptoHack] DIFFIE-HELLMAN (Script Kiddie)
- -
Script Kiddie
문제
저는 Github에서 이 멋진 스크립트를 찾았고, 학교 Wi-Fi를 돌면서 듣고 있는 누구에게도 내 비밀을 지키기 위해 사용하고 있습니다! |
풀이
더보기
from Crypto.Cipher import AES
import hashlib
import secrets
def header():
print(""" _____ _ __ __ _
| __ \(_)/ _|/ _(_)
| | | |_| |_| |_ _ ___
| | | | | _| _| |/ _ \
| |__| | | | | | | | __/
|_____/|_|_| |_| |_|\___|
| | | | | | |
| |__| | ___| | |_ __ ___ __ _ _ __
| __ |/ _ \ | | '_ ` _ \ / _` | '_ \
| | | | __/ | | | | | | | (_| | | | |
|_| |_|\___|_|_|_| |_| |_|\__,_|_| |_|
""")
def is_pkcs7_padded(message):
padding = message[-message[-1]:]
return all(padding[i] == len(padding) for i in range(0, len(padding)))
def pkcs7_unpad(message, block_size=16):
if len(message) == 0:
raise Exception("The input data must contain at least one byte")
if not is_pkcs7_padded(message):
return message
padding_len = message[-1]
return message[:-padding_len]
def decrypt_flag(shared_secret: int, iv: str, ciphertext: str):
# Derive AES key from shared secret
sha1 = hashlib.sha1()
sha1.update(str(shared_secret).encode('ascii'))
key = sha1.digest()[:16]
# Decrypt flag
ciphertext = bytes.fromhex(ciphertext)
iv = bytes.fromhex(iv)
cipher = AES.new(key, AES.MODE_CBC, iv)
plaintext = cipher.decrypt(ciphertext)
return pkcs7_unpad(plaintext).decode('ascii')
def generate_public_int(g, a, p):
return g ^ a % p
def generate_shared_secret(A, b, p):
return A ^ b % p
def goodbye():
print('Goodbye!')
def main():
header()
print('[-] Collecting data from Alice')
p = int(input('> p: '))
q = (p - 1) // 2
g = int(input('> g: '))
A = int(input('> A: '))
print('[+] All data collected from Alice')
print('[+] Generating public integer for alice')
b = secrets.randbelow(q)
B = generate_public_int(g, b, p)
print(f'[+] Please send the public integer to Alice: {B}')
print('')
input('[+] Press any key to continue')
print('')
print('[+] Generating shared secret')
shared_secret = generate_shared_secret(A, b, p)
query = input('Would you like to decrypt a message? (y/n)\n')
if query == 'y':
iv = input('[-] Please enter iv (hex string)\n')
ciphertext = input('[-] Please enter ciphertext (hex string)\n')
flag = decrypt_flag(shared_secret, iv, ciphertext)
print(f'[+] Flag recovered: {flag}')
goodbye()
else:
goodbye()
if __name__ == '__main__':
main()
문제에서 제공해준 코드를 보게 되면
패딩과 언패딩, 플래그값을 복호화 시켜주는 함수가 있고,
앨리스로부터 p, q, g, A값을 입력후
그리고 공개값 B를 출력 후, 그리고 공유된 비밀값 생성 한다.
현재 b의 값과 shared_secret값을 모르는 상태이지만
여기서 봐야할 부분은
generate_public_int, generate_shared_secret이 함수인데
def generate_public_int(g, a, p):
return g ^ a % p
def generate_shared_secret(A, b, p):
return A ^ b % p
'^'연산은 파이썬에선 XOR연산이고 교환법칙이 성립되기에
generate_public_int(g, b, p)는
g^b=B
g^B=b
generate_shared_secret(g,b,p)
A^b=shared_secret
이므로
해당 output.txt를 통해 플래그값을 구할수가 있다.
from Crypto.Util.Padding import unpad
from Crypto.Cipher import AES
import hashlib
def is_pkcs7_padded(message):
padding = message[-message[-1]:]
return all(padding[i] == len(padding) for i in range(0, len(padding)))
def decrypt_flag(shared_secret: int, iv: str, ciphertext: str):
sha1 = hashlib.sha1()
sha1.update(str(shared_secret).encode('ascii'))
key = sha1.digest()[:16]
ciphertext = bytes.fromhex(ciphertext)
iv = bytes.fromhex(iv)
cipher = AES.new(key, AES.MODE_CBC, iv)
plaintext = cipher.decrypt(ciphertext)
if is_pkcs7_padded(plaintext):
return unpad(plaintext, 16).decode('utf-8')
else:
return plaintext.decode('utf-8')
p = 2410312426921032588552076022197566074856950548502459942654116941958108831682612228890093858261341614673227141477904012196503648957050582631942730706805009223062734745341073406696246014589361659774041027169249453200378729434170325843778659198143763193776859869524088940195577346119843545301547043747207749969763750084308926339295559968882457872412993810129130294592999947926365264059284647209730384947211681434464714438488520940127459844288859336526896320919633919
g = 2
A = 539556019868756019035615487062583764545019803793635712947528463889304486869497162061335997527971977050049337464152478479265992127749780103259420400564906895897077512359628760656227084039215210033374611483959802841868892445902197049235745933150328311259162433075155095844532813412268773066318780724878693701177217733659861396010057464019948199892231790191103752209797118863201066964703008895947360077614198735382678809731252084194135812256359294228383696551949882
B = 652888676809466256406904653886313023288609075262748718135045355786028783611182379919130347165201199876762400523413029908630805888567578414109983228590188758171259420566830374793540891937904402387134765200478072915215871011267065310188328883039327167068295517693269989835771255162641401501080811953709743259493453369152994501213224841052509818015422338794357540968552645357127943400146625902468838113443484208599332251406190345653880206706388377388164982846343351
iv = 'c044059ae57b61821a9090fbdefc63c5'
encrypted_flag = 'f60522a95bde87a9ff00dc2c3d99177019f625f3364188c1058183004506bf96541cf241dad1c0e92535564e537322d7'
b = g ^ B
s = A ^ b
print(decrypt_flag(s, iv, encrypted_flag))
답은 crypto{b3_c4r3ful_w1th_y0ur_n0tati0n}이다.
'워게임 > CryptoHack' 카테고리의 다른 글
[CryptoHack] Misc (Gotta Go Fast) (0) | 2023.07.30 |
---|---|
[CryptoHack] HASH FUNCTIONS (Collider) (0) | 2023.07.30 |
[CryptoHack] DIFFIE-HELLMAN (Diffie-Hellman Starter 3, 4, 5) (0) | 2023.06.28 |
[CryptoHack] DIFFIE-HELLMAN (Diffie-Hellman Starter 1, 2) (0) | 2023.05.31 |
[CryptoHack] Mathmatics (Adrien's Signs) (0) | 2023.05.30 |
Contents