인코딩과 디코딩

Etc

0 views

1. 개요 및 정의

1.1 한 줄 요약

  • 인코딩은 데이터를 안전하게 운송하기 위해 규해진 규칙대로 포장(변환)하는 과정이며, 디코딩은 포장을 뜯어 원래의 내용물을 꺼내는 과정이다. 이는 비밀번호를 잠그는 '암호화'와는 근본적으로 다르다.

1.2 공식 정의

  • 인코딩(Encoding):
    • 정보의 형태나 형식을 표준화, 보안, 처리 속도 향상, 저장 공간 절약 등을 목적으로 다른 형태나 형식으로 변환하는 처리 방식이다.
  • 디코딩(Decoding):
    • 인코딩된 데이터를 다시 원래의 정보 형태로 되돌리는 역변환 과정이다.
  • 주요 목적:
    • 시스템 간 호환성:
      • 서로 다른 시스템이 데이터를 주고받을 때 깨지지 않게 한다 (예: UTF-8).
    • 전송 효율성 및 안전성:
      • 바이너리 데이터를 텍스트 기반 프로토콜(HTTP, SMTP)로 전송 가능하게 한다 (예: Base64).

2. 동작 원리 (Deep Dive)

  • 인코딩은 적용 분야에 따라 문자 인코딩(Character Encoding)과 전송 인코딩(Transfer Encoding)으로 나뉜다.
    • 이 두 가지 핵심 메커니즘을 상세히 분석한다.

2.1 문자 인코딩 (Character Encoding)

  • 컴퓨터는 0과 1만 이해하므로, 사람이 사용하는 문자를 숫자로 매핑해야 한다.
    1. 문자 집합(Character Set): 문자에 고유한 번호(Code Point)를 부여하는 약속이다. (예: 'A' = 65)
    2. 인코딩 방식: 이 번호를 컴퓨터 메모리에 어떻게 비트(Bit)로 저장할지 결정하는 규칙이다.
  • 대표적 예시: UTF-8
    • 가변 길이: 문자에 따라 1바이트에서 4바이트까지 가변적으로 사용한다.
    • 동작 방식:
      • ASCII 문자(0~127): 1바이트만 사용 (0xxxxxxx).
      • 다국어 문자: 첫 바이트에 바이트 수를 표시하는 헤더 비트가 들어간다 (예: 3바이트 문자 → 1110xxxx 10xxxxxx 10xxxxxx).
    • 엔디안(Endianness) 이슈 없음: 바이트 순서가 정해져 있어 BOM(Byte Order Mark)이 필수적이지 않다.

2.2 바이너리-텍스트 인코딩 (Base64)

  • 이미지나 실행 파일 같은 바이너리 데이터를 텍스트만 처리 가능한 프로토콜(이메일 등)로 전송할 때 사용한다.
    1. 입력: 원본 데이터를 24비트(3바이트)씩 끊는다.
    2. 분할: 24비트를 6비트씩 4개로 쪼갠다 (6×4=246 \times 4 = 246×4=24).
    3. 매핑: 각 6비트 값(0~63)을 Base64 색인표(A-Z, a-z, 0-9, +, /)에 매핑한다.
    4. 패딩: 원본 데이터가 3바이트로 나누어 떨어지지 않으면 끝에 = 문자를 붙여 길이를 맞춘다.

3. 사용법 및 구문 (Syntax)

  • 가장 범용적으로 사용되는 Python을 기준으로 인코딩과 디코딩을 시연한다.

3.1 문자열 인코딩 (String to Bytes)

  • 문자열(str)을 네트워크 전송이나 파일 저장을 위해 바이트(bytes)로 변환한다.

    # 원본 문자열
    text = "안녕하세요"
    
    # 1. 인코딩 (UTF-8)
    # 문자를 UTF-8 바이트 시퀀스로 변환한다.
    encoded_bytes = text.encode('utf-8')
    print(f"Encoded: {encoded_bytes}")
    # 출력 예: b'\xec\x95\x88\xeb\x85\x95\xed\x95\x98\xec\x84\xb8\xec\x9a\x94'
    
    # 2. 디코딩
    # 바이트 시퀀스를 다시 문자열로 복원한다.
    decoded_text = encoded_bytes.decode('utf-8')
    print(f"Decoded: {decoded_text}")
    

3.2 Base64 인코딩

  • 바이너리 데이터를 ASCII 문자열로 변환한다.

    import base64
    
    # 바이너리 데이터 (: "Python"의 ASCII 값)
    data = b'Python'
    
    # 1. Base64 인코딩
    # 결과는 bytes 타입의 ASCII 호환 문자열이다.
    b64_encoded = base64.b64encode(data)
    print(f"Base64 Encoded: {b64_encoded}")
    # 출력: b'UHl0aG9u'
    
    # 2. Base64 디코딩
    b64_decoded = base64.b64decode(b64_encoded)
    print(f"Base64 Decoded: {b64_decoded}")
    

3.3 URL 인코딩 (Percent Encoding)

  • URL에 포함될 수 없는 특수 문자나 공백을 변환한다.

    import urllib.parse
    
    # 쿼리 파라미터
    query = "이름=홍길동&직업=개발자"
    
    # 1. URL 인코딩
    url_encoded = urllib.parse.quote(query)
    print(f"URL Encoded: {url_encoded}")
    # 출력: %EC%9D%B4%EB%A6%84%3D%ED%99%8D%EA%B8%B8%EB%8F%99%26%EC%A7%81%EC%97%85%3D%EA%B0%9C%EB%B0%9C%EC%9E%90
    
    # 2. URL 디코딩
    url_decoded = urllib.parse.unquote(url_encoded)
    print(f"URL Decoded: {url_decoded}")
    

4. 심화 및 보안 (Advanced & Security)

4.1 인코딩은 암호화가 아니다

  • 인코딩:
    • 알고리즘(규칙)만 알면 누구나 원본을 복구할 수 있다.
    • 기밀성(Confidentiality)을 제공하지 않는다.
  • 암호화:
    • 키(Key)가 있어야만 복호화할 수 있다.
  • 보안 권고:
    • 비밀번호나 개인정보를 Base64로만 인코딩하여 저장하거나 전송해서는 안 된다.
    • 반드시 해시(Hash)하거나 암호화해야 한다.

4.2 보안 장비 우회 (WAF Evasion)

  • Double Encoding:
    • 공격 코드를 두 번 인코딩하여 WAF가 1차 디코딩만 수행하고 검사할 때 통과한 뒤, 애플리케이션 내부에서 2차 디코딩되어 실행되게 하는 기법이다.
    • 예: \rightarrow %3Cscript%3E (1차) \rightarrow %253Cscript%253E (2차)
  • 방어 대책:
    • 입력값을 디코딩한 후 정규화(Normalization) 과정을 거쳐 검증해야 한다.
    • 순환 디코딩을 통해 더 이상 변하지 않을 때까지 디코딩한 후 패턴을 매칭해야 한다.

Loading comments...