이 번역은 참고용입니다. 정식 기준은 영어판이며, 내용이 다를 경우 영어판이 우선합니다. 영어판 읽기

레코드

Label 309 와이어 포맷 — 레코드가 메타데이터 라벨 309 아래에 놓이는 위치, 맵 구조, 정규 CBOR 규칙, 전송 청크 분할, 그리고 CDDL 스키마를 정의합니다.

Label 309 레코드는 Cardano 트랜잭션 메타데이터 안에 라벨 309 아래로 실리는 하나의 CBOR 맵입니다. 이 맵은 하나 이상의 콘텐츠 해시를 체인에 기록합니다. 트랜잭션의 블록 시각이, 그 바이트들이 늦어도 그 시점에는 존재했다는 사실의 증인이 됩니다. 레코드가 추가로 담을 수 있는 그 밖의 모든 것 — 스토리지 URI, 암호화 봉투, 작성자 서명, 대체 포인터 — 은 모두 이 핵심 주장에 부수하는 선택적 메타데이터입니다.

이 페이지는 와이어 상의 형태를 정의합니다. 레코드가 어디에 놓이는지, 어떻게 인코딩되는지, 지나치게 큰 값이 어떻게 전송되는지, 그리고 구조 검증기가 대조하는 닫힌 스키마가 무엇인지를 다룹니다. 여기서 참조하는 암호 구성(해시 알고리즘, 봉인된 봉투, 서명)에는 각각 전용 페이지가 있습니다. 이 페이지가 다루는 것은 와이어 포맷입니다.

레코드가 놓이는 위치

PoE 레코드는 트랜잭션 메타데이터 라벨 309 아래에 놓여야 합니다(MUST). 이 라벨은 CIP-10 메타데이터 라벨 레지스트리 에 "Proof of Existence record"로 예약되어 있습니다. 트랜잭션 메타데이터는 정수 라벨에서 값으로의 맵이므로, 하나의 트랜잭션은 둘 이상의 PoE 레코드를 실어서는 안 됩니다(MUST NOT). 트랜잭션마다 정확히 하나의 레코드입니다.

트랜잭션은 다른 라벨 아래에 추가 메타데이터를 실을 수 있습니다(MAY). 예를 들어 CIP-20674 메시지 등입니다. PoE를 처리하는 검증자는 309 이외의 모든 라벨을 무시해야 합니다(MUST).

Conway 시대 원장에서 트랜잭션 메타데이터는 트랜잭션의 auxiliary_data 안에 있는 metadata 필드입니다. 어떤 라벨 아래에서든 허용되는 값은 원장의 재귀적 metadatum 타입 — 정수, 바이트 문자열, 텍스트 문자열, 배열, 맵 — 으로 제한되며, 바이트 문자열과 텍스트 문자열은 각각 최대 64바이트입니다.

CDDL
metadatum =
    { * metadatum => metadatum }
  / [ * metadatum ]
  / int
  / bstr .size (0..64)
  / tstr .size (0..64)

64바이트를 초과하는 단일 bstr 또는 tstr을 담은 트랜잭션은, 어떤 검증자의 눈에 닿기 전에 제출 시점에서 Cardano 노드에 의해 거부됩니다. 바로 이 상한이 Label 309가 전송 청크 분할 규율(아래)을 정의하는 이유입니다. 레코드가 싣는 모든 필드는 — 기본 필드든 확장 필드든 — metadatum으로 환원될 수 있어야 합니다.

전송: 본문 전체 청크 배열

직렬화된 레코드 본문은 통상적으로 64바이트를 초과하므로, 라벨 309 아래에 맨값으로 저장할 수 없습니다. 그래서 레코드 본문은 불투명한 본문 전체 청크 배열로 실립니다. 이는 ≤ 64바이트 바이트 문자열(bstr .size (1..64))로 이루어진 단일 CBOR 배열이며, 그 순서대로의 연결이 레코드 본문 그 자체입니다. 이 전송 분할이 Label 309가 수행하는 유일한 청크 분할이며, 이 포맷에서 진정으로 원장에 의해 강제되는 유일한 단계입니다.

원장은 이 전송 배열만 볼 뿐, 재조립된 본문 내부의 필드는 결코 보지 않습니다. 그래서 그 필드들은 필드별 청크 래퍼도, 필드 수준의 64바이트 상한도 없는 평범한 CBOR 값입니다. 스토리지 URI는 단일 텍스트 문자열, COSE_Sign1은 단일 바이트 문자열, X-Wing의 kem_ct는 단일 1120바이트 바이트 문자열입니다. 64바이트를 초과하는 필드는, 본문의 다른 어떤 구간과도 마찬가지로 본문 전체 배열의 청크 경계를 넘나들며 실릴 뿐입니다.

생산자는 레코드 본문을 정규 CBOR로 한 번만 직렬화하고, 그 바이트 문자열을 1바이트 에서 64바이트의 청크로 분할하며, 그렇게 얻은 확정 길이 바이트 문자열로 이루어진 확정 길이 배열을 라벨 309의 값으로 저장해야 합니다(MUST). 배열 형태는 64바이트 이하의 본문이라도 항상 필수입니다. 그러한 본문도 길이 1짜리 배열이며, 맨 맵이나 맨 바이트 문자열이 아닙니다. 생산자는 최소 분할(마지막을 제외한 모든 청크를 정확히 64바이트로 함)을 사용해야 하며(SHOULD), 길이 0짜리 청크를 내보내서는 안 됩니다(SHOULD NOT). 과도한 청크 분할은 아무런 이점도 없이 트랜잭션 바이트를 낭비합니다.

검증자는 구조 검증을 수행하기 전에 배열 요소를 순서대로 바이트 연결하여 레코드 본문을 재조립해야 하며(MUST), 그러한 배열이 아닌 라벨 309 값은 모두 거부해야 합니다(MUST). 청크 경계는 어떠한 의미도 담지 않습니다. 연결 결과가 바이트 단위로 동일한 두 전송 배열은 같은 레코드를 나타냅니다. 운반 오류 분류 체계가 거부 코드를 못박습니다. 64바이트를 초과하는 청크는 CHUNK_TOO_LARGE이고, 바이트 문자열이 아닌 배열 요소, 불확정 길이 배열 또는 요소, 배열이 아닌 라벨 309 값(맨 맵, 맨 바이트 문자열, 정수)은 MALFORMED_CBOR입니다. 길이 0짜리 청크는 어떤 바이트도 기여하지 않으며, 그 자체로 거부되지 않고 허용됩니다.

스키마는 재조립된 본문을 기술합니다

아래의 모든 것 — 레코드 맵, CDDL, 필드 규칙 — 은 청크 재조립 이후의 레코드 본문을 기술합니다. 본문 전체 청크 배열은 스키마의 일부가 아닙니다. 그것을 먼저 풀어낸 다음, 본문을 검증합니다.

레코드 맵

재조립된 레코드 본문은 CBOR 맵입니다. 정수 값 필드는 CBOR 메이저 타입 0/1, 텍스트 필드는 메이저 타입 3이며 유효한 UTF-8이어야 합니다(MUST). 바이트 필드는 메이저 타입 2, 배열은 메이저 타입 4, 중첩된 맵은 메이저 타입 5입니다. 존재하는 선택적 필드는 빈 값을 담아서는 안 됩니다(MUST NOT).

최상위 구조는 다음과 같습니다.

타입상태의미
vuintREQUIRED스키마 버전. 이 문서는 v = 1을 정의합니다.
items아이템 맵의 배열OPTIONAL콘텐츠별 커밋먼트 — 콘텐츠와 해싱 참조.
merkle커밋먼트의 배열OPTIONAL오프체인 리프 목록을 하나의 루트에 묶는 목록 커밋먼트.
supersedesbytes (32)OPTIONAL이 레코드가 대체하는 선행 레코드의 트랜잭션 해시.
sigs서명 맵의 배열OPTIONAL레코드 수준의 작성자 서명 — 서명 참조.
crit텍스트 문자열의 배열OPTIONAL반드시 이해해야 하는 확장 키.

적합한 레코드는 items(엔트리 1개 이상) 또는 merkle(엔트리 1개 이상) 가운데 적어도 하나에 커밋해야 합니다(MUST). 둘 다 담지 않거나 — 또는 둘 중 하나를 빈 배열로 담은 — 레코드는 빈 레코드로 거부됩니다. 이 규칙을 제외하면 itemsmerkle은 직교합니다. 레코드는 둘 중 하나만 담을 수도, 둘 다 함께 담을 수도 있습니다.

Label 309는 엔트리 수에 수치적 상한을 두지 않습니다. 유일한 천장은 그 시점에 유효한 Cardano 최대 트랜잭션 크기이며, 생산자는 바이트 단위 수수료를 지불하므로 레코드 크기는 자연스럽게 억제됩니다. 검증기는 원장의 크기 제한 안에 들어맞는 한, 단지 엔트리가 많다는 이유만으로 레코드를 거부해서는 안 됩니다(MUST NOT).

버전 필드

v는 CBOR 부호 없는 정수이며, 시맨틱 버전 문자열이 아닙니다. 이 문서가 정의하는 것은 정확히 v = 1뿐입니다. 검증기는 지원 집합을 벗어난 v를 가진 레코드를 타입이 지정된 오류로 거부해야 하며(MUST), 패닉이나 비정상 종료를 일으키거나 그 레코드를 다른 메타데이터 스키마로 묵시적으로 취급해서는 안 됩니다(MUST NOT). v 정수는 어떤 변경이 v1 파서로 하여금 레코드를 잘못 해석하게 만들 때에만 올라갑니다. 추가적이고 네임스페이스화된 확장은 그것을 올리지 않습니다.

Items

items의 각 엔트리는 하나의 필수 필드와 두 개의 선택적 필드를 가진 CBOR 맵입니다.

  • hashes — REQUIRED. 해시 알고리즘 식별자에서 원시 32바이트 다이제스트로의 비어 있지 않은 맵. 적어도 1개의 엔트리가 필요합니다. CBOR 맵 키는 고유하므로 알고리즘 중복은 구조적으로 일어날 수 없습니다. 콘텐츠와 해싱 참조.
  • uris — OPTIONAL. 발견용 URI의 복수형 목록(규칙은 아래 참조).
  • enc — OPTIONAL. 봉인된 아이템의 암호화 봉투. 봉인된 PoE 참조.

아이템별 서명 슬롯은 없습니다. 작성자는 레코드 수준에서만, 모든 아이템을 균일하게 포괄하는 sigs[] 엔트리에 의해 표현됩니다.

Merkle 커밋먼트

merkle의 각 엔트리는 정규 해시 트리 구성을 통해 레코드를 32바이트 리프의 순서가 정해진 목록에 묶습니다. 이로써 체인 위의 하나의 32바이트 루트가 임의로 큰 오프체인 리프 목록을 대신할 수 있습니다. 커밋먼트는 닫힌 맵입니다.

필드타입상태의미
algtstrREQUIRED등록된 목록 커밋먼트 알고리즘 식별자.
rootbytes (32)REQUIRED생산자의 순서가 정해진 리프 목록에 대한 정규 루트.
leaf_countuintREQUIRED커밋된 리프의 수. 루트를 목록 크기에 묶습니다.
urisURI 목록OPTIONAL오프체인 리프 목록 파일의 콘텐츠 주소 지정 URI.

Merkle 루트는 리프 목록 구조에 커밋하는 반면, hashes 엔트리는 평문 바이트에 커밋합니다. 둘은 서로 다른 방식으로 검증됩니다(포함 증명 대 평문 재계산). 이것이 목록 커밋먼트가 아이템 안이 아니라 최상위에 놓이는 이유입니다. 목록 커밋먼트 레지스트리는 콘텐츠 해시 레지스트리와 서로 분리되어 있습니다 — 알고리즘 레지스트리 참조.

Supersedes

supersedes는 하나의 더 이른 Label 309 레코드를 가리키는, 선택적 32바이트 Cardano 트랜잭션 해시입니다. 이는 서비스에 의존하지 않는 추가 전용 링크로서, 후속 레코드가 오프체인 데이터베이스나 벤더 레코드 ID 없이 선행 레코드를 가리킬 수 있게 합니다.

대체(supersedence)는 선행 레코드를 제거·취소·무효화하지 않습니다. 체인은 추가 전용이며, 검증자는 더 이른 레코드를 여전히 존재하고 독립적으로 검증 가능한 것으로 계속 취급해야 합니다(MUST). 이 포인터에는 이유나 자유 텍스트 필드가 없습니다. 어떤 인간적 의미(정정, 교체, 철회)든 라벨 309가 아니라 새로운 콘텐츠에 담겨야 합니다. 포인터를 해소하는 검증자는 그것을 담은 트랜잭션과 동일한 Cardano 네트워크에서 조회해야 합니다(MUST). 트랜잭션 해시는 자신의 네트워크 안에서만 고유하므로, 이 필드에는 네트워크 식별자가 담기지 않습니다.

서명

sigs는 레코드 수준 서명 엔트리로 이루어진 선택적 배열입니다. 각 엔트리는 레코드 본문 — 즉 sigs를 제거한 전체 레코드 맵 — 에 대한 분리형(detached) COSE_Sign1 구조를 담고, 지갑 서명 경로를 위해서는 선택적으로 서명자의 공개 키도 담습니다. 하나의 서명이 본문 전체를 증명합니다. 즉 모든 아이템, 모든 URI, 모든 봉투, (존재한다면) 대체 포인터, 그리고 모든 확장 키를 증명합니다. 서명은 언제나 선택적이며, 인식되지 않는 서명 알고리즘이 콘텐츠 주장을 무효로 만드는 일은 결코 없습니다. 서명되는 페이로드, 도메인 분리 접두사, 서명자 키 해소, 그리고 엄격한 검증 규칙은 서명에서 규정됩니다.

URI 규칙

uris는 존재할 때 비어 있지 않은 목록이며, 각 엔트리는 정확히 하나의 URI를 담는 단일 CBOR 텍스트 문자열입니다. URI별 길이 상한도, 감싸는 형태도 없습니다. 본문 전체 전송이 이미 원장의 64바이트 문자열 상한을 충족하므로, 긴 ipfs://<CIDv1>/<path> URI도 다른 어떤 텍스트 문자열과 마찬가지로 하나의 텍스트 문자열입니다. 각 URI는 절대 URI여야 하며(MUST), 스킴과 계층 부분을 포함해야 하고(MUST), 프래그먼트 식별자를 포함해서는 안 됩니다(MUST NOT). PoE는 콘텐츠 바이트에 관한 주장이지 문서의 하위 구성요소에 관한 주장이 아니기 때문입니다.

v1 스킴 집합은 닫혀 있고 콘텐츠 주소 지정 방식입니다.

스킴비고
ar://Arweave 트랜잭션 ID(43자 base64url). 형식 ar://<txid>.
ipfs://IPFS CID, CIDv1 권장. 형식 ipfs://<cid> 또는 ipfs://<cid>/<path>.

생산자는 다른 어떤 스킴도 내보내서는 안 됩니다(MUST NOT). https://, http://, file://, data: 등은 모두 거부됩니다. 이 제한은 의도적인 것이지 일시적인 것이 아닙니다. 콘텐츠 주소 지정 URI는 스토리지 계층의 무결성 모델을 통해 가져온 바이트를 URI 자체에 묶습니다(IPFS CID는 콘텐츠의 멀티해시이며, Arweave 트랜잭션 ID는 Arweave 합의 아래 데이터에 커밋합니다). 그래서 검증자는 DNS, TLS, 게이트웨이, 인증 기관을 신뢰하지 않고도 "내가 가져온 바이트가 생산자가 커밋한 바로 그 바이트다"라는 사실을 확인할 수 있습니다. 집합 밖의 스킴은 레코드를 구조적으로 무효로 만들며, 결코 valid로 검증을 통과하지 않습니다.

uris는 처음부터 끝까지 선택적입니다. uris를 생략한 해시 전용 레코드도 완결된 주장입니다. 콘텐츠의 존재는 검색 경로에 커밋하지 않고도 단언할 수 있습니다. 정확한 CID 프로파일(허용되는 멀티베이스 접두사, 코덱, 멀티해시)은 검증 규칙의 일부입니다. 검증 참조.

정규 CBOR

모든 Label 309 레코드는 RFC 8949 §4.2.1(Core Deterministic Encoding)에 따라 정규 CBOR로 인코딩되어야 합니다(MUST). 구체적으로 다음과 같습니다.

  1. 모든 정수에 대해 선호되는(최단 형식) 직렬화.
  2. 모든 바이트 문자열, 텍스트 문자열, 배열, 맵에 대해 확정 길이 인코딩.
  3. 시맨틱 태그 없음(이 문서는 어떤 태그도 필요로 하지 않습니다 — bignum 태그 2/3은 나타나서는 안 됩니다(MUST NOT)).
  4. 맵 키는 그 CBOR 인코딩의 바이트 사전식 순서로 정렬.
  5. 바이트 순서 표시(byte-order mark)가 없는 UTF-8 텍스트 문자열.
  6. 어떤 맵에도 중복 키 없음.
  7. 부동소수점이나 비자명한 단순 값 없음 — 레코드는 정수, 바이트 문자열, 텍스트 문자열, 배열, 맵, 그리고 (스키마가 허용하는 경우) true/false/null만 담습니다. 메이저 타입 7 부동소수점(정수 값 1.0을 포함), 음의 0, 그리고 undefined는 강제 변환이 아니라 거부되어야 합니다(MUST).

결정성이야말로 이 포맷을 상호운용 가능하게 만드는 것입니다. 같은 논리적 레코드를 표현하는 두 생산자는 바이트 단위로 동일한 바이트를 내보내므로, 한 구현이 본문에 대해 계산한 서명이 다른 구현에서도 검증됩니다. 검증기는 정규가 아닌 인코딩을 거부해야 합니다(MUST). 익스플로러와 지갑은 메타데이터를 JSON 투영을 통해 표시할 수 있으나, 적합한 검증자는 손실을 동반한 JSON 재인코딩이 아니라 원본 트랜잭션 CBOR를 검증해야 합니다(MUST).

전방 호환성

Label 309 v1은 닫힌 기본 키 집합 v, items, merkle, supersedes, sigs, crit을 예약합니다. 레코드는 추가로, 이름이 다음 두 예약 네임스페이스 중 하나에 일치하는 확장 키를 담을 수 있습니다(MAY).

  • ^x-.+ — 벤더 / 실험용 네임스페이스.
  • ^[a-z]+-.+ — 동반 명세 네임스페이스. 접두사가 등록하는 명세의 이름을 나타냅니다.

검증기는 확장 키를 디코딩하여 보존해야 하며(MUST), 단지 그것이 존재한다는 이유만으로 레코드를 거부해서는 안 되고(MUST NOT), 그 내용을 검증했다고 주장하지 않으면서 정보로서 제시해야 합니다(MUST). 확장 키는 서명된 본문의 일부이므로, 레코드 수준 서명이 그것들을 포괄합니다 — 중계자는 서명이 생성된 뒤에 확장 키를 주입할 수 없습니다. 두 패턴 어느 쪽에도 일치하지 않는 알 수 없는 최상위 키(supersedess 같은 오타나 Sigs 같은 대소문자 변형)는 알 수 없는 필드로 거부됩니다. 패턴 기반의 이러한 관용은 기본 집합에 대한 오타 탐지를 유지하면서, 미래의 추가를 위한 안정적인 풀을 열어 둡니다.

검증자에게 비기본 필드의 이해를 요구하는 생산자는 그 필드의 이름을 최상위 crit 배열에 열거해야 합니다(MUST). 자신이 구현하지 않은 crit 엔트리를 마주친 v1 검증자는 그 레코드를 유효한 것으로 보고해서는 안 됩니다(MUST NOT). 각 crit 엔트리는 확장 키 패턴에 일치해야 하고(MUST, 기본 키는 crit에서 금지됩니다), 레코드에 실제로 존재하는 필드를 가리켜야 하며(MUST), 고유해야 합니다(MUST). 그래서 임계 표시는 언제나, 검증자가 그 의미를 이해할 의무를 지는 구체적인 필드로 추적될 수 있습니다. 이 규칙들은 RFC 9052 §3.1(COSE crit) 및 RFC 7515 §4.1.11(JWS crit)의 must-understand / must-ignore 선례를 따릅니다.

바이트 예산

레코드 크기에 대한 유일한 절대적 천장은 그 시점에 유효한 Cardano maxTxSize 프로토콜 파라미터입니다 — 메인넷의 프로토콜 메이저 버전 10에서는 16 384바이트이며, 원장 파라미터 업데이트의 영향을 받습니다. Label 309는 그 아래로 어떤 스키마 수준 상한도 두지 않습니다. 이 제한을 초과하는 레코드는 제출 시점에서 Cardano 노드에 의해 거부되므로 어떤 검증자도 그것을 보지 못합니다. 검증기는 maxTxSize 아래로 Label 309 고유의 천장을 멋대로 만들어 내서는 안 됩니다(MUST NOT).

실제로는 트랜잭션의 비메타데이터 구조(입력, 출력, 위트니스, 수수료 및 유효성 필드)가 대략 245바이트를 소비하므로, 라벨 309 레코드에는 16 KB 정도가 남습니다. 생산자는 수수료 변동을 흡수하기 위해 제한보다 수백 바이트 아래를 목표로 삼아야 하며(SHOULD), 제출 전에 후보 레코드의 크기를 계산하여 들어맞지 않으면 빠르게 실패해야 합니다 (SHOULD). 들어맞는 현실적인 형태는 넉넉합니다. 100개를 훌쩍 넘는 단일 해시 아이템, 수십 개의 레코드 수준 서명, 또는 다수의 고전적 수신자 슬롯이 모두 하나의 트랜잭션 안에 여유롭게 들어갑니다 — 그리고 하나의 Merkle 루트는 온체인에서 32바이트 라는 고정 비용으로 한계 없는 오프체인 리프 목록에 커밋합니다.

CDDL 스키마

다음 CDDL은 재조립된 레코드 본문의 구조 스키마입니다 — 즉 라벨 309 아래에 저장된 ≤ 64바이트 청크 배열을 연결하여 얻는 정규 CBOR 바이트를 대상으로 합니다. 재조립된 본문은 순수한 결정론적 CBOR입니다. 그것 자체는 원장 metadatum이 아니며, 그 필드는 64바이트 문자열 상한의 대상이 아닙니다. 그 상한은 본문 전체 전송 래퍼만이 충족합니다. 래퍼는 여기서 모델링하지 않습니다.

이 블록은 정상 형식 형태의 관대한 상위 집합을 기술합니다. 필드 간 불변 조건 (items-or-merkle 규칙, 암호화 봉투의 slotspassphrase 배타성, 알고리즘 식별자의 레지스트리 소속, KEM별 슬롯 형태 규칙)은 CDDL 자체가 아니라, 디코딩된 구조에 대한 타입이 지정된 검증 패스에 의해 적용됩니다.

CDDL
; An extension value is any CBOR value the canonical (deterministic) encoding
; profile admits. Floats and semantic tags are excluded by that profile (they
; are rejected as MALFORMED_CBOR on decode), so the exclusion is not repeated
; here; the reassembled body carries no field-level 64-byte cap.
extension-value =
    { * extension-value => extension-value }
  / [ * extension-value ]
  / int
  / bstr
  / tstr
  / bool
  / null

; A conformant record MUST carry at least one of `items` (>= 1 entry) or
; `merkle` (>= 1 entry); a record with both absent (or both empty) is rejected
; as SCHEMA_EMPTY_RECORD by the typed pass, not at the CDDL layer.
poe-record = {
  poe-common,
  ? "items": [ 1* item-entry ],
  ? "crit":  [ 1* tstr ],
  * extension-key => extension-value
}

poe-common = (
  "v": 1,
  ? "merkle": [ 1* merkle-commit ],
  ? "supersedes": bytes32,
  ? "sigs": [ 1* sig-entry ],
)

extension-key = tstr .regexp "^x-.+"
              / tstr .regexp "^[a-z]+-.+"

item-entry = {
  "hashes": hash-map,
  ? "uris": [ 1* uri ],
  ? "enc": enc,
}

; A non-empty CBOR map keyed by a content-hash algorithm identifier with the
; 32-byte digest as value. Map-key uniqueness makes duplicate algorithms
; structurally impossible.
hash-map = { + content-hash-alg => bytes32 }

; A list commitment binds the record to an ordered leaf list. `leaf_count`
; binds the on-chain commitment to the off-chain list size.
merkle-commit = {
  "alg":        merkle-commit-alg,
  "root":       bytes32,
  "leaf_count": uint32,
  ? "uris":     [ 1* uri ],
}

; `enc` is a choice between the scheme-1 envelope shape and a bounded opaque
; envelope (the degrade-to-opaque rule for an unsupported scheme/kem/aead). The
; typed pass enforces the slots/passphrase exclusivity and the per-KEM
; slot-shape rules over a supported envelope.
enc = enc-scheme-1 / enc-opaque

; `scheme: 1` is not a version counter for the `enc` map alone: it names the
; ENTIRE sealed cryptographic suite — the canonicalEncode rules, the slot
; schema, the HKDF and HMAC hashes, the wrap AEAD, the segmented-STREAM content
; format, the transcript schemas, the in-ciphertext passphrase commitment, the
; pinned X-Wing revision, every domain-separation label, and the Argon2id and
; passphrase-normalization profiles. Changing any one of them requires a new
; `scheme` value; see Sealed PoE for the construction it pins.
enc-scheme-1 = {
  "scheme": 1,
  "aead":   aead-alg,
  "nonce":  bstr,
  ? "kem":        kem-alg,
  ? "slots":      [ 1* slot ],
  ? "slots_mac":  bytes32,
  ? "passphrase": passphrase-block,
}

; The opaque reading of an envelope under an unsupported identifier: `scheme`
; is the only structurally required key, and every other entry is any key/value
; pair the canonical profile admits, subject to the generic decode bounds.
enc-opaque = {
  "scheme": uint,
  * tstr => extension-value
}

slot = classical-slot / hybrid-slot

; enc.kem = "x25519": the per-slot X25519 ephemeral public key + wrapped CEK.
classical-slot = {
  "epk":  bytes32,
  "wrap": bytes48,
}

; enc.kem = "mlkem768x25519": the 1120-byte X-Wing ciphertext plus the wrapped
; CEK. There is NO `epk` — the X25519 ephemeral is the trailing 32 bytes of the
; X-Wing ciphertext inside `kem_ct`.
hybrid-slot = {
  "kem_ct": bstr .size 1120,
  "wrap":   bytes48,
}

passphrase-block = {
  "alg":    kdf-alg,
  "salt":   bstr .size (16..64),
  "params": { "m": uint32, "t": uint32, "p": uint32 },
}

; A signature entry is a closed map. `cose_sign1` is REQUIRED and carries the
; CBOR-encoded COSE_Sign1 as a single byte string; `cose_key` is OPTIONAL and
; carries the CBOR-encoded COSE_Key for the wallet-signing path as a single
; byte string.
sig-entry = {
  "cose_sign1":  bstr,
  ? "cose_key":  bstr,
}

; A uri is one absolute URI in a single text string. The URI shape rules
; (absolute, no fragment, closed scheme set {ar://, ipfs://}) are enforced in
; the typed pass; the rule carries no length cap.
uri = tstr

bytes32 = bstr .size 32
bytes48 = bstr .size 48

; uint32 is the pinned range of every numeric field: an unsigned integer
; representable in 4 bytes (0 .. 2^32-1), handled as an exact integer.
uint32 = uint .size 4

; Algorithm-identifier strings are open `tstr`: the registries are
; authoritative for accepted values, and the typed pass emits the precise
; unsupported-algorithm code for any unrecognised identifier.
content-hash-alg   = tstr  ; e.g. "sha2-256", "blake2b-256"
merkle-commit-alg  = tstr  ; e.g. "rfc9162-sha256"
aead-alg           = tstr
kem-alg            = tstr
kdf-alg            = tstr

관련 페이지

  • 콘텐츠와 해싱hashes 맵, 다이제스트가 커밋하는 대상, 그리고 정확한 바이트 의미론.
  • 알고리즘 레지스트리 — 해시, 목록 커밋먼트, AEAD, KEM, KDF의 명명된 식별자.
  • 서명 — 레코드 수준 sigs 구성과 검증.
  • 봉인된 PoEenc 봉투와 수신자 키 슬롯.
  • 검증 — 검증 파이프라인, CID 프로파일, 그리고 오류 카탈로그.