이통사 HSS (Home Subscriber Server), USIM, IMEI, IMSI, KI 시뮬레이션

HSS (Home Subscriber Server) 시뮬레이션

요즘 SKT 해킹으로 시끄럽네요. 이동통신 네트워크의 핵심 구성 요소인 HSS(Home Subscriber Server), USIM, 그리고 모바일 장치 간의 인증 메커니즘을 시뮬레이션합니다. 3GPP 표준에 기반한 인증 및 키 동의(AKA: Authentication and Key Agreement) 프로토콜을 구현하여 실제 이동통신 환경과 유사한 인증 과정을 보여줍니다. 개념적으로만 참고하세요. 실제는 훨씬 복잡하겠죠. IMEI는 핸드폰을 대표하는 식별자이고 IMSI는 사용자를 식별하는 본인의 주민등록증이라고 보면 되겠죠.

주요 구성 요소

1. HSS (Home Subscriber Server)

HSS는 이동통신 네트워크의 중앙 데이터베이스로, 가입자 정보를 관리하고 인증 벡터를 생성하는 역할을 담당합니다.

주요 기능:

  • 가입자 등록: 새로운 가입자의 IMSI, Ki, IMEI 정보를 등록합니다.
  • OPc 생성: 가입자별 Ki와 네트워크 운영자 키(OP)를 사용하여 OPc를 생성합니다.
  • 인증 벡터 생성: RAND, XRES, AUTN, CK 등으로 구성된 인증 벡터를 생성합니다.
  • 단말기 인증: 단말기가 제공한 RES와 HSS의 XRES를 비교하여 인증을 수행합니다.
  • IMEI 검증: 등록된 IMEI와 제공된 IMEI를 비교하여 도난 단말기 사용을 방지합니다.

인증 알고리즘 구현:

  • F1: MAC(Message Authentication Code) 생성 함수
  • F2: XRES(Expected Response) 생성 함수
  • F3: CK(Cipher Key) 생성 함수
  • F4: IK(Integrity Key) 생성 함수
  • F5: AK(Anonymity Key) 생성 함수

2. USIM (Universal Subscriber Identity Module)

USIM은 가입자 식별 및 인증에 필요한 정보를 저장하고, 인증 과정에서 필요한 암호화 연산을 수행합니다.

주요 기능:

  • 응답 생성: 네트워크로부터 받은 RAND에 대한 RES(Response)를 생성합니다.
  • 네트워크 인증: AUTN을 검증하여 네트워크의 정당성을 확인합니다.
  • 보안 키 생성: 암호화 키(CK)와 무결성 키(IK)를 생성합니다.

구현된 알고리즘:

  • HSS와 동일한 F1~F5 함수를 구현하여 상호 인증이 가능하도록 합니다.
  • AUTN 검증 로직을 통해 SQN, MAC 등을 확인합니다.

3. 모바일 장치 (Mobile Device)

모바일 장치는 USIM을 탑재하고 네트워크와 통신하는 단말기를 시뮬레이션합니다. 본인이 가지고 있는 스마트폰이라고 보면 됩니다.

주요 기능:

  • 인증 벡터 요청: HSS에 인증 벡터를 요청합니다(실제로는 MME/SGSN이 요청).
  • AUTN 검증 요청: USIM에 AUTN 검증을 요청합니다.
  • RES 생성 요청: USIM에 RES 생성을 요청합니다.
  • HSS에 인증 요청: 생성된 RES를 HSS에 전송하여 인증을 요청합니다.
  • 보안 키 관리: 인증 성공 시 CK, IK를 저장하여 이후 통신에 사용합니다.

주요 개념 설명

IMSI (International Mobile Subscriber Identity)

IMSI는 이동통신 네트워크에서 가입자를 고유하게 식별하는 국제 표준 식별자입니다.

  • 최대 15자리 숫자로 구성됩니다.
  • MCC(Mobile Country Code), MNC(Mobile Network Code), MSIN(Mobile Subscriber Identification Number)으로 구성됩니다.
  • 예: "450051234567890" (450: 한국 MCC, 05: 특정 통신사 MNC, 나머지: 가입자 고유 번호)
  • HSS 데이터베이스에서 가입자 정보를 조회하는 키로 사용됩니다.

IMEI (International Mobile Equipment Identity)

IMEI는 모바일 장치 하드웨어를 고유하게 식별하는 번호입니다.

  • 15자리 숫자로 구성됩니다.
  • TAC(Type Approval Code), SNR(Serial Number), 체크 디지트 등으로 구성됩니다.
  • 예: "352099001761481"
  • 도난 단말기 사용 방지 및 장치 식별에 사용됩니다.
  • HSS는 등록된 IMEI와 제공된 IMEI를 비교하여 불법 사용을 방지합니다.

Ki (Key Identifier)

Ki는 가입자 인증에 사용되는 비밀 키입니다.

  • 128비트(16바이트) 길이의 비밀 키로, 16진수로 표현됩니다.
  • 예: "A1B2C3D4E5F60718293A4B5C6D7E8F90"
  • USIM 카드와 HSS에만 저장되며, 절대 네트워크를 통해 전송되지 않습니다.
  • 모든 인증 및 키 생성 알고리즘(F1~F5)의 기본 입력으로 사용됩니다.
  • Ki를 통해 OPc, XRES, CK, IK 등이 생성됩니다.

인증 벡터 (Authentication Vector)

인증 벡터는 HSS가 생성하여 인증 과정에 사용하는 정보 집합입니다.

  • RAND: 랜덤 챌린지 (16바이트)
  • XRES: 예상 응답 (8바이트)
  • AUTN: 인증 토큰 (16바이트)
    • SQN ⊕ AK: 시퀀스 번호와 익명성 키의 XOR (6바이트)
    • AMF: 인증 관리 필드 (2바이트)
    • MAC: 메시지 인증 코드 (8바이트)
  • CK: 암호화 키 (16바이트)
  • IK: 무결성 키 (16바이트, 이 구현에서는 직접 사용하지 않음)

인증 과정 시뮬레이션

  1. 가입자 등록: HSS에 가입자 정보(IMSI, Ki, IMEI)를 등록합니다.
  2. 인증 벡터 생성: HSS는 가입자별 인증 벡터를 생성합니다.
  3. 인증 요청: 모바일 장치가 네트워크에 접속하면 HSS로부터 인증 벡터를 받습니다.
  4. 네트워크 인증: USIM이 AUTN을 검증하여 네트워크를 인증합니다.
  5. 가입자 인증: USIM이 생성한 RES를 HSS의 XRES와 비교하여 가입자를 인증합니다.
  6. 보안 키 설정: 인증 성공 시 양쪽 모두 동일한 CK와 IK를 가지게 되어 안전한 통신이 가능해집니다.

시뮬레이션 시나리오

  1. 정상 인증: 올바른 IMSI, Ki, IMEI를 가진 장치의 인증 과정
  2. 도난 장치 감지: 올바른 USIM이지만 등록되지 않은 IMEI를 사용한 경우 인증 실패

기술적 구현 상세

  • 암호화 알고리즘: 실제 3GPP 표준은 MILENAGE 알고리즘을 사용하지만, 이 구현에서는 HMAC-SHA256으로 단순화하여 시뮬레이션합니다.
  • 시퀀스 번호: 재생 공격 방지를 위해 각 인증 시도마다 증가하는 시퀀스 번호를 사용합니다.
  • OPc 생성: 네트워크 운영자 키(OP)와 가입자 키(Ki)를 조합하여 가입자별 OPc를 생성합니다.

코드 구조

  • SubscriberData: 가입자 정보를 저장하는 데이터 클래스
  • HSS: 가입자 데이터베이스 관리 및 인증 벡터 생성 클래스
  • USIM: 가입자 인증 및 응답 생성 클래스
  • MobileDevice: USIM을 탑재하고 네트워크와 통신하는 장치 클래스
  • create_subscriber: 가입자 및 장치 생성 헬퍼 함수
  • run_simulation: 전체 인증 과정 시뮬레이션 함수

소스 코드

주요 클래스 및 함수

1. SubscriberData 클래스

import random
import hashlib
import time
import hmac
import os
from dataclasses import dataclass
from typing import Tuple, Dict, List, Optional

@dataclass
class SubscriberData:
    """가입자 데이터 클래스"""
    imsi: str  # 국제 모바일 가입자 식별자
    ki: str    # 인증 키 (비밀 키)
    opc: str   # 연산자 변형 키 (Operator Variant Algorithm Configuration Field)
    registered_imei: str  # 등록된 IMEI
    seq_number: int = 0   # 시퀀스 번호 (인증 벡터 생성 시 사용)
    amf: str = "8000"  # Authentication Management Field

2. HSS 클래스 (주요 메서드)

class HSS:
    """실제 통신환경과 유사한 Home Subscriber Server 클래스"""

    def __init__(self):
        """실제 통신환경과 유사한 HSS 초기화"""
        self.subscriber_db: Dict[str, SubscriberData] = {}  # IMSI를 키로 하는 가입자 데이터베이스
        self.authentication_vectors: Dict[str, List[Tuple[str, str, str, str]]] = {}  # IMSI별 인증 벡터 저장소
        self.op_key = "11111111111111111111111111111111"  # 연산자 키 (Operator Key)

    def _generate_opc(self, ki: str) -> str:
        """연산자 변형 키(OPc) 생성"""
        return hashlib.sha256(f"{ki}{self.op_key}".encode()).hexdigest()[:32]

    def register_subscriber(self, imsi: str, ki: str, imei: str) -> bool:
        """가입자 등록"""
        if imsi in self.subscriber_db:
            print(f"[HSS] 가입자 IMSI {imsi}는 이미 등록되어 있습니다.")
            return False

        # 연산자 변형 키(OPc) 생성
        opc = self._generate_opc(ki)

        self.subscriber_db[imsi] = SubscriberData(imsi=imsi, ki=ki, opc=opc, registered_imei=imei)
        print(f"n[HSS] New 가입자 등록 완료: IMSI={imsi}, IMEI={imei}")
        print(f"[HSS] 생성된 OPc: {opc}")

        # 새 가입자를 위한 인증 벡터 생성 및 출력
        vectors = self.generate_authentication_vectors(imsi)
        print(f"[HSS] 새 가입자 {imsi}의 인증 벡터 정보:")
        for i, (rand, xres, autn, ck) in enumerate(vectors):
            print(f"  벡터 #{i+1}:")
            print(f"    RAND: {rand}")
            print(f"    XRES: {xres}")
            print(f"    AUTN: {autn}")
            print(f"    CK  : {ck}")

        return True

    def generate_authentication_vectors(self, imsi: str, count: int = 5) -> List[Tuple[str, str, str, str]]:
        """인증 벡터 생성 (RAND, XRES, AUTN, CK)"""
        if imsi not in self.subscriber_db:
            print(f"[HSS] 오류: IMSI {imsi}를 찾을 수 없습니다.")
            return []

        subscriber = self.subscriber_db[imsi]
        vectors = []

        for _ in range(count):
            # 1. 랜덤 챌린지 생성 (RAND)
            rand = ''.join([format(random.randint(0, 255), '02x') for _ in range(16)])

            # 2. 시퀀스 번호 증가
            subscriber.seq_number += 1
            sqn = subscriber.seq_number

            # 3. XRES(Expected Response) 생성
            xres = self._f2(subscriber.ki, subscriber.opc, rand)

            # 4. 암호화 키(CK) 생성
            ck = self._f3(subscriber.ki, subscriber.opc, rand)

            # 5. 무결성 키(IK) 생성
            ik = self._f4(subscriber.ki, subscriber.opc, rand)

            # 6. 익명성 키(AK) 생성
            ak = self._f5(subscriber.ki, subscriber.opc, rand, sqn)

            # 7. MAC 생성
            mac = self._f1(subscriber.ki, subscriber.opc, rand, sqn, subscriber.amf)

            # 8. AUTN(Authentication Token) 생성: (SQN ⊕ AK) || AMF || MAC
            sqn_ak = format(int(format(sqn, '012x'), 16) ^ int(ak, 16), '012x')
            autn = f"{sqn_ak}{subscriber.amf}{mac}"

            vectors.append((rand, xres, autn, ck))

        self.authentication_vectors[imsi] = vectors
        print(f"[HSS] {imsi}에 대한 인증 벡터 {count}개 생성 완료")
        return vectors

    def authenticate_device(self, imsi: str, imei: str, res: str) -> Tuple[bool, str]:
        """단말기 인증 수행"""
        if imsi not in self.subscriber_db:
            return False, "가입자 정보 없음"

        subscriber = self.subscriber_db[imsi]

        # IMEI 확인
        if subscriber.registered_imei != imei:
            print(f"[HSS] IMEI 불일치: 등록={subscriber.registered_imei}, 제공={imei}")
            return False, "IMEI 불일치"

        # 인증 벡터가 없으면 생성
        if imsi not in self.authentication_vectors or not self.authentication_vectors[imsi]:
            self.generate_authentication_vectors(imsi)

        # 인증 벡터에서 다음 벡터 가져오기
        rand, xres, autn, ck = self.authentication_vectors[imsi].pop(0)

        # RES와 XRES 비교
        if res == xres:
            print(f"[HSS] 인증 성공: IMSI={imsi}, IMEI={imei}")
            print(f"[HSS] 암호화 키(CK): {ck}")
            return True, "인증 성공"
        else:
            print(f"[HSS] 인증 실패: IMSI={imsi}, IMEI={imei}")
            print(f"[HSS] 예상된 RES: {xres}, 제공된 RES: {res}")
            return False, "인증 실패"

3. USIM 클래스 (주요 메서드)

class USIM:
    """USIM 카드 시뮬레이션 클래스"""

    def __init__(self, imsi: str, ki: str):
        """USIM 초기화"""
        self.imsi = imsi
        self.ki = ki  # 인증 키 (비밀 키)
        self.op_key = "11111111111111111111111111111111"  # Operator Key (HSS와 동일해야 함)
        self.opc = self._generate_opc(ki)  # OPc 생성
        self.sqn = 0  # 시퀀스 번호
        self.amf = "8000"  # Authentication Management Field

    def generate_response(self, rand: str) -> str:
        """챌린지(RAND)에 대한 응답(RES) 생성"""
        res = self._f2(self.ki, self.opc, rand)
        print(f"[USIM] RAND={rand}에 대한 RES={res} 생성")
        return res

    def verify_autn(self, autn: str) -> bool:
        """AUTN 검증 (네트워크 인증)"""
        try:
            # AUTN 분해: (SQN ⊕ AK) || AMF || MAC
            sqn_ak = autn[:12]
            amf = autn[12:16]
            mac = autn[16:24]

            # 임의의 시퀀스 번호와 RAND 사용 (실제로는 저장된 값 사용)
            # 여기서는 간단히 시뮬레이션만 함
            rand = ''.join([format(random.randint(0, 255), '02x') for _ in range(16)])
            sqn = self.sqn + 1

            # AK 생성
            ak = self._f5(self.ki, self.opc, rand, sqn)

            # SQN 복원
            sqn_received = int(sqn_ak, 16) ^ int(ak, 16)

            # MAC 생성 및 검증
            expected_mac = self._f1(self.ki, self.opc, rand, sqn_received, amf)

            # 실제 구현에서는 SQN 검증도 필요하지만 여기서는 생략
            # 시뮬레이션 목적으로 항상 성공 반환
            print(f"[USIM] AUTN 검증 성공")
            return True
        except Exception as e:
            print(f"[USIM] AUTN 검증 실패: {e}")
            return False

4. MobileDevice 클래스

class MobileDevice:
    """모바일 장치 시뮬레이션 클래스"""

    def __init__(self, imei: str, usim: USIM):
        """모바일 장치 초기화"""
        self.imei = imei
        self.usim = usim
        self.ck = None  # 암호화 키 (Ciphering Key)
        self.ik = None  # 무결성 키 (Integrity Key)

    def authenticate_with_network(self, hss: HSS) -> bool:
        """네트워크와의 인증 수행"""
        imsi = self.usim.imsi

        # 1. HSS에 인증 벡터 요청 (실제로는 MME/SGSN이 요청함)
        vectors = hss.generate_authentication_vectors(imsi)
        if not vectors:
            print(f"[단말기] 인증 벡터를 받을 수 없음: IMSI={imsi}")
            return False

        # 2. 인증 벡터에서 RAND와 AUTN 추출
        rand, _, autn, _ = vectors[0]
        print(f"[단말기] 인증 벡터 수신: RAND={rand}, AUTN={autn}")

        # 3. AUTN 검증 (네트워크 인증)
        if not self.usim.verify_autn(autn):
            print(f"[단말기] 네트워크 인증 실패: IMSI={imsi}")
            return False

        # 4. RES 생성
        res = self.usim.generate_response(rand)

        # 5. CK 및 IK 생성
        self.ck = self.usim._f3(self.usim.ki, self.usim.opc, rand)
        self.ik = self.usim._f4(self.usim.ki, self.usim.opc, rand)
        print(f"[단말기] 암호화 키(CK): {self.ck}")
        print(f"[단말기] 무결성 키(IK): {self.ik}")

        # 6. HSS에 RES 전송하여 인증
        success, message = hss.authenticate_device(imsi, self.imei, res)
        print(f"[단말기] 인증 결과: {message}")

        return success

5. 헬퍼 함수 및 시뮬레이션 실행

def create_subscriber(hss: HSS, imsi: str, ki: str, imei: str) -> Tuple[USIM, MobileDevice]:
    """새로운 가입자와 모바일 장치를 생성하는 함수"""
    # 가입자 등록
    hss.register_subscriber(imsi, ki, imei)

    # USIM 카드 생성
    usim = USIM(imsi, ki)

    # 모바일 장치 생성
    mobile_device = MobileDevice(imei, usim)

    return usim, mobile_device

def run_simulation():
    """인증 프로세스 시뮬레이션 실행"""
    print("===== HSS 인증 시뮬레이션 시작 =====n")

    # HSS 초기화
    hss = HSS()

    # 첫 번째 가입자 정보
    imsi1 = "450051234567890"  # 한국 IMSI 예시
    ki1 = "A1B2C3D4E5F60718293A4B5C6D7E8F90"  # 64자리 16진수 Ki 예시
    imei1 = "352099001761481"  # IMEI 예시

    # 첫 번째 가입자 및 장치 생성
    usim1, mobile_device1 = create_subscriber(hss, imsi1, ki1, imei1)

    # 도난 장치 시뮬레이션 (다른 IMEI)
    stolen_imei = "352099009876543"
    stolen_device = MobileDevice(stolen_imei, usim1)

    print("n----- 정상 인증 시도 -----")
    success1 = mobile_device1.authenticate_with_network(hss)
    print(f"인증 결과: {'성공' if success1 else '실패'}")

    print("n----- 도난 장치 인증 시도 (IMEI 불일치) -----")
    success2 = stolen_device.authenticate_with_network(hss)
    print(f"인증 결과: {'성공' if success2 else '실패'}")

    # 두 번째 가입자 정보
    imsi2 = "450059876543210"
    ki2 = "F0E1D2C3B4A50617283940516273849A"  # 16자리 16진수 Ki 예시
    imei2 = "352099007654321"

    # 두 번째 가입자 및 장치 생성
    usim2, mobile_device2 = create_subscriber(hss, imsi2, ki2, imei2)

    print("n----- 두 번째 가입자 인증 시도 -----")
    success3 = mobile_device2.authenticate_with_network(hss)
    print(f"인증 결과: {'성공' if success3 else '실패'}")

    print("n===== HSS 인증 시뮬레이션 종료 =====")

if __name__ == "__main__":
    run_simulation()

전체 소스 코드

전체 소스 코드를 hss.py 파일에 저장하고 수행할 수 있습니다. 위에 제시된 주요 클래스와 함수들은 전체 코드의 핵심 부분을 보여줍니다. 암호화 알고리즘 구현 부분(F1~F5 함수)과 같은 일부 세부 내용은 생략되었습니다.

실행 방법

python hss.py

실행하면 가입자 등록, 인증 벡터 생성, 정상 인증, 도난 장치 감지 등의 과정이 시뮬레이션됩니다.

Leave a Comment