개념 설명
대칭 키 알고리즘의 키는 비밀번호나 기타 예측 가능한 데이터가 아닌 무작위 바이트여야 한다.
무작위 바이트는 암호학적으로 안전한 의사 난수 생성기(CSPRNG)를 사용하여 생성해야 한다.
어떤 식으로든 키를 예측할 수 있는 경우 암호의 보안 수준이 낮아지고 암호 텍스트에 엑세스한 공격자가 암호를 해독할 수 있다.
! PRNG는 Pseudo RandomNumber Generator이고 CSPRNG는 앞에 Cryptography Secure가 붙는다. 난수 생성에 대해서는 다른 글에서 다뤄보자.
키가 무작위 바이트처럼 보인다고 해서 반드시 그게 무작위라는 것은 아니다. 이 경우에 키는 해싱 함수를 사용하여 비밀번호에서 파생된 것이므로 암호문 해독이 가능하다.
이 챌린지의 경우, 엔드포인트*에 대한 HTTP요청을 스크립팅하거나 오프라인에서 암호 텍스트를 공격할 수 있다. 행운을 빈다!
https://aes.cryptohack.org/passwords_as_keys
*엔드포인트: 외부에서 침해나 공격으로부터 보호해야하는 대상 디바이스, 라우터나 스위치 등의 인프라는 제거한다. 그냥 우리가 알고 있는 디바이스 개념이라고 생각하면 될 듯..? AWS에서는 스위치나 라우터도 엔드포인트라고 적혀있네..
문제 풀이
문제에 적혀진 사이트에 가서 그냥 단어 파일을 다운로드 한다.
해당 단어를 md5 해시함수를 거쳐서 128bit로 만들고 해시 값으로 암호화하는데
복호화하는 과정으로 단어들에 있는 모든 키워드를 가지고 브루트포싱을 하면 된다.
from Crypto.Cipher import AES
import hashlib
def decrypt(ciphertext, password_hash):
ciphertext = bytes.fromhex(ciphertext)
key = bytes.fromhex(password_hash)
cipher = AES.new(key, AES.MODE_ECB)
try:
decrypt = cipher.decrypt(ciphertext)
except ValueError as e:
return {"error" : str(e)}
return decrypt
ciphertext = 'c92b7734070205bdf6c0087a751466ec13ae15e6f1bcdd3f3a535ec0f4bbae66'
with open('words.txt', 'r') as f:
words = [w.strip() for w in f.readlines()]
for w in words:
password_hash = hashlib.md5(w.encode()).hexdigest()
plain = decrypt(ciphertext, password_hash)
if b'crypto' in plain:
print(plain)
print(password_hash)
위 코드는 복호화 과정을 수행한다. decrypt에서 입력받은 password_hash와 ciphertext를 bytes로 변경하고 AES의 key와 AES Mode를 ECB로 세팅한다. 복호화 과정을 수행하고 복호화한 값을 reutrn 한다 return value는 bytes 이다.
with open을 사용하여 다운로드한 단어 후보를 얻어온다.
각각의 단어들에 대해서 md5로 해싱하고 그 값으로 복호화하였을 때, crypto라는 문자열이 존재하면 flag라 판단하고 출력한다.