문제 설명
OFB, CTR 또는 CFB와 같은 일부 블록 사이퍼 모드는 블록 사이퍼를 스트림 사이퍼로 변환합니다. 스트림 암호의 기본 개념은 의사 랜덤 키 스트림을 생성한 다음 일반 텍스트와 XOR하는 것입니다. 스트림 암호의 한 가지 장점은 패딩 없이 임의의 길이의 평문으로 작업할 수 있다는 것입니다.
OFB는 모호한 암호 모드로, 요즘에는 CTR을 사용하는 것보다 실질적인 이점이 없습니다. 이번 챌린지는 OFB의 특이한 속성을 소개합니다.
from Crypto.Cipher import AES
KEY = ?
FLAG = ?
@chal.route('/symmetry/encrypt/<plaintext>/<iv>/')
def encrypt(plaintext, iv):
plaintext = bytes.fromhex(plaintext)
iv = bytes.fromhex(iv)
if len(iv) != 16:
return {"error": "IV length must be 16"}
cipher = AES.new(KEY, AES.MODE_OFB, iv)
encrypted = cipher.encrypt(plaintext)
ciphertext = encrypted.hex()
return {"ciphertext": ciphertext}
@chal.route('/symmetry/encrypt_flag/')
def encrypt_flag():
iv = os.urandom(16)
cipher = AES.new(KEY, AES.MODE_OFB, iv)
encrypted = cipher.encrypt(FLAG.encode())
ciphertext = iv.hex() + encrypted.hex()
return {"ciphertext": ciphertext}
코드에서 encrypt_flag를 하면 OFB모드를 사용해서 encrypt 하고 iv는 준다.
encrypt에서는 평문과 iv를 입력하면 평문을 OFB를 사용해서 encrypt한다.
OFB는 iv를 암호화하여 동작한다. OFB 모드는 CBC에서 오류 전파를 개선하였다.
찾아본 결과로, 오류 전파는 암호문을 암, 복호화하는 관점에서 데이터 손실등으로 오류가 생겼을 때를 말한다.
그 오류가 결과 전체에 전파되느냐를 말하는데, CBC 모드에서 암호화할 때는 평문 블록이 잘못되었다면 암호화된 평문 블록이 암호문 전체에 영향을 미치고,
암호문이 잘못되었다면 복호화 시 인접한 블록 하나에 영향을 미친다(총 2블록 오류).
반면, OFB는 위 과정과 같이 암, 복호화를 수행하는데 iv를 암호화하여 xor한다.
그래서 평문 블록이 잘못되거나 암호문 블록이 잘못될 경우에 해당 블록에만 오류가 일어난다.
또, 암호화 시에 어떻게 보면 xor을 쓰는 거기 때문에 같은 키로 복호화하기 위해서는 iv를 암호화해야 한다.
풀이
이 문제에서는 평문을 입력하고 OFB로 암호화하는 함수가 주어진다.
복호화할 때는 그냥 암호문을 plaintext에 넣고 암호화하듯이 하면 되니 간단하다.
얻어낸 ciphertext에서 iv를 추출하고 암호문을 encrypt하면 복호화된 결과가 나올 것이다.
crypto{0fb_15_5ymm37r1c4l_!!!11!}