from Crypto.Cipher import AES
import hashlib
import secrets
defheader():
print(""" _____ _ __ __ _
| __ \(_)/ _|/ _(_)
| | | |_| |_| |_ _ ___
| | | | | _| _| |/ _ \
| |__| | | | | | | | __/
|_____/|_|_| |_| |_|\___|
| | | | | | |
| |__| | ___| | |_ __ ___ __ _ _ __
| __ |/ _ \ | | '_ ` _ \ / _` | '_ \
| | | | __/ | | | | | | | (_| | | | |
|_| |_|\___|_|_|_| |_| |_|\__,_|_| |_|
""")
defis_pkcs7_padded(message):
padding = message[-message[-1]:]
returnall(padding[i] == len(padding) for i inrange(0, len(padding)))
defpkcs7_unpad(message, block_size=16):
iflen(message) == 0:
raise Exception("The input data must contain at least one byte")
ifnot is_pkcs7_padded(message):
return message
padding_len = message[-1]
return message[:-padding_len]
defdecrypt_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')
defgenerate_public_int(g, a, p):
return g ^ a % p
defgenerate_shared_secret(A, b, p):
return A ^ b % p
defgoodbye():
print('Goodbye!')
defmain():
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()
output.txt
문제에서 제공해준 코드를 보게 되면
패딩과 언패딩, 플래그값을 복호화 시켜주는 함수가 있고,
앨리스로부터 p, q, g, A값을 입력후
그리고 공개값 B를 출력 후, 그리고 공유된 비밀값 생성 한다.
현재 b의 값과 shared_secret값을 모르는 상태이지만
여기서 봐야할 부분은
generate_public_int, generate_shared_secret이 함수인데
defgenerate_public_int(g, a, p):
return g ^ a % p
defgenerate_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
defis_pkcs7_padded(message):
padding = message[-message[-1]:]
returnall(padding[i] == len(padding) for i inrange(0, len(padding)))
defdecrypt_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))