
💡 대칭 키 알고리즘의 키는 암호나 기타 예측 가능한 데이터 대신 임의 바이트여야 합니다. 임의 바이트는 암호화 보안 의사 난수 생성기(CSPRNG)를 사용하여 생성해야 합니다. 어떤 식으로든 키를 예측할 수 있으면 암호의 보안 수준이 낮아지고 암호문에 액세스하는 공격자가 암호문을 해독할 수 있습니다.
키가 임의의 바이트로 구성된 것처럼 보인다고 해서 반드시 그런 것은 아닙니다. 이 경우 키는 해싱 함수를 사용하여 간단한 암호에서 파생되어 암호문을 해독할 수 있습니다.
이 챌린지에서는 끝점에 대한 HTTP 요청을 스크립팅하거나 오프라인에서 암호문을 공격할 수 있습니다. 행운을 빌어요!
원래는 키가 의사 난수 생성기에 의해 생성된다고 하는데, 이번 문제에서는 키를 알아낼 수 있다고 하는 것 같다. 일단 문제를 보자.

사이트는 저번 문제 때와 비슷하게 구성되어 있다.
from Crypto.Cipher import AES
import hashlib
import random
# /usr/share/dict/words from
# <https://gist.githubusercontent.com/wchargin/8927565/raw/d9783627c731268fb2935a731a618aa8e95cf465/words>
with open("/usr/share/dict/words") as f:
words = [w.strip() for w in f.readlines()]
keyword = random.choice(words)
KEY = hashlib.md5(keyword.encode()).digest()
FLAG = ?
@chal.route('/passwords_as_keys/decrypt/<ciphertext>/<password_hash>/')
def decrypt(ciphertext, password_hash):
ciphertext = bytes.fromhex(ciphertext)
key = bytes.fromhex(password_hash)
cipher = AES.new(key, AES.MODE_ECB)
try:
decrypted = cipher.decrypt(ciphertext)
except ValueError as e:
return {"error": str(e)}
return {"plaintext": decrypted.hex()}
@chal.route('/passwords_as_keys/encrypt_flag/')
def encrypt_flag():
cipher = AES.new(KEY, AES.MODE_ECB)
encrypted = cipher.encrypt(FLAG.encode())
return {"ciphertext": encrypted.hex()}
소스 코드이다. 먼저 주석으로 된 경로에서 단어들을 가져와서 랜덤하게 단어를 뽑은 후, md5로 해시를 돌려서 KEY를 얻어내고 있다.
decrypt 부분과 encrypt_flag 부분은 전과 동일하다.


올바른 키를 얻어오기 위해 주석에서 제공해준 단어 리스트들을 다운 받아서 words.txt로 저장해줬다.
from Crypto.Cipher import AES
import hashlib
with open("./words.txt") as f:
words = [w.strip() for w in f.readlines()]
ciphertext_hex='c92b7734070205bdf6c0087a751466ec13ae15e6f1bcdd3f3a535ec0f4bbae66'
ciphertext=bytes.fromhex(ciphertext_hex)
print(len(words))
for keyword in words:
KEY = hashlib.md5(keyword.encode()).digest()
cipher = AES.new(KEY, AES.MODE_ECB)
try:
decrypted = cipher.decrypt(ciphertext)
check=decrypted.decode('ascii')
print(bytes.hex(KEY))
print(check)
except ValueError as e:
pass
그다음 내가 작성한 코드이다. 문제에서 encrypt_flag로 주어진 ciphertext를 받아와서 박았고, words에서 하나씩 골라가면서 해시 돌려서 KEY로 만든다음 ciphertext와 함께 decrypt하는 과정을 거쳤다.
만약 올바른 key가 아니라면 bytes에서 ascii로 decode하는 과정에서 오류가 발생할 것이라고 생각하여 try, except 구문을 통해서 다른 오답들은 걸러냈다. 만약 ascii로 변환하는 데 성공한다면 이는 flag일 것이다!

flag를 따냈다! 99171은 단어의 개수이고, 아래는 사용된 key이다.

🚩 crypto{k3y5__r__n07__p455w0rdz?}