제 3 장: 오프라인 인가 프로토콜

본 장은 Authorization_Descriptor의 완전한 라이프사이클 프로토콜 흐름을 정의한다. 발급, 로컬 보관, 검증, 폐기, 갱신의 5 단계를 포함한다. 본 장의 흐름은 블루프린트 §2.1의 설계 의도에 대응한다.

3.1 발급 흐름(Issuance)

발급 흐름은 Descriptor_Issuer가 인가자의 명시적 인가를 받은 후 실행한다. 본 사양은 발급 결과의 형식 제약을 정의하지만, 인가자와 Descriptor_Issuer 간의 구체적 상호작용 방식은 규정하지 않는다(서로 다른 배포는 Web 폼, 모바일 App 인가, 기업 인가 관리 시스템 등 서로 다른 형식을 채택할 수 있다).

3.1.1 발급 입력

Descriptor_Issuer는 발급 시 MUST 다음 정보를 확인한다:

  1. 인가자 신원(grantor_id)이 Descriptor_Issuer 자체의 신원 검증 메커니즘을 통과함
  2. 인가 범위(대상 subject_fay_id, terminal_id, grants)가 인가자에 의해 명시적으로 지정됨
  3. 유효 기간(not_before, not_after)이 인가자에 의해 명시적으로 지정되거나 기본 정책 채택

3.1.2 발급 단계

Descriptor_Issuer는 MUST 다음 단계로 Authorization_Descriptor를 생성한다:

  1. 식별자 생성: 새 descriptor_id(UUID v7)를 할당, MUST NOT 이미 사용된 ID를 재사용한다
  2. 페이로드 구축: §2.3.2에 따라 DescriptorPayload를 채우며, 모든 required 필드를 MUST 설정한다
  3. 제약 검증: not_after - not_before ≤ 90일 등의 제약을 로컬 검증한다(§2.3.2 참조)
  4. CBOR 시리얼라이제이션: RFC 8949 결정적 인코딩으로 payload를 시리얼라이즈한다
  5. 디지털 서명: Descriptor_Issuer 개인 키를 사용하여 §8 정의의 알고리즘으로 payload 바이트를 서명한다
  6. 구조 조립: 완전한 AuthorizationDescriptor를 구축, version, payload, signature를 포함한다
  7. 기록 등록: Descriptor_Issuer 내부 상태 저장소에 해당 자격 증명을 등록한다(후속 폐기 관리용)

3.1.3 발급 후 전달

발급 완료 후, Descriptor_Issuer는 Authorization_Descriptor를 대상 Fay에 전달한다. 전달 방식은 본 사양의 범위를 벗어나지만, SHOULD 다음을 충족한다:

  1. 암호화 채널을 통해 전달하여, 전송 과정에서 자격 증명이 가로채지지 않도록 한다
  2. Fay가 소속된 iFay_Runtime에 전달하여, iFay_Runtime이 대리 보유한다

3.2 로컬 보관 흐름(Local Storage)

Fay는 iFay_Runtime을 통해 Authorization_Descriptor를 대상 단말에 제출하여 로컬 보관을 수행한다.

3.2.1 제출 메시지

iFay_Runtime은 Protocol_Engine에 DescriptorSubmit 메시지를 전송한다:

DescriptorSubmit (body of ProtocolMessage) {
  required descriptor : AuthorizationDescriptor
}

3.2.2 단말 처리

단말은 DescriptorSubmit를 받은 후 MUST 다음 순서로 처리한다:

  1. 구조 검증: descriptor가 §2.3에서 정의된 구조에 부합하는지 검증
  2. 서명 검증: 대응하는 key_id의 Verification_Key를 사용하여 signature를 검증(§3.3.4 참조)
  3. 중복 확인: 로컬에 동일 descriptor_id의 자격 증명이 이미 보관되어 있고, 새로 제출된 내용이 이미 보관된 것과 바이트 레벨에서 일치하면 성공 반환; 그렇지 않으면 중복 ID 에러로 거부
  4. 보관: Authorization_Descriptor를 로컬 안전 보관 영역에 암호화 보관(§3.2.3 참조)
  5. 결과 반환: iFay_Runtime에 DescriptorSubmitResult 메시지를 반환하며, 성공 또는 에러 코드를 포함한다

3.2.3 보관 요구사항

단말은 MUST:

  1. Authorization_Descriptor를 암호화 보관하며, 암호화 키는 미인가 프로세스가 읽을 수 없다
  2. 보관 매체는 SHOULD 물리적 분해 방지 능력을 갖춘다(보안 칩, TEE 등)
  3. 보관 용량 상한은 SHOULD 1024 개 이상의 자격 증명; 상한 초과 시 LRU 정책으로 만료된 자격 증명을 도태한다

단말은 MUST NOT:

  1. Authorization_Descriptor를 평문 형식으로 보관한다
  2. 보관 전에 descriptor의 어떤 필드도 수정한다(metadata 포함)

3.2.4 에러 코드

에러 코드발동 조건
E_INVALID_STRUCTURE구조가 §2.3에 부합하지 않음
E_INVALID_SIGNATURE서명 검증 실패
E_UNKNOWN_ISSUERkey_id에 대응하는 Verification_Key가 단말에 미등록
E_DUPLICATE_DESCRIPTOR_ID이미 보관된 descriptor_id와 충돌하며 내용 불일치
E_STORAGE_FULL보관 용량 만 차고 도태 불가
E_VALIDITY_OUT_OF_RANGEnot_after - not_before가 제한 초과

3.3 검증 흐름(Validation)

검증 흐름은 매번 리소스 접근 요청 시 실행된다. 본 절은 검증의 완전한 단계와 판정 규칙을 정의한다.

3.3.1 검증 발동

iFay_Runtime이 AuthRequest를 전송하여 리소스 접근을 요청하면, 단말 Protocol_Engine은 검증 흐름을 발동한다:

AuthRequest (body of ProtocolMessage) {
  required fay_id        : Fay_ID
  required resource_id   : Resource_ID
  required access_mode   : AccessMode
  required credential    : CredentialReference
}

CredentialReference {
  required type : enum["descriptor", "ticket"]
  required id   : string                      // descriptor_id 또는 jti
}

주의: 본 사양의 오프라인 인가 시나리오에서, credential이 참조하는 것은 단말에 이미 보관된 Authorization_Descriptor이며, 요청 중에 완전한 자격 증명을 전송할 필요가 없다.

3.3.2 검증 단계(순서대로 실행)

단말은 MUST 다음 순서로 검증을 실행한다. 임의 단계 실패 시 즉시 대응하는 에러 코드를 반환하며, 후속 단계를 실행하지 않는다.

단계 1: 자격 증명 존재성

단말은 로컬 보관에서 credential.id에 대응하는 Authorization_Descriptor를 검색한다.

  • 미발견 → E_DESCRIPTOR_NOT_FOUND 반환

단계 2: 폐기 상태

단말은 로컬 폐기 목록을 확인하여, 해당 descriptor_id가 미폐기 상태임을 확인한다.

  • 폐기됨 → E_DESCRIPTOR_REVOKED 반환

단계 3: 유효 기간

단말은 현재 시각이 [not_before, not_after] 구간 내에 있는지 확인한다.

  • 현재 시각 < not_beforeE_DESCRIPTOR_NOT_YET_VALID 반환
  • 현재 시각 ≥ not_afterE_DESCRIPTOR_EXPIRED 반환

단말 시계 출처: MUST 보정된 시스템 시계를 사용한다. 단말은 SHOULD 장시간 미온라인 시 검증 요청을 신중히 처리한다(§3.6 시계 드리프트 처리 참조).

단계 4: 주체 매칭

단말은 payload.subject_fay_id == AuthRequest.fay_id를 검증한다.

  • 불일치 → E_SUBJECT_MISMATCH 반환

단계 5: 단말 매칭

단말은 payload.terminal_id == 현재 단말 ID를 검증한다.

  • 불일치 → E_TERMINAL_MISMATCH 반환

단계 6: 리소스와 모드 매칭

단말은 payload.grants를 순회하여, 다음 조건을 충족하는 Grant를 검색한다:

  1. Grant.resource_pattern이 §2.3.5 규칙에 따라 AuthRequest.resource_id와 매칭
  2. Grant.modesAuthRequest.access_mode를 포함
  3. Grant.constraints가 비어 있지 않은 경우, 모든 제약 조건이 충족됨(제약 시맨틱은 §7.4 참조)
  • 충족하는 Grant를 찾을 수 없음 → E_AUTHORIZATION_INSUFFICIENT 반환

단계 7: 서명 검증

단말은 signature.key_id에 대응하는 Verification_Key로 payload의 서명을 재검증한다.

주의: 단계 1–6의 빠른 검증 완료 후에 서명 검증을 실행하여, 합리적인 실패 시맨틱을 제공한다(예: "자격 증명 폐기됨"을 "서명 실패"보다 먼저 알림). 다만 검증 통과 후 성공을 반환하기 전에, 서명 검증은 MUST 실행되고 통과되어야 한다.

  • 서명 검증 실패 → E_INVALID_SIGNATURE 반환
  • 서명 키 폐기 또는 만료 → E_VERIFICATION_KEY_INVALID 반환

3.3.3 검증 통과 후

7 단계 모두 통과 후, 단말은 제 5 장 흐름에 따라 Session을 생성하고, iFay_Runtime에 다음을 반환한다:

AuthResult (body of ProtocolMessage, success) {
  required status         : "granted"
  required session_id     : Session_ID
  required granted_modes  : array<AccessMode>
  required session_expires_at : timestamp
}

session_expires_at은 SHOULD min(not_after, 현재 시각 + 기본 세션 최대 시간)과 같다.

3.3.4 서명 검증 세부사항

서명 검증의 구체적 단계:

  1. descriptor.signature.key_id를 추출하고, 단말 Verification_Key 보관소에서 대응하는 공개 키를 검색한다
  2. 해당 Verification_Key가 현재 시각에 유효함을 검증한다(valid_from ≤ 현재 시각 ≤ valid_until, valid_until이 설정된 경우)
  3. §2.3.3 규칙에 따라 descriptor.payload를 다시 CBOR 시리얼라이즈한다
  4. Verification_Key와 descriptor.signature.algorithm을 사용하여 시리얼라이즈 바이트의 서명을 검증한다
  5. 검증 성공 후 MUST 결과를 캐시한다(동일 descriptor는 라이프사이클 내에서 한 번만 서명 검증이 필요)

3.4 폐기 흐름(Revocation)

3.4.1 폐기 발동

인가자는 Descriptor_Issuer를 통해 폐기 요청을 발동한다. 폐기 요청의 구체적 상호작용 형식은 본 사양의 범위를 벗어난다.

Descriptor_Issuer는 폐기 요청을 받은 후 MUST:

  1. 폐기 요청이 원래 인가자 또는 폐기 권한을 가진 엔티티에서 온 것임을 검증
  2. §2.8에 따라 RevocationStatement를 생성
  3. 원본 Authorization_Descriptor와 동일한 서명 키로 폐기 선언에 서명
  4. 폐기 선언을 Descriptor_Issuer가 유지하는 폐기 목록에 추가

3.4.2 폐기 배포

폐기 선언은 다음 방식으로 단말에 배포되며, 단말은 MUST 최소 두 가지를 지원한다:

  1. 풀 동기화(Pull-based): 단말은 온라인 시 Descriptor_Issuer 또는 폐기 서비스에서 증분 폐기 목록을 능동적으로 풀한다. 동기화 빈도는 단말 정책으로 결정되며, SHOULD 1 시간에 1 회 이상(온라인 기간)
  2. 푸시 알림(Push-based): Descriptor_Issuer는 Registration_Authority 또는 전용 폐기 배포 서비스를 통해 폐기 선언을 단말에 푸시한다
  3. 자격 증명 내장(In-band): Trusted_Ticket의 metadata에 최근 폐기 목록의 요약을 휴대하여, 온라인 기간에 획득한 티켓이 자동으로 폐기 정보를 함께 가지도록 한다

3.4.3 단말 폐기 목록 유지

단말의 로컬 폐기 목록은 MUST:

  1. 모든 미만료 폐기 선언을 영구 보관한다
  2. 자격 증명의 not_after 시각이 지난 후, 대응하는 폐기 선언을 MAY 삭제할 수 있다(자격 증명은 자연 만료됨)
  3. 각 폐기 선언의 서명을 검증하며, 무효 서명의 폐기 선언을 거부한다

3.4.4 폐기 발효 시각

폐기 선언의 발효 시각은:

발효 시각 = max(폐기 선언이 단말에 도달한 시각, RevocationStatement.revoked_at)

단말은 MUST 폐기 선언 도달 후 다음 검증 요청에서 즉시 해당 자격 증명을 거부함을 보장한다. 단말은 MAY 모든 활성 Session이 폐기된 자격 증명을 참조하는지 능동적으로 확인하고, 그러한 경우 제 5 장 규칙에 따라 이러한 Session을 강제 종료한다.

3.4.5 폐기 지연 윈도우

오프라인 배포의 고유 지연으로 인해, 다음의 불가피한 폐기 지연 윈도우가 존재한다:

시나리오최대 지연
단말 지속 온라인1 동기화 주기(기본 ≤ 1 시간)
단말 단기 오프라인재온라인 후 다음 동기화
단말 장기 오프라인최대 지연은 자격 증명의 not_after - 폐기 시각이지만, 90 일(자격 증명 최대 유효 기간)을 초과하지 않음

발급자는 SHOULD 더 짧은 not_after(예: 7 일)를 설정하여 최대 폐기 지연을 제한한다.

3.5 갱신 흐름(Renewal)

갱신은 본질적으로 새 Authorization_Descriptor를 발급하여 구버전을 대체하는 것이며, 기존 자격 증명을 수정하는 것이 아니다.

3.5.1 갱신 정책

인가자 또는 자동 갱신 메커니즘은 다음 시나리오에서 갱신을 발동할 수 있다:

  1. 자격 증명이 not_after에 가까워지고 인가 관계가 여전히 유효
  2. 인가 범위 조정 필요(grants 추가/삭감)
  3. 인가 제약 조정 필요(constraints 수정)

3.5.2 갱신 흐름

갱신 프로세스:

  1. Descriptor_Issuer는 §3.1 흐름에 따라 새 descriptor_id를 사용하여 새 Authorization_Descriptor를 발급한다
  2. 새 자격 증명은 §3.2 흐름에 따라 단말에 제출 및 보관된다
  3. 구 자격 증명은 MAY 발급자가 능동적으로 폐기(§3.4에 따름) 또는 MAY 자연 만료로 실효된다

단말은 신구 자격 증명 병존 기간 동안 처리 우선순위:

  • 검증 요청은 MUST 미만료 자격 증명을 우선 매칭
  • 여러 미만료 자격 증명이 모두 매칭되는 경우, issued_at이 가장 최근인 자격 증명을 사용

3.5.3 허용되지 않는 갱신 동작

구현은 MUST NOT:

  1. 이미 발급된 자격 증명의 어떤 필드도 수정한다(metadata 포함)
  2. 구 자격 증명의 descriptor_id를 재사용한다
  3. 구 자격 증명이 여전히 유효한 기간에 그 시맨틱을 수정한다(폐기 + 신규 발급으로 실현해야 함)

3.6 시계 드리프트 처리

단말 시계는 장기 오프라인 또는 하드웨어 문제로 인해 드리프트할 수 있다. 본 절은 시계 드리프트 상황 하의 처리 규칙을 정의한다.

3.6.1 시계 허용 오차

단말은 유효 기간 검증 시 MAY 허용 오차를 도입할 수 있다:

  • not_before에 대해: 최대 5분의 조기 허용 오차를 허용할 수 있다(현재 시각 ≥ not_before - 5min을 수용)
  • not_after에 대해: MUST NOT 허용 오차를 도입한다(만료는 만료)

허용 오차는 단기 시계 편차의 보정에만 사용되며, 유효 기간 제약 우회에 사용되어서는 안 된다.

3.6.2 시계 신뢰성

단말은 SHOULD 다음 시계 이상을 감지하고 보호 조치를 취한다:

  • 시계 현저 후퇴(시스템 시계가 과거로 > 1시간 점프): 시계 동기화까지 검증 요청 거부
  • 시계 현저 전진(시스템 시계가 미래로 > 24시간 점프): 시계 동기화까지 검증 요청 거부

3.7 완전 흐름도

[Descriptor_Issuer]                    [Fay/iFay_Runtime]                   [Terminal/Protocol_Engine]
        │                                       │                                       │
        │── AuthorizationDescriptor 발급 ─────→│                                       │
        │   (디지털 서명 포함)                  │                                       │
        │                                       │                                       │
        │                                       │── DescriptorSubmit ─────────────────→│
        │                                       │                                       │── 서명 검증 + 보관
        │                                       │←─ DescriptorSubmitResult ──────────── │
        │                                       │                                       │
        │                                       │── AuthRequest(descriptor_id 포함)──→│
        │                                       │                                       │── 7 단계 검증
        │                                       │←─ AuthResult(granted)────────────────│
        │                                       │                                       │── Session 생성
        │                                       │                                       │
        │                                       │       【Fay 지속적 리소스 접근】     │
        │                                       │                                       │
        │── RevocationStatement 폐기 ──────────────────────────────────────────────────→│
        │                                       │                                       │── 폐기 목록에 추가
        │                                       │                                       │── 관련 Session 강제 종료