Data Integrity ECDSA Cryptosuites v1.0

Achieving Data Integrity using ECDSA with NIST-compliant curves

W3C Recommendation

More details about this document
This version:
https://www.w3.org/TR/2025/REC-vc-di-ecdsa-20250515/
Latest published version:
https://www.w3.org/TR/vc-di-ecdsa/
Latest editor's draft:
https://w3c.github.io/vc-di-ecdsa/
History:
https://www.w3.org/standards/history/vc-di-ecdsa/
Commit history
Implementation report:
https://w3c.github.io/vc-di-ecdsa-test-suite/
Editors:
Manu Sporny (Digital Bazaar)
Dave Longley (Digital Bazaar)
Greg Bernstein (Invited Expert)
Authors:
Dave Longley (Digital Bazaar)
Manu Sporny (Digital Bazaar)
Greg Bernstein (Invited Expert)
Feedback:
GitHub w3c/vc-di-ecdsa (pull requests, new issue, open issues)
Errata:
Errata exists.
Related Specifications
The Verifiable Credentials Data Model v2.0
Verifiable Credential Data Integrity v1.0
Controlled Identifiers v1.0
Data Integrity EdDSA Cryptosuites v1.0
Data Integrity BBS Cryptosuites v1.0

See also translations.


이 문서는 W3C Data Integrity ECDSA Cryptosuites v1.0의 한국어 번역본입니다.

이 문서에 오역 및 오타를 포함할 수 있습니다. 영어 원문만이 공식적이고 규범적인 효력을 가지고 있습니다. 문의나 개선사항은 깃헙 링크lukas.j.han@gmail.com로 연락주시기 바랍니다.

원문작성일: 2025-05-15
최초번역일: 2026-07-17
최종수정일: 2026-07-18

편집자 (가나다순):
한종호 (Hopae S.A.)

요약

이 규격은 타원 곡선 디지털 서명 알고리즘(ECDSA)을 사용하여 디지털 서명을 생성할 때 사용하는 데이터 무결성 암호 스위트를 기술한다.

현재 문서의 상태

이 절은 발행 시점의 이 문서의 상태를 기술한다. 현재 W3C 발행물 목록과 이 기술 보고서의 최신 개정판은 https://www.w3.org/TR/ 의 W3C 표준 및 초안 색인에서 확인할 수 있다.

이 규격에 대한 의견은 언제든 환영한다. 이슈는 GitHub에 직접 올리거나, 그것이 불가능하면 public-vc-comments@w3.org로 보내주기 바란다. (구독, 아카이브).

이 문서는 Verifiable Credentials Working Group권고안 트랙(Recommendation track)을 사용하여 권고안(Recommendation)으로 발행하였다.

W3C는 이 규격을 웹의 표준으로 널리 배포할 것을 권장한다.

W3C 권고안이란 폭넓은 합의 형성을 거쳐 W3C와 그 회원사가 승인하고, 워킹 그룹 구성원들이 구현에 대해 로열티 없는 라이선스를 제공하기로 약속한 규격이다.

이 문서는 W3C 특허 정책(Patent Policy) 아래 운영되는 그룹이 작성하였다. W3C는 그 그룹의 산출물과 관련하여 이루어진 특허 공개의 공개 목록을 유지한다. 그 페이지에는 특허를 공개하는 방법에 대한 안내도 포함되어 있다. 필수 청구항(Essential Claim)을 포함한다고 믿는 특허를 실제로 알고 있는 개인은 W3C 특허 정책 6절에 따라 그 정보를 공개해야 한다.

이 문서는 2023년 11월 3일자 W3C 프로세스 문서(Process Document)의 적용을 받는다.

1. 소개

이 규격은 데이터 무결성 [VC-DATA-INTEGRITY] 규격을 준수하여 ECDSA 서명에 대한 증명을 생성하고 검증할 목적의 암호 스위트를 정의한다. ECDSA 서명은 [FIPS-186-5]에 규정되어 있으며, 타원 곡선 P-256과 P-384는 [NIST-SP-800-186]에 규정되어 있다. [FIPS-186-5]는 결정론적(deterministic) ECDSA 알고리즘을 포함하며, 이는 [RFC6979]에도 규정되어 있다.

참고

[NIST-SP-800-186]의 타원 곡선 P-256과 P-384는 [SECG2]에서 각각 secp256r1secp384r1로 지칭된다. 이 표기법은 ECDSA 소프트웨어 라이브러리에서도 종종 사용된다.

개발자는 secp256r1 용어를 secp256k1 용어와 혼동하지 않도록 주의해야 한다. 후자는 이 규격에서 사용하지 않는, 세 번째의 다른 타원 곡선에서 온 것이다. ECDSA 소프트웨어 라이브러리가 이 곡선들을 모두 구현하지 않을 수 있으므로, 개발자는 구현에 사용할 ECDSA 소프트웨어 라이브러리를 고를 때 주의를 기울일 필요가 있다.

이 규격은 입력 문서를 정규 형식으로 변환하기 위해 RDF 데이터셋 정규화 알고리즘 [RDF-CANON] 또는 JSON 정규화 스킴 [RFC8785] 중 하나를 사용한다. 다이제스트와 서명에는 두 가지 메커니즘 중 하나를 사용한다. 즉, 메시지 다이제스트 알고리즘으로 SHA-256 [RFC6234]과 서명 알고리즘으로 Curve P-256을 사용하는 ECDSA를 쓰거나, 메시지 다이제스트 알고리즘으로 SHA-384 [RFC6234]와 서명 알고리즘으로 Curve P-384를 사용하는 ECDSA를 쓴다.

1.1 용어

이 문서 전반에서 사용하는 용어는 Verifiable Credential Data Integrity 1.0 규격의 용어 절에 정의되어 있다.

1.2 적합성

비규범적이라고 표시된 절과 더불어, 이 규격의 모든 저작 지침, 다이어그램, 예시, 참고도 비규범적이다. 이 규격의 그 밖의 모든 것은 규범적이다.

이 문서의 핵심어 MAY, MUST, MUST NOT, SHOULD는 여기에 표시된 것처럼 모두 대문자로 나타날 때에만 BCP 14 [RFC2119] [RFC8174]에 기술된 대로 해석된다.

적합 증명(conforming proof)이란 이 규격의 규범적 진술을 준수하는 데이터 모델의 모든 구체적 표현을 말한다. 구체적으로, 이 문서의 2. 데이터 모델3. 알고리즘 절의 모든 관련 규범적 진술이 시행되어야 한다.

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

이 문서는 JSON 및 JSON-LD 데이터의 예시를 포함한다. 이러한 예시 중 일부는 유효한 JSON이 아닌데, 특정 부분을 설명하는 인라인 주석(//)과 예시와 무관한 정보의 생략을 나타내는 생략 부호(...) 같은 요소를 포함하기 때문이다. 구현자가 예시를 유효한 JSON 또는 JSON-LD로 다루려면 그러한 부분을 제거해야 한다.

2. 데이터 모델

다음 절들은 암호학적 공개키와 같은 검증 방법과, 디지털 서명과 같은 데이터 무결성 증명을 표현하기 위해 이 규격이 사용하는 데이터 모델을 개괄한다.

2.1 검증 방법

이 검증 방법들은 [FIPS-186-5]를 준수하는 타원 곡선 암호학적 키 재료를 사용하여 생성된 데이터 무결성 증명 [VC-DATA-INTEGRITY]을 검증하는 데 사용된다. 이 키 유형들의 인코딩 형식은 이 절에서 제공한다. 동등한 암호학적 키 재료를 산출하는 무손실 암호학적 키 변환 과정을 디지털 서명 처리 중에 사용해도 된다.

2.1.1 Multikey

Controlled Identifiers v1.0에 정의된 Multikey 형식은 이 규격에 정의된 암호 스위트의 공개키를 표현하는 데 사용된다.

publicKeyMultibase 속성은 P-256 또는 P-384 공개키의 Multibase 인코딩된 Multikey 표현을 나타낸다.

검증 방법의 publicKeyMultibase 값은 Controlled Identifiers v1.0Multibase 절에 정의된 대로 base-58-btc 접두사(z)로 시작해야 한다. 그 뒤에는 Controlled Identifiers v1.0Multikey 절에 정의된 대로 Multibase 인코딩된 ECDSA 256비트 공개키 값 또는 ECDSA 384비트 공개키 값이 온다. 그 밖의 어떤 인코딩도 허용되어서는 안 된다.

개발자는 개인키의 표현을 실수로 게시하지 않도록 주의하는 것이 좋다. 이 규격의 구현은 publicKeyMultibase 값에 0x1200 또는 0x1201 이외의 Multicodec 값이 사용되는 경우 오류를 일으킨다.

예시 1: Multikey로 인코딩된 P-256 공개키
{
  "id": "https://example.com/issuer/123#key-0",
  "type": "Multikey",
  "controller": "https://example.com/issuer/123",
  "publicKeyMultibase": "zDnaerx9CtbPJ1q36T5Ln5wYt3MQYeGRG5ehnPAmxcf5mDZpv"
}
예시 2: Multikey로 인코딩된 P-384 공개키
{
  "id": "https://example.com/issuer/123#key-0",
  "type": "Multikey",
  "controller": "https://example.com/issuer/123",
  "publicKeyMultibase": "z82LkvCwHNreneWpsgPEbV3gu1C6NFJEBg4srfJ5gdxEsMGRJ
    Uz2sG9FE42shbn2xkZJh54"
}
예시 3: 제어자 문서 안에서 Multikey로 인코딩된 두 공개키(P-256과 P-384)
{
  "@context": [
    "https://www.w3.org/ns/did/v1",
    "https://w3id.org/security/multikey/v1"
  ],
  "id": "did:example:123",
  "verificationMethod": [{
    "id": "https://example.com/issuer/123#key-1",
    "type": "Multikey",
    "controller": "https://example.com/issuer/123",
    "publicKeyMultibase": "zDnaerx9CtbPJ1q36T5Ln5wYt3MQYeGRG5ehnPAmxcf5mDZpv"
  }, {
    "id": "https://example.com/issuer/123#key-2",
    "type": "Multikey",
    "controller": "https://example.com/issuer/123",
    "publicKeyMultibase": "z82LkvCwHNreneWpsgPEbV3gu1C6NFJEBg4srfJ5gdxEsMGRJ
      Uz2sG9FE42shbn2xkZJh54"
  }],
  "authentication": [
    "did:example:123#key-1"
  ],
  "assertionMethod": [
    "did:example:123#key-2"
  ],
  "capabilityDelegation": [
    "did:example:123#key-2"
  ],
  "capabilityInvocation": [
    "did:example:123#key-2"
  ]
}

secretKeyMultibase 속성은 P-256 또는 P-384 비밀키(때로는 개인키라고도 함)의 Multibase 인코딩된 Multikey 표현을 나타낸다.

검증 방법의 secretKeyMultibase 값은 Controlled Identifiers v1.0Multibase 절에 정의된 대로 base-58-btc 접두사(z)로 시작해야 한다. 그 뒤에는 Controlled Identifiers v1.0Multikey 절에 정의된 대로 Multibase 인코딩된 ECDSA 256비트 비밀키 값 또는 ECDSA 384비트 비밀키 값이 온다. 그 밖의 어떤 인코딩도 허용되어서는 안 된다.

개발자는 키 쌍을 Multikey로 직렬화할 때 비밀키의 표현이 실수로 게시되는 것을 방지하고, secretKeyMultibase 속성을 기본적으로 내보내지 않는 것이 좋다.

2.2 증명 표현

이 절은 이 규격이 정의하는 증명 표현 형식을 상세히 기술한다.

2.2.1 DataIntegrityProof

증명은 [VC-DATA-INTEGRITY]의 증명(Proofs) 절에 규정된 속성을 다음 제약과 함께 포함한다.

type 속성은 DataIntegrityProof어야 한다.

cryptosuite 속성은 ecdsa-rdfc-2019, ecdsa-jcs-2019, ecdsa-sd-2023 중 하나이어야 한다.

proofValue 속성의 값은 cryptosuite 유형에 따라 생성되며, 3.2.1 증명 생성(ecdsa-rdfc-2019) 절, 3.3.1 증명 생성(ecdsa-jcs-2019) 절, 3.6.1 기본 증명 생성(ecdsa-sd-2023) 절, 3.6.6 파생 증명 추가(ecdsa-sd-2023) 절 중 하나에 규정되어 있다.

예시 4: DataIntegrityProof로 표현된 ECDSA P-256 디지털 서명
{
  "@context": [
    {"myWebsite": "https://vocabulary.example/myWebsite"},
    "https://www.w3.org/ns/credentials/v2"
  ],
  "myWebsite": "https://hello.world.example/",
  "proof": {
    "type": "DataIntegrityProof",
    "cryptosuite": "ecdsa-rdfc-2019",
    "created": "2023-02-24T23:36:38Z",
    "verificationMethod": "https://vc.example/issuers/5678#zDnaepBuvsQ8cpsWrVKw8
      fbpGpvPeNSjVPTWoq6cRqaYzBKVP",
    "proofPurpose": "assertionMethod",
    "proofValue": "z2iAR3F2Sk3mWfYyrinKzSQpSbvfxnz9kkv7roxxumB5RZDP9JUw5QAXuchUd
      huiwE18hyyZTjiEreKmhH3oj9Q8"
  }
}

3. 알고리즘

The following section describes multiple Data Integrity cryptographic suites that utilize the Elliptic Curve Digital Signature Algorithm (ECDSA) [FIPS-186-5]. When generating ECDSA signatures, the signature value MUST be expressed according to section 7 of [RFC4754] (sometimes referred to as the IEEE P1363 format) and encoded according to the specific cryptosuite proof generation algorithm. All ECDSA signatures SHOULD use the deterministic variant of the algorithm defined in [FIPS-186-5].

Implementations SHOULD fetch and cache verification method information as early as possible when adding or verifying proofs. Parameters passed to functions in this section use information from the verification method — such as the public key size — to determine function parameters — such as the cryptographic hashing algorithm.

When the RDF Dataset Canonicalization Algorithm (RDFC-1.0) [RDF-CANON] is used with ECDSA algorithms, the cryptographic hashing function used by RDFC-1.0 is chosen based on the size of the associated public key. For P-256 keys, the default hashing function, SHA-2 with 256 bits of output, MUST be used. For P-384 keys, SHA-2 with 384-bits of output MUST be used, specified via the RDFC-1.0 implementation-specific parameter.

When the RDF Dataset Canonicalization Algorithm [RDF-CANON] is used, implementations of that algorithm will detect dataset poisoning by default, and abort processing upon detection.

3.1 암호 스위트 인스턴스화

이 알고리즘은 Verifiable Credential Data Integrity 1.0증명 추가(Add Proof)증명 검증(Verify Proof) 함수가 사용할 암호 스위트를 구성하는 데 사용된다. 이 알고리즘은 옵션 객체 ( options)를 입력으로 받아 암호 스위트 인스턴스(구조체 cryptosuite)를 반환한다.

  1. cryptosuite를 빈 구조체로 초기화한다.
  2. options.typeDataIntegrityProof와 같지 않으면 cryptosuite를 반환한다.
  3. options.cryptosuiteecdsa-rdfc-2019이면:
    1. cryptosuite.createProof3.2.1 증명 생성(ecdsa-rdfc-2019) 절의 알고리즘으로 설정한다.
    2. cryptosuite.verifyProof3.2.7 증명 확인(ecdsa-rdfc-2019) 절의 알고리즘으로 설정한다.
  4. options.cryptosuiteecdsa-jcs-2019이면:
    1. cryptosuite.createProof3.3.1 증명 생성(ecdsa-jcs-2019) 절의 알고리즘으로 설정한다.
    2. cryptosuite.verifyProof3.3.7 증명 확인(ecdsa-jcs-2019) 절의 알고리즘으로 설정한다.
  5. options.cryptosuiteecdsa-sd-2023이면:
    1. cryptosuite.createProof3.6.1 기본 증명 생성(ecdsa-sd-2023) 절의 알고리즘으로 설정한다.
    2. cryptosuite.verifyProof3.6.7 파생 증명 검증(ecdsa-sd-2023) 절의 알고리즘으로 설정한다.
  6. cryptosuite를 반환한다.

3.2 ecdsa-rdfc-2019

ecdsa-rdfc-2019 암호 스위트는 입력 문서를 받아, RDF 데이터셋 정규화 [RDF-CANON]를 사용하여 문서를 정규화한 뒤, 그 출력을 암호학적으로 해싱하고 서명하여 데이터 무결성 증명을 생성한다. 이 절의 알고리즘은 그러한 데이터 무결성 증명의 검증도 포함한다.

3.2.1 증명 생성(ecdsa-rdfc-2019)

다음 알고리즘은 비보안 데이터 문서가 주어졌을 때 데이터 무결성 증명을 생성하는 방법을 지정한다. 필요한 입력은 비보안 데이터 문서( unsecuredDocument)와 증명 옵션 집합( options)이다. 데이터 무결성 증명() 또는 오류가 출력으로 생성된다.

  1. proof를 증명 옵션 options의 복제본으로 둔다.
  2. proofConfig3.2.5 증명 구성(ecdsa-rdfc-2019) 절의 알고리즘을 options를 매개변수로 전달하여 실행한 결과로 둔다.
  3. transformedData3.2.3 변환(ecdsa-rdfc-2019) 절의 알고리즘을 unsecuredDocument, proofConfig, options를 매개변수로 전달하여 실행한 결과로 둔다.
  4. hashData3.2.4 해싱(ecdsa-rdfc-2019) 절의 알고리즘을 transformedDataproofConfig를 매개변수로 전달하여 실행한 결과로 둔다.
  5. proofBytes3.2.6 증명 직렬화(ecdsa-rdfc-2019) 절의 알고리즘을 hashDataoptions를 매개변수로 전달하여 실행한 결과로 둔다.
  6. proof.proofValueproofBytes base58-btc 인코딩된 Multibase 값으로 둔다.
  7. proof데이터 무결성 증명으로 반환한다.

3.2.2 증명 검증(ecdsa-rdfc-2019)

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

verified
true 또는 false
verifiedDocument
verifiedfalse이면 Null, 그렇지 않으면 비보안 데이터 문서
  1. unsecuredDocumentsecuredDocument에서 proof 값을 제거한 사본으로 둔다.
  2. proofConfigsecuredDocument.proof에서 proofValue를 제거한 사본으로 둔다.
  3. proofBytessecuredDocument.proof.proofValue에 있는 Multibase 디코딩된 base58-btc 값으로 둔다.
  4. transformedData3.2.3 변환(ecdsa-rdfc-2019) 절의 알고리즘을 unsecuredDocumentproofConfig를 매개변수로 전달하여 실행한 결과로 둔다.
  5. hashData3.2.4 해싱(ecdsa-rdfc-2019) 절의 알고리즘을 transformedDataproofConfig를 매개변수로 전달하여 실행한 결과로 둔다.
  6. verified3.2.7 증명 확인(ecdsa-rdfc-2019) 절의 알고리즘을 hashData, proofBytes, proofConfig에 대해 실행한 결과로 둔다.
  7. 다음 항목을 갖는 검증 결과를 반환한다:
    verified
    verified
    verifiedDocument
    verifiedtrue이면 unsecuredDocument, 그렇지 않으면 Null

3.2.3 변환(ecdsa-rdfc-2019)

다음 알고리즘은 비보안 입력 문서를 3.2.4 해싱(ecdsa-rdfc-2019) 절의 해싱 알고리즘에 입력으로 제공될 준비가 된 변환된 문서로 변환하는 방법을 지정한다.

이 알고리즘에 필요한 입력은 비보안 데이터 문서(unsecuredDocument)와 변환 옵션(options)이다. 변환 옵션은 암호 스위트에 대한 타입 식별자(type)와 암호 스위트 식별자(cryptosuite)를 포함해야 한다. 변환된 데이터 문서가 출력으로 생성된다. 이 알고리즘이 문자열을 인코딩할 때는 언제나 UTF-8 인코딩을 사용해야 한다.

  1. options.type이 문자열 DataIntegrityProof로 설정되어 있지 않고 options.cryptosuite가 문자열 ecdsa-rdfc-2019로 설정되어 있지 않으면, 오류를 일으켜야 하며 PROOF_TRANSFORMATION_ERROR 오류 유형을 전달하는 것이 좋다.
  2. canonicalDocumentunsecuredDocumentJSON-LD 확장형으로 변환한 뒤 RDF 문장으로 변환하고, 그 결과에 RDF 데이터셋 정규화 알고리즘 [RDF-CANON]을 적용한 다음, 그 결과를 직렬화된 정규형 [RDF-CANON]으로 직렬화한 결과로 둔다. 정규화 시에는 사용하는 곡선에 적절한 보안 수준을 갖는 해시 알고리즘을 사용해야 하며, 자세한 내용을 참조한다.
  3. canonicalDocument변환된 데이터 문서로 반환한다.

3.2.4 해싱(ecdsa-rdfc-2019)

다음 알고리즘은 변환된 데이터 문서증명 구성을, 3.2.6 증명 직렬화(ecdsa-rdfc-2019) 절 또는 3.2.7 증명 확인(ecdsa-rdfc-2019) 절의 알고리즘에 입력으로 제공될 준비가 된 암호 해시 데이터로 암호학적으로 해싱하는 방법을 지정한다. 사용하는 곡선에 보안 수준이 적절한 해시 알고리즘을 사용해야 하는데, 즉 곡선 P-256에는 SHA-256을, 곡선 P-384에는 SHA-384를 사용한다.

이 알고리즘에 필요한 입력은 변환된 데이터 문서(transformedDocument)와 정규 증명 구성(canonicalProofConfig)이다. 바이트 열로 표현되는 단일 해시 데이터 값이 출력으로 생성된다.

  1. transformedDocumentHash를, 곡선 P-256 또는 곡선 P-384의 transformedDocument에 각각 SHA-256(256비트 출력의 SHA-2) 또는 SHA-384(384비트 출력의 SHA-2) 암호 해싱 알고리즘 [RFC6234]을 적용한 결과로 둔다. 각 transformedDocumentHash는 정확히 32바이트 또는 48바이트 크기가 된다.
  2. proofConfigHash를, 곡선 P-256 또는 곡선 P-384의 canonicalProofConfig에 각각 SHA-256(256비트 출력의 SHA-2) 또는 SHA-384(384비트 출력의 SHA-2) 암호 해싱 알고리즘 [RFC6234]을 적용한 결과로 둔다. 각 proofConfigHash는 정확히 32바이트 또는 48바이트 크기가 된다.
  3. hashDataproofConfigHash(첫 번째 해시)에 transformedDocumentHash (두 번째 해시)를 결합한 결과로 둔다.
  4. hashData해시 데이터로 반환한다.

3.2.5 증명 구성(ecdsa-rdfc-2019)

다음 알고리즘은 증명 해싱 알고리즘에 입력으로 사용되는 증명 구성증명 옵션 집합으로부터 생성하는 방법을 지정한다.

이 알고리즘에 필요한 입력은 증명 옵션(options)이다. 증명 옵션 암호 스위트에 대한 타입 식별자(type)를 포함해야 하고 암호 스위트 식별자(cryptosuite)를 포함해야 한다. 증명 구성 객체가 출력으로 생성된다.

  1. proofConfigoptions 객체의 복제본으로 둔다.
  2. proofConfig.typeDataIntegrityProof로 설정되어 있지 않거나 proofConfig.cryptosuiteecdsa-rdfc-2019로 설정되어 있지 않으면, 오류를 일으켜야 하며 PROOF_GENERATION_ERROR 오류 유형을 전달하는 것이 좋다.
  3. proofConfig.created가 설정되어 있고 그 값이 유효한 [XMLSCHEMA11-2] 날짜시간이 아니면, 오류를 일으켜야 하며 PROOF_GENERATION_ERROR 오류 유형을 전달하는 것이 좋다.
  4. proofConfig.@contextunsecuredDocument.@context로 설정한다.
  5. canonicalProofConfigproofConfigRDF 데이터셋 정규화 [RDF-CANON]를 적용한 결과로 둔다.
  6. canonicalProofConfig를 반환한다.

3.2.6 증명 직렬화(ecdsa-rdfc-2019)

다음 알고리즘은 암호 해시 데이터 집합으로부터 디지털 서명을 직렬화하는 방법을 지정한다. 이 알고리즘은 데이터 무결성 [VC-DATA-INTEGRITY] 규격 4절: 알고리즘에 정의된 알고리즘과 함께 사용되도록 설계되었다. 필요한 입력은 암호 해시 데이터(hashData)와 증명 옵션(options)이다. 증명 옵션 암호 스위트에 대한 타입 식별자(type)를 포함해야 하고 암호 스위트 식별자(cryptosuite)를 포함할 수 있다. 바이트 열로 표현되는 단일 디지털 증명 값이 출력으로 생성된다.

  1. privateKeyBytesoptions.verificationMethod 값이 식별하는 검증 방법에 연관된 개인키 바이트(또는 그 개인키 바이트의 사용을 가능하게 하는 서명 인터페이스)를 조회한 결과로 둔다.
  2. proofBytes를, privateKeyBytes가 지정하는 개인키를 사용하여 hashData를 서명할 데이터로 하여, 타원 곡선 디지털 서명 알고리즘(ECDSA) [FIPS-186-5]을 적용한 결과로 둔다. proofBytes는 P-256 키의 경우 정확히 64바이트, P-384 키의 경우 정확히 96바이트 크기가 된다.
  3. proofBytes디지털 증명으로 반환한다.

3.2.7 증명 확인(ecdsa-rdfc-2019)

다음 알고리즘은 암호 해시 데이터 집합으로부터 디지털 서명을 검증하는 방법을 지정한다. 이 알고리즘은 데이터 무결성 [VC-DATA-INTEGRITY] 규격 4절: 알고리즘에 정의된 알고리즘과 함께 사용되도록 설계되었다. 필요한 입력은 암호 해시 데이터(hashData), 디지털 서명(proofBytes), 증명 옵션(options)이다. 불리언 값으로 표현되는 검증 결과가 출력으로 생성된다.

  1. publicKeyBytes를, Controlled Identifiers v1.0 규격 검증 방법 조회 절에서 기술한 대로 options.verificationMethod 값에 연관된 공개키 바이트를 조회한 결과로 둔다.
  2. verificationResult를, publicKeyBytes가 지정하는 공개키를 사용하여 hashDataproofBytes에 대해 검증할 데이터로 하여, 검증 알고리즘인 타원 곡선 디지털 서명 알고리즘(ECDSA) [FIPS-186-5]을 적용한 결과로 둔다.
  3. verificationResult검증 결과로 반환한다.

3.3 ecdsa-jcs-2019

ecdsa-jcs-2019 암호 스위트는 입력 문서를 받아, JSON 정규화 스킴 [RFC8785]을 사용하여 문서를 정규화한 뒤, 그 출력을 암호학적으로 해싱하고 서명하여 데이터 무결성 증명을 생성한다. 이 절의 알고리즘은 그러한 데이터 무결성 증명의 검증도 포함한다.

3.3.1 증명 생성(ecdsa-jcs-2019)

다음 알고리즘은 비보안 데이터 문서가 주어졌을 때 데이터 무결성 증명을 생성하는 방법을 지정한다. 필요한 입력은 비보안 데이터 문서( unsecuredDocument)와 증명 옵션 집합( options)이다. 데이터 무결성 증명() 또는 오류가 출력으로 생성된다.

  1. proof를 증명 옵션 options의 복제본으로 둔다.
  2. unsecuredDocument.@context가 존재하면, proof.@contextunsecuredDocument.@context로 설정한다.
  3. proofConfig3.3.5 증명 구성(ecdsa-jcs-2019) 절의 알고리즘을 proof증명 옵션 매개변수로 전달하여 실행한 결과로 둔다.
  4. transformedData3.3.3 변환(ecdsa-jcs-2019) 절의 알고리즘을 unsecuredDocumentoptions를 매개변수로 전달하여 실행한 결과로 둔다.
  5. hashData3.3.4 해싱(ecdsa-jcs-2019) 절의 알고리즘을 transformedDataproofConfig를 매개변수로 전달하여 실행한 결과로 둔다.
  6. proofBytes3.3.6 증명 직렬화(ecdsa-jcs-2019) 절의 알고리즘을 hashDataoptions를 매개변수로 전달하여 실행한 결과로 둔다.
  7. proof.proofValueproofBytes base58-btc 인코딩된 Multibase 값으로 둔다.
  8. proof데이터 무결성 증명으로 반환한다.

3.3.2 증명 검증(ecdsa-jcs-2019)

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

verified
true 또는 false
verifiedDocument
verifiedtrue이면 비보안 데이터 문서, 그렇지 않으면 Null
  1. unsecuredDocumentsecuredDocument에서 proof 값을 제거한 사본으로 둔다.
  2. proofOptionssecuredDocument.proof에서 proofValue를 제거한 사본으로 둔다.
  3. Let proofBytes be the Multibase decoded base58-btc value in securedDocument.proof.proofValue.
  4. proofOptions.@context가 존재하면:
    1. securedDocument.@contextproofOptions.@context에 담긴 모든 값으로 같은 순서로 시작하는지 확인한다. 그렇지 않으면 verifiedfalse로 설정하고 마지막 단계로 건너뛴다.
    2. unsecuredDocument.@contextproofOptions.@context와 같게 설정한다.
  5. transformedData3.3.3 변환(ecdsa-jcs-2019) 절의 알고리즘을 unsecuredDocumentproofOptions를 매개변수로 전달하여 실행한 결과로 둔다.
  6. proofConfig3.3.5 증명 구성(ecdsa-jcs-2019) 절의 알고리즘을 proofOptions를 매개변수로 전달하여 실행한 결과로 둔다.
  7. hashData3.3.4 해싱(ecdsa-jcs-2019) 절의 알고리즘을 transformedDataproofConfig를 매개변수로 전달하여 실행한 결과로 둔다.
  8. verified3.3.7 증명 확인(ecdsa-jcs-2019) 절의 알고리즘을 hashData, proofBytes, proofConfig에 대해 실행한 결과로 둔다.
  9. 다음 항목을 갖는 검증 결과를 반환한다:
    verified
    verified
    verifiedDocument
    verifiedtrue이면 unsecuredDocument, 그렇지 않으면 Null

3.3.3 변환(ecdsa-jcs-2019)

다음 알고리즘은 비보안 입력 문서를 3.3.4 해싱(ecdsa-jcs-2019) 절의 해싱 알고리즘에 입력으로 제공될 준비가 된 변환된 문서로 변환하는 방법을 지정한다.

이 알고리즘에 필요한 입력은 비보안 데이터 문서(unsecuredDocument)와 변환 옵션(options)이다. 변환 옵션은 암호 스위트에 대한 타입 식별자(type)와 암호 스위트 식별자(cryptosuite)를 포함해야 한다. 변환된 데이터 문서가 출력으로 생성된다. 이 알고리즘이 문자열을 인코딩할 때는 언제나 UTF-8 인코딩을 사용해야 한다.

  1. options.type이 문자열 DataIntegrityProof로 설정되어 있지 않거나 options.cryptosuite가 문자열 ecdsa-jcs-2019로 설정되어 있지 않으면, 오류를 일으켜야 하며 PROOF_TRANSFORMATION_ERROR 오류 유형을 전달하는 것이 좋다.
  2. canonicalDocumentunsecuredDocument의 JSON 직렬화에 JSON 정규화 스킴 [RFC8785]을 적용한 결과로 둔다.
  3. canonicalDocument변환된 데이터 문서로 반환한다.

3.3.4 해싱(ecdsa-jcs-2019)

다음 알고리즘은 변환된 데이터 문서증명 구성을, 3.3.6 증명 직렬화(ecdsa-jcs-2019) 절 또는 3.3.7 증명 확인(ecdsa-jcs-2019) 절의 알고리즘에 입력으로 제공될 준비가 된 암호 해시 데이터로 암호학적으로 해싱하는 방법을 지정한다. 사용하는 곡선에 보안 수준이 적절한 해시 알고리즘을 사용해야 하는데, 즉 곡선 P-256에는 SHA-256을, 곡선 P-384에는 SHA-384를 사용한다.

이 알고리즘에 필요한 입력은 변환된 데이터 문서(transformedDocument)와 정규 증명 구성(canonicalProofConfig)이다. 바이트 열로 표현되는 단일 해시 데이터 값이 출력으로 생성된다.

  1. transformedDocumentHash를, 곡선 P-256 또는 곡선 P-384의 transformedDocument에 각각 SHA-256(256비트 출력의 SHA-2) 또는 SHA-384(384비트 출력의 SHA-2) 암호 해싱 알고리즘 [RFC6234]을 적용한 결과로 둔다. 각 transformedDocumentHash는 정확히 32바이트 또는 48바이트 크기가 된다.
  2. proofConfigHash를, 곡선 P-256 또는 곡선 P-384의 canonicalProofConfig에 각각 SHA-256(256비트 출력의 SHA-2) 또는 SHA-384(384비트 출력의 SHA-2) 암호 해싱 알고리즘 [RFC6234]을 적용한 결과로 둔다. 각 proofConfigHash는 정확히 32바이트 또는 48바이트 크기가 된다.
  3. hashDataproofConfigHash(첫 번째 해시) 뒤에 transformedDocumentHash (두 번째 해시)를 이어 붙인 결과로 둔다.
  4. hashData해시 데이터로 반환한다.

3.3.5 증명 구성(ecdsa-jcs-2019)

다음 알고리즘은 증명 해싱 알고리즘에 입력으로 사용되는 증명 구성증명 옵션 집합으로부터 생성하는 방법을 지정한다.

이 알고리즘에 필요한 입력은 증명 옵션(options)이다. 증명 옵션 암호 스위트에 대한 타입 식별자(type)를 포함해야 하고 암호 스위트 식별자(cryptosuite)를 포함해야 한다. 증명 구성 객체가 출력으로 생성된다.

  1. proofConfigoptions 객체의 복제본으로 둔다.
  2. proofConfig.typeDataIntegrityProof로 설정되어 있지 않거나 proofConfig.cryptosuiteecdsa-jcs-2019로 설정되어 있지 않으면, 오류를 일으켜야 하며 PROOF_GENERATION_ERROR 오류 유형을 전달하는 것이 좋다.
  3. proofConfig.created가 설정되어 있고 그 값이 유효한 [XMLSCHEMA11-2] 날짜시간이 아니면, 오류를 일으켜야 하며 PROOF_GENERATION_ERROR 오류 유형을 전달하는 것이 좋다.
  4. canonicalProofConfigproofConfig에 JSON 정규화 스킴 [RFC8785]을 적용한 결과로 둔다.
  5. canonicalProofConfig를 반환한다.

3.3.6 증명 직렬화(ecdsa-jcs-2019)

다음 알고리즘은 암호 해시 데이터 집합으로부터 디지털 서명을 직렬화하는 방법을 지정한다. 이 알고리즘은 데이터 무결성 [VC-DATA-INTEGRITY] 규격 4절: 알고리즘에 정의된 알고리즘과 함께 사용되도록 설계되었다. 필요한 입력은 암호 해시 데이터(hashData)와 증명 옵션(options)이다. 증명 옵션 암호 스위트에 대한 타입 식별자(type)를 포함해야 하고 암호 스위트 식별자(cryptosuite)를 포함할 수 있다. 바이트 열로 표현되는 단일 디지털 증명 값이 출력으로 생성된다.

  1. privateKeyBytesoptions.verificationMethod 값에 연관된 개인키 바이트를 조회한 결과로 둔다.
  2. proofBytes를, privateKeyBytes가 지정하는 개인키를 사용하여 hashData를 서명할 데이터로 하여, 타원 곡선 디지털 서명 알고리즘(ECDSA) [FIPS-186-5]을 적용한 결과로 둔다. proofBytes는 P-256 키의 경우 정확히 64바이트, P-384 키의 경우 정확히 96바이트 크기가 된다.
  3. proofBytes디지털 증명으로 반환한다.

3.3.7 증명 확인(ecdsa-jcs-2019)

다음 알고리즘은 암호 해시 데이터 집합으로부터 디지털 서명을 검증하는 방법을 지정한다. 이 알고리즘은 데이터 무결성 [VC-DATA-INTEGRITY] 규격 4절: 알고리즘에 정의된 알고리즘과 함께 사용되도록 설계되었다. 필요한 입력은 암호 해시 데이터(hashData), 디지털 서명(proofBytes), 증명 옵션(options)이다. 불리언 값으로 표현되는 검증 결과가 출력으로 생성된다.

  1. publicKeyBytes를, Controlled Identifiers v1.0 규격 검증 방법 조회 절에서 기술한 대로 options.verificationMethod 값에 연관된 공개키 바이트를 조회한 결과로 둔다.
  2. verificationResult를, publicKeyBytes가 지정하는 공개키를 사용하여 hashDataproofBytes에 대해 검증할 데이터로 하여, 검증 알고리즘인 타원 곡선 디지털 서명 알고리즘(ECDSA) [FIPS-186-5]을 적용한 결과로 둔다.
  3. verificationResult검증 결과로 반환한다.

3.4 선택적 공개 함수

다음 절은 선택적 공개를 수행하는 암호 스위트 전반에서 사용되는 함수 모음을 담고 있다.

3.4.1 labelReplacementCanonicalizeNQuads

다음 알고리즘은 N-Quad [N-QUADS] 문자열 배열을 정규화하고, 레이블 맵 팩토리 함수 labelMapFactoryFunction을 사용하여 정규화 결과의 공백 노드 식별자를 치환한다. 필요한 입력은 N-Quad 문자열 배열(nquads)과 레이블 맵 팩토리 함수(labelMapFactoryFunction)이다. 임의의 사용자 지정 옵션도 전달할 수 있다. 치환된 공백 노드 레이블을 가진 N-Quad 문자열 배열 형태의 canonicalNQuads의 N-Quads 표현과, 이전 공백 노드 ID에서 새 공백 노드 ID로의 맵인 labelMap이 출력으로 생성된다.

  1. 결합된 nquads에 대해 RDF 데이터셋 정규화 알고리즘 [RDF-CANON]을 실행하되 임의의 사용자 지정 옵션을 전달하고, 출력으로 정규 bnode 식별자 맵 canonicalIdMap을 포함하는 정규화된 데이터셋을 얻는다.
  2. canonicalIdMaplabelMapFactoryFunction에 전달하여 새 bnode 식별자 맵 labelMap을 생성한다.
  3. 정규화된 데이터셋과 labelMap을 사용하여 N-Quad 문자열 배열 형태의 정규 N-Quads 표현 canonicalNQuads를 생성한다.
  4. labelMapcanonicalNQuads를 포함하는 객체를 반환한다.

3.4.2 labelReplacementCanonicalizeJsonLd

다음 알고리즘은 JSON-LD 문서를 정규화하고, 레이블 맵 팩토리 함수 labelMapFactoryFunction을 사용하여 정규화 결과의 공백 노드 식별자를 치환한다. 필요한 입력은 JSON-LD 문서(document)와 레이블 맵 팩토리 함수 (labelMapFactoryFunction)이다. 추가적인 사용자 지정 옵션(예: 문서 로더)도 전달할 수 있다. 치환된 공백 노드 레이블을 가진 N-Quad 문자열 배열 형태의 canonicalNQuads의 N-Quads 표현과, 이전 공백 노드 ID에서 새 공백 노드 ID로의 맵인 labelMap이 출력으로 생성된다.

  1. Deserialize JSON-LD to RDF 알고리즘을 사용하여 임의의 사용자 지정 옵션(예: 문서 로더)을 전달하며 JSON-LD 문서를 RDF rdf로 역직렬화한다.
  2. rdf를 N-Quad 문자열 배열 nquads로 직렬화한다.
  3. 3.4.1 labelReplacementCanonicalizeNQuads 절의 알고리즘을 nquads, labelMapFactoryFunction, 그리고 임의의 사용자 지정 옵션을 전달하여 호출한 결과를 반환한다.

3.4.3 createLabelMapFunction

다음 알고리즘은 입력 레이블 맵을 사용하여 정규 공백 노드 식별자를 다른 값으로 치환하는 레이블 맵 팩토리 함수를 생성한다. 필요한 입력은 레이블 맵 labelMap이다. 함수 labelMapFactoryFunction이 출력으로 생성된다.

  1. 필수 입력 하나(정규 노드 식별자 맵 canonicalIdMap)를 받아 출력으로 공백 노드 식별자 맵 bnodeIdMap을 반환하는 함수 labelMapFactoryFunction을 생성한다. 함수의 구현을 다음과 같이 설정한다:
    1. 비어 있는 새 bnode 식별자 맵 bnodeIdMap을 생성한다.
    2. canonicalIdMap의 각 맵 항목 entry에 대해:
      1. entry의 값에 있는 정규 식별자를 labelMap의 키로 사용하여 새 레이블 newLabel을 얻는다.
      2. entry의 키와 값으로서의 newLabel을 사용하여 bnodeIdMap에 새 항목 newEntry를 추가한다.
    3. bnodeIdMap을 반환한다.
  2. labelMapFactoryFunction을 반환한다.

3.4.4 createHmacIdLabelMapFunction

다음 알고리즘은 HMAC를 사용하여 정규 공백 노드 식별자를 인코딩된 HMAC 다이제스트로 치환하는 레이블 맵 팩토리 함수를 생성한다. 필요한 입력은 (사전에 비밀키로 초기화된) HMAC HMAC이다. 함수 labelMapFactoryFunction이 출력으로 생성된다.

  1. 필수 입력 하나(정규 노드 식별자 맵 canonicalIdMap)를 받아 출력으로 공백 노드 식별자 맵 bnodeIdMap을 반환하는 함수 labelMapFactoryFunction을 생성한다. 함수의 구현을 다음과 같이 설정한다:
    1. 비어 있는 새 bnode 식별자 맵 bnodeIdMap을 생성한다.
    2. canonicalIdMap의 각 맵 항목 entry에 대해:
      1. entry의 값에 있는 정규 식별자에 HMAC를 적용하여 HMAC 다이제스트 digest를 얻는다.
      2. 새 문자열 값 b64urlDigest를 생성하고, "u" 뒤에 digest 값을 base64url-no-pad로 인코딩한 값을 붙인 것으로 초기화한다.
      3. entry의 키와 값으로서의 b64urlDigest를 사용하여 bnodeIdMap에 새 항목 newEntry를 추가한다.
    3. bnodeIdMap을 반환한다.
  2. labelMapFactoryFunction을 반환한다.
참고: 다른 알고리즘도 가능함

결과 HMAC 다이제스트를 정렬한 뒤, 그 정렬 순서에 기반한 접두사와 정수를 사용하여 생성되는 레이블 맵에 레이블을 할당하는 레이블 맵 팩토리 함수를 반환하는 다른 프리미티브를 만들 수도 있다. 이러한 프리미티브는 미공개 데이터 유출 최소화보다 연결 불가능성을 선호하는 BBS와 같은 선택적 공개 스킴에 유용할 수 있다.

3.4.5 skolemizeNQuads

다음 알고리즘은 N-Quad 문자열 배열에 있는 모든 공백 노드 식별자를 사용자 지정 스킴 URN으로 치환한다. 필요한 입력은 N-Quad 문자열 배열(inputNQuads)과 URN 스킴(urnScheme)이다. N-Quad 문자열 배열 skolemizedNQuads가 출력으로 생성된다. 이 연산은 3.4.6 deskolemizeNQuads 절의 알고리즘을 사용하여 되돌릴 수 있도록 의도되었다.

  1. 새 N-Quad 문자열 배열 skolemizedNQuads를 생성한다.
  2. inputNQuads의 각 N-Quad 문자열 s1에 대해:
    1. s1의 사본인 새 문자열 s2를 생성하되, 공백 노드 식별자가 나타나는 모든 위치를 URN("urn:")과 입력 사용자 지정 스킴(urnScheme), 콜론(":"), 그리고 공백 노드 식별자의 값으로 치환한다. 예를 들어, 다음과 유사한 형태의 정규 표현식으로 원하는 결과를 얻을 수 있다: s1.replace(/(_:([^\s]+))/g, '<urn:custom-scheme:$2>').
    2. s2skolemizedNQuads에 추가한다.
  3. skolemizedNQuads를 반환한다.

3.4.6 deskolemizeNQuads

다음 알고리즘은 N-Quad 문 배열에 있는 모든 사용자 지정 스킴 URN을 공백 노드 식별자로 치환한다. 필요한 입력은 N-Quad 문자열 배열(inputNQuads)과 URN 스킴(urnScheme)이다. N-Quad 문자열 배열 deskolemizedNquads가 출력으로 생성된다. 이 연산은 3.4.6 deskolemizeNQuads 절의 알고리즘 사용을 되돌리도록 의도되었다.

  1. 새 N-Quad 문자열 배열 deskolemizedNQuads를 생성한다.
  2. inputNQuads의 각 N-Quad 문자열 s1에 대해:
    1. s1의 사본인 새 문자열 s2를 생성하되, URN("urn:")과 입력 사용자 지정 스킴(urnScheme), 콜론(":"), 그리고 공백 노드 식별자의 값이 나타나는 모든 위치를 공백 노드 접두사("_:")와 공백 노드 식별자의 값으로 치환한다. 예를 들어, 다음과 유사한 형태의 정규 표현식으로 원하는 결과를 얻을 수 있다: s1.replace(/(<urn:custom-scheme:([^>]+)>)/g, '_:$2')..
    2. s2deskolemizedNQuads에 추가한다.
  3. deskolemizedNQuads를 반환한다.

3.4.7 skolemizeExpandedJsonLd

다음 알고리즘은 확장된 JSON-LD 문서에 있는 모든 공백 노드 식별자를 사용자 지정 스킴 URN으로 치환하며, 레이블이 없는 공백 노드에 그러한 URN을 할당하는 것도 포함한다. 필요한 입력은 확장된 JSON-LD 문서(expanded), 사용자 지정 URN 스킴(urnScheme), UUID 문자열 또는 그에 준하는 무작위 문자열 (randomString), 그리고 공유 정수에 대한 참조(count)이다. 추가적인 사용자 지정 옵션(예: 문서 로더)도 전달할 수 있다. 이 알고리즘은 스콜렘화된 JSON-LD 문서의 확장 형식(skolemizedExpandedDocument)을 출력으로 생성한다. 이 연산에서 사용되는 스콜렘화는 3.4.9 toDeskolemizedNQuads 절의 알고리즘을 사용하여 되돌릴 수 있도록 의도되었다.

  1. skolemizedExpandedDocument를 빈 배열로 초기화한다.
  2. expanded의 각 element에 대해:
    1. element가 객체가 아니거나 @value 키를 포함하면, element의 사본을 skolemizedExpandedDocument에 추가하고 다음 element로 계속 진행한다.
    2. 그렇지 않으면, skolemizedNode를 객체로 초기화하고, element의 각 propertyvalue에 대해:
      1. value가 배열이면, skolemizedNodeproperty 값을 expandedvalue를 전달하고 나머지 매개변수는 동일하게 유지하여 이 알고리즘을 재귀적으로 호출한 결과로 설정한다.
      2. 그렇지 않으면, skolemizedNodeproperty 값을 value를 유일한 요소로 갖는 배열을 expanded에 전달하고 나머지 매개변수는 동일하게 유지하여 이 알고리즘을 재귀적으로 호출한 배열 결과의 첫 번째 요소로 설정한다.
    3. skolemizedNode@id 속성이 없으면, skolemizedNode@id 속성 값을 "urn:", urnScheme, "_", randomString, "_", 그리고 count 값을 연결한 것으로 설정하고, 그 후 count 값을 증가시킨다.
    4. 그렇지 않고 skolemizedNode@id 속성 값이 "_:"로 시작하면, skolemizedNode@id 속성 값을 "urn:", urnScheme, 그리고 공백 노드 식별자를 연결한 것으로 설정하여 스콜렘화 시 기존 공백 노드 식별자를 보존한다(즉, 공백 노드 식별자는 @id 속성의 기존 값에서 "_:" 접두사를 뺀 것이다. 예를 들어 @id 속성의 기존 값이 _:b0이면 공백 노드 식별자는 b0이다).
    5. skolemizedNodeskolemizedExpandedDocument에 추가한다.
  3. skolemizedExpandedDocument를 반환한다.

3.4.8 skolemizeCompactJsonLd

다음 알고리즘은 컴팩트 JSON-LD 문서에 있는 모든 공백 노드 식별자를 사용자 지정 스킴 URN으로 치환한다. 필요한 입력은 컴팩트 JSON-LD 문서(document)와 기본값이 "custom-scheme:"인 사용자 지정 URN 스킴(urnScheme)이다. document는 문서 최상위에서 하나의 @context 속성만 사용한다고 가정한다. 추가적인 사용자 지정 옵션(예: 문서 로더)도 전달할 수 있다. 이 알고리즘은 스콜렘화된 JSON-LD 문서의 확장 형식(skolemizedExpandedDocument)과 스콜렘화된 JSON-LD 문서의 컴팩트 형식(skolemizedCompactDocument)을 모두 출력으로 생성한다. 이 연산에서 사용되는 스콜렘화는 동일한 사용자 지정 URN 스킴 (urnScheme)을 사용하는 3.4.9 toDeskolemizedNQuads 절의 알고리즘을 사용하여 되돌릴 수 있도록 의도되었다.

  1. expandeddocument와 임의의 사용자 지정 옵션을 전달하여 JSON-LD Expansion Algorithm을 실행한 결과로 초기화한다.
  2. skolemizedExpandedDocument3.4.7 skolemizeExpandedJsonLd 절의 알고리즘 결과로 초기화한다.
  3. skolemizedCompactDocumentskolemizedExpandedDocument와 임의의 사용자 지정 옵션을 전달하여 JSON-LD Compaction Algorithm을 실행한 결과로 초기화한다.
  4. skolemizedExpandedDocumentskolemizedCompactDocument를 모두 포함하는 객체를 반환한다.

3.4.9 toDeskolemizedNQuads

다음 알고리즘은 3.4.8 skolemizeCompactJsonLd 절의 알고리즘으로 생성된 것과 같은 스콜렘화된 JSON-LD 문서를 역스콜렘화된 N-Quads 배열로 변환한다. 필요한 입력은 JSON-LD 문서 skolemizedDocument이다. 추가적인 사용자 지정 옵션(예: 문서 로더)도 전달할 수 있다. 역스콜렘화된 N-Quad 문자열 배열 (deskolemizedNQuads)이 출력으로 생성된다.

  1. skolemizedDataset를, 임의의 사용자 지정 옵션(예: 문서 로더)을 전달하여 skolemizedDocument를 JSON-LD에서 N-Quads 형식의 RDF로 변환하는 Deserialize JSON-LD to RDF 알고리즘의 결과로 초기화한다.
  2. skolemizedDataset를 개별 N-Quads의 배열 skolemizedNQuads로 분할한다.
  3. deskolemizedNQuadsskolemizedNQuads와 "custom-scheme:"을 매개변수로 하여 3.4.6 deskolemizeNQuads 절 알고리즘의 결과로 설정한다. 구현체는 skolemizedDocument를 생성하는 데 동일한 스킴 이름이 사용되었다면 "custom-scheme:"과 다른 urnScheme을 선택할 수 있다.
  4. deskolemizedNQuads를 반환한다.

3.4.10 jsonPointerToPaths

다음 알고리즘은 JSON 포인터 [RFC6901]를 JSON 트리로 향하는 경로 배열로 변환한다. 필요한 입력은 JSON 포인터 문자열(pointer)이다. 경로 배열 (paths)이 출력으로 생성된다.

  1. paths를 빈 배열로 초기화한다.
  2. pointer를 "/" 문자로 분할하고 첫 번째 빈 분할 요소를 건너뛰어 splitPath를 배열로 초기화한다. JavaScript 표기법으로 이 단계는 다음 코드와 동등하다: pointer.split('/').slice(1)
  3. splitPath의 각 path에 대해:
    1. path~를 포함하지 않으면, 정수로 파싱되면 정수로 변환하고 그렇지 않으면 문자열로 두어 pathpaths에 추가한다.
    2. 그렇지 않으면, path의 모든 JSON 포인터 이스케이프 시퀀스를 언이스케이프하고 그 결과를 paths에 추가한다.
  4. paths를 반환한다.

3.4.11 createInitialSelection

다음 알고리즘은 JSON-LD 객체를 기반으로 초기 선택(JSON-LD 문서의 조각)을 생성한다. 이는 3.4.13 selectJsonLd 절의 알고리즘 내에서 사용되는 헬퍼 함수이다. 필요한 입력은 JSON-LD 객체(source)이다. JSON-LD 문서 조각 객체 (selection)가 출력으로 생성된다.

  1. selection을 빈 객체로 초기화한다.
  2. source가 공백 노드 식별자가 아닌 id를 가지면, selection.id를 그 값으로 설정한다. 참고: 임의의 JSON 포인터 경로에 있는 모든 비공백 노드 식별자는 선택에 포함되어야 하며, 여기에는 임의의 루트 문서 식별자도 포함된다.
  3. source.type이 설정되어 있으면, selection.type을 그 값으로 설정한다. 참고: 선택은 임의의 루트 문서 type을 포함하여 임의의 JSON 포인터 경로에 있는 모든 type을 포함해야 한다.
  4. selection을 반환한다.

3.4.12 selectPaths

다음 알고리즘은 파싱된 JSON 포인터에서 파싱한 경로를 사용하여 컴팩트 JSON-LD 문서의 일부를 선택한다. 이는 3.4.13 selectJsonLd 절의 알고리즘 내에서 사용되는 헬퍼 함수이다. 필요한 입력은 JSON 포인터에서 파싱된 경로 배열 (paths), 컴팩트 JSON-LD 문서(document), 채워질 선택 문서 (selectionDocument), 그리고 선택된 배열을 추적하기 위한 배열의 배열 (arrays)이다. 이 알고리즘은 출력을 생성하지 않는다. 대신 주어진 selectionDocumentpaths를 통해 선택된 값들로 채운다.

  1. parentValuedocument로 초기화한다.
  2. valueparentValue로 초기화한다.
  3. selectedParentselectionDocument로 초기화한다.
  4. selectedValueselectedParent로 초기화한다.
  5. paths의 각 path에 대해:
    1. selectedParentselectedValue로 설정한다.
    2. parentValuevalue로 설정한다.
    3. valueparentValue.path로 설정한다. 이제 value가 undefined이면, 오류를 일으켜야 하며 JSON 포인터가 주어진 document와 일치하지 않음을 나타내는 PROOF_GENERATION_ERROR 오류 유형을 전달하는 것이 좋다.
    4. selectedValueselectedParent.path로 설정한다.
    5. 이제 selectedValue가 undefined이면:
      1. value가 배열이면, selectedValue를 빈 배열로 설정하고 selectedValuearrays에 추가한다.
      2. 그렇지 않으면, valuesource로 하여 3.4.11 createInitialSelection 절의 알고리즘에 전달한 초기 선택으로 selectedValue를 설정한다.
      3. selectedParent.pathselectedValue로 설정한다.
  6. 참고: 대상 값에서 경로 순회가 완료되면, 이제 선택된 값이 계산된다.
  7. value가 리터럴이면, selectedValuevalue로 설정한다.
  8. value가 배열이면, selectedValuevalue의 사본으로 설정한다.
  9. 그 밖의 모든 경우에는, selectedValueselectedValue의 얕은 복사와 value의 깊은 복사를 병합한 객체로 설정한다. 예: {...selectedValue, …deepCopy(value)}.
  10. paths에서 마지막 pathlastPath를 가져온다.
  11. selectedParent.lastPathselectedValue로 설정한다.

3.4.13 selectJsonLd

다음 알고리즘은 JSON 포인터 배열을 사용하여 컴팩트 JSON-LD 문서의 일부를 선택한다. 필요한 입력은 JSON 포인터 배열(pointers)과 컴팩트 JSON-LD 문서 (document)이다. document@id@type을 각각 idtype으로 별칭 처리하는 JSON-LD 컨텍스트를 사용하고, 문서 최상위에서 하나의 @context 속성만 사용한다고 가정한다. 원본 JSON-LD 문서의 선택을 나타내는 새 JSON-LD 문서(selectionDocument)가 출력으로 생성된다.

  1. pointers가 비어 있으면 null을 반환한다. 이는 원본 문서에서 아무것도 선택되지 않았음을 나타낸다.
  2. arrays를 빈 배열로 초기화한다. 이 변수는 모든 pointers가 처리된 후 선택된 희소 배열을 밀집 배열로 만들기 위해 그것들을 추적하는 데 사용된다.
  3. documentsource로 하여 3.4.11 createInitialSelection 절의 알고리즘에 전달한 초기 선택으로 selectionDocument를 초기화한다.
  4. selectionDocument@context 속성 값을 document@context 속성 값의 사본으로 설정한다.
  5. pointers의 각 pointer에 대해, 문서를 루트에서 포인터 대상 값까지 순회하며 selectionDocument를 구축한다:
    1. 3.4.10 jsonPointerToPaths 절의 알고리즘을 사용하여 pointer를 경로 배열 paths로 파싱한다.
    2. document, paths, selectionDocument, arrays를 전달하여 3.4.12 selectPaths 절의 알고리즘을 사용한다.
  6. arrays의 각 array에 대해:
    1. 정의된 요소들 사이의 undefined 요소를 모두 제거하여 array를 밀집 배열로 만든다.
  7. selectionDocument를 반환한다.

3.4.14 relabelBlankNodes

다음 알고리즘은 공백 노드 레이블 맵을 사용하여 N-Quad 문자열 배열에 있는 공백 노드 식별자를 재레이블한다. 필요한 입력은 N-Quad 문자열 배열(nquads)과 공백 노드 레이블 맵(labelMap)이다. 재레이블된 공백 노드 식별자를 가진 N-Quad 문자열 배열(relabeledNQuads)이 출력으로 생성된다.

  1. 새 N-Quad 문자열 배열 relabeledNQuads를 생성한다.
  2. nquads의 각 N-Quad 문자열 s1에 대해:
    1. s1의 사본이되 그 안의 각 공백 노드 식별자가 labelMap에서 그것을 키로 하여 연관된 값으로 치환된 새 문자열 s2를 생성한다.
    2. s2relabeledNQuads에 추가한다.
  3. relabeledNQuads를 반환한다.

3.4.15 selectCanonicalNQuads

다음 알고리즘은 JSON 포인터 배열을 사용하여 스콜렘화된 컴팩트 JSON-LD 문서의 일부를 선택하고, 주어진 레이블 맵을 사용하여 공백 노드 레이블이 치환된 결과 정규 N-Quads를 출력한다. 필요한 입력은 JSON 포인터 배열(pointers), 스콜렘화된 컴팩트 JSON-LD 문서(skolemizedCompactDocument), 그리고 공백 노드 레이블 맵 (labelMap)이다. 추가적인 사용자 지정 옵션(예: 문서 로더)도 전달할 수 있다. document@id@type을 각각 idtype으로 별칭 처리하는 JSON-LD 컨텍스트를 사용하고, 문서 최상위에서 하나의 @context 속성만 사용한다고 가정한다. 원본 JSON-LD 문서의 선택을 나타내는 새 JSON-LD 문서 (selectionDocument), 역스콜렘화된 N-Quad 문자열 배열 (deskolemizedNQuads), 그리고 공백 노드 레이블이 치환된 정규 N-Quads 배열 (nquads)을 포함하는 객체가 출력으로 생성된다.

  1. pointersskolemizedCompactDocumentdocument로 전달하여 3.4.13 selectJsonLd 절 알고리즘의 결과로 selectionDocument를 초기화한다.
  2. selectionDocumentskolemizedCompactDocument로 전달하고 임의의 사용자 지정 옵션을 전달하여 3.4.9 toDeskolemizedNQuads 절 알고리즘의 결과로 deskolemizedNQuads를 초기화한다.
  3. labelMapdeskolemizedNQuadsnquads로 전달하여 3.4.14 relabelBlankNodes 절 알고리즘의 결과로 nquads를 초기화한다.
  4. selectionDocument, deskolemizedNQuads, nquads를 포함하는 객체를 반환한다.

3.4.16 canonicalizeAndGroup

다음 알고리즘은 컴팩트 JSON-LD 문서의 사용자 지정 선택과 일치하는 정규 N-Quad 문자열을 출력하는 데 사용된다. 이는 컴팩트 JSON-LD 문서를 정규화하고(레이블 맵을 사용하여 공백 노드 식별자를 치환하며) 결과 정규 N-Quad 문자열을 각 그룹에 연관된 선택에 따라 그룹화함으로써 이루어진다. 각 그룹은 할당된 이름과 JSON 포인터 배열을 사용하여 정의된다. JSON 포인터는 스콜렘화된 문서의 일부를 선택하는 데 사용되며, 그 출력을 정규 N-Quads로 변환하여 그룹 매칭을 수행할 수 있게 한다.

필요한 입력은 컴팩트 JSON-LD 문서(document), 레이블 맵 팩토리 함수 (labelMapFactoryFunction), 그리고 명명된 그룹 정의의 맵 (groupDefinitions)이다. 추가적인 사용자 지정 옵션(예: 문서 로더)도 전달할 수 있다. document@id@type을 각각 idtype으로 별칭 처리하는 JSON-LD 컨텍스트를 사용하고, 문서 최상위에서 하나의 @context 속성만 사용한다고 가정한다. 생성된 그룹(groups), 스콜렘화된 컴팩트 JSON-LD 문서(skolemizedCompactDocument), 스콜렘화된 확장 JSON-LD 문서 (skolemizedExpandedDocument), 역스콜렘화된 N-Quad 문자열 (deskolemizedNQuads), 공백 노드 레이블 맵(labelMap), 그리고 정규 N-Quad 문자열 nquads를 포함하는 객체가 출력으로 생성된다.

  1. document와 임의의 사용자 지정 옵션을 전달하여 3.4.8 skolemizeCompactJsonLd 절 알고리즘의 결과에서 각각에 연관된 값으로 skolemizedExpandedDocumentskolemizedCompactDocument를 초기화한다.
  2. skolemizedExpandedDocument와 임의의 사용자 지정 옵션을 전달하여 3.4.9 toDeskolemizedNQuads 절 알고리즘의 결과로 deskolemizedNQuads를 초기화한다.
  3. labelMapFactoryFunction, deskolemizedNQuadsnquads로, 그리고 임의의 사용자 지정 옵션을 전달하여 3.4.1 labelReplacementCanonicalizeNQuads 절 알고리즘의 결과에서 각각에 연관된 값으로 nquadslabelMap을 초기화한다.
  4. selections를 새 맵으로 초기화한다.
  5. groupDefinitions의 각 키(name)와 값(pointers) 항목에 대해:
    1. pointers, labelMap, skolemizedCompactDocumentdocument로, 그리고 임의의 사용자 지정 옵션을 전달하여 3.4.15 selectCanonicalNQuads 절 알고리즘의 결과를 값으로, name을 키로 하는 항목을 추가한다.
  6. groups를 빈 객체로 초기화한다.
  7. selections의 각 키(name)와 값(selectionResult) 항목에 대해:
    1. matching을 빈 맵으로 초기화한다.
    2. nonMatching을 빈 맵으로 초기화한다.
    3. selectedNQuadsselectionResultnquads로 초기화한다.
    4. selectedDeskolemizedNQuadsselectionResultdeskolemizedNQuads로 초기화한다.
    5. nquads의 각 요소(nq)와 인덱스(index)에 대해:
      1. index를 키로, nq를 값으로 하는 맵 항목 entry를 생성한다.
      2. selectedNQuadsnq를 포함하면 entrymatching에 추가하고, 그렇지 않으면 entrynonMatching에 추가한다.
    6. groupsnamematching, nonMatching, 그리고 selectedDeskolemizedNQuadsdeskolemizedNQuads로 포함하는 객체로 설정한다.
  8. groups, skolemizedExpandedDocument, skolemizedCompactDocument, deskolemizedNQuads, labelMap, nquads를 포함하는 객체를 반환한다.

3.4.17 hashMandatoryNQuads

다음 알고리즘은 제공된 해싱 API를 사용하여 공개가 필수인 N-Quads 배열을 암호학적으로 해싱한다. 필요한 입력은 공개가 필수인 N-Quads 배열(mandatory)과 해싱 함수 (hasher)이다. 암호학적 해시(mandatoryHash)가 출력으로 생성된다.

  1. bytes를 결합된 mandatory N-Quads의 UTF-8 표현으로 초기화한다.
  2. mandatoryHashhasher를 사용하여 bytes를 해싱한 결과로 초기화한다.
  3. mandatoryHash를 반환한다.

3.5 ecdsa-sd-2023 함수

이 절은 ecdsa-sd-2023 암호 스위트에 유용한 하위 알고리즘을 담고 있다.

3.5.1 serializeSignData

다음 알고리즘은 기본 증명 검증 방법에 연관된 개인키로 서명될 데이터를 직렬화한다. 필요한 입력은 증명 옵션 해시(proofHash), 증명 범위의 multikey 인코딩된 공개키(publicKey), 그리고 필수 해시(mandatoryHash)이다. 바이트열로 표현되는 단일 서명 데이터 값이 출력으로 생성된다.

  1. proofHash, publicKey, mandatoryHash를 그 순서대로 연결한 것을 서명 데이터로 반환한다.

3.5.2 serializeBaseProofValue

다음 알고리즘은 기본 서명, 공개키, HMAC 키, 서명, 필수 포인터를 포함하여 기본 증명 값을 직렬화한다. 필요한 입력은 기본 서명 baseSignature, 공개키 publicKey, HMAC 키 hmacKey, signatures 배열, 그리고 mandatoryPointers 배열이다. 단일 기본 증명 문자열 값이 출력으로 생성된다.

  1. ECDSA-SD 기본 증명 헤더 바이트 0xd9, 0x5d, 0x00으로 시작하는 바이트 배열 proofValue를 초기화한다.
  2. components를 다음 값들, 즉 baseSignature, publicKey, hmacKey, signatures, mandatoryPointers를 담은 다섯 요소의 배열로 초기화한다.
  3. components를 [RFC8949]에 따라 CBOR로 인코딩하되, components 중 어느 것에도 CBOR 태깅을 사용해서는 안 된다. 생성된 인코딩 값을 proofValue에 추가한다.
  4. baseProof를, Controlled Identifiers v1.0 Multibase 절에 설명된 대로 proofValue의 Multibase base64url-no-pad 인코딩을 담은 문자열로 초기화한다. 즉, "u"로 시작하고 proofValue의 base64url-no-pad 인코딩 값으로 끝나는 문자열을 반환한다.
  5. baseProof기본 증명으로 반환한다.

3.5.3 parseBaseProofValue

다음 알고리즘은 ecdsa-sd-2023 선택적 공개 기본 증명 값의 구성 요소를 파싱한다. 필요한 입력은 증명 값(proofValue)이다. baseSignature, publicKey, hmacKey, signatures, mandatoryPointers라는 이름을 사용하는 다섯 요소를 담은 단일 객체 파싱된 기본 증명이 출력으로 생성된다.

  1. proofValue 문자열이 multibase-base64url-no-pad 인코딩된 값임을 나타내는 u로 시작하지 않으면, 오류를 일으켜야 하며 PROOF_VERIFICATION_ERROR 오류 유형을 전달하는 것이 좋다.
  2. decodedProofValueproofValue에서 앞의 u 다음 부분 문자열을 base64url-no-pad 디코딩한 결과로 초기화한다.
  3. decodedProofValue가 ECDSA-SD 기본 증명 헤더 바이트 0xd9, 0x5d, 0x00으로 시작하지 않으면, 오류를 일으켜야 하며 PROOF_VERIFICATION_ERROR 오류 유형을 전달하는 것이 좋다.
  4. components를 3바이트 ECDSA-SD 기본 증명 헤더 뒤에 오는 바이트를 CBOR 디코딩한 결과인 배열로 초기화한다. 그 결과가 다섯 요소의 배열임을 확인한다.
  5. 각각 baseSignature, publicKey, hmacKey, signatures, mandatoryPointers라는 이름을 사용하여 다섯 요소로 속성을 설정한 객체를 반환한다.

3.5.4 createDisclosureData

다음 알고리즘은 파생 증명을 생성하는 데 사용할 데이터를 만든다. 입력에는 JSON-LD 문서(document), ECDSA-SD 기본 증명(proof), 문을 선택적으로 공개하는 데 사용할 JSON 포인터 배열(selectivePointers), 그리고 문서 로더와 같은 임의의 사용자 지정 JSON-LD API 옵션이 포함된다. "baseSignature", "publicKey", "filteredSignatures"에 대한 "signatures", "labelMap", "mandatoryIndexes", "revealDocument" 필드를 담은 단일 객체 공개 데이터가 출력으로 생성된다.

  1. proofproofValue를 전달하여 3.5.3 parseBaseProofValue 절의 알고리즘을 호출했을 때 반환되는 객체에서 각각에 연관된 속성 값으로 baseSignature, publicKey, hmacKey, signatures, mandatoryPointers를 초기화한다.
  2. hmachmacKey를 사용하는 HMAC API로 초기화한다. HMAC는 서명 알고리즘에서 사용되는 것과 동일한 해시 알고리즘, 즉 P-256 곡선의 경우 SHA-256을 사용한다.
  3. labelMapFactoryFunctionhmac를 전달하여 3.4.4 createHmacIdLabelMapFunction 절 알고리즘을 호출한 결과로 초기화한다.
  4. combinedPointersmandatoryPointersselectivePointers를 연결한 것으로 초기화한다.
  5. groupDefinitions를 다음 항목들을 갖는 맵으로 초기화한다: 문자열 "mandatory" 키와 mandatoryPointers 값, 문자열 "selective" 키와 selectivePointers 값, 문자열 "combined" 키와 combinedPointers 값.
  6. document, labelMapFactoryFunction, groupDefinitions, 그리고 임의의 사용자 지정 JSON-LD API 옵션을 매개변수로 전달하여 3.4.16 canonicalizeAndGroup 절의 알고리즘을 호출한 결과에서 각각에 연관된 값으로 groupslabelMap을 초기화한다. 참고: 이 단계는 문서를 hmac에 기반한 의사난수 공백 노드 식별자를 가진 정규 N-Quad 문자열 배열로 변환하고, JSON 포인터에 기반한 선택에 따라 N-Quad 문자열을 그룹화한다.
  7. relativeIndex를 0으로 초기화한다.
  8. mandatoryIndexes를 빈 배열로 초기화한다.
  9. groups.combined.matching의 키에 있는 각 absoluteIndex에 대해, 임의의 필수 N-Quad의 절대 인덱스를 공개될 결합 출력에 대한 상대 인덱스로 변환한다:
    1. groups.mandatory.matchingabsoluteIndex를 키로 가지면, relativeIndexmandatoryIndexes에 추가한다.
    2. relativeIndex를 증가시킨다.
  10. 어떤 서명이 선택적으로 공개된 문과 일치하는지 결정한다. 이는 필수 그룹과 일치하는 인덱스를 건너뛰면서 모든 signatures를 순회하는 동안 인덱스 카운터를 증가시키는 것을 요구한다.
    1. index0으로 초기화한다.
    2. filteredSignatures를 빈 배열로 초기화한다.
    3. signatures의 각 signature에 대해:
      1. indexgroups.mandatory.matching에 있는 동안 index를 증가시킨다.
      2. indexgroups.selective.matching에 있으면, signaturefilteredSignatures에 추가한다.
      3. index를 증가시킨다.
  11. documentcombinedPointerspointers로 전달하여 3.4.13 selectJsonLd 절의 알고리즘을 호출한 결과로 revealDocument를 초기화한다.
  12. 결합된 |combinedGroup.deskolemizedNQuads|에 대해 임의의 사용자 지정 옵션을 전달하여 RDF 데이터셋 정규화 알고리즘 [RDF-CANON]을 실행하고, 정규 bnode 식별자 맵 canonicalIdMap을 얻는다. 참고: 이 맵은 검증자가 공개 문서를 정규화할 때 생성할 정규 공백 노드 식별자를 포함한다.
  13. verifierLabelMap을 빈 맵으로 초기화한다. 이 맵은 검증자가 공개된 문서를 정규화할 때 생성할 정규 공백 노드 식별자를 기본 증명에서 원래 서명되었던 공백 노드 식별자로 매핑한다.
  14. canonicalIdMap의 각 키(inputLabel)와 값(verifierLabel)에 대해:
    1. verifierLabel을 키로, inputLabellabelMap의 키로 하여 연관된 값을 값으로 사용하여 verifierLabelMap에 항목을 추가한다.
  15. baseSignature, publicKey, filteredSignatures에 대한 signatures, labelMap에 대한 verifierLabelMap, mandatoryIndexes, revealDocument에 해당하는 속성을 갖는 객체를 반환한다.

3.5.5 compressLabelMap

다음 알고리즘은 레이블 맵을 압축한다. 필요한 입력은 레이블 맵(labelMap)이다. 출력은 압축된 레이블 맵이다.

  1. map을 빈 맵으로 초기화한다.
  2. labelMap의 각 항목(k, v)에 대해:
    1. k의 "c14n" 접두사 다음 문자들에서 파싱한 10진 정수를 키로, v의 "u" 접두사 다음 문자들을 base64url-no-pad 디코딩한 바이트 배열을 값으로 하여 map에 항목을 추가한다.
  3. map압축된 레이블 맵으로 반환한다.

3.5.6 decompressLabelMap

다음 알고리즘은 레이블 맵을 압축 해제한다. 필요한 입력은 압축된 레이블 맵 (compressedLabelMap)이다. 출력은 압축 해제된 레이블 맵이다.

  1. map을 빈 맵으로 초기화한다.
  2. compressedLabelMap의 각 항목(k, v)에 대해:
    1. k에 접두사 "c14n"을 붙인 것을 키로, v의 base64url-no-pad 인코딩 값에 접두사 "u"를 붙인 것을 값으로 하여 map에 항목을 추가한다.
  3. map압축 해제된 레이블 맵으로 반환한다.

3.5.7 serializeDerivedProofValue

다음 알고리즘은 파생 증명 값을 직렬화한다. 필요한 입력은 기본 서명 (baseSignature), 공개키(publicKey), 서명 배열 (signatures), 레이블 맵(labelMap), 그리고 필수 인덱스 배열 (mandatoryIndexes)이다. 바이트열로 직렬화된 단일 파생 증명 값이 출력으로 생성된다.

  1. compressedLabelMaplabelMap을 매개변수로 전달하여 3.5.5 compressLabelMap 절의 알고리즘을 호출한 결과로 초기화한다.
  2. ECDSA-SD 공개 증명 헤더 바이트 0xd9, 0x5d, 0x01로 시작하는 바이트 배열 proofValue를 초기화한다.
  3. components를 다음 값들, 즉 baseSignature, publicKey, signatures, compressedLabelMap, mandatoryIndexes를 담은 다섯 요소의 배열로 초기화한다.
  4. components를 [RFC8949]에 따라 CBOR로 인코딩하되, components 중 어느 것에도 CBOR 태깅을 사용해서는 안 된다. 생성된 인코딩 값을 proofValue에 추가한다.
  5. Controlled Identifiers v1.0 Multibase 절에 설명된 대로 proofValue의 base64url-no-pad 인코딩을 담은 문자열로 파생 증명을 반환한다. 즉, "u"로 시작하고 proofValue의 base64url-no-pad 인코딩 값으로 끝나는 문자열을 반환한다.

3.5.8 parseDerivedProofValue

다음 알고리즘은 파생 증명 값의 구성 요소를 파싱한다. 필요한 입력은 파생 증명 값 (proofValue)이다. "baseSignature", "publicKey", "signatures", "labelMap", "mandatoryIndexes"라는 이름을 사용하는 다섯 요소의 집합을 담은 단일 파생 증명 값 객체가 출력으로 생성된다.

  1. proofValue 문자열이 multibase-base64url-no-pad 인코딩된 값임을 나타내는 u로 시작하지 않으면, 오류를 일으켜야 하며 PROOF_VERIFICATION_ERROR 오류 유형을 전달하는 것이 좋다.
  2. decodedProofValueproofValue에서 앞의 u 다음 부분 문자열을 base64url-no-pad 디코딩한 결과로 초기화한다.
  3. decodedProofValue가 ECDSA-SD 공개 증명 헤더 바이트 0xd9, 0x5d, 0x01로 시작하지 않으면, 오류를 일으켜야 하며 PROOF_VERIFICATION_ERROR 오류 유형을 전달하는 것이 좋다.
  4. components를 3바이트 ECDSA-SD 공개 증명 헤더 뒤에 오는 바이트를 CBOR 디코딩한 결과인 배열로 초기화한다. 그 결과가 다음 다섯 요소의 배열이 아니면 — 길이 64의 바이트 배열, 길이 36의 바이트 배열, 각각 길이 64인 바이트 배열의 배열, 정수를 각각 길이 32인 바이트 배열로 매핑하는 맵, 그리고 정수 배열 — 오류를 일으켜야 하며 PROOF_VERIFICATION_ERROR 오류 유형을 전달하는 것이 좋다.
  5. components의 기존 네 번째 요소를 compressedLabelMap으로 전달하여 3.5.6 decompressLabelMap 절의 알고리즘을 호출한 결과로 components의 네 번째 요소를 교체한다.
  6. 각각 "baseSignature", "publicKey", "signatures", "labelMap", "mandatoryIndexes"라는 이름을 사용하여 다섯 요소로 속성을 설정한 객체로 파생 증명 값을 반환한다.

3.5.9 createVerifyData

다음 알고리즘은 ECDSA-SD로 보호된 검증가능한 크리덴셜의 검증을 수행하는 데 필요한 데이터를 만든다. 입력에는 JSON-LD 문서(document), ECDSA-SD 공개 증명 (proof), 그리고 문서 로더와 같은 임의의 사용자 지정 JSON-LD API 옵션이 포함된다. "baseSignature", "proofHash", "publicKey", "signatures", "nonMandatory", "mandatoryHash" 필드를 담은 단일 검증 데이터 객체 값이 출력으로 생성된다.

  1. proofHash를 증명 옵션에 대해 RDF 데이터셋 정규화 [RDF-CANON]을 수행한 결과로 초기화한다. 사용되는 해시는 서명 알고리즘에서 사용되는 것과 동일하며, 즉 P-256 곡선의 경우 SHA-256이다. 참고: 이 단계는 병렬로 수행할 수 있다. 이 알고리즘이 proofHash 값을 사용해야 하기 전에만 완료되면 된다.
  2. proofproofValue를 전달하여 3.5.8 parseDerivedProofValue 절의 알고리즘을 호출했을 때 반환되는 객체에서 각각의 속성 이름에 연관된 값으로 baseSignature, publicKey, signatures, labelMap, mandatoryIndexes를 초기화한다.
  3. labelMapFactoryFunction3.4.3 createLabelMapFunction 절 알고리즘을 호출한 결과로 초기화한다.
  4. nquadsdocument, labelMapFactoryFunction, 그리고 임의의 사용자 지정 JSON-LD API 옵션을 전달하여 3.4.2 labelReplacementCanonicalizeJsonLd 절 알고리즘을 호출한 결과로 초기화한다. 참고: 이 단계는 문서를 labelMap에 기반한 의사난수 공백 노드 식별자를 가진 정규 N-Quads 배열로 변환한다.
  5. mandatory를 빈 배열로 초기화한다.
  6. nonMandatory를 빈 배열로 초기화한다.
  7. nquads의 각 항목(index, nq)에 대해, N-Quads를 필수 및 비필수 범주로 분리한다:
    1. mandatoryIndexesindex를 포함하면, nqmandatory에 추가한다.
    2. 그렇지 않으면, nqnonMandatory에 추가한다.
  8. mandatoryHashmandatory를 전달하여 "hashMandatory" 프리미티브를 호출한 결과로 초기화한다.
  9. baseSignature, proofHash, publicKey, signatures, nonMandatory, mandatoryHash에 해당하는 속성을 갖는 객체를 반환한다.

3.6 ecdsa-sd-2023

ecdsa-sd-2023 암호 스위트는 입력 문서를 받아, RDF 데이터셋 정규화 [RDF-CANON]를 사용하여 문서를 정규화한 뒤, 그 출력을 암호학적으로 해싱하고 서명하여 데이터 무결성 증명을 생성한다. 이 절의 알고리즘은 그러한 데이터 무결성 증명의 검증도 포함한다.

3.6.1 기본 증명 생성(ecdsa-sd-2023)

다음 알고리즘은 비보안 데이터 문서가 주어졌을 때 데이터 무결성 증명을 생성하는 방법을 지정한다. 필요한 입력은 비보안 데이터 문서( unsecuredDocument)와 증명 옵션 집합( options)이다. 데이터 무결성 증명() 또는 오류가 출력으로 생성된다.

  1. proof를 증명 옵션 options의 복제본으로 둔다.
  2. proofConfigoptions를 매개변수로 전달하여 3.6.4 기본 증명 구성(ecdsa-sd-2023) 절의 알고리즘을 실행한 결과로 둔다.
  3. transformedDataunsecuredDocument, proofConfig, options를 매개변수로 전달하여 3.6.2 기본 증명 변환(ecdsa-sd-2023) 절의 알고리즘을 실행한 결과로 둔다.
  4. hashDatatransformedDataproofConfig를 매개변수로 전달하여 3.6.3 기본 증명 해싱(ecdsa-sd-2023) 절의 알고리즘을 실행한 결과로 둔다.
  5. proofByteshashDataoptions를 매개변수로 전달하여 3.6.5 기본 증명 직렬화(ecdsa-sd-2023) 절의 알고리즘을 실행한 결과로 둔다.
  6. proof.proofValueproofBytes base64-url 인코딩된 Multibase 값으로 둔다.
  7. proof데이터 무결성 증명으로 반환한다.

3.6.2 기본 증명 변환(ecdsa-sd-2023)

다음 알고리즘은 비보안 입력 문서를 3.6.3 기본 증명 해싱(ecdsa-sd-2023) 절의 해싱 알고리즘에 입력으로 제공될 준비가 된 변환된 문서로 변환하는 방법을 지정한다.

이 알고리즘에 필요한 입력은 비보안 데이터 문서(unsecuredDocument)와 변환 옵션(options)이다. 변환 옵션은 암호 스위트에 대한 타입 식별자(type), 암호 스위트 식별자 (cryptosuite), 그리고 검증 방법(verificationMethod)을 포함해야 한다. 변환 옵션은 필수 JSON 포인터 배열 (mandatoryPointers)을 포함해야 하며 JSON-LD 문서 로더와 같은 추가 옵션을 포함할 수 있다. 변환된 데이터 문서가 출력으로 생성된다. 이 알고리즘이 문자열을 인코딩할 때는 언제나 UTF-8 인코딩을 사용해야 한다.

  1. hmac를 로컬에서 생성되고 내보내기 가능한 HMAC 키를 사용하는 HMAC API로 초기화한다. HMAC는 서명 알고리즘에서 사용되는 것과 동일한 해시 알고리즘을 사용하며, 이는 함수에 제공된 verificationMethod를 통해 감지된다. 즉, P-256 곡선의 경우 SHA-256이다. [RFC2104]의 권고에 따라, HMAC 키는 다이제스트 크기와 동일한 길이이어야 한다. SHA-256의 경우 이는 256비트 또는 32바이트이다.
  2. labelMapFactoryFunctionhmac를 전달하여 3.4.4 createHmacIdLabelMapFunction 절 알고리즘을 호출한 결과로 초기화한다.
  3. groupDefinitions를 문자열 "mandatory" 키와 mandatoryPointers 값을 갖는 항목이 있는 맵으로 초기화한다.
  4. groupslabelMapFactoryFunction, groupDefinitions, unsecuredDocumentdocument로, 그리고 임의의 사용자 지정 JSON-LD API 옵션을 전달하여 3.4.16 canonicalizeAndGroup 절의 알고리즘을 호출한 결과로 초기화한다. 참고: 이 단계는 문서를 hmac에 기반한 의사난수 공백 노드 식별자를 가진 정규 N-Quads 배열로 변환하고, JSON 포인터에 기반한 선택에 따라 N-Quad 문자열을 그룹화한다.
  5. mandatorygroups.mandatory.matching 맵의 값들로 초기화한다.
  6. nonMandatorygroups.mandatory.nonMatching 맵의 값들로 초기화한다.
  7. hmacKeyhmac에서 HMAC 키를 내보낸 결과로 초기화한다.
  8. mandatoryPointersmandatoryPointers로, mandatorymandatory로, nonMandatorynonMandatory로, hmacKeyhmacKey로 설정한 객체를 반환한다.

3.6.3 기본 증명 해싱(ecdsa-sd-2023)

다음 알고리즘은 변환된 데이터 문서증명 구성3.6.5 기본 증명 직렬화(ecdsa-sd-2023) 절의 알고리즘에 입력으로 제공될 준비가 된 암호학적 해시 데이터로 암호학적으로 해싱하는 방법을 지정한다.

이 알고리즘에 필요한 입력은 변환된 데이터 문서 (transformedDocument)와 정규 증명 구성 (canonicalProofConfig)이다. 객체로 표현되는 해시 데이터 값이 출력으로 생성된다.

  1. proofHashcanonicalProofConfig에 대해 RDF 데이터셋 정규화 알고리즘 [RDF-CANON]을 호출한 뒤 그 결과를 서명 알고리즘에서 사용하는 것과 동일한 해시, 즉 P-256 곡선의 경우 SHA-256을 사용하여 암호학적으로 해싱한 결과로 초기화한다. 참고: 이 단계는 병렬로 수행할 수 있다. 그 결과가 반환 값의 일부이므로 이 알고리즘이 종료되기 전에만 완료되면 된다.
  2. mandatoryHashtransformedDocument.mandatory를 전달하여 3.4.17 hashMandatoryNQuads 절의 알고리즘을 호출한 결과로 초기화한다.
  3. hashDatatransformedDocument의 깊은 복사로 초기화하고, 그 객체에 proofHashproofHash로, mandatoryHashmandatoryHash로 추가한다.
  4. hashData해시 데이터로 반환한다.

3.6.4 기본 증명 구성(ecdsa-sd-2023)

다음 알고리즘은 기본 증명 해싱 알고리즘에 입력으로 사용되는 증명 구성증명 옵션 집합으로부터 생성하는 방법을 지정한다.

이 알고리즘에 필요한 입력은 증명 옵션(options)과 비보안 데이터 문서(unsecuredDocument)이다. 증명 옵션 암호 스위트에 대한 타입 식별자(type)를 포함해야 하며 암호 스위트 식별자(cryptosuite)를 포함해야 한다. 증명 구성 객체가 출력으로 생성된다.

  1. proofConfigoptions 객체의 복제본으로 둔다.
  2. proofConfig.typeDataIntegrityProof로 설정되어 있지 않거나 proofConfig.cryptosuiteecdsa-sd-2023으로 설정되어 있지 않으면, 오류를 일으켜야 하며 PROOF_GENERATION_ERROR 오류 유형을 전달하는 것이 좋다.
  3. proofConfig.created가 설정되어 있고 그 값이 유효한 [XMLSCHEMA11-2] datetime이 아니면, 오류를 일으켜야 하며 PROOF_GENERATION_ERROR 오류 유형을 전달하는 것이 좋다.
  4. proofConfig.@contextunsecuredDocument.@context로 설정한다.
  5. canonicalProofConfigproofConfigRDF 데이터셋 정규화 [RDF-CANON]를 적용한 결과로 둔다.
  6. canonicalProofConfig를 반환한다.

3.6.5 기본 증명 직렬화(ecdsa-sd-2023)

다음 알고리즘은 기본 증명을 생성하는 방법을 지정한다. 이는 ECDSA-SD로 보호된 검증가능한 크리덴셜의 발급자가 호출한다. 기본 증명은 보유자에게만 주어져야 하며, 보유자는 그것으로부터 파생 증명을 생성하여 증명에서 선택적으로 공개된 세부 정보만 검증자에게 노출할 책임이 있다. 이 알고리즘은 데이터 무결성 [VC-DATA-INTEGRITY] 규격의 4절: 알고리즘에 정의된 알고리즘과 함께 사용되도록 설계되었다. 필요한 입력은 암호학적 해시 데이터(hashData)와 증명 옵션(options)이다. 증명 옵션 암호 스위트에 대한 타입 식별자(type)를 포함해야 하며 암호 스위트 식별자(cryptosuite)를 포함할 수 있다. 바이트열로 표현되는 단일 디지털 증명 값이 출력으로 생성된다.

  1. proofHash, mandatoryPointers, mandatoryHash, nonMandatory, hmacKeyhashData에서 각각의 속성 이름에 연관된 값으로 초기화한다.
  2. proofScopedKeyPair를 로컬에서 생성된 P-256 ECDSA 키 쌍으로 초기화한다. 참고: 이 키 쌍은 특정 증명에 한정된다. 다른 어떤 용도로도 사용되지 않으며 개인키는 이 알고리즘이 종료될 때 파기된다.
  3. signatures를, 각 요소가 nonMandatory의 각 N-Quad 문자열의 UTF-8 표현을 순서대로 디지털 서명한 결과를 담는 배열로 초기화한다. 디지털 서명 알고리즘은 ES256이며, 즉 SHA-256 다이제스트에 대해 P-256 곡선을 사용하고 proofScopedKeyPair의 개인키를 사용한다. 참고: 이 단계는 선택적으로 공개될 수 있는 각 문에 대해, 그것들을 함께 묶는 로컬 증명 범위 키 쌍을 사용하여 개별 서명을 생성한다. 이 키 쌍은 기본 증명 검증 방법에 연관된 개인키를 사용하여 그 공개키에 대한 서명으로 증명에 묶인다.
  4. publicKeyproofScopedKeyPair에서 내보낸 공개키의 multikey 표현으로 초기화한다. 즉, 바이트 0x80과 0x24(varint로 표현된 multikey p256-pub 헤더(0x1200))로 시작하고 그 뒤에 압축된 공개키 바이트(짝수 y 좌표의 경우 2, 홀수의 경우 3인 압축 헤더 뒤에 공개키의 x 좌표가 오는 것)가 오는 바이트 배열이다.
  5. toSignproofHash, publicKey, mandatoryHash를 알고리즘의 매개변수로 전달하여 3.5.1 serializeSignData 절의 알고리즘을 호출한 결과로 초기화한다.
  6. baseSignature를 기본 증명 검증 방법에 연관된 개인키를 사용하여 toSign을 디지털 서명한 결과로 초기화한다.
  7. proofValuebaseSignature, publicKey, hmacKey, signatures, mandatoryPointers를 알고리즘의 매개변수로 전달하여 3.5.2 serializeBaseProofValue 절의 알고리즘을 호출한 결과로 초기화한다.
  8. proofValue디지털 증명으로 반환한다.

3.6.6 파생 증명 추가(ecdsa-sd-2023)

다음 알고리즘은 선택적 공개 파생 증명을 생성한다. 이는 ecdsa-sd-2023으로 보호된 검증가능한 크리덴셜의 보유자가 호출한다. 파생 증명은 검증자에게 주어진다. 입력에는 JSON-LD 문서(document), ECDSA-SD 기본 증명 (proof), 문을 선택적으로 공개하는 데 사용할 JSON 포인터 배열 (selectivePointers), 그리고 문서 로더와 같은 임의의 사용자 지정 JSON-LD API 옵션이 포함된다. 객체로 표현되는 단일 선택적으로 공개된 문서 값이 출력으로 생성된다.

  1. baseSignature, publicKey, signatures, labelMap, mandatoryIndexes, revealDocumentdocument, proof, selectivePointers, 그리고 문서 로더와 같은 임의의 사용자 지정 JSON-LD API 옵션을 전달하여 3.5.4 createDisclosureData 절의 알고리즘을 호출했을 때 반환되는 객체에서 각각의 속성 이름에 연관된 값으로 초기화한다.
  2. newProofproof의 얕은 복사로 초기화한다.
  3. newProofproofValuebaseSignature, publicKey, signatures, labelMap, mandatoryIndexes를 전달하여 3.5.7 serializeDerivedProofValue 절의 알고리즘을 호출한 결과로 교체한다.
  4. revealDocument의 "proof" 속성 값을 newProof로 설정한다.
  5. revealDocument선택적으로 공개된 문서로 반환한다.

3.6.7 파생 증명 검증(ecdsa-sd-2023)

다음 알고리즘은 ecdsa-sd-2023 파생 증명의 검증을 시도한다. 이 알고리즘은 ECDSA-SD로 보호된 검증가능한 크리덴셜의 검증자가 호출한다. 입력에는 JSON-LD 문서(document), ECDSA-SD 공개 증명(proof), 그리고 문서 로더와 같은 임의의 사용자 지정 JSON-LD API 옵션이 포함된다. 이 알고리즘은 검증 결과를 반환한다:

  1. unsecuredDocumentdocument에서 proof 값을 제거한 사본으로 둔다.
  2. baseSignature, proofHash, publicKey, signatures, nonMandatory, mandatoryHashdocument, proof, 그리고 문서 로더와 같은 임의의 사용자 지정 JSON-LD API 옵션을 전달하여 3.5.9 createVerifyData 절의 알고리즘을 호출했을 때 반환되는 객체에서 각각의 속성 이름에 연관된 값으로 초기화한다.
  3. signatures의 길이가 nonMandatory의 길이와 일치하지 않으면, 서명 개수가 비필수 메시지 개수와 일치하지 않음을 나타내는 오류를 일으켜야 하며 PROOF_VERIFICATION_ERROR 오류 유형을 전달하는 것이 좋다.
  4. publicKeyBytespublicKey에 표현된 공개키 바이트로 초기화한다. 공개키 값을 디코딩하는 방법에 대한 설명은 2.1.1 Multikey 절에서 찾을 수 있다.
  5. toVerifyproofHash, publicKey, mandatoryHash를 전달하여 3.5.1 serializeSignData 절의 알고리즘을 호출한 결과로 초기화한다.
  6. verified를 true로 초기화한다.
  7. verificationCheckpublicKeyBytes로 지정된 공개키를 사용하여 baseSignature에 대해 검증할 데이터로 toVerify를 사용해 타원곡선 디지털 서명 알고리즘(ECDSA) [FIPS-186-5]의 검증 알고리즘을 적용한 결과로 초기화한다. verificationCheckfalse이면, verified를 false로 설정한다.
  8. signatures의 모든 항목(index, signature)에 대해, 선택적으로 공개된 (비필수) 모든 문에 대한 모든 서명을 검증한다:
    1. verificationCheckpublicKeyBytes로 지정된 공개키를 사용하여 signature에 대해 검증할 데이터로 nonMandatoryindex 위치 값의 UTF-8 표현을 사용해 타원곡선 디지털 서명 알고리즘(ECDSA) [FIPS-186-5] 검증 알고리즘을 적용한 결과로 초기화한다.
    2. verificationCheckfalse이면, verified를 false로 설정한다.
  9. 다음 항목을 갖는 검증 결과를 반환한다:
    verified
    verified의 값
    verifiedDocument
    verifiedtrue이면 unsecuredDocument, 그렇지 않으면 Null

4. 보안 고려사항

이 부분은 비규범적입니다.

이 절을 읽기 전에, 독자는 데이터 무결성 규격의 보안 고려사항 절에서 제공되는 일반적인 보안 조언을 숙지할 것을 강력히 권한다.

이 암호 스위트로 보호되는 보안 문서의 무결성과 진정성은 다음을 포함한 여러 요인에 의존한다:

다음 절들에서 이러한 중요한 사항을 검토하고 독자를 추가 정보로 안내한다.

4.1 ECDSA와 매개변수 선택

이 부분은 비규범적입니다.

ECDSA 서명 스킴은 EUF-CMA(선택 메시지 공격 하에서의 존재적 위조 불가능성) 보안 속성을 갖는다. 이 속성은, 서명자의 공개키 pk를 가지고 자신이 선택한 메시지에 대한 임의 개수의 서명을 (적응적으로) 받은 어떤 효율적인 공격자라도 새로운 메시지에 대한 유효한 서명을 (무시할 수 있는 확률을 제외하고) 출력할 수 없음을 보장한다.

SUF-CMA(선택 메시지 공격 하에서의 강한 위조 불가능성)는 EUF-CMA보다 더 강한 개념이다. 이는 서명자의 공개키 pk를 가지고 자신이 선택한 메시지에 대한 임의 개수의 서명을 받은 어떤 효율적인 공격자라도 새로운 메시지에 대한 새로운 유효한 서명 쌍이나 기존 메시지에 대한 새로운 서명을 (무시할 수 있는 확률을 제외하고) 출력할 수 없음을 보장한다. ECDSA 서명 스킴은 SUF-CMA 속성을 갖지 않지만, EdDSA [FIPS-186-5]와 같은 다른 스킴은 갖는다.

[NIST-SP-800-57-Part-1]에 따르면, 대규모 양자 컴퓨터가 없는 경우 128비트의 보안 강도 수준은 약 256비트의 키 크기를 요구하는 반면, 192비트의 보안 강도 수준은 384비트의 키 크기를 요구한다. [NIST-SP-800-186]의 권고에는 이러한 각각의 보안 강도 수준에서 P-256과 P-384 곡선이 포함된다.

4.2 ECDSA 알고리즘 구현 고려사항

이 부분은 비규범적입니다.

[FIPS-186-5]에 상세히 기술된 ECDSA 알고리즘은 다음과 같이 명시한다: "새로운 비밀 난수 k(0 < k < n)는 서명 생성 과정에서 사용하기 위해 각 디지털 서명의 생성에 앞서 생성되어야 한다." 이 k 값을 제대로 생성하지 못한 것은 널리 배포된 시스템에서 크게 공론화된 몇몇 무결성 침해로 이어졌다. 이 문제에 대응하기 위해, 결정론적 ECDSA라고 불리는, 비밀 난수 k를 결정하는 해시 기반 방법이 [FIPS-186-5]와 [RFC6979]에 제시되어 있다.

ECDSA 서명의 검증은 k를 생성하는 방법과 무관하다. 따라서 다른 요구사항이 달리 요구하지 않는 한 일반적으로 결정론적 ECDSA를 사용하는 것이 권장된다. 예를 들어, 서로 다른 k 값을 사용하면 동일한 문서에 대해 서로 다른 서명 값이 생성되는데, 이는 일부 프라이버시 강화 상황에서 바람직한 속성일 수 있다.

4.3 키 관리

이 부분은 비규범적입니다.

ECDSA 알고리즘의 보안은 그 개인 서명 키의 품질과 보호에 의존한다. 암호화 키의 관리에 관한 지침은 방대한 주제이며, 더 광범위한 권고와 논의에 대해서는 독자에게 [NIST-SP-800-57-Part-1]을 참조하도록 안내한다. [FIPS-186-5]와 [NIST-SP-800-57-Part-1] 양쪽에서 강력히 권장하듯이, ECDSA 개인 서명 키는 ECDSA 서명 외의 다른 어떤 용도로도 사용되어서는 안 된다.

ECDSA 개인 서명 키와 공개 검증 키는 제한된 암호기간(cryptoperiod) [NIST-SP-800-57-Part-1]을 갖도록 강력히 권고되며, 여기서 암호기간이란 "특정 키가 정당한 엔티티에 의해 사용하도록 인가되어 있거나 주어진 시스템의 키가 유효하게 유지되는 기간"이다. [NIST-SP-800-57-Part-1]은 서로 다른 상황에서 서로 다른 키 유형에 대한 암호기간에 관한 광범위한 지침을 제공하며, 일반적으로 개인 서명 키에 대해 1~3년의 암호기간을 권장한다.

잠재적인 개인키 유출에 대처하기 위해, [NIST-SP-800-57-Part-1]은 보호 조치, 피해 경감, 폐기에 관한 권고를 제공한다. 우리가 개인 서명 키의 보안을 강조해 왔지만, [NIST-SP-800-57-Part-1]에 따라 모든 공개키에 대해 사용하기 전에 공개키 유효성의 보증이 강력히 권장된다.

5. 프라이버시 고려사항

이 절을 읽기 전에, 독자는 데이터 무결성 규격의 프라이버시 고려사항 절에서 제공되는 일반적인 프라이버시 조언을 숙지할 것을 강력히 권한다.

다음 절은 이 규격을 구현하는 개발자가 프라이버시 가정을 위반하지 않기 위해 알고 있어야 할 프라이버시 고려사항을 설명한다.

5.1 연결 불가능한 공개

이 규격에 기술된 암호 스위트는 연결 불가능한 공개를 지원하지 않는다. 연결 불가능한 공개에 관심이 있다면, Data Integrity BBS Cryptosuites v1.0 규격이 연결 불가능한 디지털 서명 메커니즘을 제공한다.

A. 테스트 벡터

이 부분은 비규범적입니다.

참고

모든 테스트 벡터는 결정론적 ECDSA를 사용하여 생성된다. 구현은 [RFC6979]의 테스트 벡터에 대해 검증되었다.

A.1 표현: ecdsa-rdfc-2019, 곡선 P-256

서명자는 서명에 사용되는 개인키와 검증을 위해 제공되는 공개키로 이루어진 개인키/공개키 쌍을 생성해야 한다. 공개키의 표현과 개인키의 표현을 아래에 나타낸다.

예시 5: 서명용 개인키 및 공개키
{
  "publicKeyMultibase": "zDnaepBuvsQ8cpsWrVKw8fbpGpvPeNSjVPTWoq6cRqaYzBKVP",
  "secretKeyMultibase": "z42twTcNeSYcnqg1FLuSFs2bsGH3ZqbRHFmvS9XMsYhjxvHN"
}

서명은 첨부된 증명이 없는 크리덴셜로 시작하며, 이는 정규형으로 변환된 뒤 해싱된다. 이는 다음 세 예시에 나타나 있다.

예시 6: 증명 없는 크리덴셜
{
    "@context": [
        "https://www.w3.org/ns/credentials/v2",
        "https://www.w3.org/ns/credentials/examples/v2"
    ],
    "id": "urn:uuid:58172aac-d8ba-11ed-83dd-0b3aef56cc33",
    "type": ["VerifiableCredential", "AlumniCredential"],
    "name": "Alumni Credential",
    "description": "A minimum viable example of an Alumni Credential.",
    "issuer": "https://vc.example/issuers/5678",
    "validFrom": "2023-01-01T00:00:00Z",
    "credentialSubject": {
        "id": "did:example:abcdefgh",
        "alumniOf": "The School of Examples"
    }
}
예시 7: 증명 없는 크리덴셜의 정규형
<did:example:abcdefgh> <https://www.w3.org/ns/credentials/examples#alumniOf> "The School of Examples" .
<urn:uuid:58172aac-d8ba-11ed-83dd-0b3aef56cc33> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://www.w3.org/2018/credentials#VerifiableCredential> .
<urn:uuid:58172aac-d8ba-11ed-83dd-0b3aef56cc33> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://www.w3.org/ns/credentials/examples#AlumniCredential> .
<urn:uuid:58172aac-d8ba-11ed-83dd-0b3aef56cc33> <https://schema.org/description> "A minimum viable example of an Alumni Credential." .
<urn:uuid:58172aac-d8ba-11ed-83dd-0b3aef56cc33> <https://schema.org/name> "Alumni Credential" .
<urn:uuid:58172aac-d8ba-11ed-83dd-0b3aef56cc33> <https://www.w3.org/2018/credentials#credentialSubject> <did:example:abcdefgh> .
<urn:uuid:58172aac-d8ba-11ed-83dd-0b3aef56cc33> <https://www.w3.org/2018/credentials#issuer> <https://vc.example/issuers/5678> .
<urn:uuid:58172aac-d8ba-11ed-83dd-0b3aef56cc33> <https://www.w3.org/2018/credentials#validFrom> "2023-01-01T00:00:00Z"^^<http://www.w3.org/2001/XMLSchema#dateTime> .
예시 8: 증명 없는 크리덴셜 정규형의 해시(hex)
517744132ae165a5349155bef0bb0cf2258fff99dfe1dbd914b938d775a36017

다음 단계는 증명 옵션 문서를 가져와 정규형으로 변환하고 그 해시를 얻는 것이며, 이는 다음 세 예시에 나타나 있다.

예시 9: 증명 옵션 문서
{
  "type": "DataIntegrityProof",
  "cryptosuite": "ecdsa-rdfc-2019",
  "created": "2023-02-24T23:36:38Z",
  "verificationMethod": "did:key:zDnaepBuvsQ8cpsWrVKw8fbpGpvPeNSjVPTWoq6cRqaYzBKVP#zDnaepBuvsQ8cpsWrVKw8fbpGpvPeNSjVPTWoq6cRqaYzBKVP",
  "proofPurpose": "assertionMethod",
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    "https://www.w3.org/ns/credentials/examples/v2"
  ]
}
예시 10: 정규 증명 옵션 문서
_:c14n0 <http://purl.org/dc/terms/created> "2023-02-24T23: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> "ecdsa-rdfc-2019"^^<https://w3id.org/security#cryptosuiteString> .
_:c14n0 <https://w3id.org/security#proofPurpose> <https://w3id.org/security#assertionMethod> .
_:c14n0 <https://w3id.org/security#verificationMethod> <did:key:zDnaepBuvsQ8cpsWrVKw8fbpGpvPeNSjVPTWoq6cRqaYzBKVP#zDnaepBuvsQ8cpsWrVKw8fbpGpvPeNSjVPTWoq6cRqaYzBKVP> .
예시 11: 정규 증명 옵션 문서의 해시(hex)
3a8a522f689025727fb9d1f0fa99a618da023e8494ac74f51015d009d35abc2e

마지막으로, 증명 옵션의 해시 뒤에 증명 없는 크리덴셜의 해시를 연결하고, 결합된 해시에 개인키를 사용하여 ECDSA 서명을 계산한 뒤, 그 서명을 base-58-btc로 인코딩한다.

예시 12: 증명 옵션과 크리덴셜의 해시 결합(hex)
3a8a522f689025727fb9d1f0fa99a618da023e8494ac74f51015d009d35abc2e517744132ae165a5349155bef0bb0cf2258fff99dfe1dbd914b938d775a36017
예시 13: 결합된 해시의 서명(hex)
1cb4290918ffb04a55ff7ae1e55e316a9990fda8eec67325eac7fcbf2ddf9dd2b06716a657e72b284c9604df3a172ecbf06a1a475b49ac807b1d9162df855636
예시 14: 결합된 해시의 서명 base-58-btc
zaHXrr7AQdydBk3ahpCDpWbxfLokDqmCToYm2dyWvpcFVyWooC2he63w1f7UNQoAMKdhaRtcnaE2KTo5o5vTCcfw

다음 두 단계로 서명된 크리덴셜을 조립한다:

  1. Add the proofValue field with the previously computed base-58-btc value to the proof options document.
  2. Set the proof field of the credential to the augmented proof option document.
예시 15: 서명된 크리덴셜
{
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    "https://www.w3.org/ns/credentials/examples/v2"
  ],
  "id": "urn:uuid:58172aac-d8ba-11ed-83dd-0b3aef56cc33",
  "type": [
    "VerifiableCredential",
    "AlumniCredential"
  ],
  "name": "Alumni Credential",
  "description": "A minimum viable example of an Alumni Credential.",
  "issuer": "https://vc.example/issuers/5678",
  "validFrom": "2023-01-01T00:00:00Z",
  "credentialSubject": {
    "id": "did:example:abcdefgh",
    "alumniOf": "The School of Examples"
  },
  "proof": {
    "type": "DataIntegrityProof",
    "cryptosuite": "ecdsa-rdfc-2019",
    "created": "2023-02-24T23:36:38Z",
    "verificationMethod": "did:key:zDnaepBuvsQ8cpsWrVKw8fbpGpvPeNSjVPTWoq6cRqaYzBKVP#zDnaepBuvsQ8cpsWrVKw8fbpGpvPeNSjVPTWoq6cRqaYzBKVP",
    "proofPurpose": "assertionMethod",
    "proofValue": "zaHXrr7AQdydBk3ahpCDpWbxfLokDqmCToYm2dyWvpcFVyWooC2he63w1f7UNQoAMKdhaRtcnaE2KTo5o5vTCcfw"
  }
}

A.2 표현에 대한 확장 예시: ecdsa-rdfc-2019, 곡선 P-256

여기서는 ecdsa-rdfc-2019 곡선 P-256 서명 크리덴셜을 생성하는 단계를 다시 거치되, 더 복잡한 입력 문서를 사용한다. 공개키의 표현과 개인키의 표현을 아래에 나타낸다.

예시 16: 서명용 개인키 및 공개키
{
  "publicKeyMultibase": "zDnaepBuvsQ8cpsWrVKw8fbpGpvPeNSjVPTWoq6cRqaYzBKVP",
  "secretKeyMultibase": "z42twTcNeSYcnqg1FLuSFs2bsGH3ZqbRHFmvS9XMsYhjxvHN"
}

서명은 첨부된 증명이 없는 크리덴셜로 시작하며, 이는 정규형으로 변환된 뒤 해싱된다. 이는 다음 세 예시에 나타나 있다.

예시 17: 증명 없는 취업 허가 크리덴셜
{
    "@context": [
      "https://www.w3.org/ns/credentials/v2",
      "https://w3id.org/citizenship/v4rc1"
    ],
    "type": [
      "VerifiableCredential",
      "EmploymentAuthorizationDocumentCredential"
    ],
    "issuer": {
      "id": "did:key:zDnaegE6RR3atJtHKwTRTWHsJ3kNHqFwv7n9YjTgmU7TyfU76",
      "image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2NgUPr/HwADaAIhG61j/AAAAABJRU5ErkJggg=="
    },
    "credentialSubject": {
      "type": [
        "Person",
        "EmployablePerson"
      ],
      "givenName": "JOHN",
      "additionalName": "JACOB",
      "familyName": "SMITH",
      "image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2Ng+M/wHwAEAQH/7yMK/gAAAABJRU5ErkJggg==",
      "gender": "Male",
      "residentSince": "2015-01-01",
      "birthCountry": "Bahamas",
      "birthDate": "1999-07-17",
      "employmentAuthorizationDocument": {
        "type": "EmploymentAuthorizationDocument",
        "identifier": "83627465",
        "lprCategory": "C09",
        "lprNumber": "999-999-999"
      }
    },
    "name": "Employment Authorization Document",
    "description": "Example Employment Authorization Document.",
    "validFrom": "2019-12-03T00:00:00Z",
    "validUntil": "2029-12-03T00:00:00Z"
  }
예시 18: 증명 없는 취업 허가 크리덴셜의 정규형
<did:key:zDnaegE6RR3atJtHKwTRTWHsJ3kNHqFwv7n9YjTgmU7TyfU76> <https://schema.org/image> <data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2NgUPr/HwADaAIhG61j/AAAAABJRU5ErkJggg==> .
_:c14n0 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/citizenship#EmploymentAuthorizationDocumentCredential> .
_:c14n0 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://www.w3.org/2018/credentials#VerifiableCredential> .
_:c14n0 <https://schema.org/description> "Example Employment Authorization Document." .
_:c14n0 <https://schema.org/name> "Employment Authorization Document" .
_:c14n0 <https://www.w3.org/2018/credentials#credentialSubject> _:c14n1 .
_:c14n0 <https://www.w3.org/2018/credentials#issuer> <did:key:zDnaegE6RR3atJtHKwTRTWHsJ3kNHqFwv7n9YjTgmU7TyfU76> .
_:c14n0 <https://www.w3.org/2018/credentials#validFrom> "2019-12-03T00:00:00Z"^^<http://www.w3.org/2001/XMLSchema#dateTime> .
_:c14n0 <https://www.w3.org/2018/credentials#validUntil> "2029-12-03T00:00:00Z"^^<http://www.w3.org/2001/XMLSchema#dateTime> .
_:c14n1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://schema.org/Person> .
_:c14n1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/citizenship#EmployablePerson> .
_:c14n1 <https://schema.org/additionalName> "JACOB" .
_:c14n1 <https://schema.org/birthDate> "1999-07-17"^^<http://www.w3.org/2001/XMLSchema#dateTime> .
_:c14n1 <https://schema.org/familyName> "SMITH" .
_:c14n1 <https://schema.org/gender> "Male" .
_:c14n1 <https://schema.org/givenName> "JOHN" .
_:c14n1 <https://schema.org/image> <data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2Ng+M/wHwAEAQH/7yMK/gAAAABJRU5ErkJggg==> .
_:c14n1 <https://w3id.org/citizenship#birthCountry> "Bahamas" .
_:c14n1 <https://w3id.org/citizenship#employmentAuthorizationDocument> _:c14n2 .
_:c14n1 <https://w3id.org/citizenship#residentSince> "2015-01-01"^^<http://www.w3.org/2001/XMLSchema#dateTime> .
_:c14n2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/citizenship#EmploymentAuthorizationDocument> .
_:c14n2 <https://schema.org/identifier> "83627465" .
_:c14n2 <https://w3id.org/citizenship#lprCategory> "C09" .
_:c14n2 <https://w3id.org/citizenship#lprNumber> "999-999-999" .
예시 19: 증명 없는 크리덴셜 정규형의 해시(hex)
03f59e5b04ab575b1172cb684f22eede72f0e9033e0b5c67d0e2506768d6ce11

다음 단계는 증명 옵션 문서를 가져와 정규형으로 변환하고 그 해시를 얻는 것이며, 이는 다음 세 예시에 나타나 있다.

예시 20: 증명 옵션 문서
{
  "type": "DataIntegrityProof",
  "cryptosuite": "ecdsa-rdfc-2019",
  "created": "2023-02-24T23:36:38Z",
  "verificationMethod": "did:key:zDnaepBuvsQ8cpsWrVKw8fbpGpvPeNSjVPTWoq6cRqaYzBKVP#zDnaepBuvsQ8cpsWrVKw8fbpGpvPeNSjVPTWoq6cRqaYzBKVP",
  "proofPurpose": "assertionMethod",
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    "https://w3id.org/citizenship/v4rc1"
  ]
}
예시 21: 정규 증명 옵션 문서
_:c14n0 <http://purl.org/dc/terms/created> "2023-02-24T23: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> "ecdsa-rdfc-2019"^^<https://w3id.org/security#cryptosuiteString> .
_:c14n0 <https://w3id.org/security#proofPurpose> <https://w3id.org/security#assertionMethod> .
_:c14n0 <https://w3id.org/security#verificationMethod> <did:key:zDnaepBuvsQ8cpsWrVKw8fbpGpvPeNSjVPTWoq6cRqaYzBKVP#zDnaepBuvsQ8cpsWrVKw8fbpGpvPeNSjVPTWoq6cRqaYzBKVP> .
예시 22: 정규 증명 옵션 문서의 해시(hex)
3a8a522f689025727fb9d1f0fa99a618da023e8494ac74f51015d009d35abc2e

마지막으로, 증명 옵션의 해시 뒤에 증명 없는 크리덴셜의 해시를 연결하고, 결합된 해시에 개인키를 사용하여 ECDSA 서명을 계산한 뒤, 그 서명을 base-58-btc로 인코딩한다.

예시 23: 증명 옵션과 크리덴셜의 해시 결합(hex)
3a8a522f689025727fb9d1f0fa99a618da023e8494ac74f51015d009d35abc2e03f59e5b04ab575b1172cb684f22eede72f0e9033e0b5c67d0e2506768d6ce11
예시 24: 결합된 해시의 서명(hex)
c6798ff29f725dfd39aa4daf60fbb423cf9baf4e157f6b49f112c201015c6e730dc877154e65cf467f8ee2b61ec86d98ed78334b1cc9f3dba2e1745f37205e92
예시 25: 결합된 해시의 서명 base-58-btc
z4y9rJ7JxwfZZUBAHgDHJh7FzMbsycPhEtcSHqrfyn7fx3S5MWdajNu1r6SsJmirzfcWHe7vp9XKHmRqW6qe7u3d3

다음 두 단계로 서명된 크리덴셜을 조립한다:

  1. Add the proofValue field with the previously computed base-58-btc value to the proof options document.
  2. Set the proof field of the credential to the augmented proof option document.
예시 26: 서명된 취업 허가 크리덴셜
{
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    "https://w3id.org/citizenship/v4rc1"
  ],
  "type": [
    "VerifiableCredential",
    "EmploymentAuthorizationDocumentCredential"
  ],
  "issuer": {
    "id": "did:key:zDnaegE6RR3atJtHKwTRTWHsJ3kNHqFwv7n9YjTgmU7TyfU76",
    "image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2NgUPr/HwADaAIhG61j/AAAAABJRU5ErkJggg=="
  },
  "credentialSubject": {
    "type": [
      "Person",
      "EmployablePerson"
    ],
    "givenName": "JOHN",
    "additionalName": "JACOB",
    "familyName": "SMITH",
    "image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2Ng+M/wHwAEAQH/7yMK/gAAAABJRU5ErkJggg==",
    "gender": "Male",
    "residentSince": "2015-01-01",
    "birthCountry": "Bahamas",
    "birthDate": "1999-07-17",
    "employmentAuthorizationDocument": {
      "type": "EmploymentAuthorizationDocument",
      "identifier": "83627465",
      "lprCategory": "C09",
      "lprNumber": "999-999-999"
    }
  },
  "name": "Employment Authorization Document",
  "description": "Example Employment Authorization Document.",
  "validFrom": "2019-12-03T00:00:00Z",
  "validUntil": "2029-12-03T00:00:00Z",
  "proof": {
    "type": "DataIntegrityProof",
    "cryptosuite": "ecdsa-rdfc-2019",
    "created": "2023-02-24T23:36:38Z",
    "verificationMethod": "did:key:zDnaepBuvsQ8cpsWrVKw8fbpGpvPeNSjVPTWoq6cRqaYzBKVP#zDnaepBuvsQ8cpsWrVKw8fbpGpvPeNSjVPTWoq6cRqaYzBKVP",
    "proofPurpose": "assertionMethod",
    "proofValue": "z4y9rJ7JxwfZZUBAHgDHJh7FzMbsycPhEtcSHqrfyn7fx3S5MWdajNu1r6SsJmirzfcWHe7vp9XKHmRqW6qe7u3d3"
  }
}

A.3 표현: ecdsa-rdfc-2019, 곡선 P-384

서명자는 서명에 사용되는 개인키와 검증을 위해 제공되는 공개키로 이루어진 개인키/공개키 쌍을 생성해야 한다. 공개키의 표현과 개인키의 표현을 아래에 나타낸다.

예시 27: 서명용 개인키 및 공개키
{
  "publicKeyMultibase": "z82LkuBieyGShVBhvtE2zoiD6Kma4tJGFtkAhxR5pfkp5QPw4LutoYWhvQCnGjdVn14kujQ",
  "secretKeyMultibase": "z2fanyY7zgwNpZGxX5fXXibvScNaUWNprHU9dKx7qpVj7mws9J8LLt4mDB5TyH2GLHWkUc"
}

서명은 첨부된 증명이 없는 크리덴셜로 시작하며, 이는 정규형으로 변환된 다음 해싱된다. 이는 다음 세 예시에 나타나 있다.

예시 28: 증명 없는 크리덴셜
{
    "@context": [
        "https://www.w3.org/ns/credentials/v2",
        "https://www.w3.org/ns/credentials/examples/v2"
    ],
    "id": "urn:uuid:58172aac-d8ba-11ed-83dd-0b3aef56cc33",
    "type": ["VerifiableCredential", "AlumniCredential"],
    "name": "Alumni Credential",
    "description": "A minimum viable example of an Alumni Credential.",
    "issuer": "https://vc.example/issuers/5678",
    "validFrom": "2023-01-01T00:00:00Z",
    "credentialSubject": {
        "id": "did:example:abcdefgh",
        "alumniOf": "The School of Examples"
    }
}
예시 29: 증명 없는 크리덴셜의 정규형
<did:example:abcdefgh> <https://www.w3.org/ns/credentials/examples#alumniOf> "The School of Examples" .
<urn:uuid:58172aac-d8ba-11ed-83dd-0b3aef56cc33> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://www.w3.org/2018/credentials#VerifiableCredential> .
<urn:uuid:58172aac-d8ba-11ed-83dd-0b3aef56cc33> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://www.w3.org/ns/credentials/examples#AlumniCredential> .
<urn:uuid:58172aac-d8ba-11ed-83dd-0b3aef56cc33> <https://schema.org/description> "A minimum viable example of an Alumni Credential." .
<urn:uuid:58172aac-d8ba-11ed-83dd-0b3aef56cc33> <https://schema.org/name> "Alumni Credential" .
<urn:uuid:58172aac-d8ba-11ed-83dd-0b3aef56cc33> <https://www.w3.org/2018/credentials#credentialSubject> <did:example:abcdefgh> .
<urn:uuid:58172aac-d8ba-11ed-83dd-0b3aef56cc33> <https://www.w3.org/2018/credentials#issuer> <https://vc.example/issuers/5678> .
<urn:uuid:58172aac-d8ba-11ed-83dd-0b3aef56cc33> <https://www.w3.org/2018/credentials#validFrom> "2023-01-01T00:00:00Z"^^<http://www.w3.org/2001/XMLSchema#dateTime> .
예시 30: 증명 없는 크리덴셜 정규형의 해시(hex)
8bf6e01df72c5b62f91b685231915ac4b8c58ea95f002c6b8f6bfafa1b251df476b56b8e01518e317dab099d3ecbff96

다음 단계는 증명 옵션 문서를 가져와 정규형으로 변환하고 그 해시를 얻는 것이며, 이는 다음 세 예시에 나타나 있다.

예시 31: 증명 옵션 문서
{
  "type": "DataIntegrityProof",
  "cryptosuite": "ecdsa-rdfc-2019",
  "created": "2023-02-24T23:36:38Z",
  "verificationMethod": "did:key:z82LkuBieyGShVBhvtE2zoiD6Kma4tJGFtkAhxR5pfkp5QPw4LutoYWhvQCnGjdVn14kujQ#z82LkuBieyGShVBhvtE2zoiD6Kma4tJGFtkAhxR5pfkp5QPw4LutoYWhvQCnGjdVn14kujQ",
  "proofPurpose": "assertionMethod",
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    "https://www.w3.org/ns/credentials/examples/v2"
  ]
}
예시 32: 정규 증명 옵션 문서
_:c14n0 <http://purl.org/dc/terms/created> "2023-02-24T23: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> "ecdsa-rdfc-2019"^^<https://w3id.org/security#cryptosuiteString> .
_:c14n0 <https://w3id.org/security#proofPurpose> <https://w3id.org/security#assertionMethod> .
_:c14n0 <https://w3id.org/security#verificationMethod> <did:key:z82LkuBieyGShVBhvtE2zoiD6Kma4tJGFtkAhxR5pfkp5QPw4LutoYWhvQCnGjdVn14kujQ#z82LkuBieyGShVBhvtE2zoiD6Kma4tJGFtkAhxR5pfkp5QPw4LutoYWhvQCnGjdVn14kujQ> .
예시 33: 정규 증명 옵션 문서의 해시(hex)
e32805a26492eac777aa7a138f6d8da3c74e0c7be7b296dcaccf97420c3b92eaad7be6449ca565e165031567f5c7cbc1

마지막으로, 증명 옵션의 해시 뒤에 증명 없는 크리덴셜의 해시를 연결하고, 결합된 해시에 개인키를 사용하여 ECDSA 서명을 계산한 뒤, 그 서명을 base-58-btc로 인코딩한다.

예시 34: 증명 옵션과 크리덴셜의 해시 결합(hex)
e32805a26492eac777aa7a138f6d8da3c74e0c7be7b296dcaccf97420c3b92eaad7be6449ca565e165031567f5c7cbc18bf6e01df72c5b62f91b685231915ac4b8c58ea95f002c6b8f6bfafa1b251df476b56b8e01518e317dab099d3ecbff96
예시 35: 결합된 해시의 서명(hex)
177ac088806c2506d49f0bfec16056a6a80ace62cd029888ad561aba22a59d192d77d9b1fc28df80dea5ee6c8bceb16f1b8bff6bd6ff2d8f8778bdde48bafa7b6cc1f914c0168b5c04499882f632deea9cb7d977e888bb0e1ee9fb20ff03b025
예시 36: 결합된 해시의 서명 base-58-btc
z967Mvv5bxtmLNqTzPZ8KmJjFmFXaAKeQNzq7GWnQkMcLtaGSSmuozE5WtJ8PipMe178B1tE28K1vsJur9bGVJhz6jgSJsRHFSQeqgH8hhjcg8gZDFJC1b9FsR5ggNmDBqHv

다음 두 단계로 서명된 크리덴셜을 조립한다:

  1. Add the proofValue field with the previously computed base-58-btc value to the proof options document.
  2. Set the proof field of the credential to the augmented proof option document.
예시 37: 서명된 크리덴셜
{
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    "https://www.w3.org/ns/credentials/examples/v2"
  ],
  "id": "urn:uuid:58172aac-d8ba-11ed-83dd-0b3aef56cc33",
  "type": [
    "VerifiableCredential",
    "AlumniCredential"
  ],
  "name": "Alumni Credential",
  "description": "A minimum viable example of an Alumni Credential.",
  "issuer": "https://vc.example/issuers/5678",
  "validFrom": "2023-01-01T00:00:00Z",
  "credentialSubject": {
    "id": "did:example:abcdefgh",
    "alumniOf": "The School of Examples"
  },
  "proof": {
    "type": "DataIntegrityProof",
    "cryptosuite": "ecdsa-rdfc-2019",
    "created": "2023-02-24T23:36:38Z",
    "verificationMethod": "did:key:z82LkuBieyGShVBhvtE2zoiD6Kma4tJGFtkAhxR5pfkp5QPw4LutoYWhvQCnGjdVn14kujQ#z82LkuBieyGShVBhvtE2zoiD6Kma4tJGFtkAhxR5pfkp5QPw4LutoYWhvQCnGjdVn14kujQ",
    "proofPurpose": "assertionMethod",
    "proofValue": "z967Mvv5bxtmLNqTzPZ8KmJjFmFXaAKeQNzq7GWnQkMcLtaGSSmuozE5WtJ8PipMe178B1tE28K1vsJur9bGVJhz6jgSJsRHFSQeqgH8hhjcg8gZDFJC1b9FsR5ggNmDBqHv"
  }
}

A.4 표현에 대한 확장 예시: ecdsa-rdfc-2019, 곡선 P-384

여기서는 ecdsa-rdfc-2019 곡선 P-384 서명 크리덴셜을 생성하는 단계를 다시 거치되, 더 복잡한 입력 문서를 사용한다. 공개키의 표현과 개인키의 표현을 아래에 나타낸다.

예시 38: 서명용 개인키 및 공개키
{
  "publicKeyMultibase": "z82LkuBieyGShVBhvtE2zoiD6Kma4tJGFtkAhxR5pfkp5QPw4LutoYWhvQCnGjdVn14kujQ",
  "secretKeyMultibase": "z2fanyY7zgwNpZGxX5fXXibvScNaUWNprHU9dKx7qpVj7mws9J8LLt4mDB5TyH2GLHWkUc"
}

서명은 첨부된 증명이 없는 크리덴셜로 시작하며, 이는 정규형으로 변환된 다음 해싱된다. 이는 다음 세 예시에 나타나 있다.

예시 39: 증명 없는 취업 허가 크리덴셜
{
    "@context": [
      "https://www.w3.org/ns/credentials/v2",
      "https://w3id.org/citizenship/v4rc1"
    ],
    "type": [
      "VerifiableCredential",
      "EmploymentAuthorizationDocumentCredential"
    ],
    "issuer": {
      "id": "did:key:zDnaegE6RR3atJtHKwTRTWHsJ3kNHqFwv7n9YjTgmU7TyfU76",
      "image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2NgUPr/HwADaAIhG61j/AAAAABJRU5ErkJggg=="
    },
    "credentialSubject": {
      "type": [
        "Person",
        "EmployablePerson"
      ],
      "givenName": "JOHN",
      "additionalName": "JACOB",
      "familyName": "SMITH",
      "image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2Ng+M/wHwAEAQH/7yMK/gAAAABJRU5ErkJggg==",
      "gender": "Male",
      "residentSince": "2015-01-01",
      "birthCountry": "Bahamas",
      "birthDate": "1999-07-17",
      "employmentAuthorizationDocument": {
        "type": "EmploymentAuthorizationDocument",
        "identifier": "83627465",
        "lprCategory": "C09",
        "lprNumber": "999-999-999"
      }
    },
    "name": "Employment Authorization Document",
    "description": "Example Employment Authorization Document.",
    "validFrom": "2019-12-03T00:00:00Z",
    "validUntil": "2029-12-03T00:00:00Z"
  }
예시 40: 증명 없는 취업 허가 크리덴셜의 정규형
<did:key:zDnaegE6RR3atJtHKwTRTWHsJ3kNHqFwv7n9YjTgmU7TyfU76> <https://schema.org/image> <data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2NgUPr/HwADaAIhG61j/AAAAABJRU5ErkJggg==> .
_:c14n0 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/citizenship#EmploymentAuthorizationDocument> .
_:c14n0 <https://schema.org/identifier> "83627465" .
_:c14n0 <https://w3id.org/citizenship#lprCategory> "C09" .
_:c14n0 <https://w3id.org/citizenship#lprNumber> "999-999-999" .
_:c14n1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://schema.org/Person> .
_:c14n1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/citizenship#EmployablePerson> .
_:c14n1 <https://schema.org/additionalName> "JACOB" .
_:c14n1 <https://schema.org/birthDate> "1999-07-17"^^<http://www.w3.org/2001/XMLSchema#dateTime> .
_:c14n1 <https://schema.org/familyName> "SMITH" .
_:c14n1 <https://schema.org/gender> "Male" .
_:c14n1 <https://schema.org/givenName> "JOHN" .
_:c14n1 <https://schema.org/image> <data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2Ng+M/wHwAEAQH/7yMK/gAAAABJRU5ErkJggg==> .
_:c14n1 <https://w3id.org/citizenship#birthCountry> "Bahamas" .
_:c14n1 <https://w3id.org/citizenship#employmentAuthorizationDocument> _:c14n0 .
_:c14n1 <https://w3id.org/citizenship#residentSince> "2015-01-01"^^<http://www.w3.org/2001/XMLSchema#dateTime> .
_:c14n2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/citizenship#EmploymentAuthorizationDocumentCredential> .
_:c14n2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://www.w3.org/2018/credentials#VerifiableCredential> .
_:c14n2 <https://schema.org/description> "Example Employment Authorization Document." .
_:c14n2 <https://schema.org/name> "Employment Authorization Document" .
_:c14n2 <https://www.w3.org/2018/credentials#credentialSubject> _:c14n1 .
_:c14n2 <https://www.w3.org/2018/credentials#issuer> <did:key:zDnaegE6RR3atJtHKwTRTWHsJ3kNHqFwv7n9YjTgmU7TyfU76> .
_:c14n2 <https://www.w3.org/2018/credentials#validFrom> "2019-12-03T00:00:00Z"^^<http://www.w3.org/2001/XMLSchema#dateTime> .
_:c14n2 <https://www.w3.org/2018/credentials#validUntil> "2029-12-03T00:00:00Z"^^<http://www.w3.org/2001/XMLSchema#dateTime> .
예시 41: 증명 없는 크리덴셜 정규형의 해시(hex)
1033878f36ffb458c6495fec9c8814dad5215aad131041e6667db28fef6ea718d0de0eb4546bf527746ad2bc908a4320

다음 단계는 증명 옵션 문서를 가져와 정규형으로 변환하고 그 해시를 얻는 것이며, 이는 다음 세 예시에 나타나 있다.

예시 42: 증명 옵션 문서
{
  "type": "DataIntegrityProof",
  "cryptosuite": "ecdsa-rdfc-2019",
  "created": "2023-02-24T23:36:38Z",
  "verificationMethod": "did:key:z82LkuBieyGShVBhvtE2zoiD6Kma4tJGFtkAhxR5pfkp5QPw4LutoYWhvQCnGjdVn14kujQ#z82LkuBieyGShVBhvtE2zoiD6Kma4tJGFtkAhxR5pfkp5QPw4LutoYWhvQCnGjdVn14kujQ",
  "proofPurpose": "assertionMethod",
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    "https://w3id.org/citizenship/v4rc1"
  ]
}
예시 43: 정규 증명 옵션 문서
_:c14n0 <http://purl.org/dc/terms/created> "2023-02-24T23: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> "ecdsa-rdfc-2019"^^<https://w3id.org/security#cryptosuiteString> .
_:c14n0 <https://w3id.org/security#proofPurpose> <https://w3id.org/security#assertionMethod> .
_:c14n0 <https://w3id.org/security#verificationMethod> <did:key:z82LkuBieyGShVBhvtE2zoiD6Kma4tJGFtkAhxR5pfkp5QPw4LutoYWhvQCnGjdVn14kujQ#z82LkuBieyGShVBhvtE2zoiD6Kma4tJGFtkAhxR5pfkp5QPw4LutoYWhvQCnGjdVn14kujQ> .
예시 44: 정규 증명 옵션 문서의 해시(hex)
e32805a26492eac777aa7a138f6d8da3c74e0c7be7b296dcaccf97420c3b92eaad7be6449ca565e165031567f5c7cbc1

마지막으로, 증명 옵션의 해시 뒤에 증명 없는 크리덴셜의 해시를 연결하고, 결합된 해시에 개인키를 사용하여 ECDSA 서명을 계산한 뒤, 그 서명을 base-58-btc로 인코딩한다.

예시 45: 증명 옵션과 크리덴셜의 해시 결합(hex)
e32805a26492eac777aa7a138f6d8da3c74e0c7be7b296dcaccf97420c3b92eaad7be6449ca565e165031567f5c7cbc11033878f36ffb458c6495fec9c8814dad5215aad131041e6667db28fef6ea718d0de0eb4546bf527746ad2bc908a4320
예시 46: 결합된 해시의 서명(hex)
a5999d1154a3fb5db8805fa762c8c41c1b7f40a231a5d42460d36245349771835f43fe0005295d2061be1789589c1f6385312f0e2e36709c310c77e8289587b79b29ecf7aad14ef61a1393cc2e1f93a7a354bd76bab47d558df060c6ae218975
예시 47: 결합된 해시의 서명 base-58-btc
zz3ca1oME3iYPHM8SgApWFUFVQjiaL9moPqCZ1NAENj3biEQ34qc1ex5VJNLD4jh4N4MY2cmDyDCYGv7EyD87yCGYwag8wRwiJE1xiHKLhTEhDQFNfuNMsgLiZnqpkCDJPye

다음 두 단계로 서명된 크리덴셜을 조립한다:

  1. Add the proofValue field with the previously computed base-58-btc value to the proof options document.
  2. Set the proof field of the credential to the augmented proof option document.
예시 48: 서명된 취업 허가 크리덴셜
{
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    "https://w3id.org/citizenship/v4rc1"
  ],
  "type": [
    "VerifiableCredential",
    "EmploymentAuthorizationDocumentCredential"
  ],
  "issuer": {
    "id": "did:key:zDnaegE6RR3atJtHKwTRTWHsJ3kNHqFwv7n9YjTgmU7TyfU76",
    "image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2NgUPr/HwADaAIhG61j/AAAAABJRU5ErkJggg=="
  },
  "credentialSubject": {
    "type": [
      "Person",
      "EmployablePerson"
    ],
    "givenName": "JOHN",
    "additionalName": "JACOB",
    "familyName": "SMITH",
    "image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2Ng+M/wHwAEAQH/7yMK/gAAAABJRU5ErkJggg==",
    "gender": "Male",
    "residentSince": "2015-01-01",
    "birthCountry": "Bahamas",
    "birthDate": "1999-07-17",
    "employmentAuthorizationDocument": {
      "type": "EmploymentAuthorizationDocument",
      "identifier": "83627465",
      "lprCategory": "C09",
      "lprNumber": "999-999-999"
    }
  },
  "name": "Employment Authorization Document",
  "description": "Example Employment Authorization Document.",
  "validFrom": "2019-12-03T00:00:00Z",
  "validUntil": "2029-12-03T00:00:00Z",
  "proof": {
    "type": "DataIntegrityProof",
    "cryptosuite": "ecdsa-rdfc-2019",
    "created": "2023-02-24T23:36:38Z",
    "verificationMethod": "did:key:z82LkuBieyGShVBhvtE2zoiD6Kma4tJGFtkAhxR5pfkp5QPw4LutoYWhvQCnGjdVn14kujQ#z82LkuBieyGShVBhvtE2zoiD6Kma4tJGFtkAhxR5pfkp5QPw4LutoYWhvQCnGjdVn14kujQ",
    "proofPurpose": "assertionMethod",
    "proofValue": "zz3ca1oME3iYPHM8SgApWFUFVQjiaL9moPqCZ1NAENj3biEQ34qc1ex5VJNLD4jh4N4MY2cmDyDCYGv7EyD87yCGYwag8wRwiJE1xiHKLhTEhDQFNfuNMsgLiZnqpkCDJPye"
  }
}

A.5 표현: ecdsa-jcs-2019, 곡선 P-256

서명자는 서명에 사용되는 개인키와 검증을 위해 제공되는 공개키로 이루어진 개인키/공개키 쌍을 생성해야 한다. 공개키의 표현과 개인키의 표현을 아래에 나타낸다.

예시 49: 서명용 개인키 및 공개키
{
  "publicKeyMultibase": "zDnaepBuvsQ8cpsWrVKw8fbpGpvPeNSjVPTWoq6cRqaYzBKVP",
  "secretKeyMultibase": "z42twTcNeSYcnqg1FLuSFs2bsGH3ZqbRHFmvS9XMsYhjxvHN"
}

서명은 첨부된 증명이 없는 크리덴셜로 시작하며, 이는 정규형으로 변환된 뒤 해싱된다. 이는 다음 세 예시에 나타나 있다.

예시 50: 증명 없는 크리덴셜
{
    "@context": [
        "https://www.w3.org/ns/credentials/v2",
        "https://www.w3.org/ns/credentials/examples/v2"
    ],
    "id": "urn:uuid:58172aac-d8ba-11ed-83dd-0b3aef56cc33",
    "type": ["VerifiableCredential", "AlumniCredential"],
    "name": "Alumni Credential",
    "description": "A minimum viable example of an Alumni Credential.",
    "issuer": "https://vc.example/issuers/5678",
    "validFrom": "2023-01-01T00:00:00Z",
    "credentialSubject": {
        "id": "did:example:abcdefgh",
        "alumniOf": "The School of Examples"
    }
}
예시 51: 증명 없는 크리덴셜의 정규형
{"@context":["https://www.w3.org/ns/credentials/v2","https://www.w3.org/ns/credentials/examples/v2"],"credentialSubject":{"alumniOf":"The School of Examples","id":"did:example:abcdefgh"},"description":"A minimum viable example of an Alumni Credential.","id":"urn:uuid:58172aac-d8ba-11ed-83dd-0b3aef56cc33","issuer":"https://vc.example/issuers/5678","name":"Alumni Credential","type":["VerifiableCredential","AlumniCredential"],"validFrom":"2023-01-01T00:00:00Z"}
예시 52: 증명 없는 크리덴셜 정규형의 해시(hex)
59b7cb6251b8991add1ce0bc83107e3db9dbbab5bd2c28f687db1a03abc92f19

다음 단계는 증명 옵션 문서를 가져와 정규형으로 변환하고 그 해시를 얻는 것이며, 이는 다음 세 예시에 나타나 있다.

예시 53: 증명 옵션 문서
{
  "type": "DataIntegrityProof",
  "cryptosuite": "ecdsa-jcs-2019",
  "created": "2023-02-24T23:36:38Z",
  "verificationMethod": "did:key:zDnaepBuvsQ8cpsWrVKw8fbpGpvPeNSjVPTWoq6cRqaYzBKVP#zDnaepBuvsQ8cpsWrVKw8fbpGpvPeNSjVPTWoq6cRqaYzBKVP",
  "proofPurpose": "assertionMethod",
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    "https://www.w3.org/ns/credentials/examples/v2"
  ]
}
예시 54: 정규 증명 옵션 문서
{"@context":["https://www.w3.org/ns/credentials/v2","https://www.w3.org/ns/credentials/examples/v2"],"created":"2023-02-24T23:36:38Z","cryptosuite":"ecdsa-jcs-2019","proofPurpose":"assertionMethod","type":"DataIntegrityProof","verificationMethod":"did:key:zDnaepBuvsQ8cpsWrVKw8fbpGpvPeNSjVPTWoq6cRqaYzBKVP#zDnaepBuvsQ8cpsWrVKw8fbpGpvPeNSjVPTWoq6cRqaYzBKVP"}
예시 55: 정규 증명 옵션 문서의 해시(hex)
fe5799489119c7fe3c528715e72bd39d2ec6b4ab345978df32e9a9312648ec25

마지막으로, 증명 옵션의 해시 뒤에 증명 없는 크리덴셜의 해시를 연결하고, 결합된 해시에 개인키를 사용하여 ECDSA 서명을 계산한 뒤, 그 서명을 base-58-btc로 인코딩한다.

예시 56: 증명 옵션과 크리덴셜의 해시 결합(hex)
fe5799489119c7fe3c528715e72bd39d2ec6b4ab345978df32e9a9312648ec2559b7cb6251b8991add1ce0bc83107e3db9dbbab5bd2c28f687db1a03abc92f19
예시 57: 결합된 해시의 서명(hex)
f15c3b599eb9b3cad05df9d8e8b39a70a86375833b53743c764ac0a88c4457d60707fd7d073e03d906130631d87803f80a9824dc9939632ba92d418181be9d16
예시 58: 결합된 해시의 서명 base-58-btc
z5ptCet75SaEgzG4v4zJhbJtfNi74Wv7Fq15hhKouJQQjEPQvPZKaYxcMXAMLPQS2FXrkCWokNJkFVkwxNzZfD5oT

다음 세 단계로 서명된 크리덴셜을 조립한다:

  1. Add the proofValue field with the previously computed base-58-btc value to the proof options document.
  2. Set the proof options @context field to the value of the unsecuredDocument.@context.
  3. Set the proof field of the credential to the augmented proof option document.
예시 59: 서명된 크리덴셜
{
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    "https://www.w3.org/ns/credentials/examples/v2"
  ],
  "id": "urn:uuid:58172aac-d8ba-11ed-83dd-0b3aef56cc33",
  "type": [
    "VerifiableCredential",
    "AlumniCredential"
  ],
  "name": "Alumni Credential",
  "description": "A minimum viable example of an Alumni Credential.",
  "issuer": "https://vc.example/issuers/5678",
  "validFrom": "2023-01-01T00:00:00Z",
  "credentialSubject": {
    "id": "did:example:abcdefgh",
    "alumniOf": "The School of Examples"
  },
  "proof": {
    "type": "DataIntegrityProof",
    "cryptosuite": "ecdsa-jcs-2019",
    "created": "2023-02-24T23:36:38Z",
    "verificationMethod": "did:key:zDnaepBuvsQ8cpsWrVKw8fbpGpvPeNSjVPTWoq6cRqaYzBKVP#zDnaepBuvsQ8cpsWrVKw8fbpGpvPeNSjVPTWoq6cRqaYzBKVP",
    "proofPurpose": "assertionMethod",
    "@context": [
      "https://www.w3.org/ns/credentials/v2",
      "https://www.w3.org/ns/credentials/examples/v2"
    ],
    "proofValue": "z5ptCet75SaEgzG4v4zJhbJtfNi74Wv7Fq15hhKouJQQjEPQvPZKaYxcMXAMLPQS2FXrkCWokNJkFVkwxNzZfD5oT"
  }
}

A.6 표현: ecdsa-jcs-2019, 곡선 P-384

서명자는 서명에 사용되는 개인키와 검증을 위해 제공되는 공개키로 이루어진 개인키/공개키 쌍을 생성해야 한다. 공개키의 표현과 개인키의 표현을 아래에 나타낸다.

예시 60: 서명용 개인키 및 공개키
{
  "publicKeyMultibase": "z82LkuBieyGShVBhvtE2zoiD6Kma4tJGFtkAhxR5pfkp5QPw4LutoYWhvQCnGjdVn14kujQ",
  "secretKeyMultibase": "z2fanyY7zgwNpZGxX5fXXibvScNaUWNprHU9dKx7qpVj7mws9J8LLt4mDB5TyH2GLHWkUc"
}

서명은 첨부된 증명이 없는 크리덴셜로 시작하며, 이는 정규형으로 변환된 뒤 해싱된다. 이는 다음 세 예시에 나타나 있다.

예시 61: 증명 없는 크리덴셜
{
    "@context": [
        "https://www.w3.org/ns/credentials/v2",
        "https://www.w3.org/ns/credentials/examples/v2"
    ],
    "id": "urn:uuid:58172aac-d8ba-11ed-83dd-0b3aef56cc33",
    "type": ["VerifiableCredential", "AlumniCredential"],
    "name": "Alumni Credential",
    "description": "A minimum viable example of an Alumni Credential.",
    "issuer": "https://vc.example/issuers/5678",
    "validFrom": "2023-01-01T00:00:00Z",
    "credentialSubject": {
        "id": "did:example:abcdefgh",
        "alumniOf": "The School of Examples"
    }
}
예시 62: 증명 없는 크리덴셜의 정규형
{"@context":["https://www.w3.org/ns/credentials/v2","https://www.w3.org/ns/credentials/examples/v2"],"credentialSubject":{"alumniOf":"The School of Examples","id":"did:example:abcdefgh"},"description":"A minimum viable example of an Alumni Credential.","id":"urn:uuid:58172aac-d8ba-11ed-83dd-0b3aef56cc33","issuer":"https://vc.example/issuers/5678","name":"Alumni Credential","type":["VerifiableCredential","AlumniCredential"],"validFrom":"2023-01-01T00:00:00Z"}
예시 63: 증명 없는 크리덴셜 정규형의 해시(hex)
3e0be671cc1881035d463158c80921973dab3534d4f8dfacf4ff2725a4115eb718e49d66de0e90e7365cd6062abf2259

다음 단계는 증명 옵션 문서를 가져와 정규형으로 변환하고 그 해시를 얻는 것이며, 이는 다음 세 예시에 나타나 있다.

예시 64: 증명 옵션 문서
{
  "type": "DataIntegrityProof",
  "cryptosuite": "ecdsa-jcs-2019",
  "created": "2023-02-24T23:36:38Z",
  "verificationMethod": "did:key:z82LkuBieyGShVBhvtE2zoiD6Kma4tJGFtkAhxR5pfkp5QPw4LutoYWhvQCnGjdVn14kujQ#z82LkuBieyGShVBhvtE2zoiD6Kma4tJGFtkAhxR5pfkp5QPw4LutoYWhvQCnGjdVn14kujQ",
  "proofPurpose": "assertionMethod",
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    "https://www.w3.org/ns/credentials/examples/v2"
  ]
}
예시 65: 정규 증명 옵션 문서
{"@context":["https://www.w3.org/ns/credentials/v2","https://www.w3.org/ns/credentials/examples/v2"],"created":"2023-02-24T23:36:38Z","cryptosuite":"ecdsa-jcs-2019","proofPurpose":"assertionMethod","type":"DataIntegrityProof","verificationMethod":"did:key:z82LkuBieyGShVBhvtE2zoiD6Kma4tJGFtkAhxR5pfkp5QPw4LutoYWhvQCnGjdVn14kujQ#z82LkuBieyGShVBhvtE2zoiD6Kma4tJGFtkAhxR5pfkp5QPw4LutoYWhvQCnGjdVn14kujQ"}
예시 66: 정규 증명 옵션 문서의 해시(hex)
83e5057817abb0c6872eafeaba1a9e53893c58eeb7414fb6d8aa3fa8c7917f7ad4792890b257c598baa17f4fbe6d183c

마지막으로, 증명 옵션의 해시 뒤에 증명 없는 크리덴셜의 해시를 연결하고, 결합된 해시에 개인키를 사용하여 ECDSA 서명을 계산한 뒤, 그 서명을 base-58-btc로 인코딩한다.

예시 67: 증명 옵션과 크리덴셜의 해시 결합(hex)
83e5057817abb0c6872eafeaba1a9e53893c58eeb7414fb6d8aa3fa8c7917f7ad4792890b257c598baa17f4fbe6d183c3e0be671cc1881035d463158c80921973dab3534d4f8dfacf4ff2725a4115eb718e49d66de0e90e7365cd6062abf2259
예시 68: 결합된 해시의 서명(hex)
8b7462ce62db0c8ff19878c4b3561c49eb71b4a743086b6d5b0eda70ecf0afc5a03fd88eb207d66b262ed87fd200a4e8e62716e0b329c032b67726b4b0fc737a44c1cefdba2fdccb3ece74cc5845aaa93374455a726f6ee4f5f30da9427f608a
예시 69: 결합된 해시의 서명 base-58-btc
zq3EuTeLiGurmB2JR5oL8oWEsT7u2tba4HT1oZbiMYWc5qzsoW2kLYcBcF4HM5vCpJyTkceULKrVXuJQkXeN5seL4uXrFNFRMm53GWy1Yrto8rTWxZi9DkNeWP7yUPs7ELAm

다음 세 단계로 서명된 크리덴셜을 조립한다:

  1. Add the proofValue field with the previously computed base-58-btc value to the proof options document.
  2. Set the proof options @context field to the value of the unsecuredDocument.@context.
  3. Set the proof field of the credential to the augmented proof option document.
예시 70: 서명된 크리덴셜
{
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    "https://www.w3.org/ns/credentials/examples/v2"
  ],
  "id": "urn:uuid:58172aac-d8ba-11ed-83dd-0b3aef56cc33",
  "type": [
    "VerifiableCredential",
    "AlumniCredential"
  ],
  "name": "Alumni Credential",
  "description": "A minimum viable example of an Alumni Credential.",
  "issuer": "https://vc.example/issuers/5678",
  "validFrom": "2023-01-01T00:00:00Z",
  "credentialSubject": {
    "id": "did:example:abcdefgh",
    "alumniOf": "The School of Examples"
  },
  "proof": {
    "type": "DataIntegrityProof",
    "cryptosuite": "ecdsa-jcs-2019",
    "created": "2023-02-24T23:36:38Z",
    "verificationMethod": "did:key:z82LkuBieyGShVBhvtE2zoiD6Kma4tJGFtkAhxR5pfkp5QPw4LutoYWhvQCnGjdVn14kujQ#z82LkuBieyGShVBhvtE2zoiD6Kma4tJGFtkAhxR5pfkp5QPw4LutoYWhvQCnGjdVn14kujQ",
    "proofPurpose": "assertionMethod",
    "@context": [
      "https://www.w3.org/ns/credentials/v2",
      "https://www.w3.org/ns/credentials/examples/v2"
    ],
    "proofValue": "zq3EuTeLiGurmB2JR5oL8oWEsT7u2tba4HT1oZbiMYWc5qzsoW2kLYcBcF4HM5vCpJyTkceULKrVXuJQkXeN5seL4uXrFNFRMm53GWy1Yrto8rTWxZi9DkNeWP7yUPs7ELAm"
  }
}

A.7 표현: ecdsa-sd-2023

선택적 공개 기능을 시연하기 위해, 테스트 벡터를 발급자가 생성하는 것(기본 증명)과 보유자가 생성하는 것(파생 증명)에 기반하여 두 그룹으로 나눈다.

A.7.1 기본 증명

문서에 선택적 공개 기본 증명을 추가하기 위해 발급자는 다음 암호화 키 자료가 필요하다:

  1. The issuers private/public key pair, i.e., the key pair corresponding to the verification method that will be part of the proof.
  2. A per proof private/public key pair created by the issuer just for this proof. This is an ephemeral, single use key pair where the private key is not kept after the proof has been generated.
  3. An HMAC key. This used to randomize the order of the blank node ids to avoid potential information leakage from the blank node id ordering. This is used only once and is shared between issuer and holder. The HMAC in this case is functioning as a pseudorandom function (PRF).

기본 증명 추가 테스트 벡터를 생성하는 데 사용되는 키 자료를 아래에 나타낸다. P-256 키 쌍에는 Multibase 표현이 사용되고 HMAC 키는 16진 문자열로 주어진다.

예시 71: 서명용 개인키 및 공개키
{
  "baseKeyPair": {
    "publicKeyMultibase": "zDnaepBuvsQ8cpsWrVKw8fbpGpvPeNSjVPTWoq6cRqaYzBKVP",
    "secretKeyMultibase": "z42twTcNeSYcnqg1FLuSFs2bsGH3ZqbRHFmvS9XMsYhjxvHN"
  },
  "proofKeyPair": {
    "publicKeyMultibase": "zDnaeTHfhmSaQKBc7CmdL3K7oYg3D6SC7yowe2eBeVd2DH32r",
    "secretKeyMultibase": "z42tqvNGyzyXRzotAYn43UhcFtzDUVdxJ7461fwrfhBPLmfY"
  },
  "hmacKeyString": "00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF"
}

우리 시나리오에서는 아래와 같이 어떤 사람에게 취업 허가 문서가 발급된다.

예시 72: 증명 없는 크리덴셜
{
    "@context": [
      "https://www.w3.org/ns/credentials/v2",
      "https://w3id.org/citizenship/v4rc1"
    ],
    "type": [
      "VerifiableCredential",
      "EmploymentAuthorizationDocumentCredential"
    ],
    "issuer": {
      "id": "did:key:zDnaegE6RR3atJtHKwTRTWHsJ3kNHqFwv7n9YjTgmU7TyfU76",
      "image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2NgUPr/HwADaAIhG61j/AAAAABJRU5ErkJggg=="
    },
    "credentialSubject": {
      "type": [
        "Person",
        "EmployablePerson"
      ],
      "givenName": "JOHN",
      "additionalName": "JACOB",
      "familyName": "SMITH",
      "image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2Ng+M/wHwAEAQH/7yMK/gAAAABJRU5ErkJggg==",
      "gender": "Male",
      "residentSince": "2015-01-01",
      "birthCountry": "Bahamas",
      "birthDate": "1999-07-17",
      "employmentAuthorizationDocument": {
        "type": "EmploymentAuthorizationDocument",
        "identifier": "83627465",
        "lprCategory": "C09",
        "lprNumber": "999-999-999"
      }
    },
    "name": "Employment Authorization Document",
    "description": "Example Employment Authorization Document.",
    "validFrom": "2019-12-03T00:00:00Z",
    "validUntil": "2029-12-03T00:00:00Z"
  }

발급자가 지정한 필수 정보는 아래와 같이 JSON 포인터 배열을 통해 지정된다.

예시 73: 필수 포인터
["/issuer"]

위 JSON 포인터를 취업 허가 문서에 적용한 결과를 아래에 나타낸다.

예시 74: JSON 포인터와 값
[
  {
    "pointer": "/issuer",
    "value": {
      "id": "did:key:zDnaegE6RR3atJtHKwTRTWHsJ3kNHqFwv7n9YjTgmU7TyfU76",
      "image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2NgUPr/HwADaAIhG61j/AAAAABJRU5ErkJggg=="
    }
  }
]

서명되지 않은 문서의 변환은 아래와 같이 문서를 정규화하는 것으로 시작한다.

예시 75: 정규 문서
[
  "<did:key:zDnaegE6RR3atJtHKwTRTWHsJ3kNHqFwv7n9YjTgmU7TyfU76> <https://schema.org/image> <data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2NgUPr/HwADaAIhG61j/AAAAABJRU5ErkJggg==> .\n",
  "_:c14n0 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/citizenship#EmploymentAuthorizationDocumentCredential> .\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> \"Example Employment Authorization Document.\" .\n",
  "_:c14n0 <https://schema.org/name> \"Employment Authorization Document\" .\n",
  "_:c14n0 <https://www.w3.org/2018/credentials#credentialSubject> _:c14n1 .\n",
  "_:c14n0 <https://www.w3.org/2018/credentials#issuer> <did:key:zDnaegE6RR3atJtHKwTRTWHsJ3kNHqFwv7n9YjTgmU7TyfU76> .\n",
  "_:c14n0 <https://www.w3.org/2018/credentials#validFrom> \"2019-12-03T00:00:00Z\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n",
  "_:c14n0 <https://www.w3.org/2018/credentials#validUntil> \"2029-12-03T00:00:00Z\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\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#EmployablePerson> .\n",
  "_:c14n1 <https://schema.org/additionalName> \"JACOB\" .\n",
  "_:c14n1 <https://schema.org/birthDate> \"1999-07-17\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n",
  "_:c14n1 <https://schema.org/familyName> \"SMITH\" .\n",
  "_:c14n1 <https://schema.org/gender> \"Male\" .\n",
  "_:c14n1 <https://schema.org/givenName> \"JOHN\" .\n",
  "_:c14n1 <https://schema.org/image> <data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2Ng+M/wHwAEAQH/7yMK/gAAAABJRU5ErkJggg==> .\n",
  "_:c14n1 <https://w3id.org/citizenship#birthCountry> \"Bahamas\" .\n",
  "_:c14n1 <https://w3id.org/citizenship#employmentAuthorizationDocument> _:c14n2 .\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#EmploymentAuthorizationDocument> .\n",
  "_:c14n2 <https://schema.org/identifier> \"83627465\" .\n",
  "_:c14n2 <https://w3id.org/citizenship#lprCategory> \"C09\" .\n",
  "_:c14n2 <https://w3id.org/citizenship#lprNumber> \"999-999-999\" .\n"
]

공백 노드 id의 순서로부터 발생할 수 있는 정보 유출을 방지하기 위해, 이들은 PRF, 즉 HMAC를 통해 처리되어 아래에 나타난 정규화된 HMAC 문서를 만든다. 이는 필수 및 선택적 공개의 대상이 될 문의 정렬된 목록을 나타내며, 즉 문이 그룹화되는 것은 이 목록으로부터이다.

예시 76: 정규 HMAC 문서
[
  "<did:key:zDnaegE6RR3atJtHKwTRTWHsJ3kNHqFwv7n9YjTgmU7TyfU76> <https://schema.org/image> <data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2NgUPr/HwADaAIhG61j/AAAAABJRU5ErkJggg==> .\n",
  "_:u3Lv2QpFgo-YAegc1cQQKWJFW2sEjQF6FfuZ0VEoMKHg <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://schema.org/Person> .\n",
  "_:u3Lv2QpFgo-YAegc1cQQKWJFW2sEjQF6FfuZ0VEoMKHg <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/citizenship#EmployablePerson> .\n",
  "_:u3Lv2QpFgo-YAegc1cQQKWJFW2sEjQF6FfuZ0VEoMKHg <https://schema.org/additionalName> \"JACOB\" .\n",
  "_:u3Lv2QpFgo-YAegc1cQQKWJFW2sEjQF6FfuZ0VEoMKHg <https://schema.org/birthDate> \"1999-07-17\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n",
  "_:u3Lv2QpFgo-YAegc1cQQKWJFW2sEjQF6FfuZ0VEoMKHg <https://schema.org/familyName> \"SMITH\" .\n",
  "_:u3Lv2QpFgo-YAegc1cQQKWJFW2sEjQF6FfuZ0VEoMKHg <https://schema.org/gender> \"Male\" .\n",
  "_:u3Lv2QpFgo-YAegc1cQQKWJFW2sEjQF6FfuZ0VEoMKHg <https://schema.org/givenName> \"JOHN\" .\n",
  "_:u3Lv2QpFgo-YAegc1cQQKWJFW2sEjQF6FfuZ0VEoMKHg <https://schema.org/image> <data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2Ng+M/wHwAEAQH/7yMK/gAAAABJRU5ErkJggg==> .\n",
  "_:u3Lv2QpFgo-YAegc1cQQKWJFW2sEjQF6FfuZ0VEoMKHg <https://w3id.org/citizenship#birthCountry> \"Bahamas\" .\n",
  "_:u3Lv2QpFgo-YAegc1cQQKWJFW2sEjQF6FfuZ0VEoMKHg <https://w3id.org/citizenship#employmentAuthorizationDocument> _:uVkUuBrlOaELGVQWJD4M_qW5bcKEHWGNbOrPA_qAOKKw .\n",
  "_:u3Lv2QpFgo-YAegc1cQQKWJFW2sEjQF6FfuZ0VEoMKHg <https://w3id.org/citizenship#residentSince> \"2015-01-01\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n",
  "_:u4YIOZn1MHES1Z4Ij2hWZG3R4dEYBqg5fHTyDEvYhC38 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/citizenship#EmploymentAuthorizationDocumentCredential> .\n",
  "_:u4YIOZn1MHES1Z4Ij2hWZG3R4dEYBqg5fHTyDEvYhC38 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://www.w3.org/2018/credentials#VerifiableCredential> .\n",
  "_:u4YIOZn1MHES1Z4Ij2hWZG3R4dEYBqg5fHTyDEvYhC38 <https://schema.org/description> \"Example Employment Authorization Document.\" .\n",
  "_:u4YIOZn1MHES1Z4Ij2hWZG3R4dEYBqg5fHTyDEvYhC38 <https://schema.org/name> \"Employment Authorization Document\" .\n",
  "_:u4YIOZn1MHES1Z4Ij2hWZG3R4dEYBqg5fHTyDEvYhC38 <https://www.w3.org/2018/credentials#credentialSubject> _:u3Lv2QpFgo-YAegc1cQQKWJFW2sEjQF6FfuZ0VEoMKHg .\n",
  "_:u4YIOZn1MHES1Z4Ij2hWZG3R4dEYBqg5fHTyDEvYhC38 <https://www.w3.org/2018/credentials#issuer> <did:key:zDnaegE6RR3atJtHKwTRTWHsJ3kNHqFwv7n9YjTgmU7TyfU76> .\n",
  "_:u4YIOZn1MHES1Z4Ij2hWZG3R4dEYBqg5fHTyDEvYhC38 <https://www.w3.org/2018/credentials#validFrom> \"2019-12-03T00:00:00Z\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n",
  "_:u4YIOZn1MHES1Z4Ij2hWZG3R4dEYBqg5fHTyDEvYhC38 <https://www.w3.org/2018/credentials#validUntil> \"2029-12-03T00:00:00Z\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n",
  "_:uVkUuBrlOaELGVQWJD4M_qW5bcKEHWGNbOrPA_qAOKKw <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/citizenship#EmploymentAuthorizationDocument> .\n",
  "_:uVkUuBrlOaELGVQWJD4M_qW5bcKEHWGNbOrPA_qAOKKw <https://schema.org/identifier> \"83627465\" .\n",
  "_:uVkUuBrlOaELGVQWJD4M_qW5bcKEHWGNbOrPA_qAOKKw <https://w3id.org/citizenship#lprCategory> \"C09\" .\n",
  "_:uVkUuBrlOaELGVQWJD4M_qW5bcKEHWGNbOrPA_qAOKKw <https://w3id.org/citizenship#lprNumber> \"999-999-999\" .\n"
]

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

예시 77: 기본 변환 추가
{
  "mandatoryPointers": [
    "/issuer"
  ],
  "mandatory": {
    "dataType": "Map",
    "value": [
      [
        0,
        "<did:key:zDnaegE6RR3atJtHKwTRTWHsJ3kNHqFwv7n9YjTgmU7TyfU76> <https://schema.org/image> <data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2NgUPr/HwADaAIhG61j/AAAAABJRU5ErkJggg==> .\n"
      ],
      [
        12,
        "_:u4YIOZn1MHES1Z4Ij2hWZG3R4dEYBqg5fHTyDEvYhC38 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/citizenship#EmploymentAuthorizationDocumentCredential> .\n"
      ],
      [
        13,
        "_:u4YIOZn1MHES1Z4Ij2hWZG3R4dEYBqg5fHTyDEvYhC38 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://www.w3.org/2018/credentials#VerifiableCredential> .\n"
      ],
      [
        17,
        "_:u4YIOZn1MHES1Z4Ij2hWZG3R4dEYBqg5fHTyDEvYhC38 <https://www.w3.org/2018/credentials#issuer> <did:key:zDnaegE6RR3atJtHKwTRTWHsJ3kNHqFwv7n9YjTgmU7TyfU76> .\n"
      ]
    ]
  },
  "nonMandatory": {
    "dataType": "Map",
    "value": [
      [
        1,
        "_:u3Lv2QpFgo-YAegc1cQQKWJFW2sEjQF6FfuZ0VEoMKHg <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://schema.org/Person> .\n"
      ],
      [
        2,
        "_:u3Lv2QpFgo-YAegc1cQQKWJFW2sEjQF6FfuZ0VEoMKHg <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/citizenship#EmployablePerson> .\n"
      ],
      [
        3,
        "_:u3Lv2QpFgo-YAegc1cQQKWJFW2sEjQF6FfuZ0VEoMKHg <https://schema.org/additionalName> \"JACOB\" .\n"
      ],
      [
        4,
        "_:u3Lv2QpFgo-YAegc1cQQKWJFW2sEjQF6FfuZ0VEoMKHg <https://schema.org/birthDate> \"1999-07-17\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n"
      ],
      [
        5,
        "_:u3Lv2QpFgo-YAegc1cQQKWJFW2sEjQF6FfuZ0VEoMKHg <https://schema.org/familyName> \"SMITH\" .\n"
      ],
      [
        6,
        "_:u3Lv2QpFgo-YAegc1cQQKWJFW2sEjQF6FfuZ0VEoMKHg <https://schema.org/gender> \"Male\" .\n"
      ],
      [
        7,
        "_:u3Lv2QpFgo-YAegc1cQQKWJFW2sEjQF6FfuZ0VEoMKHg <https://schema.org/givenName> \"JOHN\" .\n"
      ],
      [
        8,
        "_:u3Lv2QpFgo-YAegc1cQQKWJFW2sEjQF6FfuZ0VEoMKHg <https://schema.org/image> <data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2Ng+M/wHwAEAQH/7yMK/gAAAABJRU5ErkJggg==> .\n"
      ],
      [
        9,
        "_:u3Lv2QpFgo-YAegc1cQQKWJFW2sEjQF6FfuZ0VEoMKHg <https://w3id.org/citizenship#birthCountry> \"Bahamas\" .\n"
      ],
      [
        10,
        "_:u3Lv2QpFgo-YAegc1cQQKWJFW2sEjQF6FfuZ0VEoMKHg <https://w3id.org/citizenship#employmentAuthorizationDocument> _:uVkUuBrlOaELGVQWJD4M_qW5bcKEHWGNbOrPA_qAOKKw .\n"
      ],
      [
        11,
        "_:u3Lv2QpFgo-YAegc1cQQKWJFW2sEjQF6FfuZ0VEoMKHg <https://w3id.org/citizenship#residentSince> \"2015-01-01\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n"
      ],
      [
        14,
        "_:u4YIOZn1MHES1Z4Ij2hWZG3R4dEYBqg5fHTyDEvYhC38 <https://schema.org/description> \"Example Employment Authorization Document.\" .\n"
      ],
      [
        15,
        "_:u4YIOZn1MHES1Z4Ij2hWZG3R4dEYBqg5fHTyDEvYhC38 <https://schema.org/name> \"Employment Authorization Document\" .\n"
      ],
      [
        16,
        "_:u4YIOZn1MHES1Z4Ij2hWZG3R4dEYBqg5fHTyDEvYhC38 <https://www.w3.org/2018/credentials#credentialSubject> _:u3Lv2QpFgo-YAegc1cQQKWJFW2sEjQF6FfuZ0VEoMKHg .\n"
      ],
      [
        18,
        "_:u4YIOZn1MHES1Z4Ij2hWZG3R4dEYBqg5fHTyDEvYhC38 <https://www.w3.org/2018/credentials#validFrom> \"2019-12-03T00:00:00Z\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n"
      ],
      [
        19,
        "_:u4YIOZn1MHES1Z4Ij2hWZG3R4dEYBqg5fHTyDEvYhC38 <https://www.w3.org/2018/credentials#validUntil> \"2029-12-03T00:00:00Z\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n"
      ],
      [
        20,
        "_:uVkUuBrlOaELGVQWJD4M_qW5bcKEHWGNbOrPA_qAOKKw <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/citizenship#EmploymentAuthorizationDocument> .\n"
      ],
      [
        21,
        "_:uVkUuBrlOaELGVQWJD4M_qW5bcKEHWGNbOrPA_qAOKKw <https://schema.org/identifier> \"83627465\" .\n"
      ],
      [
        22,
        "_:uVkUuBrlOaELGVQWJD4M_qW5bcKEHWGNbOrPA_qAOKKw <https://w3id.org/citizenship#lprCategory> \"C09\" .\n"
      ],
      [
        23,
        "_:uVkUuBrlOaELGVQWJD4M_qW5bcKEHWGNbOrPA_qAOKKw <https://w3id.org/citizenship#lprNumber> \"999-999-999\" .\n"
      ]
    ]
  },
  "hmacKeyString": "00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF"
}

다음 단계는 기본 증명 구성을 생성하고 이를 정규화하는 것이다. 이는 다음 두 예시에 나타나 있다.

예시 78: 기본 증명 구성
{
  "type": "DataIntegrityProof",
  "cryptosuite": "ecdsa-sd-2023",
  "created": "2023-08-15T23:36:38Z",
  "verificationMethod": "did:key:zDnaepBuvsQ8cpsWrVKw8fbpGpvPeNSjVPTWoq6cRqaYzBKVP#zDnaepBuvsQ8cpsWrVKw8fbpGpvPeNSjVPTWoq6cRqaYzBKVP",
  "proofPurpose": "assertionMethod",
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    "https://w3id.org/citizenship/v4rc1"
  ]
}
예시 79: 정규 기본 증명 구성
_: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> "ecdsa-sd-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:zDnaepBuvsQ8cpsWrVKw8fbpGpvPeNSjVPTWoq6cRqaYzBKVP#zDnaepBuvsQ8cpsWrVKw8fbpGpvPeNSjVPTWoq6cRqaYzBKVP> .

해싱 단계에서는 정규화된 증명 옵션의 SHA-256 해시를 계산하여 proofHash를 생성하고, 모든 필수 nquad를 결합한 것의 SHA-256 해시를 계산하여 mandatoryHash를 생성한다. 이들을 아래에 16진 형식으로 나타낸다.

예시 80: 기본 해시 추가
{
  "proofHash": "9c5c9b189f06cfa9d9f21a838ccb9b04316f07ad1a517bfd4955ee28c6a8229c",
  "mandatoryHash": "a042dc047c236816f49fbe5282a79c5e77abe111e47f4c20203b5064c7f0f059"
}

발급자의 장기 privateKey를 사용하여 proofHash, proofPublicKey, mandatoryHash를 연결한 것에 대해 baseSignature를 계산한다. 증명별 proofPrivateKey를 사용하여 각 비필수 nquad에 서명함으로써 signatures 배열을 계산한다. 최종 직렬화 단계에 입력되는 이 서명들과 proofPublicKey, mandatoryPointers를 아래에 나타낸다.

예시 81: 기본 서명 추가
{
  "baseSignature": "b8dc55afeb6427a990e9d60c0d363b654306d92703e5036210ca29619d8ed204194ba3d86e31cdbc99f4ee9d5f25f0cc1c1f44f5fa39abec9a50cdf519b457e0",
  "publicKey": "zDnaeTHfhmSaQKBc7CmdL3K7oYg3D6SC7yowe2eBeVd2DH32r",
  "signatures": [
    "fd91ec48b3524965f7a1453e9ffa067054eca6f7d6338a84525eb3288bb0caf7a9651f02fee14d6d33ee1679aa8828348ccc574e194d7f57fca8be354c1b30f7",
    "c92e6ea5f65343c704ac9450da4d55f87342829b9bad7aface8300a0879bc9972ec4879eebbaaffd9ad9e3f91d291971c8ffe5d768497d62fa27256a7e03bf99",
    "5d98f7d800ae2aa62927a65e0345a5ae02df041c9cd26de1525a63431b9360c24216737d2374d0789d4e40acdd0bf75b077c06534a6d258084ad8beb149980d6",
    "c8d70ede67864b3219dcb3c3831401ca069ac5f8db9e2714d5f57f367c76320d1e0a9fa4917551add811a415e19bcc32c017ef5ba02e81fed672c72711230b10",
    "3a6263590ab7fbc4e5ef7bc6c3f6b9cdd8a96c7c4d9a1f120612213ca39a50f39d7b56d6365ead6054bdbe4b971b2769d61841a3f7236a7434e5f1b0f6e2e8fc",
    "f5f1fe2990af59361ccd4863359405164ce6a0807dfedd2d1972826e6b79ee051df16f5dfc43d57ed0d57743b94c4f57dd5784fbb04a9bf2b6b7258f5c595524",
    "44b68330d1b12ceec6c07ed560587b6bfd49c831fa90c1a8725a41a3e3247f2950bcfe51a0b26bf422e94f811001dc17b1b93b3f82423457acc5c19f214da5e1",
    "c29744b9bfb68a250eb17aaf49416a8a77a5eed01be18c3278a3784db8f6731bda3da956855bc27f3bc91e3f8331371e100722fc223becb47072a45b7653be08",
    "2b66d296f2d09ff280d4cdec1d02b6c38065ed36c99b6db40a9a800f4faea46187c7b42c6cb232b5103bc88445f5e1f32c89692071546f316a836cd31a979f8d",
    "016fdf24189adefa773c26ad2e0482aebf74a7bb8d5a142723d43d18adc049c408faafdcef8bb11cdc9c728d8f746ae32e03197767bb1aa91fd61a8fc4993abe",
    "e7ee420aa027ba4671b926c29e2c574f94461660a0b3d6c828cce50314d9e1e4c346ed119352adf6141c66e2fce4a2cb7486c3f81cc42e388a5f921285677d94",
    "ff516e1c599ef23779cdd5a6ae34a7db1a1d244514d32308a809752e6c2d112e5a7b473360c0b8caf27949aa161d10876d19c77b50e76160736f1ea4cfdefaa2",
    "c85373002c77fb25e7880c1b2df2e2fa6c25decf563b0a88332e4654773b08b9286b65effe00f8689df03df6e2dfcd4575eff23a08c92bd360e285c22bfa2b5d",
    "09e91f89dfd0a252f79a970caec55814cd570a8e41ec2ac25c33bd8afe479a70b8e744d363bc7daa313625d0cb4c1ea8c64c87577835e9b7416b4615bb82def9",
    "b181986ef2cfb77b71f27cfb4365b8860799d9e84c3df62b3863319250d57a91d429cb15127122c36fd34a92ea0745b4a641454c561c55c37741ee247a866264",
    "13d02a9caf0d96b9fbec397d4faad90e78c56d0cbd933224d58b5c81623e3571b22aa15bc4ad201c364e3566793c9dda9c983e9965f47c7ce5ff6e1b42484dd4",
    "91cc9524b4aa346fc6e409e94b28b8a9891491ae627e47e60f0cd36d90034eb97a8595fcb35a07d3faa5fc213e759b0bea03cb82c58a3711c9de299b7e77904b",
    "22d951c202cd2dbf92a5fd20483f618177f16c08aa798fd6e8a0631fba6d059e304c1ed96a3785aa1be2539eb1fac22caace1f450b5a3a48602c7fb4c68f2d7b",
    "d0fbcf518ec15c3f10d8d2b275963807030ad7e4b03e6c7a6ca0e6b73d61f15a94d76097fc91e1a828c7d9272b178b8ced6422db36e9a1a85ce2a18e39115542",
    "be6366acec557376a71a450f862979f60e642b8edafc104eaf4691784bb48245f3d79f093cd1f631d55217ae2f9f30f17d9ba1b98aae45e02461e1db9bde121f"
  ],
  "mandatoryPointers": [
    "/issuer"
  ]
}

마지막으로, 위 값들을 3.5.2 serializeBaseProofValue 절의 알고리즘에 통과시켜 proofValue를 생성하며, 이는 아래에 나타난 서명된 기본 문서에 사용된다.

예시 82: 서명된 기본 문서
{
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    "https://w3id.org/citizenship/v4rc1"
  ],
  "type": [
    "VerifiableCredential",
    "EmploymentAuthorizationDocumentCredential"
  ],
  "issuer": {
    "id": "did:key:zDnaegE6RR3atJtHKwTRTWHsJ3kNHqFwv7n9YjTgmU7TyfU76",
    "image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2NgUPr/HwADaAIhG61j/AAAAABJRU5ErkJggg=="
  },
  "credentialSubject": {
    "type": [
      "Person",
      "EmployablePerson"
    ],
    "givenName": "JOHN",
    "additionalName": "JACOB",
    "familyName": "SMITH",
    "image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2Ng+M/wHwAEAQH/7yMK/gAAAABJRU5ErkJggg==",
    "gender": "Male",
    "residentSince": "2015-01-01",
    "birthCountry": "Bahamas",
    "birthDate": "1999-07-17",
    "employmentAuthorizationDocument": {
      "type": "EmploymentAuthorizationDocument",
      "identifier": "83627465",
      "lprCategory": "C09",
      "lprNumber": "999-999-999"
    }
  },
  "name": "Employment Authorization Document",
  "description": "Example Employment Authorization Document.",
  "validFrom": "2019-12-03T00:00:00Z",
  "validUntil": "2029-12-03T00:00:00Z",
  "proof": {
    "type": "DataIntegrityProof",
    "cryptosuite": "ecdsa-sd-2023",
    "created": "2023-08-15T23:36:38Z",
    "verificationMethod": "did:key:zDnaepBuvsQ8cpsWrVKw8fbpGpvPeNSjVPTWoq6cRqaYzBKVP#zDnaepBuvsQ8cpsWrVKw8fbpGpvPeNSjVPTWoq6cRqaYzBKVP",
    "proofPurpose": "assertionMethod",
    "proofValue": "u2V0AhVhAuNxVr-tkJ6mQ6dYMDTY7ZUMG2ScD5QNiEMopYZ2O0gQZS6PYbjHNvJn07p1fJfDMHB9E9fo5q-yaUM31GbRX4FgjgCQCKnLOGbY_FuM-ASpSkkOxsIR2E8n7Ml2q1UQ6tEwzi5NYIAARIjNEVWZ3iJmqu8zd7v8AESIzRFVmd4iZqrvM3e7_lFhA_ZHsSLNSSWX3oUU-n_oGcFTspvfWM4qEUl6zKIuwyvepZR8C_uFNbTPuFnmqiCg0jMxXThlNf1f8qL41TBsw91hAyS5upfZTQ8cErJRQ2k1V-HNCgpubrXr6zoMAoIebyZcuxIee67qv_ZrZ4_kdKRlxyP_l12hJfWL6JyVqfgO_mVhAXZj32ACuKqYpJ6ZeA0WlrgLfBByc0m3hUlpjQxuTYMJCFnN9I3TQeJ1OQKzdC_dbB3wGU0ptJYCErYvrFJmA1lhAyNcO3meGSzIZ3LPDgxQBygaaxfjbnicU1fV_Nnx2Mg0eCp-kkXVRrdgRpBXhm8wywBfvW6Augf7WcscnESMLEFhAOmJjWQq3-8Tl73vGw_a5zdipbHxNmh8SBhIhPKOaUPOde1bWNl6tYFS9vkuXGydp1hhBo_cjanQ05fGw9uLo_FhA9fH-KZCvWTYczUhjNZQFFkzmoIB9_t0tGXKCbmt57gUd8W9d_EPVftDVd0O5TE9X3VeE-7BKm_K2tyWPXFlVJFhARLaDMNGxLO7GwH7VYFh7a_1JyDH6kMGoclpBo-MkfylQvP5RoLJr9CLpT4EQAdwXsbk7P4JCNFesxcGfIU2l4VhAwpdEub-2iiUOsXqvSUFqinel7tAb4YwyeKN4Tbj2cxvaPalWhVvCfzvJHj-DMTceEAci_CI77LRwcqRbdlO-CFhAK2bSlvLQn_KA1M3sHQK2w4Bl7TbJm220CpqAD0-upGGHx7QsbLIytRA7yIRF9eHzLIlpIHFUbzFqg2zTGpefjVhAAW_fJBia3vp3PCatLgSCrr90p7uNWhQnI9Q9GK3AScQI-q_c74uxHNycco2PdGrjLgMZd2e7Gqkf1hqPxJk6vlhA5-5CCqAnukZxuSbCnixXT5RGFmCgs9bIKMzlAxTZ4eTDRu0Rk1Kt9hQcZuL85KLLdIbD-BzELjiKX5IShWd9lFhA_1FuHFme8jd5zdWmrjSn2xodJEUU0yMIqAl1LmwtES5ae0czYMC4yvJ5SaoWHRCHbRnHe1DnYWBzbx6kz976olhAyFNzACx3-yXniAwbLfLi-mwl3s9WOwqIMy5GVHc7CLkoa2Xv_gD4aJ3wPfbi381Fde_yOgjJK9Ng4oXCK_orXVhACekfid_QolL3mpcMrsVYFM1XCo5B7CrCXDO9iv5HmnC450TTY7x9qjE2JdDLTB6oxkyHV3g16bdBa0YVu4Le-VhAsYGYbvLPt3tx8nz7Q2W4hgeZ2ehMPfYrOGMxklDVepHUKcsVEnEiw2_TSpLqB0W0pkFFTFYcVcN3Qe4keoZiZFhAE9AqnK8Nlrn77Dl9T6rZDnjFbQy9kzIk1YtcgWI-NXGyKqFbxK0gHDZONWZ5PJ3anJg-mWX0fHzl_24bQkhN1FhAkcyVJLSqNG_G5AnpSyi4qYkUka5ifkfmDwzTbZADTrl6hZX8s1oH0_ql_CE-dZsL6gPLgsWKNxHJ3imbfneQS1hAItlRwgLNLb-Spf0gSD9hgXfxbAiqeY_W6KBjH7ptBZ4wTB7ZajeFqhviU56x-sIsqs4fRQtaOkhgLH-0xo8te1hA0PvPUY7BXD8Q2NKydZY4BwMK1-SwPmx6bKDmtz1h8VqU12CX_JHhqCjH2ScrF4uM7WQi2zbpoahc4qGOORFVQlhAvmNmrOxVc3anGkUPhil59g5kK47a_BBOr0aReEu0gkXz158JPNH2MdVSF64vnzDxfZuhuYquReAkYeHbm94SH4FnL2lzc3Vlcg"
  }
}

A.7.2 파생 증명

파생 증명을 생성하기 위해 보유자는 기본 증명을 담은 서명된 문서로 시작한다. 이 테스트 벡터에 사용할 기본 문서는 위 A.7.1 기본 증명 절의 마지막 예시이다. 첫 번째 단계는 3.5.3 parseBaseProofValue 절의 알고리즘을 실행하여 아래와 같이 baseSignature, publicKey, hmacKey, signatures, mandatoryPointers를 복원하는 것이다.

예시 83: 복원된 기본 서명 데이터
{
  "baseSignature": "b8dc55afeb6427a990e9d60c0d363b654306d92703e5036210ca29619d8ed204194ba3d86e31cdbc99f4ee9d5f25f0cc1c1f44f5fa39abec9a50cdf519b457e0",
  "proofPublicKey": "zDnaeTHfhmSaQKBc7CmdL3K7oYg3D6SC7yowe2eBeVd2DH32r",
  "hmacKey": "00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff",
  "signatures": [
    "fd91ec48b3524965f7a1453e9ffa067054eca6f7d6338a84525eb3288bb0caf7a9651f02fee14d6d33ee1679aa8828348ccc574e194d7f57fca8be354c1b30f7",
    "c92e6ea5f65343c704ac9450da4d55f87342829b9bad7aface8300a0879bc9972ec4879eebbaaffd9ad9e3f91d291971c8ffe5d768497d62fa27256a7e03bf99",
    "5d98f7d800ae2aa62927a65e0345a5ae02df041c9cd26de1525a63431b9360c24216737d2374d0789d4e40acdd0bf75b077c06534a6d258084ad8beb149980d6",
    "c8d70ede67864b3219dcb3c3831401ca069ac5f8db9e2714d5f57f367c76320d1e0a9fa4917551add811a415e19bcc32c017ef5ba02e81fed672c72711230b10",
    "3a6263590ab7fbc4e5ef7bc6c3f6b9cdd8a96c7c4d9a1f120612213ca39a50f39d7b56d6365ead6054bdbe4b971b2769d61841a3f7236a7434e5f1b0f6e2e8fc",
    "f5f1fe2990af59361ccd4863359405164ce6a0807dfedd2d1972826e6b79ee051df16f5dfc43d57ed0d57743b94c4f57dd5784fbb04a9bf2b6b7258f5c595524",
    "44b68330d1b12ceec6c07ed560587b6bfd49c831fa90c1a8725a41a3e3247f2950bcfe51a0b26bf422e94f811001dc17b1b93b3f82423457acc5c19f214da5e1",
    "c29744b9bfb68a250eb17aaf49416a8a77a5eed01be18c3278a3784db8f6731bda3da956855bc27f3bc91e3f8331371e100722fc223becb47072a45b7653be08",
    "2b66d296f2d09ff280d4cdec1d02b6c38065ed36c99b6db40a9a800f4faea46187c7b42c6cb232b5103bc88445f5e1f32c89692071546f316a836cd31a979f8d",
    "016fdf24189adefa773c26ad2e0482aebf74a7bb8d5a142723d43d18adc049c408faafdcef8bb11cdc9c728d8f746ae32e03197767bb1aa91fd61a8fc4993abe",
    "e7ee420aa027ba4671b926c29e2c574f94461660a0b3d6c828cce50314d9e1e4c346ed119352adf6141c66e2fce4a2cb7486c3f81cc42e388a5f921285677d94",
    "ff516e1c599ef23779cdd5a6ae34a7db1a1d244514d32308a809752e6c2d112e5a7b473360c0b8caf27949aa161d10876d19c77b50e76160736f1ea4cfdefaa2",
    "c85373002c77fb25e7880c1b2df2e2fa6c25decf563b0a88332e4654773b08b9286b65effe00f8689df03df6e2dfcd4575eff23a08c92bd360e285c22bfa2b5d",
    "09e91f89dfd0a252f79a970caec55814cd570a8e41ec2ac25c33bd8afe479a70b8e744d363bc7daa313625d0cb4c1ea8c64c87577835e9b7416b4615bb82def9",
    "b181986ef2cfb77b71f27cfb4365b8860799d9e84c3df62b3863319250d57a91d429cb15127122c36fd34a92ea0745b4a641454c561c55c37741ee247a866264",
    "13d02a9caf0d96b9fbec397d4faad90e78c56d0cbd933224d58b5c81623e3571b22aa15bc4ad201c364e3566793c9dda9c983e9965f47c7ce5ff6e1b42484dd4",
    "91cc9524b4aa346fc6e409e94b28b8a9891491ae627e47e60f0cd36d90034eb97a8595fcb35a07d3faa5fc213e759b0bea03cb82c58a3711c9de299b7e77904b",
    "22d951c202cd2dbf92a5fd20483f618177f16c08aa798fd6e8a0631fba6d059e304c1ed96a3785aa1be2539eb1fac22caace1f450b5a3a48602c7fb4c68f2d7b",
    "d0fbcf518ec15c3f10d8d2b275963807030ad7e4b03e6c7a6ca0e6b73d61f15a94d76097fc91e1a828c7d9272b178b8ced6422db36e9a1a85ce2a18e39115542",
    "be6366acec557376a71a450f862979f60e642b8edafc104eaf4691784bb48245f3d79f093cd1f631d55217ae2f9f30f17d9ba1b98aae45e02461e1db9bde121f"
  ],
  "mandatoryPointers": [
    "/issuer"
  ]
}

다음으로, 보유자는 선택적 공개를 위한 JSON 포인터를 지정하여 그 외에 검증자에게 공개하고자 하는 것이 있다면 무엇인지 표시한다.

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

결국 서명되어 검증자에게 전송될 서명되지 않은 문서인 revealDocument를 생성하기 위해, 필수 포인터에 선택 포인터를 덧붙이고, 이 결합된 포인터를 증명 없는 문서와 함께 3.4.13 selectJsonLd 절의 알고리즘에 입력하여 아래에 나타난 결과를 얻는다.

예시 85: 서명되지 않은 공개 문서
{
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    "https://w3id.org/citizenship/v4rc1"
  ],
  "type": [
    "VerifiableCredential",
    "EmploymentAuthorizationDocumentCredential"
  ],
  "issuer": {
    "id": "did:key:zDnaegE6RR3atJtHKwTRTWHsJ3kNHqFwv7n9YjTgmU7TyfU76",
    "image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2NgUPr/HwADaAIhG61j/AAAAABJRU5ErkJggg=="
  },
  "validFrom": "2019-12-03T00:00:00Z",
  "validUntil": "2029-12-03T00:00:00Z",
  "credentialSubject": {
    "type": [
      "Person",
      "EmployablePerson"
    ],
    "birthCountry": "Bahamas"
  }
}

이제 공개된 문서가 어떤 모습인지 알았으므로, 어떤 문이 필수인지, 선택된 비필수 문에 대한 서명, 그리고 공개 문서의 정규 공백 노드 id와 HMAC 공백 노드 id의 부분집합 사이의 매핑에 관한 적절히 갱신된 정보를 검증자에게 제공해야 한다. 3.5.4 createDisclosureData의 6단계를 실행하면 원본 문서를 기준으로 다양한 문 그룹에 관한 풍부한 정보가 산출된다. 아래에 그 그룹들의 인덱스 일부를 나타낸다.

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

검증자는 필수 문을 집계하고 해싱할 수 있어야 한다. 이를 가능하게 하기 위해, 공개 문서에서의 위치에 맞게 조정된 필수 문의 인덱스 목록을 검증자에게 제공한다. 이전 예시에서 combinedIndexes는 공개 문서를 구성하는 모든 원본 nquad(문)의 인덱스를 순서대로 보여준다. 아래에 나타난 조정된 필수 인덱스를 얻기 위해, 아래와 같이 combinedIndexes를 기준으로 각 원본 필수 인덱스의 인덱스를 구한다.

예시 87: 조정된 필수 인덱스
{
    "adjMandatoryIndexes":[0,4,5,7]
}

우리는 필수가 아닌 선택적 문(nquad)에 대한 서명 목록을 검증자에게 제공해야 한다. 원본 서명 목록은 모든 비필수 문에 대응하며, 원본 문서에서 이들의 인덱스는 위에 주어져 있다. 이제 우리는 목록에 없는 선택 인덱스는 무시하고, 비필수 인덱스 목록에서 각 선택 인덱스의 인덱스를 계산함으로써 조정된 서명 인덱스 목록을 계산한다. 그런 다음 조정된 서명 인덱스를 사용하여 필터링된 서명 목록을 얻는다. 이 목록들을 아래에 나타낸다.

예시 88: 필터링된 서명
{
    "adjSignatureIndexes":[0,1,8,13,14,15],
    "filteredSignatures":[
        "fd91ec48b3524965f7a1453e9ffa067054eca6f7d6338a84525eb3288bb0caf7a9651f02fee14d6d33ee1679aa8828348ccc574e194d7f57fca8be354c1b30f7",
        "c92e6ea5f65343c704ac9450da4d55f87342829b9bad7aface8300a0879bc9972ec4879eebbaaffd9ad9e3f91d291971c8ffe5d768497d62fa27256a7e03bf99",
        "2b66d296f2d09ff280d4cdec1d02b6c38065ed36c99b6db40a9a800f4faea46187c7b42c6cb232b5103bc88445f5e1f32c89692071546f316a836cd31a979f8d",
        "09e91f89dfd0a252f79a970caec55814cd570a8e41ec2ac25c33bd8afe479a70b8e744d363bc7daa313625d0cb4c1ea8c64c87577835e9b7416b4615bb82def9",
        "b181986ef2cfb77b71f27cfb4365b8860799d9e84c3df62b3863319250d57a91d429cb15127122c36fd34a92ea0745b4a641454c561c55c37741ee247a866264",
        "13d02a9caf0d96b9fbec397d4faad90e78c56d0cbd933224d58b5c81623e3571b22aa15bc4ad201c364e3566793c9dda9c983e9965f47c7ce5ff6e1b42484dd4"
    ]
}

공개 데이터의 마지막 중요한 부분은 정규 공백 노드 id를 HMAC 기반 id로 매핑하는 labelMap이며, 이는 3.5.4 createDisclosureData 절의 12~14단계에 따라 계산된다. 이를 공개 문서를 제외한 나머지 공개 데이터와 함께 아래에 나타낸다.

예시 89: 공개 데이터
{
  "baseSignature": "b8dc55afeb6427a990e9d60c0d363b654306d92703e5036210ca29619d8ed204194ba3d86e31cdbc99f4ee9d5f25f0cc1c1f44f5fa39abec9a50cdf519b457e0",
  "publicKey": "zDnaeTHfhmSaQKBc7CmdL3K7oYg3D6SC7yowe2eBeVd2DH32r",
  "signatures": [
    "fd91ec48b3524965f7a1453e9ffa067054eca6f7d6338a84525eb3288bb0caf7a9651f02fee14d6d33ee1679aa8828348ccc574e194d7f57fca8be354c1b30f7",
    "c92e6ea5f65343c704ac9450da4d55f87342829b9bad7aface8300a0879bc9972ec4879eebbaaffd9ad9e3f91d291971c8ffe5d768497d62fa27256a7e03bf99",
    "2b66d296f2d09ff280d4cdec1d02b6c38065ed36c99b6db40a9a800f4faea46187c7b42c6cb232b5103bc88445f5e1f32c89692071546f316a836cd31a979f8d",
    "09e91f89dfd0a252f79a970caec55814cd570a8e41ec2ac25c33bd8afe479a70b8e744d363bc7daa313625d0cb4c1ea8c64c87577835e9b7416b4615bb82def9",
    "b181986ef2cfb77b71f27cfb4365b8860799d9e84c3df62b3863319250d57a91d429cb15127122c36fd34a92ea0745b4a641454c561c55c37741ee247a866264",
    "13d02a9caf0d96b9fbec397d4faad90e78c56d0cbd933224d58b5c81623e3571b22aa15bc4ad201c364e3566793c9dda9c983e9965f47c7ce5ff6e1b42484dd4"
  ],
  "labelMap": {
    "dataType": "Map",
    "value": [
      [
        "c14n0",
        "u3Lv2QpFgo-YAegc1cQQKWJFW2sEjQF6FfuZ0VEoMKHg"
      ],
      [
        "c14n1",
        "u4YIOZn1MHES1Z4Ij2hWZG3R4dEYBqg5fHTyDEvYhC38"
      ]
    ]
  },
  "mandatoryIndexes": [
    0,
    4,
    5,
    7
  ]
}

마지막으로 위 공개 데이터를 3.5.7 serializeDerivedProofValue 절의 알고리즘과 함께 사용하여 아래에 나타난 서명된 파생(공개) 문서를 얻는다.

예시 90: 서명된 파생 문서
{
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    "https://w3id.org/citizenship/v4rc1"
  ],
  "type": [
    "VerifiableCredential",
    "EmploymentAuthorizationDocumentCredential"
  ],
  "issuer": {
    "id": "did:key:zDnaegE6RR3atJtHKwTRTWHsJ3kNHqFwv7n9YjTgmU7TyfU76",
    "image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2NgUPr/HwADaAIhG61j/AAAAABJRU5ErkJggg=="
  },
  "validFrom": "2019-12-03T00:00:00Z",
  "validUntil": "2029-12-03T00:00:00Z",
  "credentialSubject": {
    "type": [
      "Person",
      "EmployablePerson"
    ],
    "birthCountry": "Bahamas"
  },
  "proof": {
    "type": "DataIntegrityProof",
    "cryptosuite": "ecdsa-sd-2023",
    "created": "2023-08-15T23:36:38Z",
    "verificationMethod": "did:key:zDnaepBuvsQ8cpsWrVKw8fbpGpvPeNSjVPTWoq6cRqaYzBKVP#zDnaepBuvsQ8cpsWrVKw8fbpGpvPeNSjVPTWoq6cRqaYzBKVP",
    "proofPurpose": "assertionMethod",
    "proofValue": "u2V0BhVhAuNxVr-tkJ6mQ6dYMDTY7ZUMG2ScD5QNiEMopYZ2O0gQZS6PYbjHNvJn07p1fJfDMHB9E9fo5q-yaUM31GbRX4FgjgCQCKnLOGbY_FuM-ASpSkkOxsIR2E8n7Ml2q1UQ6tEwzi5OGWED9kexIs1JJZfehRT6f-gZwVOym99YzioRSXrMoi7DK96llHwL-4U1tM-4WeaqIKDSMzFdOGU1_V_yovjVMGzD3WEDJLm6l9lNDxwSslFDaTVX4c0KCm5utevrOgwCgh5vJly7Eh57ruq_9mtnj-R0pGXHI_-XXaEl9YvonJWp-A7-ZWEArZtKW8tCf8oDUzewdArbDgGXtNsmbbbQKmoAPT66kYYfHtCxssjK1EDvIhEX14fMsiWkgcVRvMWqDbNMal5-NWEAJ6R-J39CiUvealwyuxVgUzVcKjkHsKsJcM72K_keacLjnRNNjvH2qMTYl0MtMHqjGTIdXeDXpt0FrRhW7gt75WECxgZhu8s-3e3HyfPtDZbiGB5nZ6Ew99is4YzGSUNV6kdQpyxUScSLDb9NKkuoHRbSmQUVMVhxVw3dB7iR6hmJkWEAT0Cqcrw2WufvsOX1PqtkOeMVtDL2TMiTVi1yBYj41cbIqoVvErSAcNk41Znk8ndqcmD6ZZfR8fOX_bhtCSE3UogBYINy79kKRYKPmAHoHNXEECliRVtrBI0BehX7mdFRKDCh4AVgg4YIOZn1MHES1Z4Ij2hWZG3R4dEYBqg5fHTyDEvYhC3-EAAQFBw"
  }
}

A.8 표현에 대한 추가 예시: ecdsa-sd-2023

여기서는 기본적인 ecdsa-sd-2023 처리에 대한 추가 예시를 제공한다. 선택적 공개 기능을 시연하기 위해, 테스트 벡터를 발급자가 생성하는 것(기본 증명)과 보유자가 생성하는 것(파생 증명)에 기반하여 두 그룹으로 나눈다.

A.8.1 기본 증명

문서에 선택적 공개 기본 증명을 추가하기 위해 발급자는 다음 암호화 키 자료가 필요하다:

  1. The issuers private/public key pair, i.e., the key pair corresponding to the verification method that will be part of the proof.
  2. A per proof private/public key pair created by the issuer just for this proof. This is an ephemeral, single use key pair where the private key is not kept after the proof has been generated.
  3. An HMAC key. This used to randomize the order of the blank node ids to avoid potential information leakage from the blank node id ordering. This is used only once and is shared between issuer and holder. The HMAC in this case is functioning as a pseudorandom function (PRF).

기본 증명 추가 테스트 벡터를 생성하는 데 사용되는 키 자료를 아래에 나타낸다. P-256 키 쌍에는 Multibase 표현이 사용되고 HMAC 키는 16진 문자열로 주어진다.

예시 91: 서명용 개인키 및 공개키
{
  "baseKeyPair": {
    "publicKeyMultibase": "zDnaepBuvsQ8cpsWrVKw8fbpGpvPeNSjVPTWoq6cRqaYzBKVP",
    "secretKeyMultibase": "z42twTcNeSYcnqg1FLuSFs2bsGH3ZqbRHFmvS9XMsYhjxvHN"
  },
  "proofKeyPair": {
    "publicKeyMultibase": "zDnaeTHfhmSaQKBc7CmdL3K7oYg3D6SC7yowe2eBeVd2DH32r",
    "secretKeyMultibase": "z42tqvNGyzyXRzotAYn43UhcFtzDUVdxJ7461fwrfhBPLmfY"
  },
  "hmacKeyString": "00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF"
}

우리 시나리오에서는 아래와 같이 어떤 사람에게 영주권 크리덴셜이 발급된다.

예시 92: 증명 없는 크리덴셜
{
    "@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 포인터 배열을 통해 지정된다.

예시 93: 필수 포인터
["/issuer"]

위 JSON 포인터를 영주권 크리덴셜에 적용한 결과를 아래에 나타낸다.

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

서명되지 않은 문서의 변환은 아래와 같이 문서를 정규화하는 것으로 시작한다.

예시 95: 정규 문서
[
  "<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의 순서로부터 발생할 수 있는 정보 유출을 방지하기 위해, 이들은 PRF, 즉 HMAC를 통해 처리되어 아래에 나타난 정규화된 HMAC 문서를 만든다. 이는 필수 및 선택적 공개의 대상이 될 문의 정렬된 목록을 나타내며, 즉 문이 그룹화되는 것은 이 목록으로부터이다.

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

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

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

다음 단계는 기본 증명 구성을 생성하고 이를 정규화하는 것이다. 이는 다음 두 예시에 나타나 있다.

예시 98: 기본 증명 구성
{
  "type": "DataIntegrityProof",
  "cryptosuite": "ecdsa-sd-2023",
  "created": "2023-08-15T23:36:38Z",
  "verificationMethod": "did:key:zDnaepBuvsQ8cpsWrVKw8fbpGpvPeNSjVPTWoq6cRqaYzBKVP#zDnaepBuvsQ8cpsWrVKw8fbpGpvPeNSjVPTWoq6cRqaYzBKVP",
  "proofPurpose": "assertionMethod",
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    "https://w3id.org/citizenship/v4rc1"
  ]
}
예시 99: 정규 기본 증명 구성
_: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> "ecdsa-sd-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:zDnaepBuvsQ8cpsWrVKw8fbpGpvPeNSjVPTWoq6cRqaYzBKVP#zDnaepBuvsQ8cpsWrVKw8fbpGpvPeNSjVPTWoq6cRqaYzBKVP> .

해싱 단계에서는 정규화된 증명 옵션의 SHA-256 해시를 계산하여 proofHash를 생성하고, 모든 필수 nquad를 결합한 것의 SHA-256 해시를 계산하여 mandatoryHash를 생성한다. 이들을 아래에 16진 형식으로 나타낸다.

예시 100: 기본 해시 추가
{
  "proofHash": "9c5c9b189f06cfa9d9f21a838ccb9b04316f07ad1a517bfd4955ee28c6a8229c",
  "mandatoryHash": "b76d8d5bf67d27f51597519d19d95809c75e35212cc65291bd71bbe36007f979"
}

발급자의 장기 privateKey를 사용하여 proofHash, proofPublicKey, mandatoryHash를 연결한 것에 대해 baseSignature를 계산한다. 증명별 proofPrivateKey를 사용하여 각 비필수 nquad에 서명함으로써 signatures 배열을 계산한다. 최종 직렬화 단계에 입력되는 이 서명들과 proofPublicKey, mandatoryPointers를 아래에 나타낸다.

예시 101: 기본 서명 추가
{
  "baseSignature": "1c00d200b76a4c87ed57aae0f09a6a05eb4e254898842a758d3b0069517ea8977f9a118b4dcc17bec33e9f9ef41b83dcde0957dc08643f546c8ca2360d1b1f2f",
  "publicKey": "zDnaeTHfhmSaQKBc7CmdL3K7oYg3D6SC7yowe2eBeVd2DH32r",
  "signatures": [
    "fd91ec48b3524965f7a1453e9ffa067054eca6f7d6338a84525eb3288bb0caf7a9651f02fee14d6d33ee1679aa8828348ccc574e194d7f57fca8be354c1b30f7",
    "3568e1402af672cb1a4c360ed7030ca8b1a744eed3c4572774e96d23e3a890db148de8dbd06594244a283f46247a540e78d14789e0e0c64ee96b6e53863707bc",
    "008fb2b467d7b2a46f16727532ae32e4027fc7746d478815c332d0a5c46021031bf72b20b0835166e21d0d3b50a6d15d75f30df14eb9b1ca10af521644564837",
    "3a6263590ab7fbc4e5ef7bc6c3f6b9cdd8a96c7c4d9a1f120612213ca39a50f39d7b56d6365ead6054bdbe4b971b2769d61841a3f7236a7434e5f1b0f6e2e8fc",
    "1b922ea997916494648491373084bc71df1fe0918665021f530829b4a387eccb48630f76015da36a079b3882f6ff70a3f87acbce78608e66867e5b2fc31df82f",
    "270f83139fe21ea6cb2176e6855580f7dc3f6694f0ab3efb723edc7844c376d2e3566b5ee1674834a8e69d197aae793e13a8a355423431a38daa442b6b440ada",
    "0106894e5850a53d4306eb237f52b11579e25916aaa97ae4f91fd258bd3806a6e24443609d469792598b17bd54da1595b8266efa20aaaee271ce1aeab7c74042",
    "ddc8430a1bf8cdbbb6e8c1e2dcb434dc0db59ab0c5501bd7dacee9e2c0234e2399ed95765d62ef4cabf0fe8117ee32f24b8f8c64d1955ddd4362269d9493035e",
    "a16b9b2761a89b79428a1c8bbf19216e4d07271022bf9867d11a0055a8f19aa9583196d01234ad63a390b2971eebde0ae748258593500277a90f0d74fd2164f1",
    "c6b8ab5a139770eef2fdabcc24ae63fbdf93a250238df7f29e2c905591e660e8fc87f74ac53eba18fe0487c6effeebbf8c9e4d075d5ae91b2ed7842c67e0b429",
    "e7ee420aa027ba4671b926c29e2c574f94461660a0b3d6c828cce50314d9e1e4c346ed119352adf6141c66e2fce4a2cb7486c3f81cc42e388a5f921285677d94",
    "8cc617955838bc95f849c8a782955374baf151727e8d12e5b4d0a200b406dcd839dbe5d5f760cc3b02bd65081d915138cbf14846b06e898916d8e30c725aaa5f",
    "e10f849d052c6de7aa2459d93552ac5ea2ebf52d2e4ec6257b10654734066553a09e418bef1154f4af9f942c4b5cc0ad5a36ea3758c858d60cad68971398ed7f",
    "acc0b0b8913da9043fdf1b5b19ac08a31dc809e128128bf9fde0558d3a05ca9198c49c152a3a55e6c3a6ab0bd59736cbe1e0c5b43af83c1a7a753a452a0241b5",
    "2aadfc3bf665674c59537988413cc3fd945536501aa6fa541bb02bc398f50d12522b52775d39921a1ed3b8c17b4c9c7f418973b9b08f6fee1d60e9e48904e1c2",
    "e41fcb03a010398c1a0a89103dbaa61f606e81548e7237a26b208ac40d5787664bd76ec4a68b6bc97aad0e771a5e884493501c5aa52aadd74fe1181bed6d4d6e",
    "b9638d13bc4c1aecb987e0f713ef5e0a9290cf69cb182f48c2761530a5d6095db9f4196e706835bf35492d23215b9b50632256ac605f74df01c55144863bf202",
    "d54d0056b279a17c591bd8580014f89c8cdabe20c80d84f7c137c4a36f97850dd0803fd6f1d70814a0b58dce9d50f30192c980d5bc451dea9a6569f90eb5d8b8",
    "a678ac62c5416d0e93b9dbd3efa9add4c1e1a79e6707ba3d831ffc119f6837c184a7652340cb8a62004f459c905067b9cc03f43b3c677a022eeab1d7d7243c05",
    "63730c42010acac32391d72d4f755b08588e1c289ab93e2a2c2d9a5d85a6d3d06fdeb39939f614efb4b3191966bae6f500ee44267ae44990f30b44e6c92943b4"
  ],
  "mandatoryPointers": [
    "/issuer"
  ]
}

마지막으로, 위 값들을 3.5.2 serializeBaseProofValue 절의 알고리즘에 통과시켜 proofValue를 생성하며, 이는 아래에 나타난 서명된 기본 문서에 사용된다.

예시 102: 서명된 기본 문서
{
  "@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": "ecdsa-sd-2023",
    "created": "2023-08-15T23:36:38Z",
    "verificationMethod": "did:key:zDnaepBuvsQ8cpsWrVKw8fbpGpvPeNSjVPTWoq6cRqaYzBKVP#zDnaepBuvsQ8cpsWrVKw8fbpGpvPeNSjVPTWoq6cRqaYzBKVP",
    "proofPurpose": "assertionMethod",
    "proofValue": "u2V0AhVhAHADSALdqTIftV6rg8JpqBetOJUiYhCp1jTsAaVF-qJd_mhGLTcwXvsM-n570G4Pc3glX3AhkP1RsjKI2DRsfL1gjgCQCKnLOGbY_FuM-ASpSkkOxsIR2E8n7Ml2q1UQ6tEwzi5NYIAARIjNEVWZ3iJmqu8zd7v8AESIzRFVmd4iZqrvM3e7_lFhA_ZHsSLNSSWX3oUU-n_oGcFTspvfWM4qEUl6zKIuwyvepZR8C_uFNbTPuFnmqiCg0jMxXThlNf1f8qL41TBsw91hANWjhQCr2cssaTDYO1wMMqLGnRO7TxFcndOltI-OokNsUjejb0GWUJEooP0YkelQOeNFHieDgxk7pa25ThjcHvFhAAI-ytGfXsqRvFnJ1Mq4y5AJ_x3RtR4gVwzLQpcRgIQMb9ysgsINRZuIdDTtQptFddfMN8U65scoQr1IWRFZIN1hAOmJjWQq3-8Tl73vGw_a5zdipbHxNmh8SBhIhPKOaUPOde1bWNl6tYFS9vkuXGydp1hhBo_cjanQ05fGw9uLo_FhAG5IuqZeRZJRkhJE3MIS8cd8f4JGGZQIfUwgptKOH7MtIYw92AV2jagebOIL2_3Cj-HrLznhgjmaGflsvwx34L1hAJw-DE5_iHqbLIXbmhVWA99w_ZpTwqz77cj7ceETDdtLjVmte4WdINKjmnRl6rnk-E6ijVUI0MaONqkQra0QK2lhAAQaJTlhQpT1DBusjf1KxFXniWRaqqXrk-R_SWL04BqbiRENgnUaXklmLF71U2hWVuCZu-iCqruJxzhrqt8dAQlhA3chDChv4zbu26MHi3LQ03A21mrDFUBvX2s7p4sAjTiOZ7ZV2XWLvTKvw_oEX7jLyS4-MZNGVXd1DYiadlJMDXlhAoWubJ2Gom3lCihyLvxkhbk0HJxAiv5hn0RoAVajxmqlYMZbQEjStY6OQspce694K50glhZNQAnepDw10_SFk8VhAxrirWhOXcO7y_avMJK5j-9-TolAjjffyniyQVZHmYOj8h_dKxT66GP4Eh8bv_uu_jJ5NB11a6Rsu14QsZ-C0KVhA5-5CCqAnukZxuSbCnixXT5RGFmCgs9bIKMzlAxTZ4eTDRu0Rk1Kt9hQcZuL85KLLdIbD-BzELjiKX5IShWd9lFhAjMYXlVg4vJX4ScingpVTdLrxUXJ-jRLltNCiALQG3Ng52-XV92DMOwK9ZQgdkVE4y_FIRrBuiYkW2OMMclqqX1hA4Q-EnQUsbeeqJFnZNVKsXqLr9S0uTsYlexBlRzQGZVOgnkGL7xFU9K-flCxLXMCtWjbqN1jIWNYMrWiXE5jtf1hArMCwuJE9qQQ_3xtbGawIox3ICeEoEov5_eBVjToFypGYxJwVKjpV5sOmqwvVlzbL4eDFtDr4PBp6dTpFKgJBtVhAKq38O_ZlZ0xZU3mIQTzD_ZRVNlAapvpUG7Arw5j1DRJSK1J3XTmSGh7TuMF7TJx_QYlzubCPb-4dYOnkiQThwlhA5B_LA6AQOYwaCokQPbqmH2BugVSOcjeiayCKxA1Xh2ZL127EpotryXqtDncaXohEk1AcWqUqrddP4Rgb7W1NblhAuWONE7xMGuy5h-D3E-9eCpKQz2nLGC9IwnYVMKXWCV259BlucGg1vzVJLSMhW5tQYyJWrGBfdN8BxVFEhjvyAlhA1U0AVrJ5oXxZG9hYABT4nIzaviDIDYT3wTfEo2-XhQ3QgD_W8dcIFKC1jc6dUPMBksmA1bxFHeqaZWn5DrXYuFhApnisYsVBbQ6TudvT76mt1MHhp55nB7o9gx_8EZ9oN8GEp2UjQMuKYgBPRZyQUGe5zAP0OzxnegIu6rHX1yQ8BVhAY3MMQgEKysMjkdctT3VbCFiOHCiauT4qLC2aXYWm09Bv3rOZOfYU77SzGRlmuub1AO5EJnrkSZDzC0TmySlDtIFnL2lzc3Vlcg"
  }
}

A.8.2 파생 증명

파생 증명을 생성하기 위해 보유자는 기본 증명을 담은 서명된 문서로 시작한다. 이 테스트 벡터에 사용할 기본 문서는 위 A.7.1 기본 증명 절의 마지막 예시이다. 첫 번째 단계는 3.5.3 parseBaseProofValue 절의 알고리즘을 실행하여 아래와 같이 baseSignature, publicKey, hmacKey, signatures, mandatoryPointers를 복원하는 것이다.

예시 103: 복원된 기본 서명 데이터
{
  "baseSignature": "1c00d200b76a4c87ed57aae0f09a6a05eb4e254898842a758d3b0069517ea8977f9a118b4dcc17bec33e9f9ef41b83dcde0957dc08643f546c8ca2360d1b1f2f",
  "proofPublicKey": "zDnaeTHfhmSaQKBc7CmdL3K7oYg3D6SC7yowe2eBeVd2DH32r",
  "hmacKey": "00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff",
  "signatures": [
    "fd91ec48b3524965f7a1453e9ffa067054eca6f7d6338a84525eb3288bb0caf7a9651f02fee14d6d33ee1679aa8828348ccc574e194d7f57fca8be354c1b30f7",
    "3568e1402af672cb1a4c360ed7030ca8b1a744eed3c4572774e96d23e3a890db148de8dbd06594244a283f46247a540e78d14789e0e0c64ee96b6e53863707bc",
    "008fb2b467d7b2a46f16727532ae32e4027fc7746d478815c332d0a5c46021031bf72b20b0835166e21d0d3b50a6d15d75f30df14eb9b1ca10af521644564837",
    "3a6263590ab7fbc4e5ef7bc6c3f6b9cdd8a96c7c4d9a1f120612213ca39a50f39d7b56d6365ead6054bdbe4b971b2769d61841a3f7236a7434e5f1b0f6e2e8fc",
    "1b922ea997916494648491373084bc71df1fe0918665021f530829b4a387eccb48630f76015da36a079b3882f6ff70a3f87acbce78608e66867e5b2fc31df82f",
    "270f83139fe21ea6cb2176e6855580f7dc3f6694f0ab3efb723edc7844c376d2e3566b5ee1674834a8e69d197aae793e13a8a355423431a38daa442b6b440ada",
    "0106894e5850a53d4306eb237f52b11579e25916aaa97ae4f91fd258bd3806a6e24443609d469792598b17bd54da1595b8266efa20aaaee271ce1aeab7c74042",
    "ddc8430a1bf8cdbbb6e8c1e2dcb434dc0db59ab0c5501bd7dacee9e2c0234e2399ed95765d62ef4cabf0fe8117ee32f24b8f8c64d1955ddd4362269d9493035e",
    "a16b9b2761a89b79428a1c8bbf19216e4d07271022bf9867d11a0055a8f19aa9583196d01234ad63a390b2971eebde0ae748258593500277a90f0d74fd2164f1",
    "c6b8ab5a139770eef2fdabcc24ae63fbdf93a250238df7f29e2c905591e660e8fc87f74ac53eba18fe0487c6effeebbf8c9e4d075d5ae91b2ed7842c67e0b429",
    "e7ee420aa027ba4671b926c29e2c574f94461660a0b3d6c828cce50314d9e1e4c346ed119352adf6141c66e2fce4a2cb7486c3f81cc42e388a5f921285677d94",
    "8cc617955838bc95f849c8a782955374baf151727e8d12e5b4d0a200b406dcd839dbe5d5f760cc3b02bd65081d915138cbf14846b06e898916d8e30c725aaa5f",
    "e10f849d052c6de7aa2459d93552ac5ea2ebf52d2e4ec6257b10654734066553a09e418bef1154f4af9f942c4b5cc0ad5a36ea3758c858d60cad68971398ed7f",
    "acc0b0b8913da9043fdf1b5b19ac08a31dc809e128128bf9fde0558d3a05ca9198c49c152a3a55e6c3a6ab0bd59736cbe1e0c5b43af83c1a7a753a452a0241b5",
    "2aadfc3bf665674c59537988413cc3fd945536501aa6fa541bb02bc398f50d12522b52775d39921a1ed3b8c17b4c9c7f418973b9b08f6fee1d60e9e48904e1c2",
    "e41fcb03a010398c1a0a89103dbaa61f606e81548e7237a26b208ac40d5787664bd76ec4a68b6bc97aad0e771a5e884493501c5aa52aadd74fe1181bed6d4d6e",
    "b9638d13bc4c1aecb987e0f713ef5e0a9290cf69cb182f48c2761530a5d6095db9f4196e706835bf35492d23215b9b50632256ac605f74df01c55144863bf202",
    "d54d0056b279a17c591bd8580014f89c8cdabe20c80d84f7c137c4a36f97850dd0803fd6f1d70814a0b58dce9d50f30192c980d5bc451dea9a6569f90eb5d8b8",
    "a678ac62c5416d0e93b9dbd3efa9add4c1e1a79e6707ba3d831ffc119f6837c184a7652340cb8a62004f459c905067b9cc03f43b3c677a022eeab1d7d7243c05",
    "63730c42010acac32391d72d4f755b08588e1c289ab93e2a2c2d9a5d85a6d3d06fdeb39939f614efb4b3191966bae6f500ee44267ae44990f30b44e6c92943b4"
  ],
  "mandatoryPointers": [
    "/issuer"
  ]
}

다음으로, 보유자는 선택적 공개를 위한 JSON 포인터를 지정하여 그 외에 검증자에게 공개하고자 하는 것이 있다면 무엇인지 표시한다.

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

결국 서명되어 검증자에게 전송될 서명되지 않은 문서인 revealDocument를 생성하기 위해, 필수 포인터에 선택 포인터를 덧붙이고, 이 결합된 포인터를 증명 없는 문서와 함께 3.4.13 selectJsonLd 절의 알고리즘에 입력하여 아래에 나타난 결과를 얻는다.

예시 105: 서명되지 않은 공개 문서
{
  "@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"
  }
}

이제 공개된 문서가 어떤 모습인지 알았으므로, 어떤 문이 필수인지, 선택된 비필수 문에 대한 서명, 그리고 공개 문서의 정규 공백 노드 id와 HMAC 공백 노드 id의 부분집합 사이의 매핑에 관한 적절히 갱신된 정보를 검증자에게 제공해야 한다. 3.5.4 createDisclosureData의 6단계를 실행하면 원본 문서를 기준으로 다양한 문 그룹에 관한 풍부한 정보가 산출된다. 아래에 그 그룹들의 인덱스 일부를 나타낸다.

예시 106: 파생 그룹 인덱스
{
    "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는 공개 문서를 구성하는 모든 원본 nquad(문)의 인덱스를 순서대로 보여준다. 아래에 나타난 조정된 필수 인덱스를 얻기 위해, 아래와 같이 combinedIndexes를 기준으로 각 원본 필수 인덱스의 인덱스를 구한다.

예시 107: 조정된 필수 인덱스
{
  "adjMandatoryIndexes":[0,4,5,7]
}

우리는 필수가 아닌 선택적 문(nquad)에 대한 서명 목록을 검증자에게 제공해야 한다. 원본 서명 목록은 모든 비필수 문에 대응하며, 원본 문서에서 이들의 인덱스는 위에 주어져 있다. 이제 우리는 목록에 없는 선택 인덱스는 무시하고, 비필수 인덱스 목록에서 각 선택 인덱스의 인덱스를 계산함으로써 조정된 서명 인덱스 목록을 계산한다. 그런 다음 조정된 서명 인덱스를 사용하여 필터링된 서명 목록을 얻는다. 이 목록들을 아래에 나타낸다.

예시 108: 필터링된 서명
{
    "adjSignatureIndexes":[0,1,7,17,18,19],
    "filteredSignatures":[
        "fd91ec48b3524965f7a1453e9ffa067054eca6f7d6338a84525eb3288bb0caf7a9651f02fee14d6d33ee1679aa8828348ccc574e194d7f57fca8be354c1b30f7",
        "3568e1402af672cb1a4c360ed7030ca8b1a744eed3c4572774e96d23e3a890db148de8dbd06594244a283f46247a540e78d14789e0e0c64ee96b6e53863707bc",
        "ddc8430a1bf8cdbbb6e8c1e2dcb434dc0db59ab0c5501bd7dacee9e2c0234e2399ed95765d62ef4cabf0fe8117ee32f24b8f8c64d1955ddd4362269d9493035e",
        "d54d0056b279a17c591bd8580014f89c8cdabe20c80d84f7c137c4a36f97850dd0803fd6f1d70814a0b58dce9d50f30192c980d5bc451dea9a6569f90eb5d8b8",
        "a678ac62c5416d0e93b9dbd3efa9add4c1e1a79e6707ba3d831ffc119f6837c184a7652340cb8a62004f459c905067b9cc03f43b3c677a022eeab1d7d7243c05",
        "63730c42010acac32391d72d4f755b08588e1c289ab93e2a2c2d9a5d85a6d3d06fdeb39939f614efb4b3191966bae6f500ee44267ae44990f30b44e6c92943b4"
        ]
}

공개 데이터의 마지막 중요한 부분은 정규 공백 노드 id를 HMAC 기반 id로 매핑하는 labelMap이며, 이는 3.5.4 createDisclosureData 절의 12~14단계에 따라 계산된다. 이를 공개 문서를 제외한 나머지 공개 데이터와 함께 아래에 나타낸다.

예시 109: 공개 데이터
{
  "baseSignature": "1c00d200b76a4c87ed57aae0f09a6a05eb4e254898842a758d3b0069517ea8977f9a118b4dcc17bec33e9f9ef41b83dcde0957dc08643f546c8ca2360d1b1f2f",
  "publicKey": "zDnaeTHfhmSaQKBc7CmdL3K7oYg3D6SC7yowe2eBeVd2DH32r",
  "signatures": [
    "fd91ec48b3524965f7a1453e9ffa067054eca6f7d6338a84525eb3288bb0caf7a9651f02fee14d6d33ee1679aa8828348ccc574e194d7f57fca8be354c1b30f7",
    "3568e1402af672cb1a4c360ed7030ca8b1a744eed3c4572774e96d23e3a890db148de8dbd06594244a283f46247a540e78d14789e0e0c64ee96b6e53863707bc",
    "ddc8430a1bf8cdbbb6e8c1e2dcb434dc0db59ab0c5501bd7dacee9e2c0234e2399ed95765d62ef4cabf0fe8117ee32f24b8f8c64d1955ddd4362269d9493035e",
    "d54d0056b279a17c591bd8580014f89c8cdabe20c80d84f7c137c4a36f97850dd0803fd6f1d70814a0b58dce9d50f30192c980d5bc451dea9a6569f90eb5d8b8",
    "a678ac62c5416d0e93b9dbd3efa9add4c1e1a79e6707ba3d831ffc119f6837c184a7652340cb8a62004f459c905067b9cc03f43b3c677a022eeab1d7d7243c05",
    "63730c42010acac32391d72d4f755b08588e1c289ab93e2a2c2d9a5d85a6d3d06fdeb39939f614efb4b3191966bae6f500ee44267ae44990f30b44e6c92943b4"
  ],
  "labelMap": {
    "dataType": "Map",
    "value": [
      [
        "c14n0",
        "u3Lv2QpFgo-YAegc1cQQKWJFW2sEjQF6FfuZ0VEoMKHg"
      ],
      [
        "c14n1",
        "uVkUuBrlOaELGVQWJD4M_qW5bcKEHWGNbOrPA_qAOKKw"
      ]
    ]
  },
  "mandatoryIndexes": [
    0,
    4,
    5,
    7
  ]
}

마지막으로 위 공개 데이터를 3.5.7 serializeDerivedProofValue 절의 알고리즘과 함께 사용하여 아래에 나타난 서명된 파생(공개) 문서를 얻는다.

예시 110: 서명된 파생 문서
{
  "@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": "ecdsa-sd-2023",
    "created": "2023-08-15T23:36:38Z",
    "verificationMethod": "did:key:zDnaepBuvsQ8cpsWrVKw8fbpGpvPeNSjVPTWoq6cRqaYzBKVP#zDnaepBuvsQ8cpsWrVKw8fbpGpvPeNSjVPTWoq6cRqaYzBKVP",
    "proofPurpose": "assertionMethod",
    "proofValue": "u2V0BhVhAHADSALdqTIftV6rg8JpqBetOJUiYhCp1jTsAaVF-qJd_mhGLTcwXvsM-n570G4Pc3glX3AhkP1RsjKI2DRsfL1gjgCQCKnLOGbY_FuM-ASpSkkOxsIR2E8n7Ml2q1UQ6tEwzi5OGWED9kexIs1JJZfehRT6f-gZwVOym99YzioRSXrMoi7DK96llHwL-4U1tM-4WeaqIKDSMzFdOGU1_V_yovjVMGzD3WEA1aOFAKvZyyxpMNg7XAwyosadE7tPEVyd06W0j46iQ2xSN6NvQZZQkSig_RiR6VA540UeJ4ODGTulrblOGNwe8WEDdyEMKG_jNu7boweLctDTcDbWasMVQG9fazuniwCNOI5ntlXZdYu9Mq_D-gRfuMvJLj4xk0ZVd3UNiJp2UkwNeWEDVTQBWsnmhfFkb2FgAFPicjNq-IMgNhPfBN8Sjb5eFDdCAP9bx1wgUoLWNzp1Q8wGSyYDVvEUd6pplafkOtdi4WECmeKxixUFtDpO529Pvqa3UweGnnmcHuj2DH_wRn2g3wYSnZSNAy4piAE9FnJBQZ7nMA_Q7PGd6Ai7qsdfXJDwFWEBjcwxCAQrKwyOR1y1PdVsIWI4cKJq5PiosLZpdhabT0G_es5k59hTvtLMZGWa65vUA7kQmeuRJkPMLRObJKUO0ogBYINy79kKRYKPmAHoHNXEECliRVtrBI0BehX7mdFRKDCh4AVggVkUuBrlOaELGVQWJD4M_qW5bcKEHWGNbOrPA_qAOKKyEAAQFBw"
  }
}

B. Revision History

이 부분은 비규범적입니다.

This section contains the substantive changes that have been made to this specification over time.

Changes since the Second Candidate Recommendation:

Changes since the First Candidate Recommendation:

Changes since the First Public Working Draft:

C. Acknowledgements

이 부분은 비규범적입니다.

Work on this specification has been supported by the Rebooting the Web of Trust community facilitated by 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, Will Abramson, and Eric Schuh. The participants in the Internet Identity Workshop, facilitated by Phil Windley, Kaliya Young, Doc Searls, and Heidi Nobantu Saul, also supported the refinement of this work through numerous working sessions designed to educate about, debate on, and improve this specification.

The Working Group also thanks our Working Group Chair Brent Zundel, and ex-chair Kristina Yasuda, as well as our W3C Staff Contact, Ivan Herman, for their expert management and steady guidance of the group through the W3C standardization cycle. We also thank the Chairs of the W3C Credentials Community Group, Christopher Allen, Joe Andrieu, Kim Hamilton Duffy, Heather Vescent, Wayne Chang, Mike Prorock, Harrison Tang, Kimberly Wilson Linson, and Will Abramson, who oversaw the incubation of this work.

Portions of the work on this specification have been funded by the United States Department of Homeland Security's Science and Technology Directorate under contracts 70RSAT20T00000029, 70RSAT21T00000016, 70RSAT23T00000005, 70RSAT20T00000010/P00001, 70RSAT20T00000029, 70RSAT21T00000016/P00001, 70RSAT23T00000005, 70RSAT23C00000030, 70RSAT23R00000006, 70RSAT24T00000011, and the National Science Foundation through NSF 22-572. The content of this specification does not necessarily reflect the position or the policy of the U.S. Government and no official endorsement should be inferred.

The Working Group would like to thank the following individuals for reviewing and providing feedback on and implementations of the specification (in alphabetical order by last name):

Greg Bernstein, Simon Bihel, Sebastian Crane, Stas Dmytryshyn, Tashi D. Gyeltshen, Ivan Herman, Andrew Jones, Filip Kolarik, Helge Krueger, Dominik Kuziński, Charles E. Lehner, Dave Longley, Tomislav Markovski, Tyler Minard, Bryan Newbold, Marty Reed, Brian Richter, Eugeniu Rusu, Markus Sabadello, Pritam Singh, Patrick St-Louis, Manu Sporny, Orie Steele, Ted Thibodeau Jr., Benjamin Young, and Dmitri Zagidulin.

D. References

D.1 Normative references

[CID]
Controlled Identifiers v1.0. Michael Jones; Manu Sporny. W3C. 20 March 2025. W3C Proposed Recommendation. URL: https://www.w3.org/TR/cid-1.0/
[FIPS-186-5]
FIPS PUB 186-5: Digital Signature Standard (DSS). U.S. Department of Commerce/National Institute of Standards and Technology. 3 February 2023. National Standard. URL: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-5.pdf
[INFRA]
Infra Standard. Anne van Kesteren; Domenic Denicola. WHATWG. Living Standard. URL: https://infra.spec.whatwg.org/
[JSON-LD11-API]
JSON-LD 1.1 Processing Algorithms and API. Gregg Kellogg; Dave Longley; Pierre-Antoine Champin. W3C. 16 July 2020. W3C Recommendation. URL: https://www.w3.org/TR/json-ld11-api/
[N-QUADS]
RDF 1.1 N-Quads. Gavin Carothers. W3C. 25 February 2014. W3C Recommendation. URL: https://www.w3.org/TR/n-quads/
[NIST-SP-800-186]
Recommendations for Discrete Logarithm-based Cryptography: Elliptic Curve Domain Parameters. Lily Chen; Dustin Moody; Karen Randall; Andrew Regenscheid; Angela Robinson. National Institute of Standards and Technology. February 2023.
[RDF-CANON]
RDF Dataset Canonicalization. Gregg Kellogg; Dave Longley; Dan Yamamoto. W3C. 21 May 2024. W3C Recommendation. URL: https://www.w3.org/TR/rdf-canon/
[RFC2104]
HMAC: Keyed-Hashing for Message Authentication. H. Krawczyk; M. Bellare; R. Canetti. IETF. February 1997. Informational. URL: https://www.rfc-editor.org/rfc/rfc2104
[RFC2119]
Key words for use in RFCs to Indicate Requirement Levels. S. Bradner. IETF. March 1997. Best Current Practice. URL: https://www.rfc-editor.org/rfc/rfc2119
[RFC4754]
IKE and IKEv2 Authentication Using the Elliptic Curve Digital Signature Algorithm (ECDSA). D. Fu; J. Solinas. IETF. January 2007. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc4754
[RFC6234]
US Secure Hash Algorithms (SHA and SHA-based HMAC and HKDF). D. Eastlake 3rd; T. Hansen. IETF. May 2011. Informational. URL: https://www.rfc-editor.org/rfc/rfc6234
[RFC6901]
JavaScript Object Notation (JSON) Pointer. P. Bryan, Ed.; K. Zyp; M. Nottingham, Ed. IETF. April 2013. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc6901
[RFC6979]
Deterministic Usage of the Digital Signature Algorithm (DSA) and Elliptic Curve Digital Signature Algorithm (ECDSA). T. Pornin. IETF. August 2013. Informational. URL: https://www.rfc-editor.org/rfc/rfc6979
[RFC8174]
Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words. B. Leiba. IETF. May 2017. Best Current Practice. URL: https://www.rfc-editor.org/rfc/rfc8174
[RFC8785]
JSON Canonicalization Scheme (JCS). A. Rundgren; B. Jordan; S. Erdtman. IETF. June 2020. Informational. URL: https://www.rfc-editor.org/rfc/rfc8785
[RFC8949]
Concise Binary Object Representation (CBOR). C. Bormann; P. Hoffman. IETF. December 2020. Internet Standard. URL: https://www.rfc-editor.org/rfc/rfc8949
[VC-DATA-INTEGRITY]
Verifiable Credential Data Integrity 1.0. Ivan Herman; Manu Sporny; Ted Thibodeau Jr; Dave Longley; Greg Bernstein. W3C. 20 March 2025. W3C Proposed Recommendation. URL: https://www.w3.org/TR/vc-data-integrity/
[vc-data-model-2.0]
Verifiable Credentials Data Model v2.0. Ivan Herman; Michael Jones; Manu Sporny; Ted Thibodeau Jr; Gabe Cohen. W3C. 20 March 2025. W3C Proposed Recommendation. URL: https://www.w3.org/TR/vc-data-model-2.0/
[XMLSCHEMA11-2]
W3C XML Schema Definition Language (XSD) 1.1 Part 2: Datatypes. David Peterson; Sandy Gao; Ashok Malhotra; Michael Sperberg-McQueen; Henry Thompson; Paul V. Biron et al. W3C. 5 April 2012. W3C Recommendation. URL: https://www.w3.org/TR/xmlschema11-2/

D.2 Informative references

[NIST-SP-800-57-Part-1]
Recommendation for Key Management: Part 1 – General. Elaine Barker. National Institute of Standards and Technology. May 2020. URL: https://doi.org/10.6028/NIST.SP.800-57pt1r5
[SECG2]
SEC 2: Recommended Elliptic Curve Domain Parameters. Certicom Research. January 27, 2010. URL: https://www.secg.org/sec2-v2.pdf
[VC-DI-BBS]
Data Integrity BBS Cryptosuites v1.0. Greg Bernstein; Manu Sporny. W3C. 3 April 2025. CRD. URL: https://www.w3.org/TR/vc-di-bbs/