데이터 무결성 BBS 암호화 스위트 v1.0

페어링 기반 암호화를 통한 연결 불가능한 데이터 무결성 달성

W3C 후보 권고안 초안

이 문서에 대한 자세한 정보
이 버전:
https://www.w3.org/TR/2026/CRD-vc-di-bbs-20260910/
최신 공개 버전:
https://www.w3.org/TR/vc-di-bbs/
최신 편집자 초안:
https://w3c.github.io/vc-di-bbs/
이력:
https://www.w3.org/standards/history/vc-di-bbs/
커밋 이력
구현 보고서:
https://w3c.github.io/vc-data-integrity/implementations/
편집자:
Greg Bernstein (초청 전문가)
Manu Sporny (Digital Bazaar)
피드백:
GitHub w3c/vc-di-bbs (풀 리퀘스트, 새 이슈, 열린 이슈)

초록

이 명세는 BBS 서명 방식을 사용하여 디지털 서명을 생성할 때 사용되는 데이터 무결성 암호화 스위트를 설명합니다. 이 서명 스위트는 BBS 서명을 사용하여 선택적 공개와 연결할 수 없는 파생 증명을 제공합니다.

이 문서의 상태

이 절에서는 이 문서가 발행된 시점의 상태를 설명합니다. 현재 W3C 발행물 목록과 이 기술 보고서의 최신 개정판은 W3C 표준 및 초안 색인에서 확인할 수 있습니다.

워킹 그룹은 이 명세에 대한 구현 피드백을 적극적으로 구하고 있습니다. 후보 권고안 단계를 종료하기 위해 워킹 그룹은 이 명세의 필수 및 선택 기능 각각에 대해 최소 두 개의 독립적인 구현을 요구 사항으로 정했습니다. 적합성 테스트 절차에 대한 자세한 내용은 구현 보고서에 나열된 테스트 스위트를 참조하십시오.

이 문서는 검증 가능한 자격 증명 워킹 그룹권고안 트랙을 사용하여 후보 권고안 초안으로 발행했습니다.

후보 권고안으로 발행되었다고 해서 W3C 및 그 회원들이 이를 승인한다는 의미는 아닙니다. 후보 권고안 초안에는 워킹 그룹이 후속 후보 권고안 스냅샷에 포함하려는 이전 후보 권고안의 변경 사항이 반영되어 있습니다.

이 문서는 초안이며 언제든지 다른 문서에 의해 업데이트, 대체되거나 폐기될 수 있습니다. 이 문서를 진행 중인 작업 이외의 것으로 인용하는 것은 적절하지 않습니다.

이 문서는 W3C 특허 정책에 따라 운영되는 그룹에서 작성했습니다. W3C는 이 그룹의 결과물과 관련하여 이루어진 모든 특허 공개의 공개 목록을 유지하고 있으며, 해당 페이지에는 특허를 공개하는 방법에 대한 지침도 포함되어 있습니다. 자신이 알고 있는 특허가 필수 청구항을 포함한다고 믿는 사람은 W3C 특허 정책 제6절에 따라 해당 정보를 공개해야 합니다.

이 문서는 2025년 8월 18일 W3C 절차 문서의 적용을 받습니다.

1. 서론

이 사양은 데이터 무결성 [VC-DATA-INTEGRITY-1.1] 사양을 준수하여 BBS 서명 스킴을 사용해 증명을 생성하고, 검증하고, 파생하기 위한 암호화 스위트를 정의합니다. BBS 서명 스킴은 선택적 공개와 연결할 수 없는 증명을 직접 제공합니다. 이 스킴은 발급자, 보유자, 검증자 모델 내에서 작동하는 네 가지 상위 수준 함수를 제공합니다. 구체적으로, 발급자는 BBS Sign 함수를 사용하여 원본 자격 증명에 서명하는 데 사용되는 "BBS 서명"이라는 암호화 값을 생성합니다. 보유자는 BBS로 서명된 자격 증명을 수신하면 BBS Verify 함수를 사용하여 해당 자격 증명을 검증합니다.

그런 다음 보유자는 수신한 자격 증명에서 선택적으로 공개할 정보를 선택하고 BBS ProofGen 함수를 사용하여 "BBS 증명"이라는 암호화 값을 생성하며, 이 값은 이 "파생 자격 증명"의 증명을 생성하는 데 사용됩니다. 암호화된 "BBS 증명" 값은 원본 "BBS 서명"과 연결할 수 없으며, 정확히 동일한 정보를 포함하는 경우를 비롯하여 추가적인 "파생 자격 증명"마다 서로 다른 연결 불가능한 "BBS 증명"을 보유자가 생성할 수 있습니다. 마지막으로 검증자는 BBS ProofVerify 함수를 사용하여 보유자로부터 받은 파생 자격 증명을 검증합니다.

검증 가능한 자격 증명에 BBS 서명 방식을 적용하려면 이 문서에 명시된 처리가 필요합니다. 일반적으로 이 스위트는 RDF 데이터셋 정규화 알고리즘 [RDF-CANON]을 사용하여 입력 문서를 정규형으로 변환합니다. 그런 다음 발급자는 선택적 공개 기본 연산을 사용하여 정규형을 필수 문장과 비필수 문장으로 분리합니다. 이들은 다른 정보와 함께 별도로 처리되어 적절한 키 자료와 함께 BBS Sign 함수의 입력으로 사용됩니다. 이 출력은 보안이 적용된 자격 증명을 생성하는 데 사용됩니다. 보유자는 자격 증명을 받은 후 일련의 선택적 공개 함수와 BBS Verify 함수를 사용하여 유효성을 확인합니다.

마찬가지로 BBS로 서명된 자격 증명을 받은 보유자는 RDF 데이터셋 정규화 알고리즘 [RDF-CANON]을 사용하여 입력 문서를 정규형으로 변환한 다음 선택적 공개 기본 연산을 적용하여 정규형을 필수 문장과 선택적으로 공개되는 문장으로 분리합니다. 이 문장들은 적절히 처리되어 BBS ProofGen 함수의 입력으로 사용됩니다. 적절하게 처리되면 이 함수의 출력은 검증자에게 전송되는 서명된 선택적 공개 자격 증명이 됩니다. 정규화 및 선택적 공개 기본 연산을 사용하여 검증자는 BBS verifyProof 함수를 사용해 자격 증명을 검증할 수 있습니다.

1.1 용어

이 문서 전체에서 사용되는 용어는 검증 가능한 자격 증명 데이터 무결성 1.1 사양의 용어 절에서 정의합니다.

1.2 적합성

비규범적으로 표시된 절뿐만 아니라 이 명세의 모든 작성 지침, 다이어그램, 예제 및 참고 사항은 비규범적입니다. 이 명세의 그 밖의 모든 내용은 규범적입니다.

이 문서에서 MAY, MUST, MUST NOT, OPTIONAL, REQUIREDSHOULD라는 핵심 단어는 여기에 표시된 것처럼 모두 대문자로 나타날 때에만 BCP 14 [RFC2119] [RFC8174]에 설명된 대로 해석해야 합니다.

적합한 증명은 이 명세의 규범적 문장을 준수하는 데이터 모델의 모든 구체적인 표현입니다. 구체적으로 이 문서의 2. 데이터 모델3. 알고리즘 절에 있는 모든 관련 규범적 문장을 반드시 적용해야 합니다.

적합한 처리기적합한 증명을 생성하거나 소비하는 소프트웨어 및/또는 하드웨어로 구현된 모든 알고리즘입니다. 적합한 처리기는 부적합한 문서를 처리할 때 반드시 오류를 발생시켜야 합니다.

이 문서에는 JSON 및 JSON-LD 데이터의 예제가 포함되어 있습니다. 이러한 예제 중 일부는 특정 부분을 설명하는 인라인 주석(//)과 예제와 관련 없는 정보의 생략을 나타내는 줄임표(...) 같은 기능을 포함하므로 유효한 JSON이 아닙니다. 구현자가 예제를 유효한 JSON 또는 JSON-LD로 처리하려면 이러한 부분을 제거해야 합니다.

2. 데이터 모델

다음 절에서는 이 사양에서 검증 방법데이터 무결성 증명 형식에 사용하는 데이터 모델을 설명합니다.

2.1 검증 방법

이러한 검증 방법은 [VC-DATA-INTEGRITY-1.1]에 따라 생성된 데이터 무결성 증명을 검증하는 데 사용되며, [CFRG-BBS-SIGNATURE]을 준수하는 BLS12-381 암호화 키 자료를 사용합니다. 이러한 키 유형의 인코딩 형식은 이 절에서 제공합니다. 동등한 암호화 키 자료를 생성하는 무손실 암호화 키 변환 프로세스는 디지털 서명을 처리하는 동안 사용될 수 있습니다(MAY).

2.1.1 Multikey

제어되는 식별자 v1.0에 정의된 Multikey 형식은 이 명세에서 정의한 암호화 스위트의 공개 키를 표현하는 데 사용됩니다.

publicKeyMultibase 속성은 G2 그룹에 속하는 BLS12-381 381비트 공개 키의 Multibase 인코딩 Multikey 표현을 나타냅니다.

검증 방법의 publicKeyMultibase 값은 제어되는 식별자 v1.0Multibase 절에 정의된 대로 반드시 base-58-btc 접두사(z)로 시작해야 합니다. 그 뒤에는 제어되는 식별자 v1.0Multikey 절에 정의된 Multibase 인코딩 BLS12-381 381비트 공개 키 값이 이어집니다. 그 밖의 모든 인코딩은 절대로 허용해서는 안 됩니다.

개발자는 실수로 비공개 키의 표현을 게시하지 않도록 주의해야 합니다. 이 명세의 구현은 publicKeyMultibase 값에서 0xeb01 이외의 Multicodec 값이 사용되는 경우 오류를 발생시킵니다.

예제 1: Multikey로 인코딩된 BLS12-381 G2 그룹 공개 키
{
  "id": "https://example.com/issuer/123#key-0",
  "type": "Multikey",
  "controller": "https://example.com/issuer/123",
  "publicKeyMultibase": "zUC7EK3ZakmukHhuncwkbySmomv3FmrkmS36E4Ks5rsb6VQSRpoCrx6
  Hb8e2Nk6UvJFSdyw9NK1scFXJp21gNNYFjVWNgaqyGnkyhtagagCpQb5B7tagJu3HDbjQ8h
  5ypoHjwBb"
}
예제 2: 제어자 문서에서 Multikey로 인코딩된 BLS12-381 G2 그룹 공개 키
{
  "@context": [
    "https://www.w3.org/ns/did/v1",
    "https://w3id.org/security/multikey/v1"
  ],
  "id": "https://example.com/issuer/123",
  "verificationMethod": [{
    "id": "https://example.com/issuer/123#key-1",
    "type": "Multikey",
    "controller": "https://example.com/issuer/123",
    "publicKeyMultibase": "zUC7EK3ZakmukHhuncwkbySmomv3FmrkmS36E4Ks5rsb6VQSRpoCr
    x6Hb8e2Nk6UvJFSdyw9NK1scFXJp21gNNYFjVWNgaqyGnkyhtagagCpQb5B7tagJu3HDbjQ8h
    5ypoHjwBb"
  }]
}

2.2 증명 표현

2.2.1 DataIntegrityProof

증명에는 [VC-DATA-INTEGRITY]의 증명 절에 명시된 속성이 다음 제한 사항과 함께 포함됩니다.

증명의 verificationMethod 속성은 반드시 URL이어야 합니다. verificationMethod를 역참조한 결과는 값이 Multikey로 설정된 type 속성을 포함하는 객체여야 합니다.

증명의 type 속성은 반드시 DataIntegrityProof여야 합니다.

증명의 cryptosuite 속성은 반드시 bbs-2023이어야 합니다.

증명의 proofValue 속성 값은 [CFRG-BBS-SIGNATURE]에 따라 생성된 BBS 서명 또는 BBS 증명이어야 하며, 3. 알고리즘 절의 절차에 따라 직렬화 및 인코딩되어야 합니다.

3. 알고리즘

다음 알고리즘에서는 BBS 서명 스킴 [CFRG-BBS-SIGNATURE]과 함께 검증 가능한 자격 증명을 사용하는 방법을 설명합니다. BBS 서명 스킴을 사용할 때는 SHA-256 변형을 사용하는 것이 좋습니다(SHOULD).

구현은 증명을 추가하거나 검증할 때 가능한 한 일찍 검증 방법 정보를 가져와 캐시하는 것이 좋습니다(SHOULD). 이 절의 함수에 전달되는 매개변수는 검증 방법의 정보(예: 공개 키 크기)를 사용하여 함수 매개변수(예: 암호화 해싱 알고리즘)를 결정합니다.

RDF 데이터셋 정규화 알고리즘 [RDF-CANON]을 사용하는 경우, 해당 알고리즘의 구현은 기본적으로 데이터셋 오염을 감지하고, 감지 시 처리를 중단합니다.

3.1 암호 스위트 인스턴스화

이 알고리즘은 검증 가능한 자격 증명 데이터 무결성 1.1증명 추가증명 검증 함수에서 사용할 암호화 스위트를 구성하는 데 사용됩니다. 이 알고리즘은 옵션 객체 ( options) 를 입력으로 받아 암호 스위트 인스턴스 (구조체 cryptosuite)를 반환합니다.

  1. cryptosuite를 빈 구조체로 초기화합니다.
  2. options.typeDataIntegrityProof와 같지 않으면, cryptosuite를 반환합니다.
  3. options.cryptosuitebbs-2023이면 다음을 수행합니다.
    1. cryptosuite.createProof를 다음 절의 알고리즘으로 설정합니다. 3.3.1 기본 증명 생성 (bbs-2023).
    2. cryptosuite.verifyProof를 다음 절의 알고리즘으로 설정합니다. 3.3.5 파생 증명 검증 (bbs-2023).
  4. cryptosuite를 반환합니다.

3.2 bbs-2023 함수

3.2.1 serializeBaseProofValue

다음 알고리즘은 BBS 서명, HMAC 키 및 필수 포인터를 포함하여 기본 증명 값을 직렬화합니다. 필수 입력은 기본 서명 bbsSignature, bbsHeader, publicKey, HMAC 키 hmacKey, mandatoryPointers 배열, featureOptionfeatureOption 값에 따라 필요할 수 있는 signer_nym_entropy 값입니다. 하나의 기본 증명 문자열 값이 출력으로 생성됩니다.

  1. featureOption 값에 따라 proofValue를 다음과 같이 설정합니다.
  2. featureOption"baseline"과 같으면:
    1. BBS 기본 증명 헤더 바이트 0xd9, 0x5d, 0x02로 시작하는 바이트 배열 proofValue를 초기화합니다.
    2. components를 다음 값이 포함된 5개 요소의 배열로 초기화합니다. bbsSignature, bbsHeader, publicKey, hmacKey, 및 mandatoryPointers.
  3. featureOption"anonymous_holder_binding"과 같으면:
    1. BBS 기본 증명 헤더 바이트 0xd9, 0x5d, 0x04로 시작하는 바이트 배열 proofValue를 초기화합니다.
    2. components를 다음 값이 포함된 6개 요소의 배열로 초기화합니다. bbsSignature, bbsHeader, publicKey, hmacKey, 및 mandatoryPointers.
  4. featureOption"pseudonym"과 같으면:
    1. BBS 기본 증명 헤더 바이트 0xd9, 0x5d, 0x06으로 시작하는 바이트 배열 proofValue를 초기화합니다.
    2. components를 다음 값이 포함된 6개 요소의 배열로 초기화합니다. bbsSignature, bbsHeader, publicKey, hmacKey, mandatoryPointerssigner_nym_entropy.
  5. featureOption"holder_binding_pseudonym"과 같으면:
    1. BBS 기본 증명 헤더 바이트 0xd9, 0x5d, 0x08로 시작하는 바이트 배열 proofValue를 초기화합니다.
    2. components를 다음 값이 포함된 6개 요소의 배열로 초기화합니다. bbsSignature, bbsHeader, publicKey, hmacKey, mandatoryPointerssigner_nym_entropy.
  6. [RFC8949]에 따라 components를 CBOR로 인코딩하며, 이때 어떤 components에도 CBOR 태깅을 사용해서는 안 됩니다(MUST NOT). 생성된 인코딩 값을 proofValue에 추가합니다.
  7. baseProofproofValue의 multibase-base64url-no-pad 인코딩 문자열로 초기화합니다. 즉, "u"로 시작하고 proofValue의 base64url-no-pad 인코딩 값으로 끝나는 문자열을 반환합니다.
  8. baseProof기본 증명으로 반환합니다.

3.2.2 parseBaseProofValue

다음 알고리즘은 bbs-2023 선택적 공개 기본 증명 값의 구성 요소를 구문 분석합니다. 필수 입력은 증명 값 (proofValue)입니다. "bbsSignature", "bbsHeader", "publicKey", "hmacKey", "mandatoryPointers", "featureOption" 및 선택적 기능 매개변수 "signer_nym_entropy"라는 이름을 사용하는 6개 또는 7개 요소가 포함된 하나의 객체 구문 분석된 기본 증명이 출력으로 생성됩니다.

  1. proofValue 문자열이 u (U+0075 라틴 소문자 U)로 시작하지 않아 multibase-base64url-no-pad-encoded 값이 아님을 나타내는 경우, 오류를 발생시켜야 하며(MUST) 오류 유형 PROOF_VERIFICATION_ERROR를 전달하는 것이 좋습니다(SHOULD).
  2. decodedProofValueproofValue의 선행 u 뒤에 오는 부분 문자열을 base64url-no-pad 디코딩한 결과로 초기화합니다.
  3. BBS 기본 증명이 허용된 헤더 값으로 시작하는지 확인하고 featureOption 변수를 다음과 같이 설정합니다.
    1. decodedProofValue가 바이트 0xd9, 0x5d0x02로 시작하면 featureOption"baseline"으로 설정합니다.
    2. decodedProofValue가 바이트 0xd9, 0x5d0x04로 시작하면 featureOption"anonymous_holder_binding"으로 설정합니다.
    3. decodedProofValue가 바이트 0xd9, 0x5d0x06으로 시작하면 featureOption"pseudonym"으로 설정합니다.
    4. decodedProofValue가 바이트 0xd9, 0x5d0x08로 시작하면 featureOption"holder_binding_pseudonym"으로 설정합니다.
    5. decodedProofValue가 다른 3바이트 시퀀스로 시작하면 오류를 발생시켜야 하며(MUST) 오류 유형 PROOF_VERIFICATION_ERROR를 전달하는 것이 좋습니다(SHOULD).
  4. components를 3바이트 BBS 기본 증명 헤더 뒤의 바이트를 CBOR 디코딩한 결과인 배열로 초기화합니다.
  5. featureOption 값에 따라 components를 기반으로 한 객체를 다음과 같이 반환합니다.
    1. featureOption"baseline"과 같으면, components를 기반으로 객체의 속성 이름을 "bbsSignature", "bbsHeader", "publicKey", "hmacKey", "mandatoryPointers" 순서로 설정하고 featureOption을 속성으로 추가합니다.
    2. featureOption"anonymous_holder_binding"과 같으면, components를 기반으로 객체의 속성 이름을 "bbsSignature", "bbsHeader", "publicKey", "hmacKey", "mandatoryPointers" 순서로 설정하고 featureOption을 속성으로 추가합니다.
    3. featureOption"pseudonym"과 같으면, components를 기반으로 객체의 속성 이름을 "bbsSignature", "bbsHeader", "publicKey", "hmacKey", "mandatoryPointers", "signer_nym_entropy" 순서로 설정하고 featureOption을 속성으로 추가합니다.
    4. featureOption"holder_binding_pseudonym"과 같으면, components를 기반으로 객체의 속성 이름을 "bbsSignature", "bbsHeader", "publicKey", "hmacKey", "mandatoryPointers", "signer_nym_entropy" 순서로 설정하고 featureOption을 속성으로 추가합니다.

3.2.3 serializeDerivedProofValue

다음 알고리즘은 파생 증명 값을 직렬화합니다. 필수 입력은 BBS 증명(bbsProof), 레이블 맵(labelMap), 필수 인덱스 배열(mandatoryIndexes), 선택적 인덱스 배열(selectiveIndexes), BBS 프레젠테이션 헤더 (presentationHeader), featureOption 표시자 및 featureOption 값에 따라 nym_domain, pseudonym, 및/또는 lengthBBSMessages 값입니다. 바이트 문자열로 직렬화된 하나의 파생 증명 값이 출력으로 생성됩니다.

  1. compressedLabelMaplabelMap을 매개변수로 전달하여 절의 알고리즘을 호출한 결과로 초기화합니다.
  2. featureOption 값에 따라 다음을 수행합니다.
    1. featureOption"baseline"과 같으면:
      1. proofValue를 공개 증명 헤더 바이트 0xd9, 0x5d0x03으로 시작하도록 초기화합니다.
      2. components를 다음 값이 포함된 요소의 배열로 초기화합니다. bbsProof, compressedLabelMap, mandatoryIndexes, selectiveIndexespresentationHeader.
    2. featureOption"anonymous_holder_binding"과 같으면:
      1. proofValue를 공개 증명 헤더 바이트 0xd9, 0x5d0x05로 시작하도록 초기화합니다.
      2. components를 다음 값이 포함된 요소의 배열로 초기화합니다. bbsProof, compressedLabelMap, mandatoryIndexes, selectiveIndexes, presentationHeaderlengthBBSMessages.
    3. featureOption"pseudonym"과 같으면:
      1. proofValue를 공개 증명 헤더 바이트 0xd9, 0x5d0x07로 시작하도록 초기화합니다.
      2. components를 다음 값이 포함된 요소의 배열로 초기화합니다. bbsProof, compressedLabelMap, mandatoryIndexes, selectiveIndexes, presentationHeader, nym_domain, pseudonymlengthBBSMessages.
    4. featureOption"holder_binding_pseudonym"과 같으면:
      1. proofValue를 공개 증명 헤더 바이트 0xd9, 0x5d0x09로 시작하도록 초기화합니다.
      2. components를 다음 값이 포함된 요소의 배열로 초기화합니다. bbsProof, compressedLabelMap, mandatoryIndexes, selectiveIndexes, presentationHeader, nym_domain, pseudonymlengthBBSMessages.
  3. [RFC8949]에 따라 components를 CBOR로 인코딩하며, 이때 어떤 components에도 CBOR 태깅을 사용해서는 안 됩니다(MUST NOT). 생성된 인코딩 값을 proofValue에 추가합니다.
  4. proofValue의 multibase-base64url-no-pad 인코딩을 사용한 문자열로 파생 증명을 반환합니다. 즉, "u"로 시작하고 proofValue의 base64url-no-pad 인코딩 값으로 끝나는 문자열을 반환합니다.

3.2.4 parseDerivedProofValue

다음 알고리즘은 파생 증명 값의 구성 요소를 구문 분석합니다. 필수 입력은 파생 증명 값(proofValue)입니다. "bbsProof", "labelMap", "mandatoryIndexes", "selectiveIndexes", "presentationHeader", "featureOption" 및 featureOption 매개변수 값에 따라 "nym_domain", "pseudonym" 및/또는 "lengthBBSMessages"라는 이름을 갖는 6개에서 9개의 요소 집합이 포함된 하나의 파생 증명 값 객체가 출력으로 생성됩니다.

  1. proofValue 문자열이 u (U+0075, 라틴 소문자 U)로 시작하지 않아 multibase-base64url-no-pad-encoded 값이 아님을 나타내는 경우, 오류를 발생시켜야 하며(MUST) 오류 유형 PROOF_VERIFICATION_ERROR를 전달하는 것이 좋습니다(SHOULD).
  2. decodedProofValueproofValue의 선행 u 뒤에 오는 부분 문자열을 base64url-no-pad 디코딩한 결과로 초기화합니다.
  3. BBS 공개 증명이 허용된 헤더 값으로 시작하는지 확인하고 featureOption 변수를 다음과 같이 설정합니다.
    1. decodedProofValue가 헤더 바이트 0xd9, 0x5d0x03으로 시작하면 featureOption"baseline"으로 설정합니다.
    2. decodedProofValue가 헤더 바이트 0xd9, 0x5d0x05로 시작하면 featureOption"anonymous_holder_binding"으로 설정합니다.
    3. decodedProofValue가 헤더 바이트 0xd9, 0x5d0x07로 시작하면 featureOption"pseudonym"으로 설정합니다.
    4. decodedProofValue가 헤더 바이트 0xd9, 0x5d0x09로 시작하면 featureOption"holder_binding_pseudonym"으로 설정합니다.
  4. components를 3바이트 BBS 공개 증명 헤더 뒤의 바이트를 CBOR 디코딩한 결과인 배열로 초기화합니다. 결과가 5개, 6개, 7개 또는 8개 요소의 배열이 아니면 오류를 발생시켜야 하며(MUST) 오류 유형 PROOF_VERIFICATION_ERROR를 전달하는 것이 좋습니다(SHOULD).
  5. 기존 components의 두 번째 요소를 compressedLabelMap으로 전달하여 절의 알고리즘을 호출한 결과를 사용해 components의 두 번째 요소를 대체합니다.
  6. 5개, 6개, 7개 또는 8개 요소에 각각 "bbsProof", "labelMap", "mandatoryIndexes", "selectiveIndexes", "presentationHeader" 및 선택적 "nym_domain", "pseudonym" 및/또는 "lengthBBSMessages"라는 이름의 속성을 설정한 객체로 파생 증명 값을 반환합니다. 또한 featureOption과 그 값을 객체에 추가합니다.

3.3 bbs-2023

bbs-2023 암호화 스위트는 입력 문서를 받아 RDF 데이터셋 정규화 알고리즘 [RDF-CANON]을 사용하여 문서를 정규화한 다음, 여러 변환 및 암호화 연산을 적용하여 데이터 무결성 증명을 생성합니다. 이 절의 알고리즘에는 이러한 데이터 무결성 증명의 검증도 포함됩니다.

3.3.1 기본 증명 생성 (bbs-2023)

다음 알고리즘은 보안 처리되지 않은 데이터 문서가 주어졌을 때 데이터 무결성 증명을 생성하는 방법을 지정합니다. 필수 입력은 보안 처리되지 않은 데이터 문서 ( unsecuredDocument), 증명 옵션 집합( options), 필수 JSON 포인터 배열 (mandatoryPointers), featureOption 표시자 매개변수 및 featureOption에 따라 commitment_with_proof 바이트 배열입니다. 데이터 무결성 증명 () 또는 오류가 출력으로 생성됩니다.

featureOption 매개변수는 선택적 기능이 사용되는 경우 어떤 기능인지 나타내는 데 사용됩니다. 다음 값 중 하나를 사용할 수 있습니다. "baseline", "anonymous_holder_binding", "pseudonym" 또는 "holder_binding_pseudonym". "baseline"은 선택적 기능이 없는 경우를 나타내는 데 사용된다는 점에 유의하십시오. featureOption"anonymous_holder_binding", "pseudonym" 또는 "holder_binding_pseudonym"으로 설정되면 commitment_with_proof 입력을 제공해야 합니다(MUST). featureOption"pseudonym" 또는 "holder_binding_pseudonym"으로 설정되면 signer_nym_entropy 입력을 제공해야 합니다(MUST).

  1. proof를 증명 옵션 options의 복제본으로 둡니다.
  2. proofConfigoptions를 매개변수로 전달하여 § 4.2.4.2 증명 구성 절의 알고리즘을 실행한 결과로 둡니다.
  3. transformedDataunsecuredDocument, proofConfigoptions를 매개변수로 전달하여 § 4.4.1 TransformSD의 알고리즘을 실행한 결과로 둡니다.
  4. hashDatatransformedDataproofConfig를 매개변수로 전달하여 § 4.4.2 HashSD의 알고리즘을 실행한 결과로 둡니다.
  5. proofByteshashData, options, featureOption 및 필요한 경우 commitment_with_proof를 매개변수로 전달하여 다음 절의 알고리즘을 실행한 결과로 둡니다. 3.3.2 기본 증명 직렬화 (bbs-2023).
  6. proof.proofValueproofBytes base64url 인코딩된 Multibase 값으로 둡니다.
  7. proof데이터 무결성 증명으로 반환합니다.

3.3.2 기본 증명 직렬화 (bbs-2023)

다음 알고리즘은 BBS로 보호된 검증 가능한 자격 증명의 발급자가 호출하며, 기본 증명을 생성하는 방법을 지정합니다. 기본 증명은 보유자에게만 제공되어야 하며, 보유자는 이 증명에서 파생 증명을 생성하고 선택적으로 공개된 세부 정보만 증명에서 검증자에게 노출할 책임이 있습니다. 이 알고리즘은 데이터 무결성 [VC-DATA-INTEGRITY-1.1] 사양의 4절: 알고리즘에 정의된 알고리즘과 함께 사용하도록 설계되었습니다. 필수 입력은 암호화 해시 데이터(hashData), featureOption 및 필요한 경우 commitment_with_proof입니다. featureOption"anonymous_holder_binding", "pseudonym" 또는 "holder_binding_pseudonym"으로 설정되면 commitment_with_proof 입력을 제공해야 하며(MUST), 제공되지 않으면 오류를 발생시켜야 하고(MUST) 오류 유형 PROOF_GENERATION_ERROR를 전달하는 것이 좋습니다(SHOULD). featureOption"pseudonym" 또는 "holder_binding_pseudonym"으로 설정되면 signer_nym_entropy 입력을 제공해야 하며(MUST), 제공되지 않으면 오류를 발생시켜야 하고(MUST) 오류 유형 PROOF_GENERATION_ERROR를 전달하는 것이 좋습니다(SHOULD). 일련의 바이트로 표현되는 하나의 디지털 증명 값이 출력으로 생성됩니다.

  1. proofHash, mandatoryPointers, mandatoryHash, nonMandatoryhmacKeyhashData에서 각 속성 이름과 연결된 값으로 초기화합니다.
  2. bbsHeaderproofHashmandatoryHash를 해당 순서로 연결한 값으로 초기화합니다.
  3. bbsMessages를 UTF-8 문자 인코딩을 사용하여 인코딩된 nonMandatory 문자열 배열의 값을 포함하는 바이트 배열의 배열로 초기화합니다.
  4. featureOption 값에 따라 아래 절차를 사용하여 bbsSignature를 계산합니다.
    1. featureOption"baseline"과 같으면 [CFRG-BBS-Signature]의 Sign 절차를 사용하여 적절한 키 자료, headerbbsHeader, messagesbbsMessages를 사용해 bbsSignature를 계산합니다.
    2. featureOption"anonymous_holder_binding"과 같으면, [CFRG-Blind-BBS-Signature]의 BlindSign 절차를 사용하여 적절한 키 자료, commitment_with_proofcommitment_with_proof, headerbbsHeader, messagesbbsMessages를 사용해 bbsSignature를 계산합니다. 이는 익명 보유자 바인딩 기능을 제공합니다.
    3. featureOption"pseudonym" 또는 "holder_binding_pseudonym"과 같으면, 발급자는 signer_nym_entropy에 사용할 암호학적으로 무작위인 값을 생성하고 [CFRG-Pseudonym-BBS-Signature]의 "블라인드 발급" 연산을 사용하여 적절한 키 자료, headerbbsHeader, messagesbbsMessages, commitment_with_proofcommitment_with_proofsigner_nym_entropy 값을 사용해 bbsSignature를 계산합니다. 발급자가 나중에 동일한 nym_secret에 바인딩된 자격 증명을 이 보유자에게 재발급해야 할 가능성이 있다면 signer_nym_entropy 값을 보관하는 것이 좋습니다. 그렇지 않으면 이 값은 폐기할 수 있습니다.

      이는 자격 증명 바인딩 가명 또는 보유자 바인딩 및 가명 기능을 제공합니다.
  5. `proofValue를 bbsSignature, bbsHeader, publicKey, hmacKey, mandatoryPointers, featureOptionfeatureOption 값에 따라 signer_nym_entropy를 매개변수로 전달하여 3.2.1 serializeBaseProofValue절의 알고리즘을 호출한 결과로 초기화합니다.

    참고: publicKey는 [CFRG-BBS-SIGNATURE]에 따라 인코딩된 공개 키의 바이트 배열입니다.
  6. proofValue디지털 증명으로 반환합니다.

3.3.3 파생 증명 추가 (bbs-2023)

다음 알고리즘은 bbs-2023로 보호된 검증 가능한 자격 증명의 보유자가 호출하며, 선택적 공개 파생 증명을 생성합니다. 파생 증명은 검증자에게 제공됩니다. 입력에는 JSON-LD 문서(document), BBS 기본 증명 (proof), 문장을 선택적으로 공개하는 데 사용할 JSON 포인터 배열 (selectivePointers), 선택 사항인(OPTIONAL) BBS presentationHeader(바이트 배열), featureOption 매개변수, 선택된 featureOption을 지원하는 추가 매개변수(아래 참조), 및 문서 로더와 같은 사용자 지정 JSON-LD API 옵션이 포함됩니다. 객체로 표현되는 하나의 선택적으로 공개된 문서 값이 출력으로 생성됩니다.

featureOption"anonymous_holder_binding"과 같으면 필수(REQUIRED) 추가 입력은 holderSecretproverBlind입니다. 이 값들은 보유자가 미리 계산했어야 합니다. 배경 정보는 익명 보유자 바인딩을 참조하십시오.

featureOption"pseudonym"과 같으면 필수(REQUIRED) 추가 입력은 보유자가 모두 알고 있는 prover_nymproverBlind과, 보유자가 설정하거나 검증자가 보유자에게 전달하는 nym_dofmain입니다. 배경 정보는 자격 증명 바인딩 가명을 참조하십시오.

featureOption"holder_binding_pseudonym"과 같으면 필수(REQUIRED) 추가 입력은 holder_secret, prover_nymproverBlind이며, 모두 보유자가 알고 있고, nym_dofmain은 보유자가 설정하거나 검증자가 보유자에게 전달합니다. 배경 정보는 보유자 바인딩 및 가명을 참조하십시오.

  1. proofData 객체를 3.2.2 parseBaseProofValue절의 알고리즘에서 반환된 결과로 둡니다. 최소한 proofData 객체에는 bbsSignature, bbsHeader, publicKey, hmacKey, mandatoryPointersfeatureOption 필드가 포함됩니다. featureOption 값에 따라 추가 필드가 존재할 수 있습니다.
  2. disclosureDatadocument, proofData, selectivePointers 및 문서 로더와 같은 사용자 지정 JSON-LD API 옵션을 전달하여 § 4.4.3 CreateDisclosureData의 알고리즘을 호출할 때 반환되는 객체로 초기화합니다. disclosureData 객체에는 다음 필드가 포함됩니다. revealDocument, mandatoryIndexes, selectiveIndexes, verifierLabelMap mandatorynonMandatory.
  3. newProofproof의 얕은 복사본으로 초기화합니다.
  4. newProofproofValueproofDatadisclosureData를 매개변수로 전달하여 3.3.4 파생 증명 직렬화절의 알고리즘을 호출한 결과로 대체합니다.
  5. revealDocument의 "proof" 속성 값을 newProof로 설정합니다.
  6. revealDocument선택적으로 공개된 문서로 반환합니다.

3.3.4 파생 증명 직렬화

다음 알고리즘은 파생 증명을 생성합니다. 입력은 proofDatadisclosureData 객체입니다.

  1. bbsMessages를 UTF-8 문자 인코딩을 사용하여 인코딩된 nonMandatory 문자열 배열의 값을 포함하는 바이트 배열의 배열로 초기화합니다.
  2. featureOption 매개변수 값을 기준으로 아래의 적절한 절차가 계산한 값으로 bbsProof를 설정합니다.
    1. featureOption"baseline"과 같으면 [CFRG-BBS-SIGNATURE]의 ProofGen 절차가 계산한 값으로 bbsProof를 설정합니다. 즉, ProofGen(PK, signature, header, ph, messages, disclosed_indexes)이며, 여기서 PK는 원래 발급자의 공개 키이고, signaturebbsSignature, headerbbsHeader, phpresentationHeader, messagesbbsMessages, disclosed_indexesselectiveIndexes입니다.
    2. featureOption"anonymous_holder_binding"과 같으면, [CFRG-Blind-BBS-Signature]의 BlindProofGen 절차가 계산한 값으로 bbsProof를 설정합니다. 여기서 PK는 원래 발급자의 공개 키이고, signaturebbsSignature, headerbbsHeader, phpresentationHeader, messagesbbsMessages, disclosed_indexesselectiveIndexes이며 commitment_with_proof도 사용합니다. 보유자는 또한 자신의 holder_secretcommitment_with_proof를 계산하는 데 사용된 proverBlind를 제공합니다. 이것은 익명 보유자 바인딩 기능 옵션입니다. IETF API가 확정되면 업데이트할 예정입니다.
    3. featureOption"pseudonym"과 같으면, [CFRG-Pseudonym-BBS-Signature]의 "검증 및 마무리" 연산을 빈 committed_messages 배열과 함께 사용하여 bbsSignature를 검증하고 nym_secret 값을 계산합니다. 이 연산은 prover_nym, signer_nym_entropysecret_prover_blind를 사용합니다.

      nym_domain을 결정합니다. 사용 시나리오에 따라 검증자가 지정하거나 보유자가 설정할 수 있습니다. [CFRG-Pseudonym-BBS-Signature]의 "가명을 사용한 증명 생성" 연산을 사용하여 파생 증명을 생성합니다. 이 연산은 다음을 입력으로 사용합니다. 원래 발급자의 공개 키를 PK로, bbsSignaturesignature로, bbsHeaderheader로, presentationHeaderph로, bbsMessagesmessages로, selectiveIndexesdisclosed_indexes로, nym_secret, nym_domain, committed_messages에 대한 빈 배열, 그리고 secret_prover_blind. bbsProof에 할당되는 원시 암호화 증명 값을 제공하는 것 외에도 pseudonym도 반환합니다.

      이것은 자격 증명 바인딩 가명 기능 옵션을 위한 것입니다. IETF API가 확정되면 업데이트할 예정입니다.
    4. featureOption"holder_binding_pseudonym"과 같으면, [CFRG-Pseudonym-BBS-Signature]의 "검증 및 마무리" 연산을 holder_secret을 유일한 값으로 포함하는 committed_messages 배열과 함께 사용하여 bbsSignature를 검증하고 nym_secret 값을 계산합니다. 이 연산은 prover_nym, signer_nym_entropysecret_prover_blind를 사용합니다.

      nym_domain을 결정합니다. 사용 시나리오에 따라 검증자가 지정하거나 보유자가 설정할 수 있습니다. [CFRG-Pseudonym-BBS-Signature]의 "가명을 사용한 증명 생성" 연산을 사용하여 파생 증명을 생성합니다. 이 연산은 다음을 입력으로 사용합니다. PK, 원래 발급자의 공개 키, signature, bbsSignature, headerbbsHeader, phpresentationHeader, messagesbbsMessages, disclosed_indexesselectiveIndexes, 이 연산은 다음을 입력으로 사용합니다. 원래 발급자의 공개 키를 PK로, bbsSignaturesignature로, bbsHeaderheader로, presentationHeaderph로, bbsMessagesmessages로, selectiveIndexesdisclosed_indexes로, nym_secret, nym_domain, committed_messages 배열의 유일한 값을 holder_secret으로, 그리고 secret_prover_blind. bbsProof에 할당되는 원시 암호화 증명 값을 제공하는 것 외에도 pseudonym도 반환합니다. 이것은 보유자 바인딩 및 가명 기능 옵션을 위한 것입니다. IETF API가 확정되면 업데이트할 예정입니다.
  3. featureOption"anonymous_holder_binding", "pseudonym" 또는 "holder_binding_pseudonym"과 같으면 lengthBBSMessages 매개변수를 bbsMessages 배열의 길이로 설정합니다.
  4. bbsProof, labelMap에 대한 "verifierLabelMap", mandatoryIndexes, selectiveIndexes, revealDocument, pseudonym 및 계산된 경우 lengthBBSMessages와 일치하는 매개변수를 사용하여 3.2.3 serializeDerivedProofValue의 알고리즘이 반환한 값을 반환합니다.

3.3.5 파생 증명 검증 (bbs-2023)

다음 알고리즘은 보안 처리된 데이터 문서가 주어졌을 때 데이터 무결성 증명을 검증하는 방법을 지정합니다. 필수 입력은 보안 처리된 데이터 문서 ( securedDocument)입니다. 이 알고리즘은 검증 결과를 반환하며, 이는 다음 항목을 갖는 구조체입니다.

verified
true 또는 false
verifiedDocument
verifiedfalse이면 Null, 그렇지 않으면 보안 처리되지 않은 데이터 문서

파생 증명을 검증하려면 다음 단계를 수행합니다.

  1. unsecuredDocumentproof 값이 제거된 document의 복사본으로 둡니다.
  2. proofData 객체를 3.2.4 parseDerivedProofValue의 알고리즘이 반환한 결과로 초기화합니다. 최소한 proofData 객체에는 bbsProof, labelMap, mandatoryIndexes, selectiveIndexes, presentationHeaderfeatureOption 필드가 포함됩니다. 또한 featureOption 값에 따라 nym_domain, |pseudonym 및/또는 lengthBBSMessages 필드가 포함될 수 있습니다.", 각각.
  3. verifyData 객체를 document, proofData 및 문서 로더와 같은 사용자 지정 JSON-LD API 옵션을 전달하여 § 4.4.4 CreateVerifyData절의 알고리즘을 호출하여 반환된 값으로 초기화합니다. verifyData 객체에는 다음 필드가 포함됩니다. proofHash, mandatoryHashnonMandatory.
  4. publicKeyBytes를 데이터 무결성 [VC-DATA-INTEGRITY-1.1] 사양의 4절: 검증 방법 검색에 설명된 대로 proof.verificationMethod 값과 연결된 공개 키 바이트를 검색한 결과로 둡니다.
  5. bbsHeaderproofHashmandatoryHash를 해당 순서로 연결한 값으로 초기화합니다. disclosedMessagesnonMandatory 배열 요소를 UTF-8로 인코딩하여 얻은 바이트 배열의 배열로 초기화합니다.
  6. featureOption 값에 따라 아래의 검증 알고리즘을 적용한 결과로 verified를 초기화합니다.
    1. featureOption"baseline"과 같으면 [CFRG-BBS-SIGNATURE]의 검증 알고리즘 ProofVerify(PK, proof, header, ph, disclosed_messages, disclosed_indexes)을 적용한 결과로 verified를 초기화합니다. 이때 PK는 원래 발급자의 공개 키, proofbbsProof, headerbbsHeader, disclosed_messagesdisclosedMessages, phpresentationHeader, disclosed_indexesselectiveIndexes로 설정합니다.
    2. featureOption"anonymous_holder_binding"과 같으면 [CFRG-Blind-BBS-Signature]의 ProofVerify 검증 알고리즘을 "L" 매개변수에 lengthBBSMessages를 사용하여 적용한 결과로 verified를 초기화합니다. IETF API가 확정되면 업데이트할 예정입니다.
    3. featureOption"pseudonym" 또는 "holder_binding_pseudonym"과 같으면 [CFRG-Pseudonym-BBS-Signature]의 "가명을 사용한 증명 검증" 연산을 "L" 매개변수에 lengthBBSMessages를 사용하고 빈 committed_messages 배열과 함께 적용한 결과로 verified를 초기화합니다. IETF API가 확정되면 업데이트할 예정입니다.
  7. 다음 항목을 갖는 검증 결과를 반환합니다.
    verified
    verified
    verifiedDocument
    verifiedtrue이면 unsecuredDocument, 그렇지 않으면 Null

4. 선택적 기능

이 절은 비규범적입니다.

BBS 서명의 암호학적 속성은 고급 기능을 지원할 수 있는 변형을 허용합니다. 이 명세는 이러한 확장 기능 중 가장 관련성이 높은 기능만 지원하며, 다음 절에서 이를 설명합니다. 변수 commitment_with_proof, holder_secret, prover_nym, signer_nym_entropypseudonym은 이러한 기능과 관련되어 있으며, 그 외에는 BBS 서명 및 증명에 필요하지 않습니다.

이슈 1: 선택적 BBS 기능은 위험 상태입니다

이 절에서 설명되고 이 명세의 알고리즘에 포함된 선택적 BBS 기능은 위험 상태이며, 해당 IETF 명세가 동일한 일정 내에 RFC 상태에 도달하지 못하거나 각 선택적 기능에 대해 최소 두 개의 독립적인 구현이 존재하지 않는 경우 이 명세가 최종 확정되기 전에 제거됩니다.

4.1 익명 보유자 바인딩

이 기능은 발급 시점에 기본 증명이 있는 문서를 보유자만 알고 있는 비밀 값에 바인딩하여, 해당 보유자만 검증 가능한 파생 증명이 있는 공개 문서를 생성할 수 있도록 합니다. 예를 들어 공격자가 기본 증명이 있는 문서를 획득하더라도 검증 가능한 파생 증명이 있는 공개 문서를 생성할 수 없습니다.

이 기능을 제공하기 위해 보유자는 일반적으로 최소 32바이트 길이이며 암호학적으로 무작위로 생성되어야 하는 holder_secret 값을 생성합니다. 이 값은 보유자가 절대로 공유하지 않습니다. 대신 보유자는 [CFRG-Blind-BBS-Signature]의 "Commitment Computation" 연산을 사용하여 이 값에 대한 영지식 지식 증명과 함께 커밋먼트를 생성합니다. 이 계산에는 암호학적 난수 값이 사용되며 commitment_with_proofsecret_prover_blind 값을 계산합니다. commitment_with_proof는 발급자에게 전달되지만, secret_prover_blind는 비밀로 유지되며 파생 증명을 생성할 때 사용하기 위해 보유자가 보관합니다. 보유자는 "Commitment Computation" 연산을 여러 번 실행하여 서로 다른 발급자와 함께 사용할 연결 불가능한 commitment_with_proof 값을 생성할 수 있습니다.

발급자는 commitment_with_proof를 받으면 이 명세의 절차를 따르고 [CFRG-Blind-BBS-Signature]의 "Blind Signature Generation" 연산을 사용하여, 보유자가 제공한 commitment_with_proof와 함께 문서에 대한 기본 증명(서명)을 생성합니다.

보유자가 파생 증명이 포함된 선택적으로 공개된 문서를 생성하려는 경우 이 명세의 절차와 [CFRG-Blind-BBS-Signature]의 "Proof Generation" 연산을 사용합니다. 보유자는 holder_secretcommited messages 배열의 유일한 "메시지"로 사용하고 secret_prover_blind를 제공합니다.

파생 증명이 있는 공개 문서의 검증에는 이 명세의 절차와 [CFRG-Blind-BBS-Signature]의 "Proof Verification" 연산을 사용합니다.

4.2 자격 증명 바인딩 가명

이 문서에 명시된 BBS 서명 검증 가능한 자격 증명은 선택적 공개와 연결 불가능한 암호학적 증명 산출물을 허용합니다. 여기서 "연결 불가능"이란 파생 증명의 암호학적 정보를 다른 증명이나 원본 서명에 연결할 수 없음을 의미합니다. 이는 검증자가 보유자가 이전에 동일한 자격 증명을 제시했는지(다른 증명 인스턴스를 사용했더라도) 판단할 수 없으며, 특정 유형의 신원을 단정할 수도 없음을 의미합니다. 자격 증명 바인딩 가명은 암호학적 가명의 제한된 연결 가능성을 허용하는 개인정보 보호 메커니즘을 제공합니다. 이러한 가명은 보유자가 단독으로 결정하거나 보유자와 검증자가 공동으로 결정할 수 있습니다.

이러한 유형의 암호학적 가명(암호학적 식별자/이름)은 두 부분으로 계산됩니다. 첫 번째 부분인 nym_secret은 보유자가 지정하며 보유자만 알게 됩니다. 두 번째 부분인 nym_domain은 보유자 또는 검증자가 지정할 수 있으며 보유자와 검증자 간에 공유됩니다. 발급자는 발급 과정에서 자격 증명을 nym_secret에 바인딩합니다. 그런 다음 보유자는 nym_secret으로부터 가명을 계산하고 해당 가명이 자신이 제시하는 자격 증명에 바인딩되어 있음을 검증자에게 증명할 수 있습니다. 동일한 nym_secret에서 계산되었지만 서로 다른 nym_domain 값을 사용하는 암호학적 가명은 서로 연결할 수 없습니다.

보유자는 특정 유형의 공개 포럼에서 자신에게 가명을 부여하기 위해 nym_domain을 선택할 수 있습니다. 예를 들어 nym_domain = "Mark Twain"을 선택할 수 있습니다. 보유자가 이 nym_domain과 자신의 nym_secret으로 계산한 암호학적 가명은 사실상 고유하며, nym_secret을 알고 해당 가명에 바인딩된 기본 검증 가능한 자격 증명을 보유한 엔터티가 아니라면 이 가명 신원을 주장할 수 없습니다. 이 가명 신원을 주장하려면 (nym_domain, pseudonym) 쌍을 파생 자격 증명과 함께 전송해야 한다는 점에 유의하십시오.

다른 상황에서는 보유자가 검증자의 서비스를 이용하고 있으며 검증자가 시간에 따른 방문을 추적하거나 보유자의 특정 리소스 사용을 모니터링하려 할 수 있습니다. 이 경우 검증자가 보유자가 파생 자격 증명을 제시할 때 사용해야 하는 nym_domain을 선택합니다. 예를 들어 검증자는 보유자가 사용할 수 있도록 자신의 DNS 도메인에 연결된 공개 nym_domain(예: "www.nym.example")을 지정할 수 있습니다. 검증자는 nym_domain을 주기적으로 변경함으로써 일정 수준의 데이터 최소화를 지원한다는 것을 보여줄 수도 있습니다 (예: 날짜에 연결하여 "www.nym.example/2025-01-02"로 설정). 이 명세는 nym_domain의 값을 규정하지 않습니다.

마지막으로, 다른 보유자의 nym_secret을 획득한 악의적인 보유자가 해당 값에 바인딩된 자격 증명을 얻는 것을 방지하기 위해 [CFRG-Pseudonym-BBS-Signature]의 연산은 발급자가 난수화 요소 signer_nym_entropy를 추가하도록 합니다. 이 값은 서명 생성 중에 보유자 측 값인 prover_nym과 안전하게 "혼합"됩니다. 그 결과 발급자가 보유자가 사용할 값이 고유하다는 암호학적 보증을 제공할 수 있는 nym_secret이 생성됩니다.

자격 증명 바인딩 가명의 생성 및 사용 개요는 다음 단계와 같습니다.

  1. 보유자는 prover_nym이라는 보안 값을 생성합니다. 이 값은 최소 32바이트 길이여야 하며 암호학적으로 무작위로 생성되어야 합니다. 그런 다음 [CFRG-Pseudonym-BBS-Signature]의 "Commitment" 연산을 빈 committed_messages 배열과 함께 사용하여 commitment_with_proofsecret_prover_blind를 계산합니다. 보유자는 자격 증명 요청과 함께 commitment_with_proof를 발급자에게 보내지만, prover_nymsecret_prover_blind는 절대로 공개하지 않고 나중에 사용하기 위해 보관합니다.
  2. 발급자는 바인딩된 가명이 포함된 자격 증명에 대한 보유자의 요청 (featureOption"pseudonym"과 같음)과 commitment_with_proof를 함께 받습니다. 발급자는 signer_nym_entropy에 사용할 암호학적 난수 값을 생성하고 [CFRG-Pseudonym-BBS-Signature]의 "Blind Issuance" 연산을 사용하여 기본 증명을 생성합니다. 다른 정보와 함께 기본 증명에는 signer_nym_entropy 값이 포함됩니다. 발급자가 동일한 nym_secret에 바인딩된 자격 증명을 이 보유자에게 다시 발급해야 할 가능성이 있다면 signer_nym_entropy 값을 보관해야 하며, 그렇지 않으면 이 값을 폐기할 수 있습니다.
  3. 바인딩된 가명이 포함된 자격 증명을 받은 보유자는 이 명세의 절차와 [CFRG-Pseudonym-BBS-Signature]의 "Verification and Finalization" 연산을 빈 committed_messages 배열과 함께 사용하여 서명을 검증하는 동시에 nym_secret 값을 계산합니다. 이 연산은 다른 값들과 함께 prover_nym, signer_nym_entropy, secret_prover_blind 값을 사용합니다. 제3자 모니터링을 사용하는 경우 nym_secret 값을 모니터링 조직과 안전하게 공유해야 합니다.
  4. 보유자가 가명에 바인딩된 파생 증명을 생성하려면 nym_domain을 결정해야 합니다. 앞서 언급했듯이 사용 시나리오에 따라 검증자가 이를 지정하거나 보유자가 설정할 수 있습니다. 그런 다음 이 명세의 절차와 [CFRG-Pseudonym-BBS-Signature]의 "Proof Generation with Pseudonym" 연산을 사용하여 파생 증명을 생성합니다. 이 연산은 다른 값들과 함께 nym_secret, nym_domain, 빈 committed_messages 배열 및 secret_prover_blind를 입력으로 받습니다. 원시 암호학적 증명 값을 제공하는 것 외에도 파생 증명에 포함되는 pseudonym 값을 반환합니다.
  5. 검증자가 바인딩된 가명이 있는 파생 증명을 받으면 이 명세의 절차와 [CFRG-Pseudonym-BBS-Signature]의 "Proof Verification with Pseudonym" 연산을 사용하여 파생 증명을 검증합니다. 이러한 절차는 지정된 nym_domainpseudonym 계산에 사용되었는지도 검증한다는 점에 유의하십시오.

4.3 보유자 바인딩 및 가명

익명 보유자 바인딩과 자격 증명 바인딩 가명은 어떤 의미에서는 서로 직교하는 기능이며, 보유자 및 자격 증명 생태계에서는 두 기능을 동시에 사용하려 할 수 있습니다. 예를 들어 보유자는 검증 가능한 자격 증명을 holder_secret에 바인딩하여 이 값을 아는 보유자만 기본 증명에서 파생 증명을 생성할 수 있도록 하고, nym_secret을 기본 증명에 바인딩하여 가명을 파생 증명에 바인딩할 수 있도록 할 수 있습니다. 이는 featureOption"holder_binding_pseudonym"과 같은 경우에 해당합니다.

익명 보유자 바인딩과 자격 증명 바인딩 가명을 모두 생성하고 사용하는 방법의 개요는 다음 단계와 같습니다.

  1. 보유자는 holder_secretprover_nym이라는 두 개의 보안 값을 생성합니다. 이 값들은 최소 32바이트 길이여야 하며 암호학적으로 무작위로 생성되어야 합니다. 그런 다음 [CFRG-Pseudonym-BBS-Signature]의 "Commitment" 연산을 사용하고, holder_secret을 유일한 요소로 포함하는 committed_messages 배열을 입력하여 commitment_with_proofsecret_prover_blind를 계산합니다. commitment_with_proof는 자격 증명 요청과 함께 발급자에게 전송되지만 holder_secret, prover_nymsecret_prover_blind는 보유자가 나중에 사용하기 위해 보관하며 절대로 공개하지 않습니다.
  2. 발급자는 바인딩된 가명이 포함된 자격 증명에 대한 보유자의 요청을 받으며, featureOption"pseudonym"과 같고 commitment_with_proof도 함께 받습니다. 발급자는 이 명세의 절차를 사용하고 signer_nym_entropy에 사용할 암호학적 난수 값을 생성한 다음 [CFRG-Pseudonym-BBS-Signature]의 "Blind Issuance" 연산을 사용하여 기본 증명을 생성합니다. 다른 정보와 함께 기본 증명에는 signer_nym_entropy 값이 포함됩니다. 발급자가 동일한 nym_secret에 바인딩된 자격 증명을 이 보유자에게 다시 발급해야 한다면 signer_nym_entropy 값을 보관해야 하며, 그렇지 않으면 이 값을 폐기할 수 있습니다.
  3. 바인딩된 가명이 포함된 자격 증명을 받은 보유자는 이 명세의 절차와 [CFRG-Pseudonym-BBS-Signature]의 "Verification and Finalization" 연산을 사용하고, holder_secret을 유일한 요소로 포함하는 committed_messages 배열을 사용하여 서명을 검증하는 동시에 nym_secret 값을 계산합니다. 이 연산은 다른 값들과 함께 holder_secret, prover_nym, signer_nym_entropy, secret_prover_blind 값을 사용합니다. 제3자 모니터링을 사용하는 경우 nym_secret 값을 모니터링 조직과 안전하게 공유합니다.
  4. 보유자가 가명에 바인딩된 파생 증명을 생성하려면 nym_domain을 결정해야 합니다. 앞서 언급했듯이 사용 시나리오에 따라 검증자가 이를 지정하거나 보유자가 설정할 수 있습니다. 그런 다음 이 명세의 절차와 [CFRG-Pseudonym-BBS-Signature]의 "Proof Generation with Pseudonym" 연산을 사용하여 파생 증명을 생성합니다. 이 연산은 다른 값들과 함께 nym_secret, nym_domain, holder_secret을 유일한 요소로 포함하는 committed_messages 배열 및 secret_prover_blind를 입력으로 받습니다. 원시 암호학적 증명 값을 제공하는 것 외에도 파생 증명에 포함되는 pseudonym 값을 반환합니다.
  5. 검증자가 바인딩된 가명이 있는 파생 증명을 받으면 이 명세의 절차와 [CFRG-Pseudonym-BBS-Signature]의 "Proof Verification with Pseudonym" 연산을 사용하여 파생 증명을 검증합니다. 이러한 절차는 지정된 nym_domainpseudonym 계산에 사용되었는지도 검증한다는 점에 유의하십시오.

4.4 선택적 기능 요약

이 절은 비규범적입니다.

이 절에서는 "baseline" BBS 증명과 선택적 기능에 대한 입력, 출력, 증명 직렬화, 작업 및 절차를 요약합니다. baseline BBS란 추가 기능이 없는 BBS 기본 증명 및 파생 증명을 의미합니다. 모든 선택적 기능은 "추가적"이며, "baseline" BBS 서명/증명의 입력, 작업 또는 출력에 추가로 일부 입력, 작업 또는 출력이 생성됩니다.

표 1 발급자의 기본 증명 생성: 입력 등.
이름 작업 입력 서명 알고리즘
기준 BBS baseline: VC에서 BBS 서명 생성 baseline: 문서, 증명 옵션, 키 자료, 필수 포인터 BBS
익명 보유자 바인딩 baseline baseline + 보유자가 제공한 증명이 포함된 커밋먼트 블라인드 BBS
자격 증명 바인딩 가명 baseline + signer_nym_entropy 생성 baseline + signer_nym_entropy, 보유자가 제공한 증명이 포함된 커밋먼트 가명 BBS
보유자 바인딩 및 가명 baseline + signer_nym_entropy 생성 baseline + signer_nym_entropy, 보유자가 제공한 증명이 포함된 커밋먼트 가명 BBS
표 2 발급자의 기본 증명 생성: 헤더 및 직렬화.
이름 증명 헤더 바이트 직렬화된 출력
기준 BBS 0xd9, 0x5d, 및 0x02 baseline: bbsSignature, bbsHeader, publicKey, hmacKey 및 mandatoryPointers
익명 보유자 바인딩 0xd9, 0x5d, 및 0x04 baseline
자격 증명 바인딩 가명 0xd9, 0x5d, 및 0x06 baseline + signer_nym_entropy
보유자 바인딩 및 가명 0xd9, 0x5d, 및 0x08 baseline + signer_nym_entropy
표 3 보유자의 파생 증명 추가: 입력 등.
이름 작업 입력 증명 생성 알고리즘
기준 BBS 기본 증명이 있는 VC에서 BBS 파생 증명 생성 baseline: (기본 증명 직렬화에서) bbsSignature, bbsHeader, publicKey, hmacKey 및 mandatoryPointers; selectivePointers (보유자의 선택) BBS
익명 보유자 바인딩 baseline baseline + holder_secret, prover_blind (둘 다 보유자가 알고 있음) 블라인드 BBS
자격 증명 바인딩 가명 baseline + nym_secret 계산, pseudonym 계산 baseline + prover_nym, prover_blind (모두 보유자가 알고 있음), signer_nym_entropy (발급자의 기본 증명에 포함됨), nym_domain 가명 BBS
보유자 바인딩 및 가명 baseline + nym_secret 계산, pseudonym 계산 baseline + holder_secret, prover_nym, prover_blind (모두 보유자가 알고 있음), signer_nym_entropy (발급자의 기본 증명에 포함됨), nym_domain 가명 BBS
표 4 보유자의 파생 증명 추가: 헤더 및 직렬화.
이름 증명 헤더 바이트 직렬화된 출력
기준 BBS 0xd9, 0x5d, 및 0x03 baseline: bbsProof, compressedLabelMap, mandatoryIndexes, selectiveIndexes, presentationHeader
익명 보유자 바인딩 0xd9, 0x5d, 및 0x05 baseline
자격 증명 바인딩 가명 0xd9, 0x5d, 및 0x07 baseline + pseudonym, nym_domain
보유자 바인딩 및 가명 0xd9, 0x5d, 및 0x09 baseline + pseudonym, nym_domain
표 5 파생 증명 검증: 입력 및 알고리즘.
이름 입력 증명 검증 알고리즘
BBS 기준 baseline: (파생 증명 직렬화에서) bbsProof, compressedLabelMap, mandatoryIndexes, selectiveIndexes, presentationHeader BBS
익명 보유자 바인딩 baseline 블라인드 BBS
자격 증명 바인딩 가명 baseline + pseudonym (파생 증명에 포함됨), nym_domain 가명 BBS
보유자 바인딩 및 가명 baseline + pseudonym (파생 증명에 포함됨), nym_domain 가명 BBS

5. 보안 고려 사항

이 절을 읽기 전에 독자는 데이터 무결성 명세의 보안 고려 사항 절에서 제공하는 일반적인 보안 지침을 숙지할 것을 권고합니다.

5.1 기본 증명의 보안 속성

이 절은 비규범적입니다.

기본 증명의 보안은 관련 BBS 서명의 보안 속성에 따라 달라집니다. 디지털 서명은 여러 바람직한 암호학적 속성을 가질 수 있으며 [Taming_EdDSAs] 그중에는 다음이 있습니다:

EUF-CMA (선택 메시지 공격에 대한 존재적 위조 불가능성)는 일반적으로 서명 방식에 요구되는 최소한의 보안 속성입니다. 이는 서명자의 공개 키 p k 를 가지고 있으며 자신이 선택한 메시지에 대한 임의 개수의 서명을 (적응적인 방식으로) 받은 효율적인 공격자가: { m i , σ i } i = 1 N , 새로운 메시지 m { m i } i = 1 N 에 대해 유효한 서명 σ 을 출력할 수 없음을 보장합니다 (무시할 수 있을 정도로 작은 확률은 제외). 공격자가 새로운 메시지에 대한 유효한 서명을 출력하는 경우: ( m , σ ) , 이를 존재적 위조라고 합니다.

SUF-CMA (선택 메시지 공격에 대한 강한 위조 불가능성)는 EUF-CMA보다 더 강한 개념입니다. 이는 서명자의 공개 키 p k 를 가지고 있으며 자신이 선택한 메시지에 대한 임의 개수의 서명을 받은 효율적인 공격자가: { m i , σ i } i = 1 N , 다음 조건을 만족하는 새로운 유효한 서명 쌍 ( m , σ ) , 을 출력할 수 없음을 보장합니다: ( m , σ ) { m i , σ i } i = 1 N (무시할 수 있을 정도로 작은 확률은 제외). 강한 위조 불가능성은 공격자가 새로운 메시지에 서명할 수 없을 뿐만 아니라 기존 메시지에 대해 새로운 서명을 찾을 수도 없음을 의미합니다.

[CDL2016]에서는 일부 합리적인 가정하에 BBS 서명이 EUF-CMA임이 증명되었습니다. 또한 [TZ2023]에서는 유사한 가정하에 BBS 서명이 SUF-CMA임이 증명되었습니다. 두 경우 모두 가정은 대규모 양자 컴퓨팅 이후에는 안전하다고 간주되지 않는 이산 로그 문제의 어려움과 관련되어 있습니다.

비양자 컴퓨팅 조건에서 [CFRG-BBS-SIGNATURE]은 BBS 서명 스위트 구현자에게 추가적인 보안 지침을 제공합니다. 페어링 친화적 곡선과 관련된 추가적인 보안 고려 사항은 [CFRG-PAIRING-FRIENDLY]에서 논의됩니다.

5.2 파생 증명의 보안 속성

이 절은 비규범적입니다.

파생 증명의 보안은 관련 BBS 증명의 보안 속성에 따라 달라집니다. [CDL2016] 및 [TZ2023] 모두 BBS 증명BBS 서명에 대한 지식의 영지식 증명임을 증명합니다.

[CFRG-BBS-SIGNATURE]에서 설명한 바와 같이 이는 다음을 의미합니다:

증명을 받은 검증 당사자는 어떤 서명이 증명 생성에 사용되었는지 판단할 수 없으므로 일반적인 상관 관계의 원인이 제거됩니다. 일반적으로 동일한 서명에서 생성된 두 증명이라도 생성된 각 증명은 난수와 구별할 수 없습니다.

그리고

이 방식으로 생성된 증명은 증명을 생성한 당사자 (보유자/증명자 또는 그 대리인)가 서명을 공개하지 않고도 해당 서명을 보유하고 있었음을 검증자에게 증명합니다.

더 정확히 말하면 BBS 증명을 검증하려면 원래 발급자의 공개 키와 변경되지 않고 공개된 BBS 메시지가 올바른 순서로 필요합니다.

6. 개인정보 보호 고려 사항

이 절은 비규범적입니다.

6.1 선택적 공개 및 데이터 유출

선택적 공개를 사용하면 보유자가 특정 목적을 달성하기 위해 검증자에게 공개하는 정보를 최소화할 수 있습니다. 선택적 공개를 지원하는 전체 시스템을 규정할 때는 검증자에게 공개하려 하지 않았던 추가 정보가 최소화되도록 주의해야 합니다. 이러한 유출은 시스템의 산출물을 통해 발생할 수 있습니다. 이러한 산출물은 데이터 구조와 같은 시스템의 상위 계층이나 하위 수준의 암호학적 기본 연산에서 발생할 수 있습니다.

예를 들어 BBS 서명 방식은 여러 메시지에 대한 서명을 생성하는 데 공간 효율성이 매우 높은 방식입니다. 즉, 보유자에게 전송되는 암호학적 서명의 크기는 메시지 수와 관계없이 일정합니다. 그런 다음 보유자는 이러한 메시지 중 원하는 것을 검증자에게 선택적으로 공개할 수 있습니다. 그러나 암호화 방식의 일부로서 발급자가 서명한 전체 메시지 수를 검증자에게 공개해야 합니다. 이러한 정보 유출을 피해야 한다면 [CFRG-BBS-SIGNATURE]의 개인정보 보호 고려 사항 절에서 제안하는 대로 메시지 수를 공통 길이에 맞게 패딩하는 것이 권장됩니다.

상위 수준에서는 데이터를 선택적 공개에 적합한 개별 문장, 즉 BBS 메시지로 매핑하는 방식이 데이터 유출의 잠재적인 원인이 됩니다. 이 암호화 스위트는 JSON-LD 처리를 사용하여 입력을 RDF로 변환함으로써 JSON 데이터를 표현하는 데 사용되며 정보를 유출할 수 있는 많은 구조적 산출물(중첩, 맵 또는 배열 위치 등)을 제거할 수 있습니다. 그런 다음 RDF는 단순한 주어, 속성, 값 문장으로 이루어진 정규화된 평면 형식으로 표현할 수 있습니다(검증 가능한 자격 증명 데이터 모델 [VC-DATA-MODEL-2.0]에서는 이를 클레임이라고 합니다). 다음에서는 선택적 공개를 위해 JSON-LD 형식의 검증 가능한 자격 증명을 문장(BBS 메시지) 집합으로 매핑하는 일반적인 방식인 RDF 정규화를 살펴봅니다. 이 과정이 수행된 후에도 정보 유출의 잠재적인 원인이 남아 있음을 보여주고, 키 기반 의사 난수 함수(PRF)를 사용하여 이러한 유출을 완화하는 방법을 보여줍니다.

RDF 정규화를 사용하여 JSON-LD VC를 문장 집합으로 평탄화할 수 있습니다. 이 알고리즘은 VC의 내용에 따라 달라지며 문장의 순서를 지정하는 데 도움을 주기 위해 암호학적 해시 함수도 사용합니다. 본질적으로 JSON-LD 문서 내에서 클레임의 주체를 나타내는 각 JSON 객체는 @id 필드가 정의되어 있지 않은 경우 id가 할당됩니다. 이러한 id빈 노드 id라고 합니다. 이러한 id는 각 클레임의 주체를 구별할 수 있도록 클레임을 단순한 주어, 속성, 값 문장으로 표현하는 데 필요합니다. id 값은 [RDF-CANON]에 따라 결정론적으로 설정되며 문서의 데이터와 SHA-256 같은 암호학적 해시 함수의 출력을 기반으로 합니다.

아래에서는 윈드서핑 돛 집합에 대한 약간 서로 다른 두 VC와 선택적 공개에 사용할 수 있는 문장 집합으로의 정규화를 보여줍니다. 6.1 크기 돛의 연도를 변경하면 두 VC 간 문장 순서가 크게 변경되는 것을 확인할 수 있습니다. 보유자가 더 큰 돛 (7.0 및 7.8)에 대한 정보만 공개하는 경우 검증자는 돛 집합에서 무언가 변경되었다는 사실을 알아낼 수 있으며, 이는 정보 유출에 해당합니다.

예제 3: 윈드서핑 돛 집합에 대한 VC
{
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    {
      "@vocab": "https://windsurf.grotto-networking.com/selective#"
    }
  ],
  "type": [
    "VerifiableCredential"
  ],
  "credentialSubject": {
    "sails": [
      {
        "size": 5.5,
        "sailName": "Kihei",
        "year": 2023
      },
      {
        "size": 6.1,
        "sailName": "Lahaina",
        "year": 2023 // 정규화에 미치는 영향을 확인하기 위해 이 값을 변경합니다
      },
      {
        "size": 7.0,
        "sailName": "Lahaina",
        "year": 2020
      },
      {
        "size": 7.8,
        "sailName": "Lahaina",
        "year": 2023
      }
    ]
  }
}

위 VC의 정규형입니다. 빈 노드 id의 할당, 즉 _:c14nX 레이블은 VC의 내용에 따라 달라지며 이는 문장의 순서에도 영향을 줍니다.

예제 4: 윈드서핑 돛 집합에 대한 VC의 정규형
_:c14n0 <https://windsurf.grotto-networking.com/selective#sailName> "Lahaina" .
_:c14n0 <https://windsurf.grotto-networking.com/selective#size> "7.8E0"^^<http://www.w3.org/2001/XMLSchema#double> .
_:c14n0 <https://windsurf.grotto-networking.com/selective#year> "2023"^^<http://www.w3.org/2001/XMLSchema#integer> .
_:c14n1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://www.w3.org/2018/credentials#VerifiableCredential> .
_:c14n1 <https://www.w3.org/2018/credentials#credentialSubject> _:c14n4 .
_:c14n2 <https://windsurf.grotto-networking.com/selective#sailName> "Lahaina" .
_:c14n2 <https://windsurf.grotto-networking.com/selective#size> "7"^^<http://www.w3.org/2001/XMLSchema#integer> .
_:c14n2 <https://windsurf.grotto-networking.com/selective#year> "2020"^^<http://www.w3.org/2001/XMLSchema#integer> .
_:c14n3 <https://windsurf.grotto-networking.com/selective#sailName> "Kihei" .
_:c14n3 <https://windsurf.grotto-networking.com/selective#size> "5.5E0"^^<http://www.w3.org/2001/XMLSchema#double> .
_:c14n3 <https://windsurf.grotto-networking.com/selective#year> "2023"^^<http://www.w3.org/2001/XMLSchema#integer> .
_:c14n4 <https://windsurf.grotto-networking.com/selective#sails> _:c14n0 .
_:c14n4 <https://windsurf.grotto-networking.com/selective#sails> _:c14n2 .
_:c14n4 <https://windsurf.grotto-networking.com/selective#sails> _:c14n3 .
_:c14n4 <https://windsurf.grotto-networking.com/selective#sails> _:c14n5 .
_:c14n5 <https://windsurf.grotto-networking.com/selective#sailName> "Lahaina" .
_:c14n5 <https://windsurf.grotto-networking.com/selective#size> "6.1E0"^^<http://www.w3.org/2001/XMLSchema#double> .
_:c14n5 <https://windsurf.grotto-networking.com/selective#year> "2023"^^<http://www.w3.org/2001/XMLSchema#integer> .

업데이트된 윈드서핑 돛 컬렉션으로, 6.1 크기 돛이 2024년 모델로 업데이트되었습니다. 이로 인해 빈 노드 id 할당을 통해 문장의 순서가 변경됩니다.

예제 5: 약간 업데이트된 윈드서핑 돛 집합에 대한 VC
{
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    {
      "@vocab": "https://windsurf.grotto-networking.com/selective#"
    }
  ],
  "type": [
    "VerifiableCredential"
  ],
  "credentialSubject": {
    "sails": [
      {
        "size": 5.5,
        "sailName": "Kihei",
        "year": 2023
      },
      {
        "size": 6.1,
        "sailName": "Lahaina",
        "year": 2024 // 기존 모델을 업데이트하는 새 돛으로, 정규화가 변경됩니다
      },
      {
        "size": 7.0,
        "sailName": "Lahaina",
        "year": 2020
      },
      {
        "size": 7.8,
        "sailName": "Lahaina",
        "year": 2023
      }
    ]
  }
}

이전 VC의 정규형입니다. 빈 노드 id 할당과 문장 순서의 차이에 유의하십시오.

예제 6: 업데이트된 윈드서핑 돛 집합에 대한 VC의 정규형
_:c14n0 <https://windsurf.grotto-networking.com/selective#sailName> "Lahaina" .
_:c14n0 <https://windsurf.grotto-networking.com/selective#size> "6.1E0"^^<http://www.w3.org/2001/XMLSchema#double> .
_:c14n0 <https://windsurf.grotto-networking.com/selective#year> "2024"^^<http://www.w3.org/2001/XMLSchema#integer> .
_:c14n1 <https://windsurf.grotto-networking.com/selective#sailName> "Lahaina" .
_:c14n1 <https://windsurf.grotto-networking.com/selective#size> "7.8E0"^^<http://www.w3.org/2001/XMLSchema#double> .
_:c14n1 <https://windsurf.grotto-networking.com/selective#year> "2023"^^<http://www.w3.org/2001/XMLSchema#integer> .
_:c14n2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://www.w3.org/2018/credentials#VerifiableCredential> .
_:c14n2 <https://www.w3.org/2018/credentials#credentialSubject> _:c14n5 .
_:c14n3 <https://windsurf.grotto-networking.com/selective#sailName> "Lahaina" .
_:c14n3 <https://windsurf.grotto-networking.com/selective#size> "7"^^<http://www.w3.org/2001/XMLSchema#integer> .
_:c14n3 <https://windsurf.grotto-networking.com/selective#year> "2020"^^<http://www.w3.org/2001/XMLSchema#integer> .
_:c14n4 <https://windsurf.grotto-networking.com/selective#sailName> "Kihei" .
_:c14n4 <https://windsurf.grotto-networking.com/selective#size> "5.5E0"^^<http://www.w3.org/2001/XMLSchema#double> .
_:c14n4 <https://windsurf.grotto-networking.com/selective#year> "2023"^^<http://www.w3.org/2001/XMLSchema#integer> .
_:c14n5 <https://windsurf.grotto-networking.com/selective#sails> _:c14n0 .
_:c14n5 <https://windsurf.grotto-networking.com/selective#sails> _:c14n1 .
_:c14n5 <https://windsurf.grotto-networking.com/selective#sails> _:c14n3 .
_:c14n5 <https://windsurf.grotto-networking.com/selective#sails> _:c14n4 .

이러한 빈 노드 id의 할당과 이로 인해 문장에 부여되는 순서에서 발생하는 정보 유출을 방지하기 위해 HMAC 기반 PRF를 빈 노드 id에 실행합니다. HMAC 비밀 키는 발급자보유자 사이에서만 공유되며, 발급자가 생성하는 각 기본 증명은 새로운 HMAC 키를 사용합니다. 이에 대한 예는 [DI-ECDSA]의 정규 HMAC 테스트 벡터에서 확인할 수 있습니다. 다음 절에서 설명하듯이 BBS가 연결 불가능성을 유지하도록 하기 위해 HMAC 기반 빈 노드 id를 사용하지 않고, 테스트 벡터 예제 12에 표시된 것처럼 HMAC을 기반으로 순서의 셔플된 버전을 생성합니다. 이는 빈 노드 id의 수에 관한 정보가 유출될 수 있으므로 ECDSA-SD 방식보다 빈 노드 id에 관한 정보 은닉 수준이 낮지만, 빈 노드 id에 HMAC을 적용하여 생성된 사실상 고유한 식별자를 통한 연결 공격은 방지합니다.

6.2 선택적 공개 및 연결 불가능성

VC의 일부 사용 사례에서는 여러 서로 다른 검증자와의 상호작용이 추적되거나 연결되는 것을 방지하는 것이 보유자의 개인정보 보호에 중요할 수 있습니다. 특히 두 가지 중요한 경우, (i) 검증자와 발급자의 공모 및 (ii) 검증자 간 공모를 고려합니다. 첫 번째 경우는 그림 1에 표시되어 있으며, 검증자보유자와의 상호작용에 관한 정보를 자격 증명의 원래 발급자에게 다시 보고합니다. 이 상황에서 발급자는 발급된 VC를 사용하여 다양한 검증자와 이루어진 모든 보유자 상호작용을 추적할 수 있습니다. 두 번째 상황은 그림 2에 표시되어 있으며, 여러 검증자가 공모하여 자신들과 상호작용한 보유자에 관한 정보를 공유합니다.


여러 검증자가 발급자에게 데이터를 다시 보내는 모습을 보여주는 다이어그램입니다.
다이어그램은 위에서 아래로 배치되어 있으며 맨 위에 발급자라고 표시된 원이 있고,
그 아래 보유자라고 표시된 원과 연결되어 있습니다. 보유자라고 표시된 원에서
검증자라고 표시된 여러 추가 원으로 여러 화살표가 이어집니다. 검증자라고
표시된 원에서 발급자라고 표시된 원으로 점선 화살표가 다시 이어져
공모에 의한 데이터 흐름을 보여줍니다.
그림 1 검증자와 발급자의 공모.

여러 검증자가 서로 정보를 공유하는 모습을 보여주는 다이어그램입니다.
다이어그램은 위에서 아래로 배치되어 있으며 맨 위에 발급자라고 표시된 원이 있고,
그 아래 보유자라고 표시된 원과 연결되어 있습니다. 보유자라고 표시된 원에서
검증자라고 표시된 여러 추가 원으로 여러 화살표가 이어집니다. 검증자라고
표시된 원에서 다른 발급자라고 표시된 원으로 점선 화살표가 이어져
검증자 간 공모에 의한 데이터 흐름을 보여줍니다.
그림 2 검증자 간 공모.

VC 시스템이 보유자의 개인정보에 대한 이러한 "연결 공격"을 방지하는 속성을 설명하기 위해 연결 불가능성이라는 용어를 사용합니다. 연결 불가능성이라는 용어는 비교적 새롭지만 [NISTIR8053]의 3.3절에서는 연결 공격을 통한 재식별을 논의하고 사례 연구를 제공합니다. 데이터 개인정보에 대한 연결 공격에 관한 지식의 체계화는 [Powar2023]에서 확인할 수 있습니다. 사용자 개인정보에 대한 연결 공격의 가장 널리 사용되는 형태는 웹 브라우저 핑거프린팅이며, 이에 관한 조사는 [Pugliese2020]에서 확인할 수 있습니다.

연결이라는 개념을 정량화하기 위해 [Powar2023]에서는 익명성 집합이라는 개념을 도입합니다. 여기서 다루는 VC의 경우 익명성 집합에는 특정 VC의 보유자와 특정 발급자와 관련된 다른 보유자가 포함됩니다. 익명성 집합이 작을수록 여러 검증자에 걸쳐 보유자를 추적할 가능성이 커집니다. 서명된 VC에는 발급자의 공개 키에 대한 참조가 포함되므로 특정 발급자의 VC를 보유한 보유자에 대한 익명성 집합의 초기 크기는 해당 발급자가 특정 공개/비공개 키 쌍으로 발급한 VC의 수입니다. 악의적이지 않은 발급자는 VC 발급에 사용하는 공개/비공개 키 쌍의 수를 최소화할 것으로 기대됩니다. 익명성 집합 개념은 [vc-bitstring-status-list]의 그룹 개인정보 보호 개념과 유사하다는 점에 유의하십시오. 여기서 연결이라는 용어를 사용할 때는 일반적으로 익명성 집합의 크기를 감소시키는 모든 메커니즘을 의미합니다.

선택적 공개를 지원하는 VC 시스템에서 연결의 원인은 다음과 같습니다:

  1. 암호학적 기본 연산에서 발생하는 산출물.
  2. VC를 선택적 공개에 적합한 문장 집합으로 매핑하는 과정에서 발생하는 산출물.
  3. VC의 증명 옵션 및 필수 공개 정보에서 발생하는 산출물.
  4. VC에서 선택적으로 공개된 정보.
  5. 외부 VC 시스템 기반 연결

아래에서 각각을 논의합니다.

6.2.1 암호학적 산출물을 통한 연결

암호학적 해시, HMAC 및 디지털 서명은 그 특성상 매우 고유한 식별자를 생성합니다. SHA-256 같은 해시 함수의 출력은 충돌 저항성 속성으로 인해 서로 다른 입력에 대해 사실상 고유함이 보장되며 강한 연결을 초래합니다. 즉, 익명성 집합의 크기를 1로 줄입니다. 마찬가지로 Ed25519 및 결정론적 ECDSA 같은 결정론적 서명 알고리즘은 서로 다른 입력에 대해 사실상 고유한 출력을 생성하고 강한 연결을 초래합니다.

이는 VC 내부의 디지털 서명, HMAC 또는 해시 산출물을 통해 보유자가 여러 검증자에 걸쳐 쉽게 추적될 수 있음을 의미하며, 따라서 검증자 간 공모 및 검증자와 발급자 간 공모에 취약합니다. 일부 형태의 ECDSA와 같은 무작위화된 서명 알고리즘을 사용하면 발급자가 동일한 입력에 대해 여러 개의 서로 다른 서명을 생성하고, 서로 다른 검증자와 함께 사용하도록 이를 보유자에게 전송할 수 있습니다. 이러한 방식은 검증자 간 공모에 기반한 추적을 방지하는 데 사용할 수 있지만 검증자와 발급자 간 공모에는 도움이 되지 않습니다.

연결 불가능성을 달성하려면 보유자서명에 대한 지식의 영지식 증명(ZKPKS)을 생성할 수 있도록 특별히 설계된 암호학적 서명 방식이 필요합니다. 이는 보유자가 이러한 방식에서 발급자의 서명을 받아 검증자에게 전송할 ZKPKS를 계산할 수 있음을 의미합니다. 이 ZKPKS는 원본 서명으로 다시 연결할 수 없지만 서명의 모든 바람직한 속성을 갖습니다. 즉, 검증자는 이를 사용하여 메시지가 발급자의 공개 키로 서명되었고 메시지가 변경되지 않았음을 검증할 수 있습니다. 또한 보유자는 서로 다른 검증자를 위해 원하는 만큼 ZKPKS를 생성할 수 있으며 이들은 사실상 서로 독립적이고 연결할 수 없습니다. BBS는 이러한 기능을 지원하는 서명 방식 중 하나입니다.

이 문서에서 BBS 증명이라고 하는 ZKPKS에는 보장된 연결 불가능성 속성이 있습니다. 그러나 BBS를 선택적 공개와 함께 사용할 때는 연결 가능성에 영향을 줄 수 있는 두 가지 산출물이 있습니다. 원래 서명된 전체 메시지 수와 공개된 문장의 인덱스 값입니다. 이에 대한 논의 및 완화 기법은 [CFRG-BBS-SIGNATURE]의 개인정보 보호 고려 사항을 참조하십시오.

[CFRG-BBS-SIGNATURE]의 발급자의 공개 키 절에서 언급했듯이, 발급자가 여러 공개 키를 사용하고 그중 일부를 검증자와 발급자 간 공모를 통해 특정 사용자 하위 집합을 추적하는 데 사용할 수 있는 잠재적 위협이 있습니다. 발급자의 공개 키는 검증자에게 보여야 하므로, 즉 BBS 증명(파생 증명)에서 참조되므로, 발급자가 많은 서로 다른 공개 키를 사용하고 특히 그 키 중 일부를 소수의 사용자(보유자)에게 사용하는 경우 연결 지점으로 사용될 수 있습니다.

6.2.2 VC 처리를 통한 연결

정보 유출에 관한 절에서 보았듯이 RDF 정규화는 해시 함수를 사용하여 문장의 순서를 지정하며, HMAC을 기반으로 문장 순서를 추가로 셔플합니다. 이로 인해 일부 연결을 가능하게 하는 핑거프린트가 남을 수 있습니다. 연결의 강도는 빈 노드의 수, 즉 VC 내 JSON 객체의 수와 공개되는 인덱스의 수에 따라 달라집니다. n개의 빈 노드와 k개의 공개된 인덱스가 있을 때 최악의 경우 익명성 집합의 크기는 C(n, k)배 감소할 수 있습니다. 즉, n개 요소 집합에서 선택한 크기 k의 조합 수입니다. VC의 빈 노드 수를 줄이는 방법, 예를 들어 VC를 짧고 간단하게 유지하는 방법으로 이 값을 상당히 낮게 유지할 수 있습니다.

6.2.3 JSON-LD 노드 식별자를 통한 연결

JSON-LD는 연결 데이터를 직렬화하기 위한 JSON 기반 형식입니다. 따라서 문서 내 각 객체(JSON-LD 용어로 "노드")에 전역적으로 모호하지 않은 @id 속성(노드 식별자)을 할당하는 기능을 지원합니다. 이를 통해 연결 데이터의 연결이 가능해지고, 동일한 엔터티에 관한 정보를 서로 연관시킬 수 있습니다. 이러한 상관 관계는 사용 사례에 따라 바람직할 수도, 바람직하지 않을 수도 있습니다.

BBS의 연결 불가능성 기능을 사용할 때는 전역적으로 모호하지 않은 노드 식별자를 개인이나 개인 식별 가능 정보에 사용할 수 없습니다. 이들이 제공하는 강한 연결은 바람직하지 않기 때문입니다. 이러한 식별자는 비개인 정보에 관한 문장을 표현할 때는 사용할 수 있다는 점에 유의하십시오(예: 큰 국가나 콘서트 이벤트를 식별하기 위해 전역적으로 모호하지 않은 식별자를 사용하는 경우). 또한 용어를 IRI에 매핑하는 JSON-LD의 @context 사용은 일반적으로 연결 불가능성에 영향을 주지 않는다는 점에 유의하십시오.

6.2.4 증명 옵션 및 필수 공개를 통한 연결

[VC-DATA-INTEGRITY-1.1] 사양에서는 VC의 proof 속성에 관한 여러 속성이 제시됩니다. 선택적 필드가 검증자 간에 강한 연결성을 제공하지 않도록 주의해야 합니다. 선택적 필드에는 다음이 포함됩니다. id, created, expires, domain, challengenonce. 예를 들어 선택적 created 필드는 증명의 생성 날짜를 임의의 1초 미만 정밀도까지 지정할 수 있는 dateTimeStamp 객체입니다. 이러한 정보가 존재하면 익명성 집합의 크기가 크게 줄어들 수 있습니다. 발급자가 이러한 정보를 포함하려는 경우 시간 경과에 따라 발급되는 VC 수에 비례하여 가능한 한 거친 단위로 만들어야 합니다.

발급자는 또한 기본 증명 생성에 사용되는 mandatoryPointers 입력을 통해 보유자가 특정 문장을 검증자에게 공개하도록 강제할 수도 있습니다. 다음 절을 참조하십시오. 예제 9예제 10. 여기서 강제한다는 것은 이러한 문장이 검증자에게 공개되지 않으면 생성된 파생 증명이 검증되지 않는다는 의미입니다. 이러한 정보를 공개해야 하는 경우에도 익명성 집합이 충분히 크게 유지되도록 주의해야 합니다.

6.2.5 보유자의 선택적 공개를 통한 연결

[Powar2023]에서 논의한 것처럼 연결 공격을 통해 개인이 재식별된 많은 사례가 문서화되어 있습니다. 따라서 보유자는 익명성 집합을 크게 유지하는 데 도움이 되도록 가능한 한 적은 정보만 공개할 것을 권고합니다. 또한 겉보기에는 무해한 정보도 매우 고유할 수 있으며, 따라서 재식별이나 추적으로 이어질 수 있음이 여러 차례 입증되었습니다. 특히 유명한 전 매사추세츠 주지사 사례의 자세한 설명은 [NISTIR8053]을 참조하고, 이러한 공개 사례 94건에 대한 추가 분석 및 분류는 [Powar2023]을 참조하십시오.

6.2.6 외부 VC 시스템 기반 연결

연결 불가능성, 즉 익명성을 유지하려면 VC를 보관하고 통신하는 시스템에서도 주의가 필요하다는 점을 지적해야 합니다. IP 주소(계층 3)나 이더넷/MAC 주소(계층 2) 같은 네트워크 산출물은 잘 알려진 연결의 원인입니다. 예를 들어 휴대전화 MAC 주소는 사용자가 특정 액세스 포인트를 다시 방문하는 경우 사용자를 추적하는 데 사용될 수 있으며, 이로 인해 휴대전화 제조업체가 MAC 주소 무작위화 기능을 제공하게 되었습니다. 공인 IP 주소는 일반적으로 개인의 위치를 한 국가 내 도시나 지역 수준까지 파악할 수 있는 충분한 정보를 제공하므로 익명성 집합을 크게 줄일 수 있습니다.

A. 테스트 벡터

이 절은 비규범적입니다.

A.1 기준 기본 예제

문서 테스트 벡터는 완전히 가상의 영주권 카드를 기반으로 하며, 두 그룹, 즉 발급자가 생성하는 것("기본 증명")과 보유자가 생성하는 것("파생 증명")으로 나뉩니다.

A.1.1 기본 증명

문서에 선택적 공개 기본 증명을 추가하려면 발급자에게 다음 암호학적 키 자료가 필요합니다:

  1. 발급자의 비공개/공개 키 쌍, 즉 증명의 일부가 될 검증 방법에 해당하는 키 쌍입니다.
  2. HMAC 키. 이는 빈 노드 ID 순서를 무작위화하여 빈 노드 ID 순서를 통한 잠재적인 정보 유출을 방지하는 데 사용됩니다. 이는 한 번만 사용되며 발급자와 보유자 간에 공유됩니다. 이 경우 HMAC은 의사 난수 함수(PRF)로 기능합니다.

기본 증명 추가 테스트를 위한 테스트 벡터 생성에 사용된 키 자료는 아래와 같습니다. BBS 키 쌍과 HMAC 키에는 16진수 표현을 사용합니다.

예제 7: 서명용 비공개 및 공개 키
{
  "publicKeyHex": "a4ef1afa3da575496f122b9b78b8c24761531a8a093206ae7c45b80759c168ba4f7a260f9c3367b6c019b4677841104b10665edbe70ba3ebe7d9cfbffbf71eb016f70abfbb163317f372697dc63efd21fc55764f63926a8f02eaea325a2a888f",
  "privateKeyHex": "66d36e118832af4c5e28b2dfe1b9577857e57b042a33e06bdea37b811ed09ee0",
  "hmacKeyString": "00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF"
}

이 시나리오에서는 영주권 자격 증명을 발급합니다. 서명되지 않은 영주권 문서는 아래와 같습니다.

예제 8: 증명이 없는 자격 증명
{
    "@context": [
      "https://www.w3.org/ns/credentials/v2",
      "https://w3id.org/citizenship/v4rc1"
    ],
    "type": [
      "VerifiableCredential",
      "PermanentResidentCardCredential"
    ],
    "issuer": {
      "id": "did:key:zDnaeTHxNEBZoKaEo6PdA83fq98ebiFvo3X273Ydu4YmV96rg",
      "image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2P4z/DiPwAG0ALnwgz64QAAAABJRU5ErkJggg=="
       },
    "name": "Permanent Resident Card",
    "description": "Government of Utopia Permanent Resident Card.",
    "credentialSubject": {
      "type": [
        "PermanentResident",
        "Person"
      ],
      "givenName": "JANE",
      "familyName": "SMITH",
      "gender": "Female",
      "image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2P4v43hPwAHIgK1v4tX6wAAAABJRU5ErkJggg==",
      "residentSince": "2015-01-01",
      "commuterClassification": "C1",
      "birthCountry": "Arcadia",
      "birthDate": "1978-07-17",
      "permanentResidentCard": {
        "type": [
          "PermanentResidentCard"
        ],
        "identifier": "83627465",
        "lprCategory": "C09",
        "lprNumber": "999-999-999"
      }
    },
    "validFrom": "2024-12-16T00:00:00Z",
    "validUntil": "2025-12-16T23:59:59Z"
}

이 필수 정보는 아래와 같이 JSON 포인터 배열을 통해 지정됩니다.

예제 9: 필수 포인터
["/issuer"]

위의 JSON 포인터를 문서에 적용한 결과는 아래와 같습니다.

예제 10: JSON 포인터 및 값
[
  {
    "pointer": "/issuer",
    "value": {
      "id": "did:key:zDnaeTHxNEBZoKaEo6PdA83fq98ebiFvo3X273Ydu4YmV96rg",
      "image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2P4z/DiPwAG0ALnwgz64QAAAABJRU5ErkJggg=="
    }
  }
]

서명되지 않은 문서의 변환은 아래와 같이 문서를 정규화하는 것부터 시작합니다.

예제 11: 정규 문서
[
  "<did:key:zDnaeTHxNEBZoKaEo6PdA83fq98ebiFvo3X273Ydu4YmV96rg> <https://schema.org/image> <data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2P4z/DiPwAG0ALnwgz64QAAAABJRU5ErkJggg==> .\n",
  "_:c14n0 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/citizenship#PermanentResidentCard> .\n",
  "_:c14n0 <https://schema.org/identifier> \"83627465\" .\n",
  "_:c14n0 <https://w3id.org/citizenship#lprCategory> \"C09\" .\n",
  "_:c14n0 <https://w3id.org/citizenship#lprNumber> \"999-999-999\" .\n",
  "_:c14n1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://schema.org/Person> .\n",
  "_:c14n1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/citizenship#PermanentResident> .\n",
  "_:c14n1 <https://schema.org/birthDate> \"1978-07-17\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n",
  "_:c14n1 <https://schema.org/familyName> \"SMITH\" .\n",
  "_:c14n1 <https://schema.org/gender> \"Female\" .\n",
  "_:c14n1 <https://schema.org/givenName> \"JANE\" .\n",
  "_:c14n1 <https://schema.org/image> <data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2P4v43hPwAHIgK1v4tX6wAAAABJRU5ErkJggg==> .\n",
  "_:c14n1 <https://w3id.org/citizenship#birthCountry> \"Arcadia\" .\n",
  "_:c14n1 <https://w3id.org/citizenship#commuterClassification> \"C1\" .\n",
  "_:c14n1 <https://w3id.org/citizenship#permanentResidentCard> _:c14n0 .\n",
  "_:c14n1 <https://w3id.org/citizenship#residentSince> \"2015-01-01\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n",
  "_:c14n2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/citizenship#PermanentResidentCardCredential> .\n",
  "_:c14n2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://www.w3.org/2018/credentials#VerifiableCredential> .\n",
  "_:c14n2 <https://schema.org/description> \"Permanent Resident Card from Government of Utopia.\" .\n",
  "_:c14n2 <https://schema.org/name> \"Permanent Resident Card\" .\n",
  "_:c14n2 <https://www.w3.org/2018/credentials#credentialSubject> _:c14n1 .\n",
  "_:c14n2 <https://www.w3.org/2018/credentials#issuer> <did:key:zDnaeTHxNEBZoKaEo6PdA83fq98ebiFvo3X273Ydu4YmV96rg> .\n",
  "_:c14n2 <https://www.w3.org/2018/credentials#validFrom> \"2024-12-16T00:00:00Z\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n",
  "_:c14n2 <https://www.w3.org/2018/credentials#validUntil> \"2025-12-16T23:59:59Z\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n"
]

빈 노드 ID의 순서를 통한 잠재적인 정보 유출을 방지하기 위해, 이러한 ID를 PRF(즉, HMAC)를 통해 처리하여 아래에 표시된 정규화된 HMAC 문서를 생성합니다. 이는 "필수" 및 "선택적"(또는 "비필수") 공개의 대상이 되는 문장들의 순서 있는 목록을 나타냅니다. 즉, 이러한 문장을 공개 요구 사항에 따라 그룹화하더라도 이 목록과 동일한 순서가 유지됩니다.

예제 12: 정규 HMAC 문서
[
  "<did:key:zDnaeTHxNEBZoKaEo6PdA83fq98ebiFvo3X273Ydu4YmV96rg> <https://schema.org/image> <data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2P4z/DiPwAG0ALnwgz64QAAAABJRU5ErkJggg==> .\n",
  "_:b0 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://schema.org/Person> .\n",
  "_:b0 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/citizenship#PermanentResident> .\n",
  "_:b0 <https://schema.org/birthDate> \"1978-07-17\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n",
  "_:b0 <https://schema.org/familyName> \"SMITH\" .\n",
  "_:b0 <https://schema.org/gender> \"Female\" .\n",
  "_:b0 <https://schema.org/givenName> \"JANE\" .\n",
  "_:b0 <https://schema.org/image> <data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2P4v43hPwAHIgK1v4tX6wAAAABJRU5ErkJggg==> .\n",
  "_:b0 <https://w3id.org/citizenship#birthCountry> \"Arcadia\" .\n",
  "_:b0 <https://w3id.org/citizenship#commuterClassification> \"C1\" .\n",
  "_:b0 <https://w3id.org/citizenship#permanentResidentCard> _:b1 .\n",
  "_:b0 <https://w3id.org/citizenship#residentSince> \"2015-01-01\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n",
  "_:b1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/citizenship#PermanentResidentCard> .\n",
  "_:b1 <https://schema.org/identifier> \"83627465\" .\n",
  "_:b1 <https://w3id.org/citizenship#lprCategory> \"C09\" .\n",
  "_:b1 <https://w3id.org/citizenship#lprNumber> \"999-999-999\" .\n",
  "_:b2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/citizenship#PermanentResidentCardCredential> .\n",
  "_:b2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://www.w3.org/2018/credentials#VerifiableCredential> .\n",
  "_:b2 <https://schema.org/description> \"Permanent Resident Card from Government of Utopia.\" .\n",
  "_:b2 <https://schema.org/name> \"Permanent Resident Card\" .\n",
  "_:b2 <https://www.w3.org/2018/credentials#credentialSubject> _:b0 .\n",
  "_:b2 <https://www.w3.org/2018/credentials#issuer> <did:key:zDnaeTHxNEBZoKaEo6PdA83fq98ebiFvo3X273Ydu4YmV96rg> .\n",
  "_:b2 <https://www.w3.org/2018/credentials#validFrom> \"2024-12-16T00:00:00Z\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n",
  "_:b2 <https://www.w3.org/2018/credentials#validUntil> \"2025-12-16T23:59:59Z\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n"
]

위 정규 문서의 목록은 필수 및 비필수 문장으로 그룹화됩니다. 선택적 공개 변환 과정의 최종 출력은 아래와 같습니다. 이제 문장은 필수 또는 비필수 공개로 그룹화되며, 이전 목록에서 각 문장의 인덱스가 기억됩니다.

예제 13: 기본 변환 추가
{
  "mandatoryPointers": [
    "/issuer"
  ],
  "mandatory": {
    "dataType": "Map",
    "value": [
      [
        0,
        "<did:key:zDnaeTHxNEBZoKaEo6PdA83fq98ebiFvo3X273Ydu4YmV96rg> <https://schema.org/image> <data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2P4z/DiPwAG0ALnwgz64QAAAABJRU5ErkJggg==> .\n"
      ],
      [
        16,
        "_:b2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/citizenship#PermanentResidentCardCredential> .\n"
      ],
      [
        17,
        "_:b2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://www.w3.org/2018/credentials#VerifiableCredential> .\n"
      ],
      [
        21,
        "_:b2 <https://www.w3.org/2018/credentials#issuer> <did:key:zDnaeTHxNEBZoKaEo6PdA83fq98ebiFvo3X273Ydu4YmV96rg> .\n"
      ]
    ]
  },
  "nonMandatory": {
    "dataType": "Map",
    "value": [
      [
        1,
        "_:b0 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://schema.org/Person> .\n"
      ],
      [
        2,
        "_:b0 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/citizenship#PermanentResident> .\n"
      ],
      [
        3,
        "_:b0 <https://schema.org/birthDate> \"1978-07-17\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n"
      ],
      [
        4,
        "_:b0 <https://schema.org/familyName> \"SMITH\" .\n"
      ],
      [
        5,
        "_:b0 <https://schema.org/gender> \"Female\" .\n"
      ],
      [
        6,
        "_:b0 <https://schema.org/givenName> \"JANE\" .\n"
      ],
      [
        7,
        "_:b0 <https://schema.org/image> <data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2P4v43hPwAHIgK1v4tX6wAAAABJRU5ErkJggg==> .\n"
      ],
      [
        8,
        "_:b0 <https://w3id.org/citizenship#birthCountry> \"Arcadia\" .\n"
      ],
      [
        9,
        "_:b0 <https://w3id.org/citizenship#commuterClassification> \"C1\" .\n"
      ],
      [
        10,
        "_:b0 <https://w3id.org/citizenship#permanentResidentCard> _:b1 .\n"
      ],
      [
        11,
        "_:b0 <https://w3id.org/citizenship#residentSince> \"2015-01-01\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n"
      ],
      [
        12,
        "_:b1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/citizenship#PermanentResidentCard> .\n"
      ],
      [
        13,
        "_:b1 <https://schema.org/identifier> \"83627465\" .\n"
      ],
      [
        14,
        "_:b1 <https://w3id.org/citizenship#lprCategory> \"C09\" .\n"
      ],
      [
        15,
        "_:b1 <https://w3id.org/citizenship#lprNumber> \"999-999-999\" .\n"
      ],
      [
        18,
        "_:b2 <https://schema.org/description> \"Permanent Resident Card from Government of Utopia.\" .\n"
      ],
      [
        19,
        "_:b2 <https://schema.org/name> \"Permanent Resident Card\" .\n"
      ],
      [
        20,
        "_:b2 <https://www.w3.org/2018/credentials#credentialSubject> _:b0 .\n"
      ],
      [
        22,
        "_:b2 <https://www.w3.org/2018/credentials#validFrom> \"2024-12-16T00:00:00Z\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n"
      ],
      [
        23,
        "_:b2 <https://www.w3.org/2018/credentials#validUntil> \"2025-12-16T23:59:59Z\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n"
      ]
    ]
  },
  "hmacKeyString": "00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF"
}

다음 단계는 기본 증명 구성을 생성하고 이를 정규화하는 것입니다. 이는 다음 두 예제에 표시되어 있습니다.

예제 14: 기본 증명 구성
{
  "type": "DataIntegrityProof",
  "cryptosuite": "bbs-2023",
  "created": "2023-08-15T23:36:38Z",
  "verificationMethod": "did:key:zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ#zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ",
  "proofPurpose": "assertionMethod",
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    "https://w3id.org/citizenship/v4rc1"
  ]
}
예제 15: 정규 기본 증명 구성
_:c14n0 <http://purl.org/dc/terms/created> "2023-08-15T23:36:38Z"^^<http://www.w3.org/2001/XMLSchema#dateTime> .
_:c14n0 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/security#DataIntegrityProof> .
_:c14n0 <https://w3id.org/security#cryptosuite> "bbs-2023"^^<https://w3id.org/security#cryptosuiteString> .
_:c14n0 <https://w3id.org/security#proofPurpose> <https://w3id.org/security#assertionMethod> .
_:c14n0 <https://w3id.org/security#verificationMethod> <did:key:zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ#zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ> .

해싱 단계에서는 정규화된 증명 옵션의 SHA-256 해시를 계산하여 proofHash를 생성하고, 모든 필수 N-Quads의 JOIN에 대한 SHA-256 해시를 계산하여 mandatoryHash를 생성합니다. 이는 아래에 16진수 형식으로 표시되어 있습니다.

예제 16: 기본 해시 추가
{
  "proofHash": "3a5bbf25d34d90b18c35cd2357be6a6f42301e94fc9e52f77e93b773c5614bdf",
  "mandatoryHash": "8e7cc22c318dd2094e02d0bf06c5d73a5dba717611a40f6d1bedc5ea7c300fd6"
}

아래에는 계산된 bbsSignature가 16진수로 표시되어 있으며, mandatoryPointers도 함께 표시되어 있습니다. 이들은 hmacKey와 함께 최종 직렬화 단계에 입력됩니다.

예제 17: 기본 서명 추가
{
  "bbsSignature": "86168dd2b5d0c7c6a56a30f4212ed116a53def05d0d6708207d483c7ff2053aefa22d24ba7659d60852694f8d85be0fa2adc3974c7dc4cc68b3db17b2423975047104162c24502b41591879ac24f1bb1",
  "mandatoryPointers": [
    "/issuer"
  ]
}

마지막으로 위의 값들을 3.2.1 serializeBaseProofValue 절의 알고리즘에 적용하여 서명된 기본 문서에서 사용되는 proofValue를 생성하며, 그 결과는 아래와 같습니다.

예제 18: 서명된 기본 문서
{
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    "https://w3id.org/citizenship/v4rc1"
  ],
  "type": [
    "VerifiableCredential",
    "PermanentResidentCardCredential"
  ],
  "issuer": {
    "id": "did:key:zDnaeTHxNEBZoKaEo6PdA83fq98ebiFvo3X273Ydu4YmV96rg",
    "image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2P4z/DiPwAG0ALnwgz64QAAAABJRU5ErkJggg=="
  },
  "name": "Permanent Resident Card",
  "description": "Permanent Resident Card from Government of Utopia.",
  "credentialSubject": {
    "type": [
      "PermanentResident",
      "Person"
    ],
    "givenName": "JANE",
    "familyName": "SMITH",
    "gender": "Female",
    "image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2P4v43hPwAHIgK1v4tX6wAAAABJRU5ErkJggg==",
    "residentSince": "2015-01-01",
    "commuterClassification": "C1",
    "birthCountry": "Arcadia",
    "birthDate": "1978-07-17",
    "permanentResidentCard": {
      "type": [
        "PermanentResidentCard"
      ],
      "identifier": "83627465",
      "lprCategory": "C09",
      "lprNumber": "999-999-999"
    }
  },
  "validFrom": "2024-12-16T00:00:00Z",
  "validUntil": "2025-12-16T23:59:59Z",
  "proof": {
    "type": "DataIntegrityProof",
    "cryptosuite": "bbs-2023",
    "created": "2023-08-15T23:36:38Z",
    "verificationMethod": "did:key:zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ#zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ",
    "proofPurpose": "assertionMethod",
    "proofValue": "u2V0ChVhQhhaN0rXQx8alajD0IS7RFqU97wXQ1nCCB9SDx_8gU676ItJLp2WdYIUmlPjYW-D6Ktw5dMfcTMaLPbF7JCOXUEcQQWLCRQK0FZGHmsJPG7FYQDpbvyXTTZCxjDXNI1e-am9CMB6U_J5S936Tt3PFYUvfjnzCLDGN0glOAtC_BsXXOl26cXYRpA9tG-3F6nwwD9ZYYKTvGvo9pXVJbxIrm3i4wkdhUxqKCTIGrnxFuAdZwWi6T3omD5wzZ7bAGbRneEEQSxBmXtvnC6Pr59nPv_v3HrAW9wq_uxYzF_NyaX3GPv0h_FV2T2OSao8C6uoyWiqIj1ggABEiM0RVZneImaq7zN3u_wARIjNEVWZ3iJmqu8zd7v-BZy9pc3N1ZXI"
  }
}

A.1.2 파생 증명

BBS 증명을 생성할 때 난수를 사용하며, 선택적 presentationHeader를 추가 입력으로 사용할 수 있습니다. 결정론적인 테스트 벡터 집합을 제공하기 위해 [CFRG-BBS-SIGNATURE]의 Mocked Random Scalars 절차를 사용했습니다. 파생 증명 테스트 벡터 생성에 사용한 seedpresentationHeader 값은 아래에 16진수로 표시되어 있습니다.

예제 19: 시드 및 프레젠테이션 헤더 값
{
  "presentationHeaderHex": "113377aa",
  "pseudoRandSeedHex": "332e313431353932363533353839373933323338343632363433333833323739"
}

파생 증명을 생성하려면 보유자는 기본 증명을 포함하는 서명된 문서에서 시작합니다. 이 테스트 벡터에 사용할 기본 문서는 위 A.1.1 기본 증명 절의 마지막 예제입니다. 첫 번째 단계는 3.2.2 parseBaseProofValue 절의 알고리즘을 실행하여 아래와 같이 bbsSignature, hmacKey, mandatoryPointers를 복구하는 것입니다.

예제 20: 복구된 기본 서명 데이터
{
  "bbsSignature": "86168dd2b5d0c7c6a56a30f4212ed116a53def05d0d6708207d483c7ff2053aefa22d24ba7659d60852694f8d85be0fa2adc3974c7dc4cc68b3db17b2423975047104162c24502b41591879ac24f1bb1",
  "hmacKey": "00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff",
  "mandatoryPointers": [
    "/issuer"
  ]
}

다음으로 보유자는 선택적 공개를 위한 JSON 포인터를 지정하여 검증자에게 공개하려는 비필수 문장이 있다면 어떤 것인지 나타내야 합니다. 이는 아래와 같습니다.

예제 21: 선택적 공개 포인터
["/validFrom", "/validUntil", "/credentialSubject/birthCountry"]

revealDocument(즉, 최종적으로 서명되어 검증자에게 전송될 서명되지 않은 문서)를 생성하기 위해 선택적 포인터를 필수 포인터에 이어 붙이고, 이 결합된 포인터와 증명을 제거한 문서를 [DI-ECDSA]의 selectJsonLd 알고리즘에 입력합니다. 그러면 아래와 같은 결과를 얻습니다.

예제 22: 서명되지 않은 공개 문서
{
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    "https://w3id.org/citizenship/v4rc1"
  ],
  "type": [
    "VerifiableCredential",
    "PermanentResidentCardCredential"
  ],
  "issuer": {
    "id": "did:key:zDnaeTHxNEBZoKaEo6PdA83fq98ebiFvo3X273Ydu4YmV96rg",
    "image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2P4z/DiPwAG0ALnwgz64QAAAABJRU5ErkJggg=="
  },
  "validFrom": "2024-12-16T00:00:00Z",
  "validUntil": "2025-12-16T23:59:59Z",
  "credentialSubject": {
    "type": [
      "PermanentResident",
      "Person"
    ],
    "birthCountry": "Arcadia"
  }
}

이제 공개 문서가 어떤 형태인지 알았으므로, 어떤 문장이 필수인지와 선택된 비필수 문장의 인덱스에 관한 적절히 갱신된 정보를 검증자에게 제공해야 합니다. § 4.4.3 CreateDisclosureData를 실행하면 원본 문서를 기준으로 여러 문장 그룹에 관한 풍부한 정보를 얻을 수 있습니다. 아래에서는 이러한 그룹에 대한 인덱스의 일부를 보여 줍니다.

예제 23: 파생 그룹 인덱스
{"combinedIndexes":[0,1,2,8,16,17,20,21,22,23],"mandatoryIndexes":[0,16,17,21],"nonMandatoryIndexes":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,18,19,20,22,23],"selectiveIndexes":[1,2,8,16,17,20,22,23]}

검증자는 필수 문장을 모아 해싱할 수 있어야 합니다. 이를 위해 필수 문장의 인덱스를 공개 문서에서의 위치에 맞게 조정한 목록 (즉, combinedIndexes를 기준으로 한 위치)을 제공하며, selectiveIndexesnonMandatoryIndexes 내 위치를 기준으로 조정됩니다. 이러한 "조정된" 인덱스는 아래와 같습니다.

예제 24: 조정된 필수 및 선택적 인덱스
{"adjMandatoryIndexes":[0,4,5,7],"adjSelectiveIndexes":[0,1,7,17,18,19]}

마지막으로 중요한 공개 데이터는 labelMap이며, 이는 정규화된 빈 노드 ID를 HMAC 기반으로 섞인 ID에 매핑한 것으로, § 4.4.3 CreateDisclosureData에 따라 계산됩니다. 이는 아래에 공개 문서를 제외한 나머지 공개 데이터와 함께 표시됩니다.

예제 25: 공개 데이터
{"bbsProof":"96ac5ff7b89bf2d8b0f3cc51c547f1a22b01e24e246579d212362cdf6bf0fabe18be0c9d1f84c904bb4c6c613fd0ecabb7ad92e615341da97a45a918721626cc859c455b473a36e39572561d5fc483c637424717a43dcffb3b130d8fe11f88a8802f3b231efe2444f8b47feded0b621e3d5cd22cb3ec23ebc4f6dca745b5c1ce2f42a710b92510a71225a7d39e00e0c26da2fae242cdf154e93de42017270b99023fe95b42c42a461a2eab19e04aa44839af39aa71f830162cb424a5aa0acc046dc7e7b8bdfc73cf3641c76aeeb7fbb56cd936776050dbd632bf7fc80d33c621dc6b837184ade619630f72bd25d8aea626ba994d15a65def1b0dc8af09c54a0cf5e5b54d1b1b28047aa2dbf63805fec9533bab46d12349ca47dfd83ff30454cedacd23da4eb9a3ebe198c80ac1992e2a203ffcf46afaa3482a63b7b00033df1a2da361d600a1cfd5139be010ca302e082af7ee34a5ff3d24cc7062f57fa36d47846edd5219e59bd438576bff709bfd7920d6bad8367b0fe8c749318ef8726beda9c1d9095bed738e4fd1c38333a27f4f2071a21a863671b43fe521f737444be865e887cbf33caa39226fb8013003721e37c6d949867befba1c8b7bf641bd647851ad92aed3da91af52f17d058a9f74eb30744304c05813840be6a528f54cd5a24b73ae2f42dec1bfc2e1354fb061a96c0df3ab96ddc9ada96cb882571cccb89774fcf0326e1c8b2b87cc4cf4eafbd75632518919cbe58a9f86ade12b0f6989c0886e358d801b99b1dd32c7e6e56a653c0e264a84b51d2d23679c75e282451af3bcaa6f19ec7bc3aa603fec87db5a57d42961e2907d899a8fd5d1ce17dde8a75cd1192494cd93b112da7774c2bb2f679f5b4b404dabe485d78a017b2be81e5ff8bacf90d5f24b2e83ab4169f8f55ca6f703141f91565abbec7445e6cf4663f5e34b9188283d57cedf36c586b18a130b83652436bf6862673ddeebd9aefdc2fbfc97dde80e36483491c4357ccd2fc131fb","labelMap":{"dataType":"Map","value":[["c14n0","b0"],["c14n1","b2"]]},"mandatoryIndexes":[0,4,5,7],"adjSelectiveIndexes":[0,1,7,17,18,19],"presentationHeader":{"0":17,"1":51,"2":119,"3":170}}

마지막으로 위의 공개 데이터를 다음 절의 알고리즘과 함께 사용하면 3.2.3 serializeDerivedProofValue, 아래에 표시된 서명된 파생(공개) 문서를 얻습니다.

예제 26: 서명된 파생 문서
{
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    "https://w3id.org/citizenship/v4rc1"
  ],
  "type": [
    "VerifiableCredential",
    "PermanentResidentCardCredential"
  ],
  "issuer": {
    "id": "did:key:zDnaeTHxNEBZoKaEo6PdA83fq98ebiFvo3X273Ydu4YmV96rg",
    "image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2P4z/DiPwAG0ALnwgz64QAAAABJRU5ErkJggg=="
  },
  "validFrom": "2024-12-16T00:00:00Z",
  "validUntil": "2025-12-16T23:59:59Z",
  "credentialSubject": {
    "type": [
      "PermanentResident",
      "Person"
    ],
    "birthCountry": "Arcadia"
  },
  "proof": {
    "type": "DataIntegrityProof",
    "cryptosuite": "bbs-2023",
    "created": "2023-08-15T23:36:38Z",
    "verificationMethod": "did:key:zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ#zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ",
    "proofPurpose": "assertionMethod",
    "proofValue": "u2V0DhVkC0JasX_e4m_LYsPPMUcVH8aIrAeJOJGV50hI2LN9r8Pq-GL4MnR-EyQS7TGxhP9Dsq7etkuYVNB2pekWpGHIWJsyFnEVbRzo245VyVh1fxIPGN0JHF6Q9z_s7Ew2P4R-IqIAvOyMe_iRE-LR_7e0LYh49XNIss-wj68T23KdFtcHOL0KnELklEKcSJafTngDgwm2i-uJCzfFU6T3kIBcnC5kCP-lbQsQqRhouqxngSqRIOa85qnH4MBYstCSlqgrMBG3H57i9_HPPNkHHau63-7Vs2TZ3YFDb1jK_f8gNM8Yh3GuDcYSt5hljD3K9Jdiupia6mU0Vpl3vGw3IrwnFSgz15bVNGxsoBHqi2_Y4Bf7JUzurRtEjScpH39g_8wRUztrNI9pOuaPr4ZjICsGZLiogP_z0avqjSCpjt7AAM98aLaNh1gChz9UTm-AQyjAuCCr37jSl_z0kzHBi9X-jbUeEbt1SGeWb1DhXa_9wm_15INa62DZ7D-jHSTGO-HJr7anB2Qlb7XOOT9HDgzOif08gcaIahjZxtD_lIfc3REvoZeiHy_M8qjkib7gBMANyHjfG2UmGe--6HIt79kG9ZHhRrZKu09qRr1LxfQWKn3TrMHRDBMBYE4QL5qUo9UzVoktzri9C3sG_wuE1T7BhqWwN86uW3cmtqWy4glcczLiXdPzwMm4ciyuHzEz06vvXVjJRiRnL5Yqfhq3hKw9picCIbjWNgBuZsd0yx-blamU8DiZKhLUdLSNnnHXigkUa87yqbxnse8OqYD_sh9taV9QpYeKQfYmaj9XRzhfd6Kdc0RkklM2TsRLad3TCuy9nn1tLQE2r5IXXigF7K-geX_i6z5DV8ksug6tBafj1XKb3AxQfkVZau-x0RebPRmP140uRiCg9V87fNsWGsYoTC4NlJDa_aGJnPd7r2a79wvv8l93oDjZINJHENXzNL8Ex-6IAAAEChAAEBQeGAAEHERITRBEzd6o"
  }
}

A.2 기준 확장 예제

필수 공개, 선택적 공개 및 이들 간의 중첩을 포함한 선택적 공개 기능을 시연하려면 이전 테스트 벡터보다 더 많은 내용을 포함하는 입력 자격 증명 문서가 필요합니다. 지나치게 긴 테스트 벡터를 피하기 위해 시작 문서 테스트 벡터는 완전히 가상의 윈드서핑(요트) 경기 시나리오를 기반으로 합니다. 또한 테스트 벡터를 발급자가 생성하는 것(기본 증명)과 보유자가 생성하는 것(파생 증명)에 따라 두 그룹으로 나눕니다.

A.2.1 기본 증명

문서에 선택적 공개 기본 증명을 추가하려면 발급자에게 다음 암호학적 키 자료가 필요합니다:

  1. 발급자의 비공개/공개 키 쌍, 즉 증명의 일부가 될 검증 방법에 해당하는 키 쌍입니다.
  2. HMAC 키. 이는 빈 노드 ID 순서를 무작위화하여 빈 노드 ID 순서를 통한 잠재적인 정보 유출을 방지하는 데 사용됩니다. 이는 한 번만 사용되며 발급자와 보유자 간에 공유됩니다. 이 경우 HMAC은 의사 난수 함수(PRF)로 기능합니다.

기본 증명 추가 테스트를 위한 테스트 벡터 생성에 사용된 키 자료는 아래와 같습니다. BBS 키 쌍과 HMAC 키에는 16진수 표현을 사용합니다.

예제 27: 서명용 비공개 및 공개 키
{
  "publicKeyHex": "a4ef1afa3da575496f122b9b78b8c24761531a8a093206ae7c45b80759c168ba4f7a260f9c3367b6c019b4677841104b10665edbe70ba3ebe7d9cfbffbf71eb016f70abfbb163317f372697dc63efd21fc55764f63926a8f02eaea325a2a888f",
  "privateKeyHex": "66d36e118832af4c5e28b2dfe1b9577857e57b042a33e06bdea37b811ed09ee0",
  "hmacKeyString": "00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF"
}

이 시나리오에서는 한 선수가 마우이에서 여러 날에 걸쳐 열리는 일련의 윈드서핑 경기에 참가하기 위해 경기 주최자에게 등록합니다. 주최자는 선수가 신고한 내용이 정확한지 인증하기 위해 장비를 검사합니다. 선수의 서명되지 않은 장비 목록은 아래와 같습니다.

예제 28: 증명이 없는 자격 증명
{
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    {
      "@vocab": "https://windsurf.grotto-networking.com/selective#"
    }
  ],
  "type": [
    "VerifiableCredential"
  ],
  "issuer": "https://vc.example/windsurf/racecommittee",
  "credentialSubject": {
    "sailNumber": "Earth101",
    "sails": [
      {
        "size": 5.5,
        "sailName": "Kihei",
        "year": 2023
      },
      {
        "size": 6.1,
        "sailName": "Lahaina",
        "year": 2023
      },
      {
        "size": 7.0,
        "sailName": "Lahaina",
        "year": 2020
      },
      {
        "size": 7.8,
        "sailName": "Lahaina",
        "year": 2023
      }
    ],
    "boards": [
      {
        "boardName": "CompFoil170",
        "brand": "Wailea",
        "year": 2022
      },
      {
        "boardName": "Kanaha Custom",
        "brand": "Wailea",
        "year": 2019
      }
    ]
  }
}

다른 선수들에게 경쟁자들이 어떤 종류의 장비를 사용할 수 있는지 알려주는 것 외에도, 각 선수는 가장 최근 윈드서핑 보드의 연도와 돛 두 개에 대한 전체 세부 정보를 반드시 공개해야 합니다. 모든 선수는 모든 장비에 인쇄된 돛 번호로 식별된다는 점에 유의하십시오. 이 필수 정보는 아래와 같이 JSON 포인터 배열을 통해 지정됩니다.

예제 29: 필수 포인터
["/issuer", "/credentialSubject/sailNumber", "/credentialSubject/sails/1", "/credentialSubject/boards/0/year", "/credentialSubject/sails/2"]

위의 JSON 포인터를 선수의 장비 문서에 적용한 결과는 아래와 같습니다.

예제 30: JSON 포인터 및 값
[
  {
    "pointer": "/sailNumber",
    "value": "Earth101"
  },
  {
    "pointer": "/sails/1",
    "value": {
      "size": 6.1,
      "sailName": "Lahaina",
      "year": 2023
    }
  },
  {
    "pointer": "/boards/0/year",
    "value": 2022
  },
  {
    "pointer": "/sails/2",
    "value": {
      "size": 7,
      "sailName": "Lahaina",
      "year": 2020
    }
  }
]

서명되지 않은 문서의 변환은 아래와 같이 문서를 정규화하는 것부터 시작합니다.

예제 31: 정규 문서
[
  "_:c14n0 <https://windsurf.grotto-networking.com/selective#boardName> \"CompFoil170\" .\n",
  "_:c14n0 <https://windsurf.grotto-networking.com/selective#brand> \"Wailea\" .\n",
  "_:c14n0 <https://windsurf.grotto-networking.com/selective#year> \"2022\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n",
  "_:c14n1 <https://windsurf.grotto-networking.com/selective#sailName> \"Lahaina\" .\n",
  "_:c14n1 <https://windsurf.grotto-networking.com/selective#size> \"7.8E0\"^^<http://www.w3.org/2001/XMLSchema#double> .\n",
  "_:c14n1 <https://windsurf.grotto-networking.com/selective#year> \"2023\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n",
  "_:c14n2 <https://windsurf.grotto-networking.com/selective#boardName> \"Kanaha Custom\" .\n",
  "_:c14n2 <https://windsurf.grotto-networking.com/selective#brand> \"Wailea\" .\n",
  "_:c14n2 <https://windsurf.grotto-networking.com/selective#year> \"2019\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n",
  "_:c14n3 <https://windsurf.grotto-networking.com/selective#sailName> \"Lahaina\" .\n",
  "_:c14n3 <https://windsurf.grotto-networking.com/selective#size> \"7\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n",
  "_:c14n3 <https://windsurf.grotto-networking.com/selective#year> \"2020\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n",
  "_:c14n4 <https://windsurf.grotto-networking.com/selective#sailName> \"Kihei\" .\n",
  "_:c14n4 <https://windsurf.grotto-networking.com/selective#size> \"5.5E0\"^^<http://www.w3.org/2001/XMLSchema#double> .\n",
  "_:c14n4 <https://windsurf.grotto-networking.com/selective#year> \"2023\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n",
  "_:c14n5 <https://windsurf.grotto-networking.com/selective#boards> _:c14n0 .\n",
  "_:c14n5 <https://windsurf.grotto-networking.com/selective#boards> _:c14n2 .\n",
  "_:c14n5 <https://windsurf.grotto-networking.com/selective#sailNumber> \"Earth101\" .\n",
  "_:c14n5 <https://windsurf.grotto-networking.com/selective#sails> _:c14n1 .\n",
  "_:c14n5 <https://windsurf.grotto-networking.com/selective#sails> _:c14n3 .\n",
  "_:c14n5 <https://windsurf.grotto-networking.com/selective#sails> _:c14n4 .\n",
  "_:c14n5 <https://windsurf.grotto-networking.com/selective#sails> _:c14n6 .\n",
  "_:c14n6 <https://windsurf.grotto-networking.com/selective#sailName> \"Lahaina\" .\n",
  "_:c14n6 <https://windsurf.grotto-networking.com/selective#size> \"6.1E0\"^^<http://www.w3.org/2001/XMLSchema#double> .\n",
  "_:c14n6 <https://windsurf.grotto-networking.com/selective#year> \"2023\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n",
  "_:c14n7 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://www.w3.org/2018/credentials#VerifiableCredential> .\n",
  "_:c14n7 <https://www.w3.org/2018/credentials#credentialSubject> _:c14n5 .\n",
  "_:c14n7 <https://www.w3.org/2018/credentials#issuer> <https://vc.example/windsurf/racecommittee> .\n"
]

빈 노드 ID의 순서에서 발생할 수 있는 정보 유출을 방지하기 위해 이를 PRF(즉, HMAC)를 통해 처리하여 아래에 표시된 정규화된 HMAC 문서를 생성합니다. 이는 필수 및 선택적 공개의 대상이 되는 문장들의 순서 있는 목록을 나타내며, 즉 이 목록을 기준으로 문장이 그룹화됩니다.

예제 32: 정규 HMAC 문서
[
  "_:b0 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://www.w3.org/2018/credentials#VerifiableCredential> .\n",
  "_:b0 <https://www.w3.org/2018/credentials#credentialSubject> _:b3 .\n",
  "_:b0 <https://www.w3.org/2018/credentials#issuer> <https://vc.example/windsurf/racecommittee> .\n",
  "_:b1 <https://windsurf.grotto-networking.com/selective#sailName> \"Lahaina\" .\n",
  "_:b1 <https://windsurf.grotto-networking.com/selective#size> \"7.8E0\"^^<http://www.w3.org/2001/XMLSchema#double> .\n",
  "_:b1 <https://windsurf.grotto-networking.com/selective#year> \"2023\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n",
  "_:b2 <https://windsurf.grotto-networking.com/selective#boardName> \"CompFoil170\" .\n",
  "_:b2 <https://windsurf.grotto-networking.com/selective#brand> \"Wailea\" .\n",
  "_:b2 <https://windsurf.grotto-networking.com/selective#year> \"2022\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n",
  "_:b3 <https://windsurf.grotto-networking.com/selective#boards> _:b2 .\n",
  "_:b3 <https://windsurf.grotto-networking.com/selective#boards> _:b4 .\n",
  "_:b3 <https://windsurf.grotto-networking.com/selective#sailNumber> \"Earth101\" .\n",
  "_:b3 <https://windsurf.grotto-networking.com/selective#sails> _:b1 .\n",
  "_:b3 <https://windsurf.grotto-networking.com/selective#sails> _:b5 .\n",
  "_:b3 <https://windsurf.grotto-networking.com/selective#sails> _:b6 .\n",
  "_:b3 <https://windsurf.grotto-networking.com/selective#sails> _:b7 .\n",
  "_:b4 <https://windsurf.grotto-networking.com/selective#boardName> \"Kanaha Custom\" .\n",
  "_:b4 <https://windsurf.grotto-networking.com/selective#brand> \"Wailea\" .\n",
  "_:b4 <https://windsurf.grotto-networking.com/selective#year> \"2019\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n",
  "_:b5 <https://windsurf.grotto-networking.com/selective#sailName> \"Kihei\" .\n",
  "_:b5 <https://windsurf.grotto-networking.com/selective#size> \"5.5E0\"^^<http://www.w3.org/2001/XMLSchema#double> .\n",
  "_:b5 <https://windsurf.grotto-networking.com/selective#year> \"2023\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n",
  "_:b6 <https://windsurf.grotto-networking.com/selective#sailName> \"Lahaina\" .\n",
  "_:b6 <https://windsurf.grotto-networking.com/selective#size> \"6.1E0\"^^<http://www.w3.org/2001/XMLSchema#double> .\n",
  "_:b6 <https://windsurf.grotto-networking.com/selective#year> \"2023\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n",
  "_:b7 <https://windsurf.grotto-networking.com/selective#sailName> \"Lahaina\" .\n",
  "_:b7 <https://windsurf.grotto-networking.com/selective#size> \"7\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n",
  "_:b7 <https://windsurf.grotto-networking.com/selective#year> \"2020\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n"
]

위 정규 문서는 필수 및 비필수 문장으로 그룹화됩니다. 선택적 공개 변환 과정의 최종 출력은 아래와 같습니다. 이제 각 문장은 필수 또는 비필수로 그룹화되고, 이전 문장 목록에서의 인덱스가 기억됩니다.

예제 33: 기본 변환 추가
{
  "mandatoryPointers": [
    "/issuer",
    "/credentialSubject/sailNumber",
    "/credentialSubject/sails/1",
    "/credentialSubject/boards/0/year",
    "/credentialSubject/sails/2"
  ],
  "mandatory": {
    "dataType": "Map",
    "value": [
      [
        0,
        "_:b0 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://www.w3.org/2018/credentials#VerifiableCredential> .\n"
      ],
      [
        1,
        "_:b0 <https://www.w3.org/2018/credentials#credentialSubject> _:b3 .\n"
      ],
      [
        2,
        "_:b0 <https://www.w3.org/2018/credentials#issuer> <https://vc.example/windsurf/racecommittee> .\n"
      ],
      [
        8,
        "_:b2 <https://windsurf.grotto-networking.com/selective#year> \"2022\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n"
      ],
      [
        9,
        "_:b3 <https://windsurf.grotto-networking.com/selective#boards> _:b2 .\n"
      ],
      [
        11,
        "_:b3 <https://windsurf.grotto-networking.com/selective#sailNumber> \"Earth101\" .\n"
      ],
      [
        14,
        "_:b3 <https://windsurf.grotto-networking.com/selective#sails> _:b6 .\n"
      ],
      [
        15,
        "_:b3 <https://windsurf.grotto-networking.com/selective#sails> _:b7 .\n"
      ],
      [
        22,
        "_:b6 <https://windsurf.grotto-networking.com/selective#sailName> \"Lahaina\" .\n"
      ],
      [
        23,
        "_:b6 <https://windsurf.grotto-networking.com/selective#size> \"6.1E0\"^^<http://www.w3.org/2001/XMLSchema#double> .\n"
      ],
      [
        24,
        "_:b6 <https://windsurf.grotto-networking.com/selective#year> \"2023\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n"
      ],
      [
        25,
        "_:b7 <https://windsurf.grotto-networking.com/selective#sailName> \"Lahaina\" .\n"
      ],
      [
        26,
        "_:b7 <https://windsurf.grotto-networking.com/selective#size> \"7\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n"
      ],
      [
        27,
        "_:b7 <https://windsurf.grotto-networking.com/selective#year> \"2020\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n"
      ]
    ]
  },
  "nonMandatory": {
    "dataType": "Map",
    "value": [
      [
        3,
        "_:b1 <https://windsurf.grotto-networking.com/selective#sailName> \"Lahaina\" .\n"
      ],
      [
        4,
        "_:b1 <https://windsurf.grotto-networking.com/selective#size> \"7.8E0\"^^<http://www.w3.org/2001/XMLSchema#double> .\n"
      ],
      [
        5,
        "_:b1 <https://windsurf.grotto-networking.com/selective#year> \"2023\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n"
      ],
      [
        6,
        "_:b2 <https://windsurf.grotto-networking.com/selective#boardName> \"CompFoil170\" .\n"
      ],
      [
        7,
        "_:b2 <https://windsurf.grotto-networking.com/selective#brand> \"Wailea\" .\n"
      ],
      [
        10,
        "_:b3 <https://windsurf.grotto-networking.com/selective#boards> _:b4 .\n"
      ],
      [
        12,
        "_:b3 <https://windsurf.grotto-networking.com/selective#sails> _:b1 .\n"
      ],
      [
        13,
        "_:b3 <https://windsurf.grotto-networking.com/selective#sails> _:b5 .\n"
      ],
      [
        16,
        "_:b4 <https://windsurf.grotto-networking.com/selective#boardName> \"Kanaha Custom\" .\n"
      ],
      [
        17,
        "_:b4 <https://windsurf.grotto-networking.com/selective#brand> \"Wailea\" .\n"
      ],
      [
        18,
        "_:b4 <https://windsurf.grotto-networking.com/selective#year> \"2019\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n"
      ],
      [
        19,
        "_:b5 <https://windsurf.grotto-networking.com/selective#sailName> \"Kihei\" .\n"
      ],
      [
        20,
        "_:b5 <https://windsurf.grotto-networking.com/selective#size> \"5.5E0\"^^<http://www.w3.org/2001/XMLSchema#double> .\n"
      ],
      [
        21,
        "_:b5 <https://windsurf.grotto-networking.com/selective#year> \"2023\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n"
      ]
    ]
  },
  "hmacKeyString": "00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF"
}

다음 단계는 기본 증명 구성을 생성하고 이를 정규화하는 것입니다. 이는 다음 두 예제에 표시되어 있습니다.

예제 34: 기본 증명 구성
{
  "type": "DataIntegrityProof",
  "cryptosuite": "bbs-2023",
  "created": "2023-08-15T23:36:38Z",
  "verificationMethod": "did:key:zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ#zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ",
  "proofPurpose": "assertionMethod",
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    {
      "@vocab": "https://windsurf.grotto-networking.com/selective#"
    }
  ]
}
예제 35: 정규 기본 증명 구성
_:c14n0 <http://purl.org/dc/terms/created> "2023-08-15T23:36:38Z"^^<http://www.w3.org/2001/XMLSchema#dateTime> .
_:c14n0 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/security#DataIntegrityProof> .
_:c14n0 <https://w3id.org/security#cryptosuite> "bbs-2023"^^<https://w3id.org/security#cryptosuiteString> .
_:c14n0 <https://w3id.org/security#proofPurpose> <https://w3id.org/security#assertionMethod> .
_:c14n0 <https://w3id.org/security#verificationMethod> <did:key:zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ#zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ> .

해싱 단계에서는 정규화된 증명 옵션의 SHA-256 해시를 계산하여 proofHash를 생성하고, 모든 필수 N-Quads를 결합한 값의 SHA-256 해시를 계산하여 mandatoryHash를 생성합니다. 이는 아래에 16진수 형식으로 표시되어 있습니다.

예제 36: 기본 해시 추가
{
  "proofHash": "3a5bbf25d34d90b18c35cd2357be6a6f42301e94fc9e52f77e93b773c5614bdf",
  "mandatoryHash": "555de05f898817e31301bac187d0c3ff2b03e2cbdb4adb4d568c17de961f9a18"
}

아래에는 계산된 bbsSignature가 16진수로 표시되어 있으며, mandatoryPointers도 함께 표시되어 있습니다. 이들은 hmacKey와 함께 최종 직렬화 단계에 입력됩니다.

예제 37: 기본 서명 추가
{
  "bbsSignature": "8331f55ad458fe5c322420b2cb806f9a20ea6b2b8a29d51710026d71ace5da080064b488818efc75a439525bd031450822a6a332da781926e19360b90166431124efcf3d060fbc750c6122c714c07f71",
  "mandatoryPointers": [
    "/issuer",
    "/credentialSubject/sailNumber",
    "/credentialSubject/sails/1",
    "/credentialSubject/boards/0/year",
    "/credentialSubject/sails/2"
  ]
}

마지막으로 위의 값들을 3.2.1 serializeBaseProofValue 절의 알고리즘에 적용하여, 아래에 표시된 서명된 기본 문서에서 사용되는 proofValue를 생성합니다.

예제 38: 서명된 기본 문서
{
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    {
      "@vocab": "https://windsurf.grotto-networking.com/selective#"
    }
  ],
  "type": [
    "VerifiableCredential"
  ],
  "issuer": "https://vc.example/windsurf/racecommittee",
  "credentialSubject": {
    "sailNumber": "Earth101",
    "sails": [
      {
        "size": 5.5,
        "sailName": "Kihei",
        "year": 2023
      },
      {
        "size": 6.1,
        "sailName": "Lahaina",
        "year": 2023
      },
      {
        "size": 7,
        "sailName": "Lahaina",
        "year": 2020
      },
      {
        "size": 7.8,
        "sailName": "Lahaina",
        "year": 2023
      }
    ],
    "boards": [
      {
        "boardName": "CompFoil170",
        "brand": "Wailea",
        "year": 2022
      },
      {
        "boardName": "Kanaha Custom",
        "brand": "Wailea",
        "year": 2019
      }
    ]
  },
  "proof": {
    "type": "DataIntegrityProof",
    "cryptosuite": "bbs-2023",
    "created": "2023-08-15T23:36:38Z",
    "verificationMethod": "did:key:zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ#zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ",
    "proofPurpose": "assertionMethod",
    "proofValue": "u2V0ChVhQgzH1WtRY_lwyJCCyy4BvmiDqayuKKdUXEAJtcazl2ggAZLSIgY78daQ5UlvQMUUIIqajMtp4GSbhk2C5AWZDESTvzz0GD7x1DGEixxTAf3FYQDpbvyXTTZCxjDXNI1e-am9CMB6U_J5S936Tt3PFYUvfVV3gX4mIF-MTAbrBh9DD_ysD4svbSttNVowX3pYfmhhYYKTvGvo9pXVJbxIrm3i4wkdhUxqKCTIGrnxFuAdZwWi6T3omD5wzZ7bAGbRneEEQSxBmXtvnC6Pr59nPv_v3HrAW9wq_uxYzF_NyaX3GPv0h_FV2T2OSao8C6uoyWiqIj1ggABEiM0RVZneImaq7zN3u_wARIjNEVWZ3iJmqu8zd7v-FZy9pc3N1ZXJ4HS9jcmVkZW50aWFsU3ViamVjdC9zYWlsTnVtYmVyeBovY3JlZGVudGlhbFN1YmplY3Qvc2FpbHMvMXggL2NyZWRlbnRpYWxTdWJqZWN0L2JvYXJkcy8wL3llYXJ4Gi9jcmVkZW50aWFsU3ViamVjdC9zYWlscy8y"
  }
}

A.2.2 파생 증명

BBS 증명을 생성할 때 난수를 사용하며, 선택적 presentationHeader를 입력으로 사용할 수 있습니다. 결정론적인 테스트 벡터 집합을 제공하기 위해 [CFRG-BBS-SIGNATURE]의 Mocked Random Scalars 절차를 사용했습니다. 파생 증명 테스트 벡터 생성에 사용한 seedpresentationHeader 값은 아래에 16진수로 표시되어 있습니다.

예제 39: 시드 및 프레젠테이션 헤더 값
{
  "presentationHeaderHex": "113377aa",
  "pseudoRandSeedHex": "332e313431353932363533353839373933323338343632363433333833323739"
}

파생 증명을 생성하려면 보유자는 기본 증명을 포함하는 서명된 문서에서 시작합니다. 이 테스트 벡터에 사용할 기본 문서는 위 A.1.1 기본 증명 절의 마지막 예제입니다. 첫 번째 단계는 3.2.2 parseBaseProofValue 절의 알고리즘을 실행하여 아래와 같이 bbsSignature, hmacKey, mandatoryPointers를 복구하는 것입니다.

예제 40: 복구된 기본 서명 데이터
{
  "bbsSignature": "8331f55ad458fe5c322420b2cb806f9a20ea6b2b8a29d51710026d71ace5da080064b488818efc75a439525bd031450822a6a332da781926e19360b90166431124efcf3d060fbc750c6122c714c07f71",
  "hmacKey": "00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff",
  "mandatoryPointers": [
    "/issuer",
    "/credentialSubject/sailNumber",
    "/credentialSubject/sails/1",
    "/credentialSubject/boards/0/year",
    "/credentialSubject/sails/2"
  ]
}

다음으로 보유자는 선택적 공개를 위한 JSON 포인터를 지정하여, 추가로 공개하려는 내용이 있다면 무엇인지 검증자에게 나타내야 합니다. 이 윈드서핑 경기 시나리오에서 선수(보유자)는 경기 첫날을 막 마쳤으며, 경기에서 사용한 모든 윈드서핑 보드의 세부 정보를 일반 대중(검증자)에게 공개하려고 합니다. 이는 아래와 같습니다. 이 정보는 가장 최근 보드의 연도만 포함했던 필수 공개 정보와 일부 중첩된다는 점에 유의하십시오.

예제 41: 선택적 공개 포인터
["/credentialSubject/boards/0", "/credentialSubject/boards/1"]

revealDocument(즉, 최종적으로 서명되어 검증자에게 전송될 서명되지 않은 문서)를 생성하기 위해 선택적 포인터를 필수 포인터에 이어 붙이고, 이 결합된 포인터와 증명을 제거한 문서를 [DI-ECDSA]의 selectJsonLd 알고리즘에 입력하여 아래와 같은 결과를 얻습니다.

예제 42: 서명되지 않은 공개 문서
{
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    {
      "@vocab": "https://windsurf.grotto-networking.com/selective#"
    }
  ],
  "type": [
    "VerifiableCredential"
  ],
  "issuer": "https://vc.example/windsurf/racecommittee",
  "credentialSubject": {
    "sailNumber": "Earth101",
    "sails": [
      {
        "size": 6.1,
        "sailName": "Lahaina",
        "year": 2023
      },
      {
        "size": 7,
        "sailName": "Lahaina",
        "year": 2020
      }
    ],
    "boards": [
      {
        "year": 2022,
        "boardName": "CompFoil170",
        "brand": "Wailea"
      },
      {
        "boardName": "Kanaha Custom",
        "brand": "Wailea",
        "year": 2019
      }
    ]
  }
}

이제 공개된 문서가 어떤 형태인지 알았으므로, 어떤 문장이 필수인지와 선택된 비필수 문장의 인덱스에 관한 적절히 갱신된 정보를 검증자에게 제공해야 합니다. § 4.4.3 CreateDisclosureData를 실행하면 원본 문서를 기준으로 여러 문장 그룹에 관한 풍부한 정보를 얻을 수 있습니다. 아래에서는 이러한 그룹에 대한 인덱스의 일부를 보여 줍니다.

예제 43: 파생 그룹 인덱스
{
    "combinedIndexes":[0,1,2,6,7,8,9,10,11,14,15,16,17,18,22,23,24,25,26,27],
    "mandatoryIndexes":[0,1,2,8,9,11,14,15,22,23,24,25,26,27],
    "nonMandatoryIndexes":[3,4,5,6,7,10,12,13,16,17,18,19,20,21],
    "selectiveIndexes":[0,1,6,7,8,9,10,16,17,18]
}

검증자는 필수 문장을 모아 해싱할 수 있어야 합니다. 이를 위해 필수 문장의 인덱스를 공개 문서에서의 위치에 맞게 조정한 목록 (즉, combinedIndexes를 기준으로 한 위치)을 제공하며, selectiveIndexesnonMandatoryIndexes 내 위치를 기준으로 조정해야 합니다. 이러한 "조정된" 인덱스는 아래와 같습니다.

예제 44: 조정된 필수 및 선택적 인덱스
{
    "adjMandatoryIndexes":[0,1,2,5,6,8,9,10,14,15,16,17,18,19],
    "adjSelectiveIndexes":[3,4,5,8,9,10]
}

마지막으로 중요한 공개 데이터는 정규화된 빈 노드 ID를 HMAC 기반으로 섞인 ID에 매핑한 labelMap이며, 다음 절에 따라 계산됩니다. § 4.4.3 CreateDisclosureData. 이는 아래에 공개 문서를 제외한 나머지 공개 데이터와 함께 표시됩니다.

예제 45: 공개 데이터
{
    "bbsProof":"9831ba06852694fb44eb56cd9f66581330d9493671a3ad5ed28610c2550c5bfda6cada7cbaf37e9af0c873a4ec6813bf857d539543bc45ba1349fe3233b446f6c46190c40aa8456d98312ed7535c3003e3a77af752ed6f7ee162df4e38a268ad87cc5a10ff38dcc6633810e08ac5a80dacfe6e7dec3ca65fb1dab8d1b0da22b8f26040238c700b8310de92c9c2ec118b2de6b0ccdc72fbdd3329ccf7bc729829e8492d0a796f6e09131884f6fdd0df8028d5ef8f05d9aa9817872598c56421526dbe5db40586cd2b83a454652f71637e57917abd22f45bb67d48fcebdf5464671aec2e845f87f87c1d0eb934db3fb9e2310d483d67110b5f64127827888e8cd9259ea78f6683184ca4e71845b803d93a3554f4577716f939bd36f26eb740771bd5c35247ef4abc2b0e701721a6e8edf62a63af3a032df895cde06d0b15ca8c1a7507249118f9d096fcc5a3f9a39ec1a870ef619efa6af61fd93b74b82b24317def59f981fc8ec2b5633d8eb8711b108552b7b6e748648503fecdf52ac0a76eca89306361262cc4767bbb84e904d1a7523bc19d67bc501c78949616bef65470b067f81759d9a29f9c2775c0888a4617b57018ece111e62cd8365b4783fbe53bcec846bf724bdddc196fced05c59c35ebb735aea9a83f0e5233cdb9fbb8fd2e3b007ee7f69cafc37c4993ddfc747d7793b48ea48213154b459260c29da6dd41de9539a3352855afa398b2bafd47d07d765",
    "labelMap":{"dataType":"Map","value":[["c14n0","b2"],["c14n1","b4"],["c14n2","b3"],["c14n3","b7"],["c14n4","b6"],["c14n5","b0"]]},
    "mandatoryIndexes":[0,1,2,5,6,8,9,10,14,15,16,17,18,19],
    "adjSelectiveIndexes":[3,4,5,8,9,10],
    "presentationHeader":{"0":17,"1":51,"2":119,"3":170}
}

마지막으로 위의 공개 데이터를 다음 절의 알고리즘과 함께 사용하면 3.2.3 serializeDerivedProofValue, 아래에 표시된 서명된 파생(공개) 문서를 얻습니다.

예제 46: 서명된 파생 문서
{
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    {
      "@vocab": "https://windsurf.grotto-networking.com/selective#"
    }
  ],
  "type": [
    "VerifiableCredential"
  ],
  "issuer": "https://vc.example/windsurf/racecommittee",
  "credentialSubject": {
    "sailNumber": "Earth101",
    "sails": [
      {
        "size": 6.1,
        "sailName": "Lahaina",
        "year": 2023
      },
      {
        "size": 7,
        "sailName": "Lahaina",
        "year": 2020
      }
    ],
    "boards": [
      {
        "year": 2022,
        "boardName": "CompFoil170",
        "brand": "Wailea"
      },
      {
        "boardName": "Kanaha Custom",
        "brand": "Wailea",
        "year": 2019
      }
    ]
  },
  "proof": {
    "type": "DataIntegrityProof",
    "cryptosuite": "bbs-2023",
    "created": "2023-08-15T23:36:38Z",
    "verificationMethod": "did:key:zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ#zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ",
    "proofPurpose": "assertionMethod",
    "proofValue": "u2V0DhVkCEJgxugaFJpT7ROtWzZ9mWBMw2Uk2caOtXtKGEMJVDFv9psrafLrzfprwyHOk7GgTv4V9U5VDvEW6E0n-MjO0RvbEYZDECqhFbZgxLtdTXDAD46d691Ltb37hYt9OOKJorYfMWhD_ONzGYzgQ4IrFqA2s_m597DymX7HauNGw2iK48mBAI4xwC4MQ3pLJwuwRiy3msMzccvvdMynM97xymCnoSS0KeW9uCRMYhPb90N-AKNXvjwXZqpgXhyWYxWQhUm2-XbQFhs0rg6RUZS9xY35XkXq9IvRbtn1I_OvfVGRnGuwuhF-H-HwdDrk02z-54jENSD1nEQtfZBJ4J4iOjNklnqePZoMYTKTnGEW4A9k6NVT0V3cW-Tm9NvJut0B3G9XDUkfvSrwrDnAXIabo7fYqY686Ay34lc3gbQsVyowadQckkRj50Jb8xaP5o57BqHDvYZ76avYf2Tt0uCskMX3vWfmB_I7CtWM9jrhxGxCFUre250hkhQP-zfUqwKduyokwY2EmLMR2e7uE6QTRp1I7wZ1nvFAceJSWFr72VHCwZ_gXWdmin5wndcCIikYXtXAY7OER5izYNltHg_vlO87IRr9yS93cGW_O0FxZw167c1rqmoPw5SM825-7j9LjsAfuf2nK_DfEmT3fx0fXeTtI6kghMVS0WSYMKdpt1B3pU5ozUoVa-jmLK6_UfQfXZaYAAgEEAgMDBwQGBQCOAAECBQYICQoODxAREhOGAwQFCAkKRBEzd6o"
  }
}

A.3 익명 보유자 바인딩 기능

A.3.1 보유자 바인딩 커밋먼트 생성

익명 보유자 바인딩 기능을 사용하는 첫 단계는 보유자가 자신의 holderSecret 값을 생성한 다음 [CFRG-Blind-BBS-Signature]의 커밋먼트 계산 절차에 따라 이 값에 대한 증명이 포함된 커밋먼트를 계산하는 것입니다. 이 절차의 예제 값과 출력은 아래와 같습니다.

예제 47: 보유자의 비밀 값
{
    "holderSecretHex": "8fc6cc3f65db4ba5e3ed63fe9d2bd57a9c7df9c7f6bf2b898b308d5493b07eb6"
}
예제 48: 보유자의 비밀 커밋먼트 정보
{
  "secretProverBlind": "12901a77b3906af68d9e4214dce887d127b2a51d6311bbe7d087d45737acd2db",
  "commitmentWithProof": "ab77a14fddfafc7ae6ea82b0ef6048059225f96c9206903a34c6ec6beba702652e9d64fac1917e372853867d944e4a8059e0c26bc871cac14736e73685cd3006299539b93df64cdf661af2bc6300976528c5092c6dc842abaaa624f2184d3d5b75be0ede9c4822161149ef51a965ddda260e10b9246ecaea020ef952e3b3ed6e724bcb5d1a9c4004f0aea2cba030c27c"
}

holderSecretsecretProverBlind는 보유자가 보관하고 비밀로 유지해야 합니다. commitmentWithProof 값은 발급자에게 전달해야 합니다.

A.3.2 보유자 바인딩 기본 증명

익명 보유자 바인딩 옵션에 따라 기본 증명을 추가하는 절차는 발급자가 보유자로부터 commitmentWithProof 값을 받은 다음 [CFRG-Blind-BBS-Signature]의 커밋먼트 검증 절차를 사용하여 해당 값을 검증하는 것부터 시작합니다. 기본 증명 절에서 설명하고 사용한 암호학적 키 자료도 여기에서 사용하며, 아래에 다시 표시합니다.

예제 49: 서명용 비공개 및 공개 키
{
  "publicKeyHex": "a4ef1afa3da575496f122b9b78b8c24761531a8a093206ae7c45b80759c168ba4f7a260f9c3367b6c019b4677841104b10665edbe70ba3ebe7d9cfbffbf71eb016f70abfbb163317f372697dc63efd21fc55764f63926a8f02eaea325a2a888f",
  "privateKeyHex": "66d36e118832af4c5e28b2dfe1b9577857e57b042a33e06bdea37b811ed09ee0",
  "hmacKeyString": "00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF"
}

이 시나리오에서는 운전면허증의 전자 버전을 고려합니다.

예제 50: 기능을 위한 증명이 없는 자격 증명
{
    "@context": [
        "https://www.w3.org/2018/credentials/v1",
        "https://w3id.org/security/data-integrity/v2",
        "https://w3id.org/vdl/v1",
        "https://w3id.org/vdl/aamva/v1"
    ],
    "type": [
        "VerifiableCredential",
        "Iso18013DriversLicenseCredential"
    ],
    "issuer": {
        "id": "did:key:z6MkjxvA4FNrQUhr8f7xhdQuP1VPzErkcnfxsRaU5oFgy2E5",
        "name": "Utopia Department of Motor Vehicles",
        "url": "https://dmv.utopia.example/",
        "image": "https://dmv.utopia.example/logo.png"
    },
    "issuanceDate": "2023-11-15T10:00:00-07:00",
    "expirationDate": "2028-11-15T12:00:00-06:00",
    "name": "Utopia Driver's License",
    "image": "data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUg...kSuQmCC",
    "description": "A license granting driving privileges in Utopia.",
    "credentialSubject": {
        "type": "LicensedDriver",
        "driversLicense": {
            "type": "Iso18013DriversLicense",
            "document_number": "542426814",
            "family_name": "TURNER",
            "given_name": "SUSAN",
            "portrait": "data:image/jpeg;base64,/9j/4AAQSkZJR...RSClooooP/2Q==",
            "birth_date": "1998-08-28",
            "issue_date": "2023-01-15T10:00:00-07:00",
            "expiry_date": "2028-08-27T12:00:00-06:00",
            "issuing_country": "UA",
            "issuing_authority": "UADMV",
            "driving_privileges": [
                {
                    "codes": [
                        {
                            "code": "D"
                        }
                    ],
                    "vehicle_category_code": "D",
                    "issue_date": "2019-01-01",
                    "expiry_date": "2027-01-01"
                },
                {
                    "codes": [
                        {
                            "code": "C"
                        }
                    ],
                    "vehicle_category_code": "C",
                    "issue_date": "2019-01-01",
                    "expiry_date": "2017-01-01"
                }
            ],
            "un_distinguishing_sign": "UTA",
            "aamva_aka_suffix": "1ST",
            "sex": 2,
            "aamva_family_name_truncation": "N",
            "aamva_given_name_truncation": "N"
        }
    }
}

보유자의 개인정보를 보호하기 위해 아래에 제시된 필수 포인터에서 구현된 것처럼 유일한 필수 필드는 "issuer" 및 "expirationDate"입니다.

예제 51: 기능을 위한 필수 포인터
["/issuer", "/expirationDate"]

서명되지 않은 문서의 변환은 아래와 같이 문서를 정규화하는 것부터 시작합니다.

예제 52: 기능을 위한 정규 문서
[
  "<did:key:z6MkjxvA4FNrQUhr8f7xhdQuP1VPzErkcnfxsRaU5oFgy2E5> <https://schema.org/image> <https://dmv.utopia.example/logo.png> .\n",
  "<did:key:z6MkjxvA4FNrQUhr8f7xhdQuP1VPzErkcnfxsRaU5oFgy2E5> <https://schema.org/name> \"Utopia Department of Motor Vehicles\" .\n",
  "<did:key:z6MkjxvA4FNrQUhr8f7xhdQuP1VPzErkcnfxsRaU5oFgy2E5> <https://schema.org/url> <https://dmv.utopia.example/> .\n",
  "_:c14n0 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/vdl#Iso18013DriversLicenseCredential> .\n",
  "_:c14n0 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://www.w3.org/2018/credentials#VerifiableCredential> .\n",
  "_:c14n0 <https://schema.org/description> \"A license granting driving privileges in Utopia.\" .\n",
  "_:c14n0 <https://schema.org/image> <data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUg...kSuQmCC> .\n",
  "_:c14n0 <https://schema.org/name> \"Utopia Driver's License\" .\n",
  "_:c14n0 <https://www.w3.org/2018/credentials#credentialSubject> _:c14n1 .\n",
  "_:c14n0 <https://www.w3.org/2018/credentials#expirationDate> \"2028-11-15T12:00:00-06:00\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n",
  "_:c14n0 <https://www.w3.org/2018/credentials#issuanceDate> \"2023-11-15T10:00:00-07:00\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n",
  "_:c14n0 <https://www.w3.org/2018/credentials#issuer> <did:key:z6MkjxvA4FNrQUhr8f7xhdQuP1VPzErkcnfxsRaU5oFgy2E5> .\n",
  "_:c14n1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/vdl#LicensedDriver> .\n",
  "_:c14n1 <https://w3id.org/vdl#license> _:c14n2 .\n",
  "_:c14n2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/vdl#Iso18013DriversLicense> .\n",
  "_:c14n2 <https://w3id.org/vdl#birthDate> \"1998-08-28\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n",
  "_:c14n2 <https://w3id.org/vdl#documentNumber> \"542426814\" .\n",
  "_:c14n2 <https://w3id.org/vdl#drivingPrivileges> \"[{\\\"codes\\\":[{\\\"code\\\":\\\"D\\\"}],\\\"expiry_date\\\":\\\"2027-01-01\\\",\\\"issue_date\\\":\\\"2019-01-01\\\",\\\"vehicle_category_code\\\":\\\"D\\\"},{\\\"codes\\\":[{\\\"code\\\":\\\"C\\\"}],\\\"expiry_date\\\":\\\"2017-01-01\\\",\\\"issue_date\\\":\\\"2019-01-01\\\",\\\"vehicle_category_code\\\":\\\"C\\\"}]\"^^<http://www.w3.org/1999/02/22-rdf-syntax-ns#JSON> .\n",
  "_:c14n2 <https://w3id.org/vdl#expiryDate> \"2028-08-27T12:00:00-06:00\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n",
  "_:c14n2 <https://w3id.org/vdl#familyName> \"TURNER\" .\n",
  "_:c14n2 <https://w3id.org/vdl#givenName> \"SUSAN\" .\n",
  "_:c14n2 <https://w3id.org/vdl#issueDate> \"2023-01-15T10:00:00-07:00\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n",
  "_:c14n2 <https://w3id.org/vdl#issuingAuthority> \"UADMV\" .\n",
  "_:c14n2 <https://w3id.org/vdl#issuingCountry> \"UA\" .\n",
  "_:c14n2 <https://w3id.org/vdl#portrait> <data:image/jpeg;base64,/9j/4AAQSkZJR...RSClooooP/2Q==> .\n",
  "_:c14n2 <https://w3id.org/vdl#sex> \"2\"^^<http://www.w3.org/2001/XMLSchema#unsignedInt> .\n",
  "_:c14n2 <https://w3id.org/vdl#unDistinguishingSign> \"UTA\" .\n",
  "_:c14n2 <https://w3id.org/vdl/aamva#akaSuffix> \"1ST\" .\n",
  "_:c14n2 <https://w3id.org/vdl/aamva#familyNameTruncation> \"N\" .\n",
  "_:c14n2 <https://w3id.org/vdl/aamva#givenNameTruncation> \"N\" .\n"
]

빈 노드 ID의 순서에서 발생할 수 있는 정보 유출을 방지하기 위해 이를 PRF(즉, HMAC)를 통해 처리하여 아래에 표시된 정규화된 HMAC 문서를 생성합니다. 이는 필수 및 선택적 공개의 대상이 되는 문장들의 순서 있는 목록을 나타내며, 즉 이 목록을 기준으로 문장이 그룹화됩니다.

예제 53: 기능을 위한 정규 HMAC 문서
[
  "<did:key:z6MkjxvA4FNrQUhr8f7xhdQuP1VPzErkcnfxsRaU5oFgy2E5> <https://schema.org/image> <https://dmv.utopia.example/logo.png> .\n",
  "<did:key:z6MkjxvA4FNrQUhr8f7xhdQuP1VPzErkcnfxsRaU5oFgy2E5> <https://schema.org/name> \"Utopia Department of Motor Vehicles\" .\n",
  "<did:key:z6MkjxvA4FNrQUhr8f7xhdQuP1VPzErkcnfxsRaU5oFgy2E5> <https://schema.org/url> <https://dmv.utopia.example/> .\n",
  "_:b0 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/vdl#LicensedDriver> .\n",
  "_:b0 <https://w3id.org/vdl#license> _:b2 .\n",
  "_:b1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/vdl#Iso18013DriversLicenseCredential> .\n",
  "_:b1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://www.w3.org/2018/credentials#VerifiableCredential> .\n",
  "_:b1 <https://schema.org/description> \"A license granting driving privileges in Utopia.\" .\n",
  "_:b1 <https://schema.org/image> <data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUg...kSuQmCC> .\n",
  "_:b1 <https://schema.org/name> \"Utopia Driver's License\" .\n",
  "_:b1 <https://www.w3.org/2018/credentials#credentialSubject> _:b0 .\n",
  "_:b1 <https://www.w3.org/2018/credentials#expirationDate> \"2028-11-15T12:00:00-06:00\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n",
  "_:b1 <https://www.w3.org/2018/credentials#issuanceDate> \"2023-11-15T10:00:00-07:00\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n",
  "_:b1 <https://www.w3.org/2018/credentials#issuer> <did:key:z6MkjxvA4FNrQUhr8f7xhdQuP1VPzErkcnfxsRaU5oFgy2E5> .\n",
  "_:b2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/vdl#Iso18013DriversLicense> .\n",
  "_:b2 <https://w3id.org/vdl#birthDate> \"1998-08-28\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n",
  "_:b2 <https://w3id.org/vdl#documentNumber> \"542426814\" .\n",
  "_:b2 <https://w3id.org/vdl#drivingPrivileges> \"[{\\\"codes\\\":[{\\\"code\\\":\\\"D\\\"}],\\\"expiry_date\\\":\\\"2027-01-01\\\",\\\"issue_date\\\":\\\"2019-01-01\\\",\\\"vehicle_category_code\\\":\\\"D\\\"},{\\\"codes\\\":[{\\\"code\\\":\\\"C\\\"}],\\\"expiry_date\\\":\\\"2017-01-01\\\",\\\"issue_date\\\":\\\"2019-01-01\\\",\\\"vehicle_category_code\\\":\\\"C\\\"}]\"^^<http://www.w3.org/1999/02/22-rdf-syntax-ns#JSON> .\n",
  "_:b2 <https://w3id.org/vdl#expiryDate> \"2028-08-27T12:00:00-06:00\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n",
  "_:b2 <https://w3id.org/vdl#familyName> \"TURNER\" .\n",
  "_:b2 <https://w3id.org/vdl#givenName> \"SUSAN\" .\n",
  "_:b2 <https://w3id.org/vdl#issueDate> \"2023-01-15T10:00:00-07:00\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n",
  "_:b2 <https://w3id.org/vdl#issuingAuthority> \"UADMV\" .\n",
  "_:b2 <https://w3id.org/vdl#issuingCountry> \"UA\" .\n",
  "_:b2 <https://w3id.org/vdl#portrait> <data:image/jpeg;base64,/9j/4AAQSkZJR...RSClooooP/2Q==> .\n",
  "_:b2 <https://w3id.org/vdl#sex> \"2\"^^<http://www.w3.org/2001/XMLSchema#unsignedInt> .\n",
  "_:b2 <https://w3id.org/vdl#unDistinguishingSign> \"UTA\" .\n",
  "_:b2 <https://w3id.org/vdl/aamva#akaSuffix> \"1ST\" .\n",
  "_:b2 <https://w3id.org/vdl/aamva#familyNameTruncation> \"N\" .\n",
  "_:b2 <https://w3id.org/vdl/aamva#givenNameTruncation> \"N\" .\n"
]

위 정규 문서는 필수 및 비필수 문장으로 그룹화됩니다. 선택적 공개 변환 과정의 최종 출력은 아래와 같습니다. 이제 각 문장은 필수 또는 비필수로 그룹화되며, 이전 문장 목록에서의 인덱스가 기억됩니다.

예제 54: 기능을 위한 기본 변환 추가
{
  "mandatoryPointers": [
    "/issuer",
    "/expirationDate"
  ],
  "mandatory": {
    "dataType": "Map",
    "value": [
      [
        0,
        "<did:key:z6MkjxvA4FNrQUhr8f7xhdQuP1VPzErkcnfxsRaU5oFgy2E5> <https://schema.org/image> <https://dmv.utopia.example/logo.png> .\n"
      ],
      [
        1,
        "<did:key:z6MkjxvA4FNrQUhr8f7xhdQuP1VPzErkcnfxsRaU5oFgy2E5> <https://schema.org/name> \"Utopia Department of Motor Vehicles\" .\n"
      ],
      [
        2,
        "<did:key:z6MkjxvA4FNrQUhr8f7xhdQuP1VPzErkcnfxsRaU5oFgy2E5> <https://schema.org/url> <https://dmv.utopia.example/> .\n"
      ],
      [
        5,
        "_:b1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/vdl#Iso18013DriversLicenseCredential> .\n"
      ],
      [
        6,
        "_:b1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://www.w3.org/2018/credentials#VerifiableCredential> .\n"
      ],
      [
        11,
        "_:b1 <https://www.w3.org/2018/credentials#expirationDate> \"2028-11-15T12:00:00-06:00\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n"
      ],
      [
        13,
        "_:b1 <https://www.w3.org/2018/credentials#issuer> <did:key:z6MkjxvA4FNrQUhr8f7xhdQuP1VPzErkcnfxsRaU5oFgy2E5> .\n"
      ]
    ]
  },
  "nonMandatory": {
    "dataType": "Map",
    "value": [
      [
        3,
        "_:b0 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/vdl#LicensedDriver> .\n"
      ],
      [
        4,
        "_:b0 <https://w3id.org/vdl#license> _:b2 .\n"
      ],
      [
        7,
        "_:b1 <https://schema.org/description> \"A license granting driving privileges in Utopia.\" .\n"
      ],
      [
        8,
        "_:b1 <https://schema.org/image> <data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUg...kSuQmCC> .\n"
      ],
      [
        9,
        "_:b1 <https://schema.org/name> \"Utopia Driver's License\" .\n"
      ],
      [
        10,
        "_:b1 <https://www.w3.org/2018/credentials#credentialSubject> _:b0 .\n"
      ],
      [
        12,
        "_:b1 <https://www.w3.org/2018/credentials#issuanceDate> \"2023-11-15T10:00:00-07:00\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n"
      ],
      [
        14,
        "_:b2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/vdl#Iso18013DriversLicense> .\n"
      ],
      [
        15,
        "_:b2 <https://w3id.org/vdl#birthDate> \"1998-08-28\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n"
      ],
      [
        16,
        "_:b2 <https://w3id.org/vdl#documentNumber> \"542426814\" .\n"
      ],
      [
        17,
        "_:b2 <https://w3id.org/vdl#drivingPrivileges> \"[{\\\"codes\\\":[{\\\"code\\\":\\\"D\\\"}],\\\"expiry_date\\\":\\\"2027-01-01\\\",\\\"issue_date\\\":\\\"2019-01-01\\\",\\\"vehicle_category_code\\\":\\\"D\\\"},{\\\"codes\\\":[{\\\"code\\\":\\\"C\\\"}],\\\"expiry_date\\\":\\\"2017-01-01\\\",\\\"issue_date\\\":\\\"2019-01-01\\\",\\\"vehicle_category_code\\\":\\\"C\\\"}]\"^^<http://www.w3.org/1999/02/22-rdf-syntax-ns#JSON> .\n"
      ],
      [
        18,
        "_:b2 <https://w3id.org/vdl#expiryDate> \"2028-08-27T12:00:00-06:00\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n"
      ],
      [
        19,
        "_:b2 <https://w3id.org/vdl#familyName> \"TURNER\" .\n"
      ],
      [
        20,
        "_:b2 <https://w3id.org/vdl#givenName> \"SUSAN\" .\n"
      ],
      [
        21,
        "_:b2 <https://w3id.org/vdl#issueDate> \"2023-01-15T10:00:00-07:00\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n"
      ],
      [
        22,
        "_:b2 <https://w3id.org/vdl#issuingAuthority> \"UADMV\" .\n"
      ],
      [
        23,
        "_:b2 <https://w3id.org/vdl#issuingCountry> \"UA\" .\n"
      ],
      [
        24,
        "_:b2 <https://w3id.org/vdl#portrait> <data:image/jpeg;base64,/9j/4AAQSkZJR...RSClooooP/2Q==> .\n"
      ],
      [
        25,
        "_:b2 <https://w3id.org/vdl#sex> \"2\"^^<http://www.w3.org/2001/XMLSchema#unsignedInt> .\n"
      ],
      [
        26,
        "_:b2 <https://w3id.org/vdl#unDistinguishingSign> \"UTA\" .\n"
      ],
      [
        27,
        "_:b2 <https://w3id.org/vdl/aamva#akaSuffix> \"1ST\" .\n"
      ],
      [
        28,
        "_:b2 <https://w3id.org/vdl/aamva#familyNameTruncation> \"N\" .\n"
      ],
      [
        29,
        "_:b2 <https://w3id.org/vdl/aamva#givenNameTruncation> \"N\" .\n"
      ]
    ]
  },
  "hmacKeyString": "00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF"
}

다음 단계에서는 기본 증명 구성을 생성하고 이를 정규화합니다. 이는 다음 두 예제에 표시되어 있습니다.

예제 55: 기능을 위한 기본 증명 구성
{
  "type": "DataIntegrityProof",
  "cryptosuite": "bbs-2023",
  "created": "2023-08-15T23:36:38Z",
  "verificationMethod": "did:key:zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ#zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ",
  "proofPurpose": "assertionMethod",
  "@context": [
    "https://www.w3.org/2018/credentials/v1",
    "https://w3id.org/security/data-integrity/v2",
    "https://w3id.org/vdl/v1",
    "https://w3id.org/vdl/aamva/v1"
  ]
}
예제 56: 기능을 위한 정규 기본 증명 구성
_:c14n0 <http://purl.org/dc/terms/created> "2023-08-15T23:36:38Z"^^<http://www.w3.org/2001/XMLSchema#dateTime> .
_:c14n0 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/security#DataIntegrityProof> .
_:c14n0 <https://w3id.org/security#cryptosuite> "bbs-2023"^^<https://w3id.org/security#cryptosuiteString> .
_:c14n0 <https://w3id.org/security#proofPurpose> <https://w3id.org/security#assertionMethod> .
_:c14n0 <https://w3id.org/security#verificationMethod> <did:key:zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ#zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ> .

해싱 단계에서는 정규화된 증명 옵션의 SHA-256 해시를 계산하여 proofHash를 생성하고, 모든 필수 N-Quads를 결합한 값의 SHA-256 해시를 계산하여 mandatoryHash를 생성합니다. 이는 아래에 16진수 형식으로 표시되어 있습니다.

예제 57: 기능을 위한 기본 해시 추가
{
  "proofHash": "3a5bbf25d34d90b18c35cd2357be6a6f42301e94fc9e52f77e93b773c5614bdf",
  "mandatoryHash": "8eea112c04d89e133880f96766ebae73693f75f1bbcbbaa473dc06254bdec4fb"
}

이제 [CFRG-Blind-BBS-Signature]의 블라인드 서명 생성 절차를 3.3.2 기본 증명 직렬화 (bbs-2023) 절차에서 사용합니다. 아래에는 계산된 bbsSignature, bbsHeader, publicKey, hmacKey, mandatoryPointersfeatureOption이 표시되어 있으며, 바이트 데이터는 16진수로 표시됩니다.

예제 58: 보유자 바인딩을 위한 기본 서명 추가
{
  "bbsSignature": "90eadd70a16661f3d596f3560fc485f7c23ba969eb7c237d481b3596b2f66279bd5a62fa523777eb73b5cfa361885f1a00864b960baf1b92d2b55c0652ebe39024f88e1377911c40bf14cb5fbc808ee1",
  "bbsHeader": "3a5bbf25d34d90b18c35cd2357be6a6f42301e94fc9e52f77e93b773c5614bdf8eea112c04d89e133880f96766ebae73693f75f1bbcbbaa473dc06254bdec4fb",
  "publicKey": "a4ef1afa3da575496f122b9b78b8c24761531a8a093206ae7c45b80759c168ba4f7a260f9c3367b6c019b4677841104b10665edbe70ba3ebe7d9cfbffbf71eb016f70abfbb163317f372697dc63efd21fc55764f63926a8f02eaea325a2a888f",
  "hmacKey": "00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff",
  "mandatoryPointers": [
    "/issuer",
    "/expirationDate"
  ],
  "featureOption": "anonymous_holder_binding"
}

마지막으로 위의 값들을 3.2.1 serializeBaseProofValue 절의 알고리즘에 적용하여 아래에 표시된 서명된 기본 문서에서 사용되는 proofValue를 생성합니다.

예제 59: 보유자 바인딩을 위한 서명된 기본 문서
{
  "@context": [
    "https://www.w3.org/2018/credentials/v1",
    "https://w3id.org/security/data-integrity/v2",
    "https://w3id.org/vdl/v1",
    "https://w3id.org/vdl/aamva/v1"
  ],
  "type": [
    "VerifiableCredential",
    "Iso18013DriversLicenseCredential"
  ],
  "issuer": {
    "id": "did:key:z6MkjxvA4FNrQUhr8f7xhdQuP1VPzErkcnfxsRaU5oFgy2E5",
    "name": "Utopia Department of Motor Vehicles",
    "url": "https://dmv.utopia.example/",
    "image": "https://dmv.utopia.example/logo.png"
  },
  "issuanceDate": "2023-11-15T10:00:00-07:00",
  "expirationDate": "2028-11-15T12:00:00-06:00",
  "name": "Utopia Driver's License",
  "image": "data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUg...kSuQmCC",
  "description": "A license granting driving privileges in Utopia.",
  "credentialSubject": {
    "type": "LicensedDriver",
    "driversLicense": {
      "type": "Iso18013DriversLicense",
      "document_number": "542426814",
      "family_name": "TURNER",
      "given_name": "SUSAN",
      "portrait": "data:image/jpeg;base64,/9j/4AAQSkZJR...RSClooooP/2Q==",
      "birth_date": "1998-08-28",
      "issue_date": "2023-01-15T10:00:00-07:00",
      "expiry_date": "2028-08-27T12:00:00-06:00",
      "issuing_country": "UA",
      "issuing_authority": "UADMV",
      "driving_privileges": [
        {
          "codes": [
            {
              "code": "D"
            }
          ],
          "vehicle_category_code": "D",
          "issue_date": "2019-01-01",
          "expiry_date": "2027-01-01"
        },
        {
          "codes": [
            {
              "code": "C"
            }
          ],
          "vehicle_category_code": "C",
          "issue_date": "2019-01-01",
          "expiry_date": "2017-01-01"
        }
      ],
      "un_distinguishing_sign": "UTA",
      "aamva_aka_suffix": "1ST",
      "sex": 2,
      "aamva_family_name_truncation": "N",
      "aamva_given_name_truncation": "N"
    }
  },
  "proof": {
    "type": "DataIntegrityProof",
    "cryptosuite": "bbs-2023",
    "created": "2023-08-15T23:36:38Z",
    "verificationMethod": "did:key:zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ#zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ",
    "proofPurpose": "assertionMethod",
    "proofValue": "u2V0EhVhQkOrdcKFmYfPVlvNWD8SF98I7qWnrfCN9SBs1lrL2Ynm9WmL6Ujd363O1z6NhiF8aAIZLlguvG5LStVwGUuvjkCT4jhN3kRxAvxTLX7yAjuFYQDpbvyXTTZCxjDXNI1e-am9CMB6U_J5S936Tt3PFYUvfjuoRLATYnhM4gPlnZuuuc2k_dfG7y7qkc9wGJUvexPtYYKTvGvo9pXVJbxIrm3i4wkdhUxqKCTIGrnxFuAdZwWi6T3omD5wzZ7bAGbRneEEQSxBmXtvnC6Pr59nPv_v3HrAW9wq_uxYzF_NyaX3GPv0h_FV2T2OSao8C6uoyWiqIj1ggABEiM0RVZneImaq7zN3u_wARIjNEVWZ3iJmqu8zd7v-CZy9pc3N1ZXJvL2V4cGlyYXRpb25EYXRl"
  }
}

A.3.3 보유자 바인딩 파생 증명

절에서 설명했듯이 모의 난수 생성 절차를 사용하고 presentationHeader의 사용을 보여줍니다. 여기에서도 동일한 seedpresentationHeader를 사용하며 아래에 다시 표시합니다.

예제 60: 시드 및 프레젠테이션 헤더 값
{
  "presentationHeaderHex": "113377aa",
  "pseudoRandSeedHex": "332e313431353932363533353839373933323338343632363433333833323739"
}

파생 증명을 생성하려면 보유자는 기본 증명을 포함하는 서명된 문서에서 시작합니다. 이 테스트 벡터에 사용할 기본 문서는 위 A.3.2 보유자 바인딩 기본 증명 절의 마지막 예제입니다. 첫 번째 단계는 3.2.2 parseBaseProofValue 절의 알고리즘을 실행하여 아래와 같이 bbsSignature, bbsHeader, publicKey, hmacKey, mandatoryPointersfeatureOption을 복구하는 것입니다.

예제 61: 보유자 바인딩을 위해 복구된 기본 서명 데이터
{
  "bbsSignature": "90eadd70a16661f3d596f3560fc485f7c23ba969eb7c237d481b3596b2f66279bd5a62fa523777eb73b5cfa361885f1a00864b960baf1b92d2b55c0652ebe39024f88e1377911c40bf14cb5fbc808ee1",
  "bbsHeader": "3a5bbf25d34d90b18c35cd2357be6a6f42301e94fc9e52f77e93b773c5614bdf8eea112c04d89e133880f96766ebae73693f75f1bbcbbaa473dc06254bdec4fb",
  "publicKey": "a4ef1afa3da575496f122b9b78b8c24761531a8a093206ae7c45b80759c168ba4f7a260f9c3367b6c019b4677841104b10665edbe70ba3ebe7d9cfbffbf71eb016f70abfbb163317f372697dc63efd21fc55764f63926a8f02eaea325a2a888f",
  "hmacKey": "00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff",
  "mandatoryPointers": [
    "/issuer",
    "/expirationDate"
  ],
  "featureOption": "anonymous_holder_binding"
}

다음으로 보유자는 선택적 공개를 위한 JSON 포인터를 지정하여 추가로 공개하려는 내용이 있다면 무엇인지 검증자에게 알려야 합니다. 이 경우 보유자는 자신의 운전 권한만 공개하려고 합니다.

예제 62: 기능을 위한 선택적 공개 포인터
["/credentialSubject/driversLicense/issuing_country", "/credentialSubject/driversLicense/driving_privileges"]

revealDocument(즉, 최종적으로 서명되어 검증자에게 전송될 서명되지 않은 문서)를 생성하기 위해 선택적 포인터를 필수 포인터에 이어 붙이고, 이 결합된 포인터와 증명을 제거한 문서를 [DI-ECDSA]의 selectJsonLd 알고리즘에 입력하여 아래와 같은 결과를 얻습니다.

예제 63: 기능을 위한 서명되지 않은 공개 문서
{
  "@context": [
    "https://www.w3.org/2018/credentials/v1",
    "https://w3id.org/security/data-integrity/v2",
    "https://w3id.org/vdl/v1",
    "https://w3id.org/vdl/aamva/v1"
  ],
  "type": [
    "VerifiableCredential",
    "Iso18013DriversLicenseCredential"
  ],
  "issuer": {
    "id": "did:key:z6MkjxvA4FNrQUhr8f7xhdQuP1VPzErkcnfxsRaU5oFgy2E5",
    "name": "Utopia Department of Motor Vehicles",
    "url": "https://dmv.utopia.example/",
    "image": "https://dmv.utopia.example/logo.png"
  },
  "expirationDate": "2028-11-15T12:00:00-06:00",
  "credentialSubject": {
    "type": "LicensedDriver",
    "driversLicense": {
      "type": "Iso18013DriversLicense",
      "issuing_country": "UA",
      "driving_privileges": [
        {
          "codes": [
            {
              "code": "D"
            }
          ],
          "vehicle_category_code": "D",
          "issue_date": "2019-01-01",
          "expiry_date": "2027-01-01"
        },
        {
          "codes": [
            {
              "code": "C"
            }
          ],
          "vehicle_category_code": "C",
          "issue_date": "2019-01-01",
          "expiry_date": "2017-01-01"
        }
      ]
    }
  }
}

이제 공개된 문서가 어떤 형태인지 알았으므로, 어떤 문장이 필수인지와 선택된 비필수 문장의 인덱스에 관한 적절히 갱신된 정보를 검증자에게 제공해야 합니다. § 4.4.3 CreateDisclosureData를 실행하면 원본 문서를 기준으로 여러 문장 그룹에 관한 풍부한 정보를 얻을 수 있습니다. 아래에서는 이러한 그룹에 대한 인덱스의 일부를 보여 줍니다.

예제 64: 기능을 위한 파생 그룹 인덱스
{"combinedIndexes":[0,1,2,3,4,5,6,10,11,13,14,17,23],"mandatoryIndexes":[0,1,2,5,6,11,13],"nonMandatoryIndexes":[3,4,7,8,9,10,12,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29],"selectiveIndexes":[3,4,5,6,10,14,17,23]}

검증자는 필수 문장을 모아 해싱할 수 있어야 합니다. 이를 위해 필수 문장의 인덱스를 공개 문서에서의 위치에 맞게 조정한 목록 (즉, combinedIndexes를 기준으로 한 위치)을 제공하며, selectiveIndexesnonMandatoryIndexes 내 위치를 기준으로 조정해야 합니다. 이러한 "조정된" 인덱스는 아래와 같습니다.

예제 65: 기능을 위한 조정된 필수 및 선택적 인덱스
{"adjMandatoryIndexes":[0,1,2,5,6,8,9],"adjSelectiveIndexes":[0,1,5,7,10,16]}

마지막으로 중요한 공개 데이터는 정규화된 빈 노드 ID를 HMAC 기반으로 섞인 ID에 매핑한 labelMap이며, 다음 절에 따라 계산됩니다. § 4.4.3 CreateDisclosureData. 이는 아래에 공개 문서를 제외한 나머지 공개 데이터와 함께 표시됩니다. 여기서는 featureOption"anonymous_holder_binding"과 같은 경우에 적합한 결과를 보여 주며, 이는 [CFRG-Blind-BBS-Signature]의 블라인드 증명 생성 절차를 사용합니다. blindAdjDisclosedIdxs는 증명 직렬화 프로세스에서 사용되는 최종 BBS 선택적 인덱스 집합이며, adjSelectiveIndexes를 입력으로 받는 블라인드 BBS 증명 생성 함수에서 가져온다는 점에 유의하십시오.

예제 66: 보유자 바인딩을 위한 공개 데이터
{"bbsProof":"a19db05cca1237d9965b0bb3197c4962a7fb49c97af131c80ea2d8f949078ff5642acdb33d27d06b97f87ff906a2a23bb0c3dd778572b892785faefdc25811318b0b46e25b8863898b0600701a71c256ee9a7347a1a577fe2e3793b1c0390e4d8f9fff9161074eebba852bcca8089eed76416ac9f178b850e7688c26cfbdee344fa75d9ba2cf22417e3c70be7891f6de040928d4a665005ddbe3b7372ecb87baad726f1535d4600a0198d3a36a17ad673160f8ef5e5fd74f2542b214cc4534ee82b0a90c0501ca9749c8327afcb97e14220f2e516dfc3cb2ed2ffdd3845a25cb64e1a2aa9987bbc122755158d787a2356e28f2affff31b83a2cdff26d5ac1aa72f4d6c40fe96ad230ce09fd4e9b8998357c2964da031e59c3b8c2241da00bc66a6216af7cd02b535577fa3b54bf9a0d230183b03aa145dbabc7fed3710d879c6b8d4273e6e377bed382de985f561ff9b2b3445f29957655600cbd1b29714f52c55ff05bc204203e65bdf6f818e976c690becfed9284b27c2dead96803efad949ffb519b7024530b08b5ed4c8e7472ed20c3866b79658e1b2d2c5b88a60da07614afa4906c73a6e5ad9113282288173e265236fa57d72c97f85c86b43349516f8e2f52f756d43cd2d9cf8c673db404d14007706ebbd4f7b5bbd19cdce9f48b2dac2db7f0f0c3fb18bd8e66e28fe46dafc3961e5945779faf5407190a33ce00efd07222cc142d40cab9b9d591589a30d056dae47d376d3ac5fab3201bbada604dd8e5e292185f38e2bcd58e81b2fec1e7b5754b7b28bd127abc929e950cb75100e94695f1ad13c09c1d394664029b66bdd49304df3ae1e2a90a6309f07c47555ccaea9cd17d80eaad6b7c29e9335a69338446ff666ac5802cfe36057c449d392bda99d2657fb8b6cf02d7ce4d9dccd8e97033accc5c10f092ec7bf0b3c0b2afc64a1a429d81cc485388f6f390dd97f648c3712ee0b93a7e96b268437e6e3537fb7918cee2a4ac3f895c7945988d7d3880238b8cf6062da171aa87545cf62072b20e698eb4ac12450c0b95a77e946fada8d46102abfa9a5a12d2a71380dedb51e2a57c97514813c17ea93e6ca19077c2a2511bf8fd158c4ed7361590b040915a3cb76f323300111303d8dd31c55474d514209bf01ed6639d4d81a1b30be54444e523e2ddef9a0a6bfe792d3037944aec29154c02bb79d09bd53856797dceb6c599f4103ff7f13dfdb8b2d18477832e5fe21","labelMap":{"dataType":"Map","value":[["c14n0","b1"],["c14n1","b2"],["c14n2","b0"]]},"mandatoryIndexes":[0,1,2,5,6,8,9],"adjSelectiveIndexes":[0,1,5,7,10,16],"presentationHeader":{"0":17,"1":51,"2":119,"3":170},"featureOption":"anonymous_holder_binding","lengthBBSMessages":23}

마지막으로 위의 공개 데이터를 다음 절의 알고리즘과 함께 사용하면 3.2.3 serializeDerivedProofValue, 아래에 표시된 서명된 파생 (공개) 문서를 얻습니다.

예제 67: 보유자 바인딩을 위한 서명된 파생 문서
{
  "@context": [
    "https://www.w3.org/2018/credentials/v1",
    "https://w3id.org/security/data-integrity/v2",
    "https://w3id.org/vdl/v1",
    "https://w3id.org/vdl/aamva/v1"
  ],
  "type": [
    "VerifiableCredential",
    "Iso18013DriversLicenseCredential"
  ],
  "issuer": {
    "id": "did:key:z6MkjxvA4FNrQUhr8f7xhdQuP1VPzErkcnfxsRaU5oFgy2E5",
    "name": "Utopia Department of Motor Vehicles",
    "url": "https://dmv.utopia.example/",
    "image": "https://dmv.utopia.example/logo.png"
  },
  "expirationDate": "2028-11-15T12:00:00-06:00",
  "credentialSubject": {
    "type": "LicensedDriver",
    "driversLicense": {
      "type": "Iso18013DriversLicense",
      "issuing_country": "UA",
      "driving_privileges": [
        {
          "codes": [
            {
              "code": "D"
            }
          ],
          "vehicle_category_code": "D",
          "issue_date": "2019-01-01",
          "expiry_date": "2027-01-01"
        },
        {
          "codes": [
            {
              "code": "C"
            }
          ],
          "vehicle_category_code": "C",
          "issue_date": "2019-01-01",
          "expiry_date": "2017-01-01"
        }
      ]
    }
  },
  "proof": {
    "type": "DataIntegrityProof",
    "cryptosuite": "bbs-2023",
    "created": "2023-08-15T23:36:38Z",
    "verificationMethod": "did:key:zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ#zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ",
    "proofPurpose": "assertionMethod",
    "proofValue": "u2V0FhlkDcKGdsFzKEjfZllsLsxl8SWKn-0nJevExyA6i2PlJB4_1ZCrNsz0n0GuX-H_5BqKiO7DD3XeFcriSeF-u_cJYETGLC0biW4hjiYsGAHAaccJW7ppzR6Gld_4uN5OxwDkOTY-f_5FhB07ruoUrzKgInu12QWrJ8Xi4UOdojCbPve40T6ddm6LPIkF-PHC-eJH23gQJKNSmZQBd2-O3Ny7Lh7qtcm8VNdRgCgGY06NqF61nMWD4715f108lQrIUzEU07oKwqQwFAcqXScgyevy5fhQiDy5Rbfw8su0v_dOEWiXLZOGiqpmHu8EidVFY14eiNW4o8q__8xuDos3_JtWsGqcvTWxA_patIwzgn9TpuJmDV8KWTaAx5Zw7jCJB2gC8ZqYhavfNArU1V3-jtUv5oNIwGDsDqhRdurx_7TcQ2HnGuNQnPm43e-04LemF9WH_mys0RfKZV2VWAMvRspcU9SxV_wW8IEID5lvfb4GOl2xpC-z-2ShLJ8LerZaAPvrZSf-1GbcCRTCwi17UyOdHLtIMOGa3lljhstLFuIpg2gdhSvpJBsc6blrZETKCKIFz4mUjb6V9csl_hchrQzSVFvji9S91bUPNLZz4xnPbQE0UAHcG671Pe1u9Gc3On0iy2sLbfw8MP7GL2OZuKP5G2vw5YeWUV3n69UBxkKM84A79ByIswULUDKubnVkViaMNBW2uR9N206xfqzIBu62mBN2OXikhhfOOK81Y6Bsv7B57V1S3sovRJ6vJKelQy3UQDpRpXxrRPAnB05RmQCm2a91JME3zrh4qkKYwnwfEdVXMrqnNF9gOqta3wp6TNaaTOERv9masWALP42BXxEnTkr2pnSZX-4ts8C185NnczY6XAzrMxcEPCS7Hvws8Cyr8ZKGkKdgcxIU4j285Ddl_ZIw3Eu4Lk6fpayaEN-bjU3-3kYzuKkrD-JXHlFmI19OIAji4z2Bi2hcaqHVFz2IHKyDmmOtKwSRQwLlad-lG-tqNRhAqv6mloS0qcTgN7bUeKlfJdRSBPBfqk-bKGQd8KiURv4_RWMTtc2FZCwQJFaPLdvMjMAERMD2N0xxVR01RQgm_Ae1mOdTYGhswvlRETlI-Ld75oKa_55LTA3lErsKRVMArt50JvVOFZ5fc62xZn0ED_38T39uLLRhHeDLl_iGjAAEBAgIAhwABAgUGCAmGAAEFBwoQRBEzd6oX"
  }
}

A.4 자격 증명 바인딩 가명 기능

A.4.1 증명자 Nym 커밋먼트 생성

자격 증명 바인딩 가명 기능을 사용하는 첫 단계는 보유자가 자신의 비밀 prover_nym 값을 생성한 다음 [CFRG-Pseudonym-BBS-Signature]의 "Commitment" 연산에 따라 이 값에 대한 증명이 포함된 커밋먼트를 계산하는 것입니다. 이 절차의 예제 값과 출력은 아래와 같습니다.

예제 68: 증명자 Nym
{
    "proverNymHex": "5e2087638f71057ef108f83923189a71cea1f7c4b4ef69afb473c9a7074ddf49"
}
예제 69: 증명자 Nym 커밋먼트 정보
{
  "secretProverBlind": "2df3cd3d451b21069b72269f9984df449219c41273b19b1a8487d836fbb8baa1",
  "commitmentWithProof": "a80f61f9470cb8ab88644fbef3616eaf5d3b147c4dc1dcad810148a5f2e73186cb3ffa27ea55728a6df470d0c3928be1408b95f5d261cee4d66992ecacf5ca2d6348c33bb7f90c2cef513cdc88be536550e9701d9a466320f49ce097551f8097317c530e2b80710748362b03f5a74280669c00eb29145eb3ec51975d8189fdf2c810d7fadefe36f93b0d2068a494175c"
}

prover_nymsecretProverBlind는 보유자가 보관하고 비밀로 유지해야 합니다. commitmentWithProof 값은 발급자에게 전달해야 합니다.

A.4.2 가명 기본 증명

가명 기능 옵션에 따라 기본 증명을 추가하는 절차는 발급자가 보유자로부터 commitmentWithProof 값을 받고 signer_nym_entropy에 사용할 암호학적 난수 값을 생성하는 것부터 시작합니다.

예제 70: 서명자 Nym 엔트로피
{
    "signerNymEntropyHex": "25555cf635188a1c33989056f5129e6ab4be0e7c5cc588c48d308e0254eed140"
}

이 예제에서는 예제 27에 표시된 것과 동일한 키 자료, 예제 50에 표시된 것과 동일한 서명되지 않은 문서, 그리고 예제 51에 표시된 것과 동일한 필수 포인터를 사용합니다. 그 결과 예제 52와 동일한 정규 문서, 예제 53과 동일한 정규 HMAC 문서, 그리고 예제 54와 동일한 "기본 변환 추가" 결과가 생성됩니다.

이 예제에서는 예제 55와 동일한 증명 구성을 사용합니다. 그 결과 예제 56과 동일한 정규 기본 증명이 생성됩니다. 이를 위의 가정과 결합하면 예제 57과 동일한 기본 해시가 생성됩니다.

featureOption"pseudonym"과 같으므로 3.3.2 기본 증명 직렬화 (bbs-2023) 절의 절차는 아래와 같은 출력을 생성합니다. 여기서는 [CFRG-Pseudonym-BBS-Signature]의 서명 생성 알고리즘을 사용합니다. signer_nym_entropyfeatureOption 값이 포함되어 있다는 점에 유의하십시오. 이 값들은 보유자에게 전달해야 합니다.

예제 71: 가명을 위한 기본 서명 추가
{
  "bbsSignature": "b9389149bab1b5a6032c20781732105a5cbc209592e712e182eec5c055f2072877683dee2949af32290d350ed9e9ffa246f65b8c3f6f199c4d29009d2ce6dff374ed4f22f2f9a7e12dc3c342e8c18107",
  "bbsHeader": "3a5bbf25d34d90b18c35cd2357be6a6f42301e94fc9e52f77e93b773c5614bdf8eea112c04d89e133880f96766ebae73693f75f1bbcbbaa473dc06254bdec4fb",
  "publicKey": "a4ef1afa3da575496f122b9b78b8c24761531a8a093206ae7c45b80759c168ba4f7a260f9c3367b6c019b4677841104b10665edbe70ba3ebe7d9cfbffbf71eb016f70abfbb163317f372697dc63efd21fc55764f63926a8f02eaea325a2a888f",
  "hmacKey": "00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff",
  "mandatoryPointers": [
    "/issuer",
    "/expirationDate"
  ],
  "signerNymEntropyHex": "25555cf635188a1c33989056f5129e6ab4be0e7c5cc588c48d308e0254eed140",
  "featureOption": "pseudonym"
}

마지막으로 위의 값들을 3.2.1 serializeBaseProofValue 절의 알고리즘에 적용하여 아래에 표시된 서명된 기본 문서에서 사용되는 proofValue를 생성합니다.

예제 72: 가명을 위한 서명된 기본 문서
{
  "@context": [
    "https://www.w3.org/2018/credentials/v1",
    "https://w3id.org/security/data-integrity/v2",
    "https://w3id.org/vdl/v1",
    "https://w3id.org/vdl/aamva/v1"
  ],
  "type": [
    "VerifiableCredential",
    "Iso18013DriversLicenseCredential"
  ],
  "issuer": {
    "id": "did:key:z6MkjxvA4FNrQUhr8f7xhdQuP1VPzErkcnfxsRaU5oFgy2E5",
    "name": "Utopia Department of Motor Vehicles",
    "url": "https://dmv.utopia.example/",
    "image": "https://dmv.utopia.example/logo.png"
  },
  "issuanceDate": "2023-11-15T10:00:00-07:00",
  "expirationDate": "2028-11-15T12:00:00-06:00",
  "name": "Utopia Driver's License",
  "image": "data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUg...kSuQmCC",
  "description": "A license granting driving privileges in Utopia.",
  "credentialSubject": {
    "type": "LicensedDriver",
    "driversLicense": {
      "type": "Iso18013DriversLicense",
      "document_number": "542426814",
      "family_name": "TURNER",
      "given_name": "SUSAN",
      "portrait": "data:image/jpeg;base64,/9j/4AAQSkZJR...RSClooooP/2Q==",
      "birth_date": "1998-08-28",
      "issue_date": "2023-01-15T10:00:00-07:00",
      "expiry_date": "2028-08-27T12:00:00-06:00",
      "issuing_country": "UA",
      "issuing_authority": "UADMV",
      "driving_privileges": [
        {
          "codes": [
            {
              "code": "D"
            }
          ],
          "vehicle_category_code": "D",
          "issue_date": "2019-01-01",
          "expiry_date": "2027-01-01"
        },
        {
          "codes": [
            {
              "code": "C"
            }
          ],
          "vehicle_category_code": "C",
          "issue_date": "2019-01-01",
          "expiry_date": "2017-01-01"
        }
      ],
      "un_distinguishing_sign": "UTA",
      "aamva_aka_suffix": "1ST",
      "sex": 2,
      "aamva_family_name_truncation": "N",
      "aamva_given_name_truncation": "N"
    }
  },
  "proof": {
    "type": "DataIntegrityProof",
    "cryptosuite": "bbs-2023",
    "created": "2023-08-15T23:36:38Z",
    "verificationMethod": "did:key:zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ#zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ",
    "proofPurpose": "assertionMethod",
    "proofValue": "u2V0IhlhQuTiRSbqxtaYDLCB4FzIQWly8IJWS5xLhgu7FwFXyByh3aD3uKUmvMikNNQ7Z6f-iRvZbjD9vGZxNKQCdLObf83TtTyLy-afhLcPDQujBgQdYQDpbvyXTTZCxjDXNI1e-am9CMB6U_J5S936Tt3PFYUvfjuoRLATYnhM4gPlnZuuuc2k_dfG7y7qkc9wGJUvexPtYYKTvGvo9pXVJbxIrm3i4wkdhUxqKCTIGrnxFuAdZwWi6T3omD5wzZ7bAGbRneEEQSxBmXtvnC6Pr59nPv_v3HrAW9wq_uxYzF_NyaX3GPv0h_FV2T2OSao8C6uoyWiqIj1ggABEiM0RVZneImaq7zN3u_wARIjNEVWZ3iJmqu8zd7v-CZy9pc3N1ZXJvL2V4cGlyYXRpb25EYXRlwlggJVVc9jUYihwzmJBW9RKearS-DnxcxYjEjTCOAlTu0UA"
  }
}

A.4.3 가명 파생 증명

A.1.2 파생 증명 절에서 설명했듯이 presentationHeader의 사용을 보여주기 위해 모의 난수 생성 절차를 사용했습니다. 예제 19에 제시된 것과 동일한 seedpresentationHeader를 여기에서 사용합니다.

파생 증명을 생성하려면 보유자는 기본 증명을 포함하는 서명된 문서에서 시작합니다. 이 테스트 벡터에 사용할 기본 문서는 위 예제 72에서 가져옵니다. 첫 번째 단계는 3.2.2 parseBaseProofValue 절의 알고리즘을 실행하여 아래와 같이 bbsSignature, bbsHeader, publicKey, hmacKey, mandatoryPointers, signer_nym_entropyfeatureOption을 복구하는 것입니다.

예제 73: 가명을 위해 복구된 기본 서명 데이터
{
  "bbsSignature": "b9389149bab1b5a6032c20781732105a5cbc209592e712e182eec5c055f2072877683dee2949af32290d350ed9e9ffa246f65b8c3f6f199c4d29009d2ce6dff374ed4f22f2f9a7e12dc3c342e8c18107",
  "bbsHeader": "3a5bbf25d34d90b18c35cd2357be6a6f42301e94fc9e52f77e93b773c5614bdf8eea112c04d89e133880f96766ebae73693f75f1bbcbbaa473dc06254bdec4fb",
  "publicKey": "a4ef1afa3da575496f122b9b78b8c24761531a8a093206ae7c45b80759c168ba4f7a260f9c3367b6c019b4677841104b10665edbe70ba3ebe7d9cfbffbf71eb016f70abfbb163317f372697dc63efd21fc55764f63926a8f02eaea325a2a888f",
  "hmacKey": "00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff",
  "mandatoryPointers": [
    "/issuer",
    "/expirationDate"
  ],
  "signerNymEntropy": "25555cf635188a1c33989056f5129e6ab4be0e7c5cc588c48d308e0254eed140",
  "featureOption": "pseudonym"
}

다음으로 보유자는 [CFRG-Pseudonym-BBS-Signature]의 "Verification and Finalization" 연산을 사용하여 서명을 검증하는 동시에 nym_secret 값을 계산합니다. 이 연산은 다른 값들과 함께 prover_nym, signer_nym_entropysecret_prover_blind 값을 사용합니다.

예제 74: 계산된 Nym 비밀 값
{
    "nymSecretHex": "f883d069aec1252f167b0880e8960d72fa2623e11b6967541a457aa5c3cb088"
}

다음으로 보유자는 선택적 공개를 위한 JSON 포인터를 지정하여 검증자에게 공개하려는 비필수 문장이 있다면 무엇인지 나타내야 합니다. 이 경우 보유자는 예제 62에 제시된 것과 동일한 정보를 공개합니다. 그 결과 예제 63에 표시된 것과 동일한 revealDocument가 생성됩니다.

§ 4.4.3 CreateDisclosureData를 실행하면 예제 64에 표시된 것과 동일한 파생 그룹 인덱스 정보와 예제 65에 표시된 것과 동일한 조정된 필수 및 선택적 인덱스를 얻습니다.

3.2.3 serializeDerivedProofValue 내에서, 에 표시된 것과 동일한 verfifier_id를 기반으로 pseudonym을 계산합니다. § 4.4.3 CreateDisclosureData의 최종 출력은 아래에 표시되어 있습니다. featureOption과 계산된 pseudonym 값이 포함되어 있다는 점에 유의하십시오.

예제 75: 가명을 위한 공개 데이터
{
    "bbsProof":"b394693d54d67937aae0e4175ecf4331200c23470171188ac5513b30d27d9bd2e06173d44e1aca7c743ba30b3f59af0595965bf8256437bce6bef824fe243183af6aa14a1e8224ed7e4eeb16445594df13a46e75d8dfbae0a3e2e1e0871260e68f71de7be4309eb53523a446b8189446b8d5c60892bdd855b5067e0433b46d5b9ffc4dc54b712ff97ec9d7c44cff648929d826bf9e3a7f873c9bcd07c6a3747fc6befceaf892c4d8d38d385c19c399ab342a76c000a3ff9050fa9223e20acfdf4404f43605a24c44622ebcaaf144b161226a6cbe7c08474f9fb80a736be3a818e4e62aa738e701007871859bea36e062324ff3afd8670a5de8b69911fae58aa40e48e29a046c37b9f9cc3868c30482d2339746955c3deaf6f1d4c8cf8be8e503f3ea4715d11e385eb7ed9de6379b7de8436a4e89cf4427d53358b1882e27c6e1e3ba2e81cf10fbc792cf3461a0fdd63f35a151b8c8350505a9b6d612e9adc1dca11b2698a3d0a9f0df6e9bc0ece7aa462afab02d93a87fd5bebb0eee058770c81c5f2fe6eeefcb0a657d9f116b96e2b04b4cc7f4baad4fe784bd9563aea20272138f2dbe94a5e25d30633b5f83eac4b42af25f144bddb631738bf3d54206e8d8b5172c8d52d3c272f799b782c73d480e1289e262ddbb70ab29491cf85a8428c4672437677407524a6dacb53332565dab5d056dbc5451becb123f91d173f6a7c785b7d9f19c43864a785bd941db248322539a097e9ac06244308a3b8df88b5213724cf09715b09e06425448c400680b943ba4711f14a719920b06ec2c6aff908ecf4f5793afd233d270a5ef92131606035517a89e4118dc65dbeb9051f92797036f54f8400910fa56cdd7b87b122e39e41233ea493239fab55c4c836a0a38732a68e6a9f9e11d32b991599e19edbb386f0d364b91e10dd9bf82898f79e90045a0c4987a0cf365d37d8380539a794284841c50c83f2bc3ee9cf7432f44dbfca897ff99feabf224e51137313630c5000d39429d9ea69a2a8237fe3a1857121c14ebb00d57b90db39e2e11bfa37858187d183027c45e317a72e5334681de26788e3176bd48d5761d54c1f2af0a6c3549a0de05b21d0a066c732a540072ae7676b867027b18323e08fcbfaf38ec22aeccd3375bb7b6965d9f6ab3ac4adc2a0700a4bc82fe58afbdd035af48fb85fcd8bf14f81d5ca3f2626be8962cbea13da31ff3cc6c6ebfeeef42f25708af872a14019f83",
    "labelMap":{"dataType":"Map","value":[["c14n0","b1"],["c14n1","b2"],["c14n2","b0"]]},
    "mandatoryIndexes":[0,1,2,5,6,8,9],
    "adjSelectiveIndexes":[0,1,5,7,10,16],
    "presentationHeader":{"0":17,"1":51,"2":119,"3":170},
    "pseudonym":"838607ff2c8dcb2a0740ef13c2c87418efb57559243232a69daf1e294dd092af833ad4df1e99e0034c737b932916f378",
    "featureOption":"pseudonym",
    "lengthBBSMessages":23
}

마지막으로 위의 공개 데이터를 다음 절의 알고리즘과 함께 사용하면 3.2.3 serializeDerivedProofValue, 아래에 표시된 서명된 파생(공개) 문서를 얻습니다.

예제 76: 가명을 위한 서명된 파생 문서
{
  "@context": [
    "https://www.w3.org/2018/credentials/v1",
    "https://w3id.org/security/data-integrity/v2",
    "https://w3id.org/vdl/v1",
    "https://w3id.org/vdl/aamva/v1"
  ],
  "type": [
    "VerifiableCredential",
    "Iso18013DriversLicenseCredential"
  ],
  "issuer": {
    "id": "did:key:z6MkjxvA4FNrQUhr8f7xhdQuP1VPzErkcnfxsRaU5oFgy2E5",
    "name": "Utopia Department of Motor Vehicles",
    "url": "https://dmv.utopia.example/",
    "image": "https://dmv.utopia.example/logo.png"
  },
  "expirationDate": "2028-11-15T12:00:00-06:00",
  "credentialSubject": {
    "type": "LicensedDriver",
    "driversLicense": {
      "type": "Iso18013DriversLicense",
      "issuing_country": "UA",
      "driving_privileges": [
        {
          "codes": [
            {
              "code": "D"
            }
          ],
          "vehicle_category_code": "D",
          "issue_date": "2019-01-01",
          "expiry_date": "2027-01-01"
        },
        {
          "codes": [
            {
              "code": "C"
            }
          ],
          "vehicle_category_code": "C",
          "issue_date": "2019-01-01",
          "expiry_date": "2017-01-01"
        }
      ]
    }
  },
  "proof": {
    "type": "DataIntegrityProof",
    "cryptosuite": "bbs-2023",
    "created": "2023-08-15T23:36:38Z",
    "verificationMethod": "did:key:zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ#zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ",
    "proofPurpose": "assertionMethod",
    "proofValue": "u2V0Jh1kDcLOUaT1U1nk3quDkF17PQzEgDCNHAXEYisVROzDSfZvS4GFz1E4aynx0O6MLP1mvBZWWW_glZDe85r74JP4kMYOvaqFKHoIk7X5O6xZEVZTfE6RuddjfuuCj4uHghxJg5o9x3nvkMJ61NSOkRrgYlEa41cYIkr3YVbUGfgQztG1bn_xNxUtxL_l-ydfETP9kiSnYJr-eOn-HPJvNB8ajdH_Gvvzq-JLE2NONOFwZw5mrNCp2wACj_5BQ-pIj4grP30QE9DYFokxEYi68qvFEsWEiamy-fAhHT5-4CnNr46gY5OYqpzjnAQB4cYWb6jbgYjJP86_YZwpd6LaZEfrliqQOSOKaBGw3ufnMOGjDBILSM5dGlVw96vbx1MjPi-jlA_PqRxXRHjhet-2d5jebfehDak6Jz0Qn1TNYsYguJ8bh47ougc8Q-8eSzzRhoP3WPzWhUbjINQUFqbbWEumtwdyhGyaYo9Cp8N9um8Ds56pGKvqwLZOof9W-uw7uBYdwyBxfL-bu78sKZX2fEWuW4rBLTMf0uq1P54S9lWOuogJyE48tvpSl4l0wYztfg-rEtCryXxRL3bYxc4vz1UIG6Ni1FyyNUtPCcveZt4LHPUgOEoniYt27cKspSRz4WoQoxGckN2d0B1JKbay1MzJWXatdBW28VFG-yxI_kdFz9qfHhbfZ8ZxDhkp4W9lB2ySDIlOaCX6awGJEMIo7jfiLUhNyTPCXFbCeBkJUSMQAaAuUO6RxHxSnGZILBuwsav-Qjs9PV5Ov0jPScKXvkhMWBgNVF6ieQRjcZdvrkFH5J5cDb1T4QAkQ-lbN17h7Ei455BIz6kkyOfq1XEyDago4cypo5qn54R0yuZFZnhntuzhvDTZLkeEN2b-CiY956QBFoMSYegzzZdN9g4BTmnlChIQcUMg_K8PunPdDL0Tb_KiX_5n-q_Ik5RE3MTYwxQANOUKdnqaaKoI3_joYVxIcFOuwDVe5DbOeLhG_o3hYGH0YMCfEXjF6cuUzRoHeJniOMXa9SNV2HVTB8q8KbDVJoN4Fsh0KBmxzKlQAcq52drhnAnsYMj4I_L-vOOwirszTN1u3tpZdn2qzrErcKgcApLyC_livvdA1r0j7hfzYvxT4HVyj8mJr6JYsvqE9ox_zzGxuv-7vQvJXCK-HKhQBn4OjAAEBAgIAhwABAgUGCAmGAAEFBwoQRBEzd6pYMIOGB_8sjcsqB0DvE8LIdBjvtXVZJDIypp2vHilN0JKvgzrU3x6Z4ANMc3uTKRbzeBc"
  }
}

A.5 보유자 바인딩 및 가명 기능

A.5.1 보유자 비밀 값 및 증명자 Nym 커밋먼트 생성

보유자 바인딩 및 가명 기능을 사용하는 첫 단계는 보유자가 자신의 holder_secretprover_nym 값을 생성한 다음 [CFRG-Pseudonym-BBS-Signature]의 "Commitment" 연산에 따라 이러한 값에 대한 증명이 포함된 커밋먼트를 계산하는 것입니다. 이 절차의 예제 값과 출력은 아래와 같습니다.

예제 77: 보유자의 비밀 값
{
    "holderSecretHex": "8fc6cc3f65db4ba5e3ed63fe9d2bd57a9c7df9c7f6bf2b898b308d5493b07eb6"
}
예제 78: 증명자 Nym
{
    "proverNymHex": "5e2087638f71057ef108f83923189a71cea1f7c4b4ef69afb473c9a7074ddf49"
}
예제 79: 보유자 비밀 값 및 증명자 Nym 커밋먼트 정보
{
  "secretProverBlind": "0d215067232c77c94a7572eb80794592090da8aff35cca53d2d528d059e70fce",
  "commitmentWithProof": "ab72f3e6d7a4185d100ede6ce7dde1c69db9a2128ad11d1b6991a018c340ca2672d7be636f153398be50f44ee434edf14322dd115f7527e770a0f0c41d8aeb2088d004f2703548db6ce15e2505368a1f686f20702aa9ff46bce301330ea0c4c16ef4d8bbf624064a60df3a563142d7b236cad6cf6bcf1f3694d0bf4c2b5ffce55bb26abc05e31f9aaf8b60674fefe02666f89c150c479694f4a89a9088b28a1e6e2cf0c2caaa01810d2e3a52853f3a2a"
}

holder_secret, prover_nymsecretProverBlind는 보유자가 보관하고 비밀로 유지해야 합니다. commitmentWithProof 값은 발급자에게 전달해야 합니다.

A.5.2 보유자 바인딩 및 가명 기본 증명

가명 기능 옵션에 따라 기본 증명을 추가하는 절차는 발급자가 보유자로부터 commitmentWithProof 값을 받고 signer_nym_entropy에 사용할 암호학적 난수 값을 생성하는 것부터 시작합니다.

예제 80: 서명자 Nym 엔트로피
{
    "signerNymEntropyHex": "25555cf635188a1c33989056f5129e6ab4be0e7c5cc588c48d308e0254eed140"
}

이 예제에서는 예제 27에 표시된 것과 동일한 키 자료, 예제 50에 표시된 것과 동일한 서명되지 않은 문서 및 예제 51에 표시된 것과 동일한 필수 포인터를 사용합니다. 그 결과 예제 52에 표시된 것과 동일한 정규 문서, 예제 53에 표시된 것과 동일한 정규 HMAC 문서, 그리고 예제 54에 표시된 것과 동일한 "기본 변환 추가" 결과가 생성됩니다.

이 예제에서는 예제 55와 동일한 증명 구성을 사용합니다. 그 결과 예제 56과 동일한 정규 기본 증명이 생성됩니다. 이를 위의 가정과 결합하면 예제 57과 동일한 기본 해시가 생성됩니다.

featureOption"holder_binding_pseudonym"과 같으므로 3.3.2 기본 증명 직렬화 (bbs-2023) 절의 절차는 아래와 같은 출력을 생성합니다. 여기서는 [CFRG-Pseudonym-BBS-Signature]의 서명 생성 알고리즘을 사용합니다. signer_nym_entropyfeatureOption 값이 포함되어 있다는 점에 유의하십시오. 이 값들은 보유자에게 전달해야 합니다.

예제 81: 보유자 바인딩 및 가명을 위한 기본 서명 추가
{
  "bbsSignature": "9251f497cb002c19f959a760fa24c5e961df9cb8ff5fbaaef14f2b7f1f41649990c30bd8c1d373e878a5d120123d658a326141275eee7833352d611cc1c05175c9c0f0ddeb0fdec09ad1bfad8796e410",
  "bbsHeader": "3a5bbf25d34d90b18c35cd2357be6a6f42301e94fc9e52f77e93b773c5614bdf8eea112c04d89e133880f96766ebae73693f75f1bbcbbaa473dc06254bdec4fb",
  "publicKey": "a4ef1afa3da575496f122b9b78b8c24761531a8a093206ae7c45b80759c168ba4f7a260f9c3367b6c019b4677841104b10665edbe70ba3ebe7d9cfbffbf71eb016f70abfbb163317f372697dc63efd21fc55764f63926a8f02eaea325a2a888f",
  "hmacKey": "00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff",
  "mandatoryPointers": [
    "/issuer",
    "/expirationDate"
  ],
  "signerNymEntropyHex": "25555cf635188a1c33989056f5129e6ab4be0e7c5cc588c48d308e0254eed140",
  "featureOption": "holder_binding_pseudonym"
}

마지막으로 위의 값들을 3.2.1 serializeBaseProofValue 절의 알고리즘에 적용하여, 아래에 표시된 서명된 기본 문서에서 사용되는 proofValue를 생성합니다.

예제 82: 보유자 바인딩 및 가명을 위한 서명된 기본 문서
{
  "@context": [
    "https://www.w3.org/2018/credentials/v1",
    "https://w3id.org/security/data-integrity/v2",
    "https://w3id.org/vdl/v1",
    "https://w3id.org/vdl/aamva/v1"
  ],
  "type": [
    "VerifiableCredential",
    "Iso18013DriversLicenseCredential"
  ],
  "issuer": {
    "id": "did:key:z6MkjxvA4FNrQUhr8f7xhdQuP1VPzErkcnfxsRaU5oFgy2E5",
    "name": "유토피아 자동차 관리국",
    "url": "https://dmv.utopia.example/",
    "image": "https://dmv.utopia.example/logo.png"
  },
  "issuanceDate": "2023-11-15T10:00:00-07:00",
  "expirationDate": "2028-11-15T12:00:00-06:00",
  "name": "유토피아 운전면허증",
  "image": "data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUg...kSuQmCC",
  "description": "유토피아에서 운전 권한을 부여하는 면허증입니다.",
  "credentialSubject": {
    "type": "LicensedDriver",
    "driversLicense": {
      "type": "Iso18013DriversLicense",
      "document_number": "542426814",
      "family_name": "TURNER",
      "given_name": "SUSAN",
      "portrait": "data:image/jpeg;base64,/9j/4AAQSkZJR...RSClooooP/2Q==",
      "birth_date": "1998-08-28",
      "issue_date": "2023-01-15T10:00:00-07:00",
      "expiry_date": "2028-08-27T12:00:00-06:00",
      "issuing_country": "UA",
      "issuing_authority": "UADMV",
      "driving_privileges": [
        {
          "codes": [
            {
              "code": "D"
            }
          ],
          "vehicle_category_code": "D",
          "issue_date": "2019-01-01",
          "expiry_date": "2027-01-01"
        },
        {
          "codes": [
            {
              "code": "C"
            }
          ],
          "vehicle_category_code": "C",
          "issue_date": "2019-01-01",
          "expiry_date": "2017-01-01"
        }
      ],
      "un_distinguishing_sign": "UTA",
      "aamva_aka_suffix": "1ST",
      "sex": 2,
      "aamva_family_name_truncation": "N",
      "aamva_given_name_truncation": "N"
    }
  },
  "proof": {
    "type": "DataIntegrityProof",
    "cryptosuite": "bbs-2023",
    "created": "2023-08-15T23:36:38Z",
    "verificationMethod": "did:key:zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ#zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ",
    "proofPurpose": "assertionMethod",
    "proofValue": "u2V0IhlhQklH0l8sALBn5Wadg-iTF6WHfnLj_X7qu8U8rfx9BZJmQwwvYwdNz6Hil0SASPWWKMmFBJ17ueDM1LWEcwcBRdcnA8N3rD97AmtG_rYeW5BBYQDpbvyXTTZCxjDXNI1e-am9CMB6U_J5S936Tt3PFYUvfjuoRLATYnhM4gPlnZuuuc2k_dfG7y7qkc9wGJUvexPtYYKTvGvo9pXVJbxIrm3i4wkdhUxqKCTIGrnxFuAdZwWi6T3omD5wzZ7bAGbRneEEQSxBmXtvnC6Pr59nPv_v3HrAW9wq_uxYzF_NyaX3GPv0h_FV2T2OSao8C6uoyWiqIj1ggABEiM0RVZneImaq7zN3u_wARIjNEVWZ3iJmqu8zd7v-CZy9pc3N1ZXJvL2V4cGlyYXRpb25EYXRlwlggJVVc9jUYihwzmJBW9RKearS-DnxcxYjEjTCOAlTu0UA"
  }
}

A.5.3 보유자 바인딩 및 가명 파생 증명

A.1.2 파생 증명 절에서 설명했듯이, 모의 난수 생성 절차를 사용하고 presentationHeader의 사용을 보여줍니다. 예제 19에 제시된 것과 동일한 seedpresentationHeader를 여기에서 사용합니다.

파생 증명을 생성하려면 보유자는 기본 증명을 포함하는 서명된 문서에서 시작합니다. 이 테스트 벡터에 사용할 기본 문서는 위 예제 72에서 가져옵니다. 첫 번째 단계는 3.2.2 parseBaseProofValue 절의 알고리즘을 실행하여 아래와 같이 bbsSignature, bbsHeader, publicKey, hmacKey, mandatoryPointers, signer_nym_entropyfeatureOption을 복구하는 것입니다.

예제 83: 보유자 바인딩 및 가명을 위해 복구된 기본 서명 데이터
{
  "bbsSignature": "9251f497cb002c19f959a760fa24c5e961df9cb8ff5fbaaef14f2b7f1f41649990c30bd8c1d373e878a5d120123d658a326141275eee7833352d611cc1c05175c9c0f0ddeb0fdec09ad1bfad8796e410",
  "bbsHeader": "3a5bbf25d34d90b18c35cd2357be6a6f42301e94fc9e52f77e93b773c5614bdf8eea112c04d89e133880f96766ebae73693f75f1bbcbbaa473dc06254bdec4fb",
  "publicKey": "a4ef1afa3da575496f122b9b78b8c24761531a8a093206ae7c45b80759c168ba4f7a260f9c3367b6c019b4677841104b10665edbe70ba3ebe7d9cfbffbf71eb016f70abfbb163317f372697dc63efd21fc55764f63926a8f02eaea325a2a888f",
  "hmacKey": "00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff",
  "mandatoryPointers": [
    "/issuer",
    "/expirationDate"
  ],
  "signerNymEntropy": "25555cf635188a1c33989056f5129e6ab4be0e7c5cc588c48d308e0254eed140",
  "featureOption": "holder_binding_pseudonym"
}

다음으로 보유자는 [CFRG-Pseudonym-BBS-Signature]의 "Verification and Finalization" 연산을 사용하여 서명을 검증하는 동시에 nym_secret 값을 계산합니다. 이 연산은 다른 값들과 함께 holder_secret, prover_nym, signer_nym_entropysecret_prover_blind 값을 사용합니다.

예제 84: 계산된 Nym 비밀 값
{"nymSecretHex":"f883d069aec1252f167b0880e8960d72fa2623e11b6967541a457aa5c3cb088"}

다음으로 보유자는 선택적 공개를 위한 JSON 포인터를 지정하여 검증자에게 공개하려는 비필수 문장이 있다면 무엇인지 나타내야 합니다. 이 경우 보유자는 예제 62에 제시된 것과 동일한 정보를 공개합니다. 그 결과 예제 63에 표시된 것과 동일한 revealDocument가 생성됩니다.

§ 4.4.3 CreateDisclosureData를 실행하면 예제 64에 표시된 것과 동일한 파생 그룹 인덱스 정보와 예제 65에 표시된 것과 동일한 조정된 필수 및 선택적 인덱스를 얻습니다.

3.2.3 serializeDerivedProofValue 내에서, 에 표시된 것과 동일한 verfifier_id를 기반으로 pseudonym을 계산합니다. 3.2.3 serializeDerivedProofValue의 최종 출력은 아래에 표시되어 있습니다. featureOption과 계산된 pseudonym 값이 포함되어 있다는 점에 유의하십시오.

예제 85: 보유자 바인딩 및 가명을 위한 공개 데이터
{
  "bbsProof":"94752c678297191b42617aca412377d4a5b3d7872779ffea31e0b418f50e95056d923a97e8dc156edc2a3a3a54e7b27cafa26a989fc3e8a8bc7a08b84e706a1863bd06c396b973b1af0da4f6c20ea463e124d2ad97060a25ccc3ff695c71977ba2e83a6468205d9e0bfb756089ad40dededab480eeb13cf00265f49824c5f89e23ac48d07fa3164823741df5c066bdc31a231a7d4fecb75c912adb800b1efe8da3cd26805ffa56775b1c32da34e36e9716a4da909fa6803ca0aa2df2d82f697229ccb210503274d4d61c7386a44e9fb459c020fbcd62c7f437da8ffd5ea7e56d2c4e7d9c3f593b2a964346f24f71bec30a2c3ededa0bd3707e2e06cac2dddb66762135a229dc09b67fa61d690d33be78150bc60f3655ac1063f96d6fe95a260004c7bf9e924cc7439c6426f951d0cee963985557097788d2387b72c9aeb390f9a4fa4b519bc11ca81dfca8a4fd3c77805e1a0ef5c165b16c3cdc564e7a5593f0ddd0560f3514393c1b305d3950c29fbb72cc8b58979843cec768e9a77b14f70704771f877c49fc0d0d4ffbe3f0aaf8e472a83b14e32e46207d5012e79b9bcfc6197c858eb18ad97f589dddb5dc45e9ef65f482d3c07fbcbfef92bf293643539fffc94a8bc98b3b4dd3335bb8b248aa606a751330516f148211d5f2d513e02d45ec5a51add1f878948a673a0349d7cb4417b1f9c16945e1f607bdecf6ca3b96a64fb14ee1fc5dbecf751be23041df32842367285f2b3b02c13512c28c0e7671874699b9ff169e35f91debc796fd487d3e41dcc5f12949558f2705be3e8195d4c93a6c149dcb5f63e62d3ce0bf51034021251b74ed2a1186fd77741ce3bf51f57f19a9d4a9e6315a88024062269a9fec426a73199882113168573da451ca38aeacf28f7eef3892181f0bc511562fba00d035f608c4f85579fc9614618763fa4e6c2210184e12f83e1c22078dd4ca488de41dbf2c146a2e0c47137be7f006c6810f44746a819229349b50ca59a51f7c51bb62cacc1a1cc4a6f089680514d41800da57470ef275f390eb4a08db78789e71bd32bd8929961c9f79d1ca071a2608a393f162c2f644584473f11b41cc35c838f11fbd2adf47051829d378ac9dc151e64bc70cd21b2ea6bca3f77b9c2b35abcebb0ecbf1c09365a8e372a2fce74b97088c9e9505c5c0272a4d6959bec54911a99b6c8a1654395f0cd4e7d38d695ab45875ecc535439dde3fb3d4658d9ff9427d8e36d7bd19ea53fb875c4b138f6ffc06bfd496b1a744a63283ebc0fa34ea828d98",
  "labelMap":{"dataType":"Map","value":[["c14n0","b1"],["c14n1","b2"],["c14n2","b0"]]},
  "mandatoryIndexes":[0,1,2,5,6,8,9],"adjSelectiveIndexes":[0,1,5,7,10,16],
  "presentationHeader":{"0":17,"1":51,"2":119,"3":170},
  "pseudonym":"838607ff2c8dcb2a0740ef13c2c87418efb57559243232a69daf1e294dd092af833ad4df1e99e0034c737b932916f378",
  "featureOption":"holder_binding_pseudonym",
  "lengthBBSMessages":23
}

마지막으로 위의 공개 데이터를 다음 절의 알고리즘과 함께 사용하면 3.2.3 serializeDerivedProofValue, 아래에 표시된 서명된 파생(공개) 문서를 얻습니다.

예제 86: 보유자 바인딩 및 가명을 위한 서명된 파생 문서
{
  "@context": [
    "https://www.w3.org/2018/credentials/v1",
    "https://w3id.org/security/data-integrity/v2",
    "https://w3id.org/vdl/v1",
    "https://w3id.org/vdl/aamva/v1"
  ],
  "type": [
    "VerifiableCredential",
    "Iso18013DriversLicenseCredential"
  ],
  "issuer": {
    "id": "did:key:z6MkjxvA4FNrQUhr8f7xhdQuP1VPzErkcnfxsRaU5oFgy2E5",
    "name": "유토피아 자동차 관리국",
    "url": "https://dmv.utopia.example/",
    "image": "https://dmv.utopia.example/logo.png"
  },
  "expirationDate": "2028-11-15T12:00:00-06:00",
  "credentialSubject": {
    "type": "LicensedDriver",
    "driversLicense": {
      "type": "Iso18013DriversLicense",
      "issuing_country": "UA",
      "driving_privileges": [
        {
          "codes": [
            {
              "code": "D"
            }
          ],
          "vehicle_category_code": "D",
          "issue_date": "2019-01-01",
          "expiry_date": "2027-01-01"
        },
        {
          "codes": [
            {
              "code": "C"
            }
          ],
          "vehicle_category_code": "C",
          "issue_date": "2019-01-01",
          "expiry_date": "2017-01-01"
        }
      ]
    }
  },
  "proof": {
    "type": "DataIntegrityProof",
    "cryptosuite": "bbs-2023",
    "created": "2023-08-15T23:36:38Z",
    "verificationMethod": "did:key:zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ#zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ",
    "proofPurpose": "assertionMethod",
    "proofValue": "u2V0Jh1kDkJR1LGeClxkbQmF6ykEjd9Sls9eHJ3n_6jHgtBj1DpUFbZI6l-jcFW7cKjo6VOeyfK-iapifw-iovHoIuE5wahhjvQbDlrlzsa8NpPbCDqRj4STSrZcGCiXMw_9pXHGXe6LoOmRoIF2eC_t1YImtQN7e2rSA7rE88AJl9JgkxfieI6xI0H-jFkgjdB31wGa9wxojGn1P7LdckSrbgAse_o2jzSaAX_pWd1scMto0426XFqTakJ-mgDygqi3y2C9pcinMshBQMnTU1hxzhqROn7RZwCD7zWLH9Dfaj_1ep-VtLE59nD9ZOyqWQ0byT3G-wwosPt7aC9Nwfi4GysLd22Z2ITWiKdwJtn-mHWkNM754FQvGDzZVrBBj-W1v6VomAATHv56STMdDnGQm-VHQzuljmFVXCXeI0jh7csmus5D5pPpLUZvBHKgd_Kik_Tx3gF4aDvXBZbFsPNxWTnpVk_Dd0FYPNRQ5PBswXTlQwp-7csyLWJeYQ87HaOmnexT3BwR3H4d8SfwNDU_74_Cq-ORyqDsU4y5GIH1QEuebm8_GGXyFjrGK2X9Ynd213EXp72X0gtPAf7y_75K_KTZDU5__yUqLyYs7TdMzW7iySKpganUTMFFvFIIR1fLVE-AtRexaUa3R-HiUimc6A0nXy0QXsfnBaUXh9ge97PbKO5amT7FO4fxdvs91G-IwQd8yhCNnKF8rOwLBNRLCjA52cYdGmbn_Fp41-R3rx5b9SH0-QdzF8SlJVY8nBb4-gZXUyTpsFJ3LX2PmLTzgv1EDQCElG3TtKhGG_Xd0HOO_UfV_GanUqeYxWogCQGImmp_sQmpzGZiCETFoVz2kUco4rqzyj37vOJIYHwvFEVYvugDQNfYIxPhVefyWFGGHY_pObCIQGE4S-D4cIgeN1MpIjeQdvywUai4MRxN75_AGxoEPRHRqgZIpNJtQylmlH3xRu2LKzBocxKbwiWgFFNQYANpXRw7ydfOQ60oI23h4nnG9Mr2JKZYcn3nRygcaJgijk_FiwvZEWERz8RtBzDXIOPEfvSrfRwUYKdN4rJ3BUeZLxwzSGy6mvKP3e5wrNavOuw7L8cCTZajjcqL850uXCIyelQXFwCcqTWlZvsVJEambbIoWVDlfDNTn041pWrRYdezFNUOd3j-z1GWNn_lCfY42170Z6lP7h1xLE49v_Aa_1Jaxp0SmMoPrwPo06oKNmKMAAQECAgCHAAECBQYICYYAAQUHChBEETN3qlgwg4YH_yyNyyoHQO8Twsh0GO-1dVkkMjKmna8eKU3Qkq-DOtTfHpngA0xze5MpFvN4Fw"
  }
}

B. 감사의 말

이 절은 비규범적입니다.

이 명세에 관한 작업은 Christopher Allen, Shannon Appelcline, Kiara Robles, Brian Weller, Betty Dhamers, Kaliya Young, Manu Sporny, Drummond Reed, Joe Andrieu, Heather Vescent, Kim Hamilton Duffy, Samantha Chase, Andrew Hughes, Erica Connell, Shigeya Suzuki 및 Zaïda Rivai가 지원한 Rebooting the Web of Trust 커뮤니티의 도움을 받았습니다. Phil Windley, Kaliya Young, Doc Searls 및 Heidi Nobantu Saul이 지원한 Internet Identity Workshop의 참가자들도 이 명세에 관해 교육하고 토론하며 개선하기 위해 마련된 수많은 작업 세션을 통해 이 작업의 개선을 지원했습니다.

워킹 그룹은 또한 의장 Brent Zundel, 전 의장 Kristina Yasuda 및 W3C 직원 담당자인 Ivan Herman에게 W3C 표준화 과정 전반에서 그룹을 전문적으로 관리하고 꾸준히 지도해 주신 데 대해 감사드립니다.

이 명세에 관한 작업의 일부는 미국 국토안보부 과학기술국의 계약 70RSAT20T00000003, 70RSAT20T00000029, 70RSAT20T00000033, 70RSAT21T00000016, 70RSAT23T00000005, 70RSAT20T00000010/P00001, 70RSAT20T00000029, 70RSAT21T00000016/P00001, 70RSAT23T00000005, 70RSAT23C00000030, 70RSAT23R00000006, 70RSAT24T00000011 및 미국 국립과학재단의 NSF 22-572를 통해 자금을 지원받았습니다. 이 명세의 내용이 반드시 미국 정부의 입장이나 정책을 반영하는 것은 아니며, 어떠한 공식적인 승인도 추론해서는 안 됩니다.

워킹 그룹은 이 명세를 검토하고 피드백을 제공해 주신 다음 분들께도 감사드립니다(알파벳순):

Will Abramson, Mahmoud Alkhraishi, Christopher Allen, Joe Andrieu, Bohdan Andriyiv, Anthony, George Aristy, Hadley Beeman, Greg Bernstein, Bob420, Sarven Capadisli, Melvin Carvalho, David Chadwick, Matt Collier, Gabe Cohen, Sebastian Crane, Kyle Den Hartog, Veikko Eeva, Eric Elliott, Raphael Flechtner, Julien Fraichot, Benjamin Goering, Kim Hamilton Duffy, Joseph Heenan, Helge, Ivan Herman, Michael Herman, Anil John, Andrew Jones, Michael B. Jones, Rieks Joosten, Gregory K, Gregg Kellogg, Filip Kolarik, David I. Lehn, Charles E. Lehner, Christine Lemmer-Webber, Eric Lim, Dave Longley, Tobias Looker, Jer Miller, nightpool, Luis Osta, Nate Otto, George J. Padayatti, Addison Phillips, Mike Prorock, Brian Richter, Anders Rundgren, Eugeniu Rusu, Markus Sabadello, silverpill, Wesley Smith, Manu Sporny, Patrick St-Louis, Orie Steele, Henry Story, Oliver Terbu, Ted Thibodeau Jr, John Toohey, Bert Van Nuffelen, Mike Varley, Snorre Lothar von Gohren Edwin, Jeffrey Yasskin, Kristina Yasuda, Benjamin Young, Dmitri Zagidulin, 그리고 Brent Zundel.

C. 참고 문헌

C.1 규범적 참고 문헌

[CFRG-BBS-SIGNATURE]
BBS 서명 방식. Tobias Looker; Vasilis Kalos; Andrew Whitehead; Mike Lodder. 초안. URL: https://www.ietf.org/archive/id/draft-irtf-cfrg-bbs-signatures-05.html
[CFRG-Blind-BBS-Signature]
블라인드 BBS 서명. V. Kalos; G. Bernstein. 2025. URL: https://www.ietf.org/archive/id/draft-irtf-cfrg-bbs-blind-signatures-02.html#name-proof-generation
[CFRG-Pseudonym-BBS-Signature]
검증자별 BBS 연결 가능성. V. Kalos. 2024. URL: https://www.ietf.org/archive/id/draft-kalos-bbs-per-verifier-linkability-00.html
[CID]
제어되는 식별자 v1.0. Michael Jones; Manu Sporny. W3C. 2025년 5월 15일. W3C 권고안. URL: https://www.w3.org/TR/cid-1.0/
[INFRA]
Infra 표준. Anne van Kesteren; Domenic Denicola. WHATWG. 현행 표준. URL: https://infra.spec.whatwg.org/
[RDF-CANON]
RDF 데이터셋 정규화. Gregg Kellogg; Dave Longley; Dan Yamamoto. W3C. 2024년 5월 21일. W3C 권고안. URL: https://www.w3.org/TR/rdf-canon/
[RFC2119]
요구 수준을 나타내기 위해 RFC에서 사용하는 핵심 단어. S. Bradner. IETF. 1997년 3월. 현행 모범 사례. URL: https://www.rfc-editor.org/info/rfc2119/
[RFC8174]
RFC 2119 핵심 단어에서 대문자와 소문자의 모호성. B. Leiba. IETF. 2017년 5월. 현행 모범 사례. URL: https://www.rfc-editor.org/info/rfc8174/
[RFC8949]
간결한 이진 객체 표현 (CBOR). C. Bormann; P. Hoffman. IETF. 2020년 12월. 인터넷 표준. URL: https://www.rfc-editor.org/info/rfc8949/
[VC-DATA-INTEGRITY]
검증 가능한 자격 증명 데이터 무결성 1.0. Ivan Herman; Manu Sporny; Ted Thibodeau Jr; Dave Longley; Greg Bernstein. W3C. 2025년 5월 15일. W3C 권고안. URL: https://www.w3.org/TR/vc-data-integrity/
[VC-DATA-INTEGRITY-1.1]
검증 가능한 자격 증명 데이터 무결성 1.1. Ivan Herman; Manu Sporny; Ted Thibodeau Jr; Dave Longley; Greg Bernstein. W3C. 2026년 4월 16일. FPWD. URL: https://www.w3.org/TR/vc-data-integrity-1.1/
[VC-DATA-MODEL-2.0]
검증 가능한 자격 증명 데이터 모델 v2.0. Ivan Herman; Michael Jones; Manu Sporny; Ted Thibodeau Jr; Gabe Cohen. W3C. 2025년 5월 15일. W3C 권고안. URL: https://www.w3.org/TR/vc-data-model-2.0/

C.2 참고용 참고 문헌

[CDL2016]
강한 Diffie Hellman 가정을 이용한 익명 증명의 재검토. Jan Camenisch; Manu Drijvers; Anja Lehmann. Cryptology ePrint Archive, 논문 2016/663. 2016. URL: https://eprint.iacr.org/2016/663
[CFRG-PAIRING-FRIENDLY]
페어링 친화적 곡선. Yumi Sakemi; Tetsutaro Kobayashi; Tsunekazu Saito; Riad S. Wahby. 초안. URL: https://www.ietf.org/archive/id/draft-irtf-cfrg-pairing-friendly-curves-11.html
[DI-ECDSA]
타원 곡선 디지털 서명 알고리즘 암호 스위트 v1.0. David Longley; Manu Sporny; Marty Reed. W3C 검증 가능한 자격 증명 워킹 그룹. W3C 워킹 드래프트. URL: https://www.w3.org/TR/vc-di-ecdsa/
[NISTIR8053]
NISTIR 8053: 개인정보 비식별화. Simson L. Garfinkel. 2015년 10월. URL: https://nvlpubs.nist.gov/nistpubs/ir/2015/NIST.IR.8053.pdf
[Powar2023]
SoK: 데이터 개인정보에 대한 연결 공격 위험 관리. J. Powar; A. R. Beresford. 개인정보 보호 강화 기술 학술지. 2023. URL: https://petsymposium.org/popets/2023/popets-2023-0043.php
[Pugliese2020]
브라우저 핑거프린팅에 대한 장기 관찰: 사용자의 추적 가능성과 관점. G. Pugliese; C. Riess; F. Gassmann; Z. Benenson. 개인정보 보호 강화 기술 학술지. 2020. URL: https://petsymposium.org/popets/2020/popets-2020-0041.php
[Taming_EdDSAs]
다양한 EdDSA 다루기. Konstantinos Chalkias; François Garillot; Valeria Nikolaenko. Cryptology ePrint Archive, 논문 2020/1244. 2020. URL: https://eprint.iacr.org/2020/1244
[TZ2023]
BBS 서명의 재검토. Stefano Tessaro; Chenzhi Zhu. Cryptology ePrint Archive, 논문 2023/275. 2023. URL: https://eprint.iacr.org/2023/275
[vc-bitstring-status-list]
비트스트링 상태 목록 v1.0. Manu Sporny; Dave Longley; Mahmoud Alkhraishi; Michael Prorock. W3C. 2025년 5월 15일. W3C 권고안. URL: https://www.w3.org/TR/vc-bitstring-status-list/