Stream cipher ( 스트림 암호 )

Moon Junsu·2025년 5월 31일

STREAM Cipher는 평문 데이터를 한 비트 ( 또는 한 바이트 ) 단위로 암호화하는 대칭키 암호화 방식이다. 여기서 대칭키는 암호화 키와 복호화 키가 같은 것을 의미한다. 일반적으로 암호화 속도가 빠르고 메모리 사용량이 적어, 제한된 자원 환경 (IOT, 무선통신)등에서 많이 사용된다.

스트림 암호의 기본 원리

  1. 키(KEY) 양쪽 (수신자, 송신자)가 공유하는 대칭키를 이용
  2. 키 스트림 : 키로부터 의사난수 생성기를 통해 비트 스트림을 생성
  3. XOR 연산 : 평문의 각 비트(또는 바이트)를 키 스트림과 XOR 연산하여 암호문 생성
  • 암호문 = 평문 ⊕ 키 스트림
  • 복호문 = 암호문 ⊕ 키 스트림 → 평문

예시)

[ 평문 비트 ] 11001010
[ 키 스트림 ] 10101100
[ XOR 결과 ] 01100110 → 암호문

  • 같은 키 스트림을 두번 이상 사용해서는 안된다.
    왜냐하면 키 재사용 공격에 취약해지기 때문이다.

정리

스트림 암호는 한 비트/바이트씩 처리하는 빠르고 경량화된 암호 방식
XOR + 키 스트림으로 암호화 수행
RC4, ChaCha20 등 다양한 알고리즘 존재
Nonce/IV를 꼭 다르게 사용해야 보안 유지

워게임 문제 및 풀이 ( STREAMer-Prototype )

먼저 주어지는 문제 파일은 2개이다.

우선 실제 암호화에 사용된 파일이 주어진다. 각 클래스 내의 함수의 역할을 살펴본다.

init : 클래스의 초기화를 담당

num2bits : 인자로 넘어온 seed(=num)의 값의 범위를 검증하고, 2진수로 변경한 뒤 빈자리는 0을 채워 16비트로 만든다.

bits2num : 인자 비트에 0b를 추가한다.

shift : 맨 마지막 비트 1개를 맨 앞으로 옮기고, 옮긴 비트를 전달한다.

getNbits : 옮겨진 비트들을 통해 8비트 스트림을 만든다.

encrypt : getNbits를 통해 8비트 스트림을 생성한 후 0b를 추가하여 2진수 스트림을 만든다. ( 키 스트림 )

그리고 해당 스트림을 평문과 XOR 연산을 하여 암호문을 생성한다.

decrypt : getNbits를 통해 8비트 스트림을 생성한 후 0b를 추가하여 2진수 스트림을 만든다. ( 키 스트림 )

암호문과 키 스트림을 XOR 연산하여 평문을 획득한다.

이제 실제 암호화를 호출하여 사용한 코드를 살펴본다.

flag라는 파일에 대해 seed값을 랜덤으로 뽑아내어 키 스트림을 생성한다. 또한 encrypt된 암호문이 주어진다.

encrypted flag > 3cef03c64ac240c349971d9e4c951cc14ec4199f409249c21e964ac540c540944f901c934cc240934d96419f4b9e4d9f1cc41dc61dc34e9219c31bc11a914f9141c61ada

우리는 이 때 사용된 키 스트림(Seed 값)이 무엇인지 모른다. 이를 알아내는 코드를 작성해야 한다.

가장 먼저 hex값을 다시 바이트 포맷으로 변경하고, 키 스트림을 찾아내야 한다. 키 스트림의 범위는 0 ~ 65535이다.

반복문을 통해 각 키 스트림에 대해 계산하여 복호화 된 메시지에 DH{ 과 } 포맷이 있다면 출력하는 방식으로 코드를 작성하였다.

위는 변경된 코드이다. 이제 실행해보면

seed값은 58654일 때, 해당 flag가 평문으로 존재했던 것을 확인할 수 있다.

Flag = DH{a2e8d10e942df6ca8851ef12b8b8377d44e8451983958dceaed65adcfb6769ab}

profile
보안 인프라 엔지니어

0개의 댓글