콘텐츠로 이동

v0.0

하드웨어 레벨 정책 엔진 설계서

1. Executive Summary

하드웨어 정책 엔진은 D'CENT X 콜드월렛의 Secure Element(SE) 내부에서 동작하는 트랜잭션 정책 평가 시스템이다. Phase 3에서 설계한 3중 방어 체계의 3차(하드웨어 SE) 계층을 상세 설계하며, 소프트웨어 정책 엔진이 우회되거나 침해된 상황에서도 물리적으로 정책을 강제하는 마지막 방어선 역할을 수행한다.

1.1. 왜 하드웨어 정책 엔진이 필요한가

소프트웨어 기반 정책 엔진만으로는 다음 공격 벡터를 방어할 수 없다:

공격 시나리오 SW 정책만 SW + HW 정책
대시보드 서버 해킹 정책 우회 가능 → 무제한 출금 SE가 건당/일일 한도 재검증 → 차단
내부자 공격 (Admin 공모) 정책 비활성화 가능 SE 정책 변경에 쿼럼 + 쿨다운 필요 → 즉시 우회 불가
오프라인 앱 변조 정책 검증 우회 가능 SE가 독립적으로 정책 평가 → 변조된 TX 거부
중간자 공격 정책 통과 데이터 조작 가능 SE 내부 정책 데이터와 독립 비교 → 탐지

핵심 원칙: "소프트웨어는 해킹할 수 있지만, SE 내부 로직은 물리적 접근 없이 변경할 수 없다."


2. SW 정책 엔진 vs HW 정책 엔진 역할 분담

2.1. 3중 방어 체계 상세

Phase 3 policy-engine.md에서 정의한 3중 방어 체계의 각 계층별 역할:

계층 컴포넌트 정책 평가 범위 리소스 목적
1차 온라인 대시보드 전체 규칙 (5종 + 확장) 무제한 (서버) 사전 차단, 복잡한 규칙 평가
2차 오프라인 서명 앱 핵심 규칙 재확인 중간 (모바일/태블릿) 에어갭 전달 전 이중 검증
3차 D'CENT X SE 핵심 불변 규칙만 극히 제한 (SE) 최종 방어 — 우회 불가

2.2. 규칙 분담 원칙

SE에서 평가하는 규칙 선정 기준: 1. 불변성이 중요한 규칙: 소프트웨어에서 우회할 수 없어야 하는 절대 한도 2. SE 리소스로 구현 가능한 규칙: 단순 비교, 카운터 기반 (복잡한 로직 불가) 3. 실시간 평가 가능한 규칙: 외부 데이터 참조 없이 SE 내부 데이터만으로 판단

SW에만 위임하는 규칙: 1. 복잡한 조합 로직: AND/OR 다중 조건, 예외 처리 2. 외부 데이터 참조: 실시간 가격 환산, 수신자 카테고리 분류 3. 시간 기반 복잡 규칙: 영업시간 판단 (SE에 RTC가 없거나 정확도 보장 불가) 4. 정책 시뮬레이션: 변경 영향도 분석 (서버 리소스 필요) 5. 누적 한도 중 장기 집계: 주간/월간 누적 (SE 리부트 시 데이터 보존 어려움)

2.3. 역할 분담 매트릭스

정책 규칙 1차 (대시보드) 2차 (오프라인 앱) 3차 (SE)
화이트리스트 주소 검증 전체 목록 대조 캐시된 목록 대조 Merkle Root 검증
건당 금액 한도 체크 재확인 절대 상한 체크
일일 누적 한도 체크 (DB 기반) 미적용 SE 카운터 기반
서명 횟수 제한 체크 (DB 기반) 미적용 SE 카운터 기반
시간 기반 제한 체크 재확인 미적용 (RTC 없음)
자산 유형 필터 체크 재확인 미적용 (토큰 매핑 복잡)
네트워크 수수료 상한 체크 재확인 미적용 (가격 변동)
Emergency Override 지원 미적용 우회 불가

3. SE 내부 정책 규칙 유형

3.1. 규칙 1: 건당 금액 상한 (Per-Transaction Absolute Limit)

목적: 단일 트랜잭션으로 이동할 수 있는 최대 금액을 하드웨어 수준에서 제한

SE 구현:

SE_Policy_AmountLimit {
  max_per_tx: uint64        // 건당 최대 금액 (satoshis 또는 wei)
  currency: enum {BTC, ETH, ERC20_6DEC, ERC20_18DEC}
  enabled: bool
}

평가 로직:
  IF tx.total_output_amount > max_per_tx:
    RETURN REJECT(POLICY_AMOUNT_EXCEEDED)
  ELSE:
    PASS

설정 값 예시:

자산 SE 기본 상한 단위 비고
BTC 10 BTC satoshis (1,000,000,000 sat) 약 $600,000 (2025 기준)
ETH 100 ETH wei (100 × 10^18) 약 $300,000
ERC-20 (6 dec) 1,000,000 USDT micro-units $1,000,000
ERC-20 (18 dec) 1,000,000 DAI wei-equivalent $1,000,000

상한 변경 절차: - Admin 쿼럼 서명 필수 (최소 3-of-5) - 에어갭 경유 정책 페이로드 전달 - 물리 버튼 확인 필수 ("한도 변경: 10 BTC → 20 BTC — 승인?") - 쿨다운 적용 (변경 후 24시간 대기 후 신규 한도 적용)

3.2. 규칙 2: 화이트리스트 주소 검증 (Merkle Root 기반)

목적: SE 저장 공간 제약 내에서 대규모 화이트리스트를 검증

문제: SE 저장 공간은 수 KB로 제한되어 수백~수천 개의 화이트리스트 주소를 직접 저장할 수 없다.

해결: Merkle Tree 기반 검증

SE 저장 데이터:
  whitelist_merkle_root: bytes32    // 화이트리스트 전체의 Merkle Root
  whitelist_version: uint32         // 버전 번호

오프라인 앱 제공 데이터:
  tx_recipient: address             // 수신 주소
  merkle_proof: bytes32[]           // Merkle Proof (최대 20 depth = 2^20 주소)

SE 검증 로직:
  leaf = SHA-256(tx_recipient)
  computed_root = verify_merkle_proof(leaf, merkle_proof)
  IF computed_root == whitelist_merkle_root:
    PASS
  ELSE:
    RETURN REJECT(POLICY_WHITELIST_FAILED)

Merkle Tree 구성:

                    Root (SE 저장)
                   /              \
              H(AB)              H(CD)
             /    \             /    \
          H(A)   H(B)       H(C)   H(D)
           |      |          |      |
         Addr1  Addr2      Addr3  Addr4

용량 분석: - Merkle Root: 32 bytes (SE 저장) - Merkle Proof: depth × 32 bytes (오프라인 앱에서 QR/USB-C로 전달) - depth 20 = 1,048,576 주소 지원 → Proof 크기 = 640 bytes - SE는 Root만 저장하므로 주소 수와 무관하게 32 bytes 고정

Merkle Root 업데이트: 1. 대시보드에서 화이트리스트 변경 → 새 Merkle Tree 구성 2. 새 Root + 업데이트 서명(Admin 쿼럼) → 에어갭 전달 3. SE 내부에서 서명 검증 후 Root 교체 4. 버전 번호 증가 (롤백 방지)

3.3. 규칙 3: 일일 누적 한도 (Daily Cumulative Limit)

목적: 24시간 내 총 이동 금액을 SE 내부 카운터로 제한

SE 구현:

SE_Policy_DailyLimit {
  daily_max: uint64             // 일일 최대 누적 금액
  daily_spent: uint64           // 현재까지 누적 금액 (서명 성공 시 증가)
  last_reset_counter: uint32    // 마지막 리셋 시점 (서명 횟수 기반)
  reset_interval: uint32        // 리셋 간격 (서명 횟수 기준, 예: 100회)
  currency: enum
}

평가 로직:
  // 리셋 체크 (시간 대신 서명 횟수 기반 — SE에 정확한 RTC 없음)
  IF current_sign_counter - last_reset_counter >= reset_interval:
    daily_spent = 0
    last_reset_counter = current_sign_counter

  IF daily_spent + tx.amount > daily_max:
    RETURN REJECT(POLICY_DAILY_LIMIT_EXCEEDED)
  ELSE:
    daily_spent += tx.amount
    PASS

RTC 부재 대응: SE에 실시간 시계(RTC)가 없거나 정확도를 보장할 수 없으므로, 시간 기반 대신 서명 횟수 기반 리셋을 채택한다. 오프라인 앱이 전달하는 타임스탬프는 신뢰할 수 없으므로(조작 가능), SE 내부 독립 카운터를 사용한다.

한계: 서명 횟수 기반 리셋은 시간과 정확히 일치하지 않지만, SE 리소스 제약 내에서 합리적인 근사치를 제공한다. 정확한 시간 기반 일일 한도는 1차(대시보드)에서 수행한다.

3.4. 규칙 4: 서명 횟수 제한 (Signing Rate Limit)

목적: 단위 기간 내 최대 서명 가능 횟수를 제한하여 대량 유출 방지

SE 구현:

SE_Policy_RateLimit {
  max_signs_per_window: uint16    // 윈도우 내 최대 서명 횟수
  window_signs: uint16            // 현재 윈도우 내 서명 횟수
  window_start_counter: uint32    // 현재 윈도우 시작 카운터
  window_size: uint16             // 윈도우 크기 (서명 횟수 기반)
}

평가 로직:
  IF global_counter - window_start_counter >= window_size:
    window_signs = 0
    window_start_counter = global_counter

  IF window_signs >= max_signs_per_window:
    RETURN REJECT(POLICY_RATE_LIMIT_EXCEEDED)
  ELSE:
    window_signs += 1
    PASS

기본 설정:

윈도우 크기 최대 서명 수 용도
10 (서명 단위) 5 단기 연속 서명 방지
100 (서명 단위) 50 중기 서명 빈도 제한
1000 (서명 단위) 200 장기 서명 총량 제한

4. SE 정책 위반 시 동작

4.1. 서명 거부 + 위반 사유 코드 반환

SE가 정책 위반을 감지하면 즉시 서명을 거부하고, 표준화된 에러 코드를 반환한다.

위반 사유 코드 체계:

코드 의미 화면 표시
0x01 POLICY_AMOUNT_EXCEEDED "정책 위반: 건당 한도 초과"
0x02 POLICY_WHITELIST_FAILED "정책 위반: 미등록 주소"
0x03 POLICY_DAILY_LIMIT_EXCEEDED "정책 위반: 일일 한도 초과"
0x04 POLICY_RATE_LIMIT_EXCEEDED "정책 위반: 서명 횟수 초과"
0x05 POLICY_VERSION_MISMATCH "정책 위반: 정책 버전 불일치"
0x06 POLICY_SIGNATURE_INVALID "정책 위반: 정책 서명 무효"
0xFE POLICY_ENGINE_ERROR "정책 엔진 내부 오류"
0xFF POLICY_NOT_INITIALIZED "정책 미설정"

4.2. 화면 위반 유형 표시

┌─────────────────────────────┐
│  ⛔ 정책 위반 — 서명 거부     │
│                              │
│  위반 유형: 건당 한도 초과     │
│                              │
│  요청 금액: 15.0 BTC          │
│  SE 한도:   10.0 BTC          │
│                              │
│  이 트랜잭션은 하드웨어        │
│  정책에 의해 차단되었습니다.   │
│                              │
│  [확인]                      │
└─────────────────────────────┘

4.3. 우회 불가 원칙

핵심 원칙: Admin이라도 SE 정책을 실시간으로 우회할 수 없다.

시도 결과 이유
Admin이 "이번만 한도 무시" 요청 거부 SE에 실시간 오버라이드 인터페이스 없음
Super Admin이 정책 즉시 변경 거부 쿨다운 기간 필수 (최소 24시간)
오프라인 앱에서 정책 바이패스 플래그 전달 무시 SE는 외부 제어 신호에 응답하지 않음
SE 정책 삭제 시도 거부 정책은 비활성화 불가, 값 변경만 가능

유일한 정책 변경 경로:

Admin 쿼럼 서명 → 에어갭 전달 → SE 서명 검증 → 쿨다운 대기 → 신규 정책 적용

이 원칙은 소프트웨어 1차/2차 정책 엔진의 Emergency Override와 명확히 구분된다. SW에서는 긴급 시 쿼럼 승인으로 오버라이드 가능하지만, HW에서는 어떤 상황에서도 즉시 우회 불가하다.


5. 정책 업데이트 메커니즘

5.1. 정책 변경 워크플로우

[1] 대시보드에서 SE 정책 변경 요청
     │
     ▼
[2] Admin 쿼럼 서명 수집 (최소 3-of-5)
     ├─ 변경 내용: 어떤 정책, 이전 값, 신규 값
     ├─ 변경 사유 필수 입력
     └─ 각 Admin이 자신의 콜드월렛으로 서명
     │
     ▼
[3] 정책 페이로드 생성
     ├─ 정책 데이터 (PolicyUpdate 구조체)
     ├─ Admin 쿼럼 서명 (집계 서명)
     ├─ 버전 번호 (현재 + 1)
     └─ 타임스탬프 (참조용, SE에서 신뢰하지 않음)
     │
     ▼
[4] 에어갭 전달 (QR/USB-C)
     ├─ 오프라인 앱을 통해 콜드월렛으로 전달
     └─ 콜드월렛 화면에 변경 내용 표시
     │
     ▼
[5] SE 내부 검증
     ├─ Admin 쿼럼 서명 검증 (공개키 매칭)
     ├─ 버전 번호 검증 (현재 + 1 만 수락, 롤백 방지)
     ├─ 정책 데이터 무결성 해시 검증
     └─ 검증 성공 시 → 쿨다운 시작
     │
     ▼
[6] 물리 버튼 확인
     ├─ "정책 변경: [항목] [이전값] → [신규값]"
     └─ 물리 버튼 2회 확인 (변경 인지 + 최종 승인)
     │
     ▼
[7] 쿨다운 적용
     ├─ 즉시 적용: 비활성화 (쿨다운 종료까지 이전 정책 유지)
     └─ 쿨다운 완료 후: 신규 정책 활성화

5.2. 정책 페이로드 구조

PolicyUpdate {
  version: uint32                    // 정책 버전 (단조 증가)
  target_policy: uint8               // 변경 대상 규칙 ID (0x01-0x04)
  previous_value: bytes32            // 이전 값 (검증용)
  new_value: bytes32                 // 신규 값
  admin_signatures: bytes[]          // Admin 쿼럼 서명 (각 64 bytes)
  admin_public_keys: bytes[]         // 서명한 Admin의 공개키
  quorum_threshold: uint8            // 필요 쿼럼 수 (M)
  payload_hash: bytes32              // 위 필드 전체의 SHA-256 해시
  cooldown_seconds: uint32           // 쿨다운 기간 (기본 86400 = 24시간)
}

5.3. 쿨다운 적용 전략

정책 변경 유형 기본 쿨다운 설정 가능 범위 이유
건당 한도 증가 24시간 12-72시간 한도 상향은 고위험
건당 한도 감소 즉시 적용 즉시 한도 하향은 보안 강화
일일 한도 증가 24시간 12-72시간 고위험
일일 한도 감소 즉시 적용 즉시 보안 강화
Merkle Root 업데이트 4시간 1-24시간 화이트리스트 변경 빈도 고려
서명 횟수 한도 증가 24시간 12-72시간 고위험
서명 횟수 한도 감소 즉시 적용 즉시 보안 강화

쿨다운 원칙: - 보안 강화 방향(한도 감소): 즉시 적용 (긴급 대응 가능) - 보안 약화 방향(한도 증가): 쿨다운 필수 (내부자 공격 시 탈취 시간 확보) - 쿨다운 중 추가 변경 요청: 거부 (이전 변경 완료 후에만 가능)

5.4. 펌웨어 업데이트 시 정책 데이터 보존

SE 펌웨어 업데이트 시 정책 데이터는 반드시 보존되어야 한다.

보존 전략: 1. SE 내 정책 저장 영역은 펌웨어 코드 영역과 물리적으로 분리 2. 펌웨어 업데이트 프로세스에서 정책 영역은 건드리지 않음 3. 업데이트 후 정책 무결성 검증 (해시 비교) → 불일치 시 정책 복구 요청 4. 최악의 경우 (정책 손상): 정책 재설정 필요 → Admin 쿼럼 + 키 세레모니 수준의 절차


6. SE 리소스 제약 고려사항

6.1. 저장 공간 배분

D'CENT X SE의 정책 관련 저장 공간을 다음과 같이 배분한다:

영역 크기 내용
정책 규칙 데이터 256 bytes 4개 규칙의 설정값 + 현재 카운터
Merkle Root 32 bytes 화이트리스트 Merkle Tree Root
Admin 공개키 세트 512 bytes 최대 8개 Admin 공개키 (각 64 bytes)
정책 버전/메타 64 bytes 버전 번호, 쿨다운 상태, 마지막 변경 정보
서명 검증 임시 256 bytes 정책 업데이트 서명 검증 작업 메모리
합계 ~1.1 KB SE 정책 전용 영역

6.2. 연산 성능 고려

연산 예상 소요 시간 빈도
금액 비교 (uint64) < 1ms 매 서명
Merkle Proof 검증 (depth 20) 20 × SHA-256 ≈ 50ms 매 서명
카운터 업데이트 < 1ms 매 서명
Admin 쿼럼 서명 검증 (3-of-5) 3 × ECDSA verify ≈ 300ms 정책 변경 시만
총 서명 시 정책 평가 < 100ms 매 서명

성능 목표: 정책 평가로 인한 서명 지연은 100ms 이내로, WYSIWYS 표시 시간(3초)에 비해 무시할 수 있는 수준이다.

6.3. 복잡한 규칙의 SW 위임

SE 리소스 제약으로 인해 다음 규칙은 반드시 SW(1차/2차)에서 처리:

규칙 SE 미적용 이유 SW에서 처리
시간 기반 제한 (영업시간) SE에 신뢰 가능한 RTC 없음 대시보드 서버 시간 기준
USD 환산 한도 실시간 가격 데이터 필요 대시보드에서 오라클 참조
복합 조건 (AND/OR 조합) SE 로직 복잡도 제한 대시보드 정책 엔진
정책 시뮬레이션 대량 과거 데이터 참조 필요 대시보드 서버
Travel Rule 검증 외부 API 연동 필요 대시보드 백엔드

7. 경쟁사 대비 차별화

7.1. 업계 최초 SE 레벨 정책 강제

항목 D'CENT Enterprise Fireblocks BitGo Ledger Enterprise
정책 강제 위치 SW + HW SE SW만 (서버) SW만 (서버) SW만 (관리 플랫폼)
SW 침해 시 정책 HW가 최종 방어 정책 우회 가능 정책 우회 가능 정책 우회 가능
정책 우회 가능성 물리적 접근 없이 불가 서버 해킹 시 가능 서버 해킹 시 가능 서버 해킹 시 가능
Admin 즉시 오버라이드 불가 (쿨다운 필수) 가능 가능 가능
화이트리스트 HW 검증 Merkle Root 기반 없음 없음 없음

7.2. 핵심 마케팅 메시지

"소프트웨어는 해킹할 수 있습니다. D'CENT의 하드웨어 정책 엔진은 해킹할 수 없습니다."

Fireblocks의 TAP(Transaction Authorization Policy)은 업계 최고 수준의 유연한 정책 엔진이지만, 전체가 소프트웨어에서 실행된다. Fireblocks 서버가 침해되면 모든 정책이 우회될 수 있다. D'CENT의 하드웨어 정책 엔진은 SE 내부에서 실행되므로, 인프라 전체가 침해되어도 하드웨어가 마지막 방어선으로 기능한다.


8. 펌웨어 요구사항 요약 (Phase 6 연계용)

8.1. SE 펌웨어 요구사항

ID 요구사항 우선순위 연계
FW-POLICY-01 건당 금액 비교 로직 (uint64 기반) 필수 섹션 3.1
FW-POLICY-02 Merkle Proof 검증 로직 (SHA-256 × 20 depth) 필수 섹션 3.2
FW-POLICY-03 일일 누적 카운터 (서명 횟수 기반 리셋) 필수 섹션 3.3
FW-POLICY-04 서명 횟수 Rate Limit (슬라이딩 윈도우) 필수 섹션 3.4
FW-POLICY-05 위반 사유 코드 체계 (8종) 필수 섹션 4.1
FW-POLICY-06 정책 업데이트 서명 검증 (Admin 쿼럼) 필수 섹션 5.1
FW-POLICY-07 쿨다운 타이머 (서명 횟수 기반) 필수 섹션 5.3
FW-POLICY-08 정책 데이터 보존 (펌웨어 업데이트 시) 필수 섹션 5.4
FW-POLICY-09 정책 위반 화면 표시 (위반 유형별 메시지) 필수 섹션 4.2
FW-POLICY-10 버전 관리 및 롤백 방지 (단조 증가) 필수 섹션 5.2

8.2. SE 리소스 요구사항

항목 요구 사양 비고
정책 저장 영역 1.1 KB (펌웨어 영역과 분리) 펌웨어 업데이트 시 보존
Merkle 검증 작업 메모리 1 KB depth 20 기준
정책 평가 시간 < 100ms WYSIWYS 파싱 전 평가 완료
서명 횟수 카운터 32-bit (4 bytes × 3 카운터) 오버플로 전 리셋

9. Phase 3 정책 엔진과의 연계

본 문서는 Phase 3 policy-engine.md에서 정의한 3중 방어 체계의 3차 계층을 상세화한 것이다.

Phase 3 정의 본 문서 상세화
"(3) Hardware — 콜드월렛 SE — Phase 4 DIF-02 범위" SE 내부 4개 규칙, 평가 로직, 위반 처리 전체 설계
"하드웨어 정책 엔진에 정책 룰셋 동기화" 에어갭 경유 정책 페이로드 전달 + Admin 쿼럼 서명 검증 메커니즘
"4-Tier 금액 에스컬레이션" SE는 Tier와 무관한 절대 상한만 적용 (Tier는 SW 책임)
"단락 평가(Short-Circuit)" SE도 화이트리스트 → 금액 → 일일 → 횟수 순서로 단락 평가

Phase 5 System Architecture Design에서 정책 페이로드의 바이트 수준 포맷과 SE-앱 간 통신 프로토콜이 추가로 명세되어야 한다.


본 문서는 Phase 4 Differentiation & Extended Architecture의 일부로, D'CENT 엔터프라이즈의 "하드웨어가 마지막 방어선" 차별화를 기술적으로 설계한다. Phase 3 정책 엔진(policy-engine.md)의 3차 계층 상세화이며, Phase 6 펌웨어 요구사항의 입력 문서가 된다.


관련 문서