Copyright © 2026 World Wide Web Consortium. W3C® liability, trademark and permissive document license rules apply.
이 명세는 BBS 서명 방식을 사용하여 디지털 서명을 생성할 때 사용되는 데이터 무결성 암호화 스위트를 설명합니다. 이 서명 스위트는 BBS 서명을 사용하여 선택적 공개와 연결할 수 없는 파생 증명을 제공합니다.
이 절에서는 이 문서가 발행된 시점의 상태를 설명합니다. 현재 W3C 발행물 목록과 이 기술 보고서의 최신 개정판은 W3C 표준 및 초안 색인에서 확인할 수 있습니다.
워킹 그룹은 이 명세에 대한 구현 피드백을 적극적으로 구하고 있습니다. 후보 권고안 단계를 종료하기 위해 워킹 그룹은 이 명세의 필수 및 선택 기능 각각에 대해 최소 두 개의 독립적인 구현을 요구 사항으로 정했습니다. 적합성 테스트 절차에 대한 자세한 내용은 구현 보고서에 나열된 테스트 스위트를 참조하십시오.
이 문서는 검증 가능한 자격 증명 워킹 그룹이 권고안 트랙을 사용하여 후보 권고안 초안으로 발행했습니다.
후보 권고안으로 발행되었다고 해서 W3C 및 그 회원들이 이를 승인한다는 의미는 아닙니다. 후보 권고안 초안에는 워킹 그룹이 후속 후보 권고안 스냅샷에 포함하려는 이전 후보 권고안의 변경 사항이 반영되어 있습니다.
이 문서는 초안이며 언제든지 다른 문서에 의해 업데이트, 대체되거나 폐기될 수 있습니다. 이 문서를 진행 중인 작업 이외의 것으로 인용하는 것은 적절하지 않습니다.
이 문서는 W3C 특허 정책에 따라 운영되는 그룹에서 작성했습니다. W3C는 이 그룹의 결과물과 관련하여 이루어진 모든 특허 공개의 공개 목록을 유지하고 있으며, 해당 페이지에는 특허를 공개하는 방법에 대한 지침도 포함되어 있습니다. 자신이 알고 있는 특허가 필수 청구항을 포함한다고 믿는 사람은 W3C 특허 정책 제6절에 따라 해당 정보를 공개해야 합니다.
이 문서는 2025년 8월 18일 W3C 절차 문서의 적용을 받습니다.
이 사양은 데이터 무결성 [VC-DATA-INTEGRITY-1.1] 사양을 준수하여
BBS 서명 스킴을 사용해 증명을 생성하고, 검증하고, 파생하기 위한 암호화 스위트를 정의합니다.
BBS 서명 스킴은 선택적 공개와 연결할 수 없는
증명을 직접 제공합니다. 이 스킴은 발급자,
보유자, 검증자 모델 내에서 작동하는 네 가지 상위 수준 함수를 제공합니다. 구체적으로, 발급자는 BBS Sign 함수를 사용하여
원본 자격 증명에 서명하는 데 사용되는 "BBS 서명"이라는 암호화 값을
생성합니다. 보유자는 BBS로 서명된
자격 증명을 수신하면 BBS Verify 함수를 사용하여 해당 자격 증명을 검증합니다.
그런 다음 보유자는 수신한 자격 증명에서 선택적으로 공개할 정보를
선택하고 BBS ProofGen 함수를 사용하여
"BBS 증명"이라는 암호화 값을 생성하며, 이 값은 이 "파생 자격 증명"의
증명을 생성하는 데 사용됩니다. 암호화된 "BBS 증명" 값은
원본 "BBS 서명"과 연결할 수 없으며, 정확히 동일한 정보를
포함하는 경우를 비롯하여 추가적인 "파생 자격 증명"마다 서로 다른 연결 불가능한 "BBS 증명"을
보유자가 생성할 수 있습니다.
마지막으로 검증자는 BBS ProofVerify 함수를 사용하여 보유자로부터 받은 파생
자격 증명을 검증합니다.
검증 가능한 자격 증명에 BBS 서명 방식을 적용하려면
이 문서에 명시된 처리가 필요합니다.
일반적으로 이 스위트는 RDF 데이터셋 정규화 알고리즘
[RDF-CANON]을 사용하여 입력 문서를
정규형으로 변환합니다. 그런 다음 발급자는 선택적 공개 기본 연산을 사용하여
정규형을 필수 문장과 비필수 문장으로 분리합니다. 이들은 다른 정보와 함께
별도로 처리되어 적절한 키 자료와 함께 BBS Sign
함수의 입력으로 사용됩니다. 이 출력은
보안이 적용된 자격 증명을 생성하는 데 사용됩니다. 보유자는 자격 증명을 받은 후 일련의 선택적 공개
함수와 BBS Verify 함수를 사용하여
유효성을 확인합니다.
마찬가지로 BBS로 서명된 자격 증명을 받은 보유자는 RDF 데이터셋
정규화 알고리즘 [RDF-CANON]을 사용하여 입력
문서를 정규형으로 변환한 다음 선택적 공개
기본 연산을 적용하여 정규형을 필수 문장과 선택적으로
공개되는 문장으로 분리합니다. 이 문장들은 적절히 처리되어
BBS ProofGen 함수의 입력으로 사용됩니다. 적절하게 처리되면 이 함수의 출력은
검증자에게 전송되는 서명된 선택적 공개 자격 증명이 됩니다.
정규화 및 선택적 공개 기본 연산을 사용하여 검증자는
BBS verifyProof 함수를 사용해 자격 증명을 검증할 수 있습니다.
이 문서 전체에서 사용되는 용어는 검증 가능한 자격 증명 데이터 무결성 1.1 사양의 용어 절에서 정의합니다.
비규범적으로 표시된 절뿐만 아니라 이 명세의 모든 작성 지침, 다이어그램, 예제 및 참고 사항은 비규범적입니다. 이 명세의 그 밖의 모든 내용은 규범적입니다.
이 문서에서 MAY, MUST, MUST NOT, OPTIONAL, REQUIRED 및 SHOULD라는 핵심 단어는 여기에 표시된 것처럼 모두 대문자로 나타날 때에만 BCP 14 [RFC2119] [RFC8174]에 설명된 대로 해석해야 합니다.
적합한 증명은 이 명세의 규범적 문장을 준수하는 데이터 모델의 모든 구체적인 표현입니다. 구체적으로 이 문서의 2. 데이터 모델 및 3. 알고리즘 절에 있는 모든 관련 규범적 문장을 반드시 적용해야 합니다.
적합한 처리기는 적합한 증명을 생성하거나 소비하는 소프트웨어 및/또는 하드웨어로 구현된 모든 알고리즘입니다. 적합한 처리기는 부적합한 문서를 처리할 때 반드시 오류를 발생시켜야 합니다.
이 문서에는 JSON 및 JSON-LD 데이터의 예제가 포함되어 있습니다. 이러한 예제 중 일부는
특정 부분을 설명하는 인라인 주석(//)과
예제와 관련 없는 정보의 생략을 나타내는 줄임표(...) 같은 기능을 포함하므로
유효한 JSON이 아닙니다. 구현자가 예제를 유효한 JSON 또는 JSON-LD로 처리하려면
이러한 부분을 제거해야 합니다.
다음 절에서는 이 사양에서 검증 방법 및 데이터 무결성 증명 형식에 사용하는 데이터 모델을 설명합니다.
이러한 검증 방법은 [VC-DATA-INTEGRITY-1.1]에 따라 생성된 데이터 무결성 증명을 검증하는 데 사용되며, [CFRG-BBS-SIGNATURE]을 준수하는 BLS12-381 암호화 키 자료를 사용합니다. 이러한 키 유형의 인코딩 형식은 이 절에서 제공합니다. 동등한 암호화 키 자료를 생성하는 무손실 암호화 키 변환 프로세스는 디지털 서명을 처리하는 동안 사용될 수 있습니다(MAY).
제어되는 식별자 v1.0에 정의된 Multikey 형식은 이 명세에서 정의한 암호화 스위트의 공개 키를 표현하는 데 사용됩니다.
publicKeyMultibase 속성은 G2 그룹에 속하는
BLS12-381 381비트 공개 키의 Multibase 인코딩 Multikey 표현을 나타냅니다.
검증 방법의 publicKeyMultibase 값은
제어되는 식별자
v1.0의
Multibase 절에 정의된 대로
반드시
base-58-btc 접두사(z)로 시작해야 합니다. 그 뒤에는
제어되는 식별자
v1.0의 Multikey 절에
정의된 Multibase 인코딩 BLS12-381 381비트 공개 키 값이
이어집니다. 그 밖의 모든 인코딩은 절대로 허용해서는 안 됩니다.
개발자는 실수로 비공개 키의 표현을 게시하지 않도록 주의해야 합니다.
이 명세의 구현은 publicKeyMultibase 값에서
0xeb01 이외의 Multicodec 값이 사용되는 경우 오류를
발생시킵니다.
{
"id": "https://example.com/issuer/123#key-0",
"type": "Multikey",
"controller": "https://example.com/issuer/123",
"publicKeyMultibase": "zUC7EK3ZakmukHhuncwkbySmomv3FmrkmS36E4Ks5rsb6VQSRpoCrx6
Hb8e2Nk6UvJFSdyw9NK1scFXJp21gNNYFjVWNgaqyGnkyhtagagCpQb5B7tagJu3HDbjQ8h
5ypoHjwBb"
}
{
"@context": [
"https://www.w3.org/ns/did/v1",
"https://w3id.org/security/multikey/v1"
],
"id": "https://example.com/issuer/123",
"verificationMethod": [{
"id": "https://example.com/issuer/123#key-1",
"type": "Multikey",
"controller": "https://example.com/issuer/123",
"publicKeyMultibase": "zUC7EK3ZakmukHhuncwkbySmomv3FmrkmS36E4Ks5rsb6VQSRpoCr
x6Hb8e2Nk6UvJFSdyw9NK1scFXJp21gNNYFjVWNgaqyGnkyhtagagCpQb5B7tagJu3HDbjQ8h
5ypoHjwBb"
}]
}
증명에는 [VC-DATA-INTEGRITY]의 증명 절에 명시된 속성이 다음 제한 사항과 함께 포함됩니다.
증명의 verificationMethod 속성은 반드시 URL이어야 합니다.
verificationMethod를 역참조한 결과는
값이 Multikey로 설정된 type 속성을 포함하는 객체여야
합니다.
증명의 type 속성은 반드시
DataIntegrityProof여야 합니다.
증명의 cryptosuite 속성은 반드시
bbs-2023이어야 합니다.
증명의 proofValue 속성 값은 [CFRG-BBS-SIGNATURE]에 따라 생성된
BBS 서명 또는 BBS 증명이어야 하며, 3.
알고리즘 절의 절차에 따라 직렬화 및
인코딩되어야 합니다.
다음 알고리즘에서는 BBS 서명 스킴 [CFRG-BBS-SIGNATURE]과 함께 검증 가능한 자격 증명을 사용하는 방법을 설명합니다. BBS 서명 스킴을 사용할 때는 SHA-256 변형을 사용하는 것이 좋습니다(SHOULD).
구현은 증명을 추가하거나 검증할 때 가능한 한 일찍 검증 방법 정보를 가져와 캐시하는 것이 좋습니다(SHOULD). 이 절의 함수에 전달되는 매개변수는 검증 방법의 정보(예: 공개 키 크기)를 사용하여 함수 매개변수(예: 암호화 해싱 알고리즘)를 결정합니다.
RDF 데이터셋 정규화 알고리즘 [RDF-CANON]을 사용하는 경우, 해당 알고리즘의 구현은 기본적으로 데이터셋 오염을 감지하고, 감지 시 처리를 중단합니다.
이 알고리즘은 검증 가능한 자격 증명 데이터 무결성 1.1의 증명 추가 및 증명 검증 함수에서 사용할 암호화 스위트를 구성하는 데 사용됩니다. 이 알고리즘은 옵션 객체 (맵 options) 를 입력으로 받아 암호 스위트 인스턴스 (구조체 cryptosuite)를 반환합니다.
DataIntegrityProof와 같지 않으면,
cryptosuite를 반환합니다.
bbs-2023이면 다음을 수행합니다.
다음 알고리즘은 BBS 서명, HMAC 키 및 필수 포인터를 포함하여 기본 증명 값을 직렬화합니다. 필수 입력은 기본 서명 bbsSignature, bbsHeader, publicKey, HMAC 키 hmacKey, mandatoryPointers 배열, featureOption 및 featureOption 값에 따라 필요할 수 있는 signer_nym_entropy 값입니다. 하나의 기본 증명 문자열 값이 출력으로 생성됩니다.
"baseline"과 같으면:
0xd9, 0x5d,
0x02로 시작하는 바이트 배열 proofValue를 초기화합니다.
"anonymous_holder_binding"과 같으면:
0xd9, 0x5d,
0x04로 시작하는 바이트 배열 proofValue를 초기화합니다.
"pseudonym"과 같으면:
0xd9, 0x5d,
0x06으로 시작하는 바이트 배열 proofValue를 초기화합니다.
"holder_binding_pseudonym"과 같으면:
0xd9, 0x5d,
0x08로 시작하는 바이트 배열 proofValue를 초기화합니다.
proofValue의 multibase-base64url-no-pad 인코딩
문자열로 초기화합니다. 즉, "u"로 시작하고
proofValue의 base64url-no-pad 인코딩 값으로 끝나는 문자열을 반환합니다.
다음 알고리즘은 bbs-2023 선택적
공개 기본 증명 값의 구성 요소를 구문 분석합니다. 필수 입력은 증명 값
(proofValue)입니다. "bbsSignature", "bbsHeader",
"publicKey",
"hmacKey", "mandatoryPointers", "featureOption" 및 선택적 기능
매개변수 "signer_nym_entropy"라는 이름을 사용하는 6개 또는 7개 요소가 포함된
하나의 객체 구문 분석된 기본 증명이 출력으로 생성됩니다.
proofValue 문자열이
u
(U+0075
라틴 소문자 U)로 시작하지 않아
multibase-base64url-no-pad-encoded 값이 아님을 나타내는 경우,
오류를 발생시켜야 하며(MUST) 오류 유형
PROOF_VERIFICATION_ERROR를
전달하는 것이 좋습니다(SHOULD).
proofValue의 선행 u 뒤에 오는
부분 문자열을 base64url-no-pad 디코딩한 결과로 초기화합니다.
0xd9,
0x5d 및 0x02로 시작하면
featureOption을 "baseline"으로 설정합니다.
0xd9,
0x5d 및 0x04로 시작하면
featureOption을 "anonymous_holder_binding"으로 설정합니다.
0xd9,
0x5d 및 0x06으로 시작하면
featureOption을 "pseudonym"으로 설정합니다.
0xd9,
0x5d 및 0x08로 시작하면
featureOption을 "holder_binding_pseudonym"으로 설정합니다.
components를 3바이트 BBS 기본 증명 헤더 뒤의
바이트를 CBOR 디코딩한 결과인 배열로 초기화합니다.
"baseline"과 같으면,
components를 기반으로 객체의 속성 이름을
"bbsSignature", "bbsHeader", "publicKey", "hmacKey",
"mandatoryPointers" 순서로 설정하고 featureOption을 속성으로 추가합니다.
"anonymous_holder_binding"과 같으면,
components를 기반으로 객체의 속성 이름을 "bbsSignature", "bbsHeader",
"publicKey", "hmacKey", "mandatoryPointers" 순서로 설정하고
featureOption을 속성으로 추가합니다.
"pseudonym"과 같으면,
components를 기반으로 객체의 속성 이름을 "bbsSignature", "bbsHeader",
"publicKey", "hmacKey", "mandatoryPointers", "signer_nym_entropy" 순서로
설정하고 featureOption을 속성으로 추가합니다.
"holder_binding_pseudonym"과 같으면,
components를 기반으로 객체의 속성 이름을 "bbsSignature", "bbsHeader",
"publicKey", "hmacKey", "mandatoryPointers", "signer_nym_entropy" 순서로
설정하고 featureOption을 속성으로 추가합니다.
다음 알고리즘은 파생 증명 값을 직렬화합니다. 필수 입력은 BBS 증명(bbsProof), 레이블 맵(labelMap), 필수 인덱스 배열(mandatoryIndexes), 선택적 인덱스 배열(selectiveIndexes), BBS 프레젠테이션 헤더 (presentationHeader), featureOption 표시자 및 featureOption 값에 따라 nym_domain, pseudonym, 및/또는 lengthBBSMessages 값입니다. 바이트 문자열로 직렬화된 하나의 파생 증명 값이 출력으로 생성됩니다.
compressedLabelMap을
labelMap을 매개변수로 전달하여
절의 알고리즘을 호출한 결과로 초기화합니다.
"baseline"과 같으면:
0xd9, 0x5d 및
0x03으로 시작하도록 초기화합니다.
"anonymous_holder_binding"과 같으면:
0xd9, 0x5d 및
0x05로 시작하도록 초기화합니다.
"pseudonym"과 같으면:
0xd9, 0x5d 및
0x07로 시작하도록 초기화합니다.
"holder_binding_pseudonym"과 같으면:
0xd9, 0x5d 및
0x09로 시작하도록 초기화합니다.
u"로 시작하고
proofValue의 base64url-no-pad 인코딩 값으로 끝나는 문자열을 반환합니다.
다음 알고리즘은 파생 증명 값의 구성 요소를 구문 분석합니다. 필수 입력은 파생 증명 값(proofValue)입니다. "bbsProof", "labelMap", "mandatoryIndexes", "selectiveIndexes", "presentationHeader", "featureOption" 및 featureOption 매개변수 값에 따라 "nym_domain", "pseudonym" 및/또는 "lengthBBSMessages"라는 이름을 갖는 6개에서 9개의 요소 집합이 포함된 하나의 파생 증명 값 객체가 출력으로 생성됩니다.
proofValue 문자열이
u
(U+0075,
라틴 소문자 U)로 시작하지 않아
multibase-base64url-no-pad-encoded 값이 아님을 나타내는 경우,
오류를 발생시켜야 하며(MUST) 오류 유형
PROOF_VERIFICATION_ERROR를
전달하는 것이 좋습니다(SHOULD).
proofValue의 선행 u 뒤에 오는
부분 문자열을 base64url-no-pad 디코딩한 결과로 초기화합니다.
0xd9,
0x5d 및
0x03으로 시작하면 featureOption을 "baseline"으로 설정합니다.
0xd9,
0x5d 및
0x05로 시작하면 featureOption을
"anonymous_holder_binding"으로 설정합니다.
0xd9,
0x5d 및
0x07로 시작하면 featureOption을 "pseudonym"으로 설정합니다.
0xd9,
0x5d 및
0x09로 시작하면 featureOption을
"holder_binding_pseudonym"으로 설정합니다.
components를 3바이트 BBS 공개 증명 헤더 뒤의
바이트를 CBOR 디코딩한 결과인 배열로 초기화합니다. 결과가
5개, 6개, 7개 또는 8개 요소의 배열이 아니면
오류를 발생시켜야 하며(MUST) 오류 유형
PROOF_VERIFICATION_ERROR를
전달하는 것이 좋습니다(SHOULD).
components의 두 번째 요소를 compressedLabelMap으로 전달하여
절의
알고리즘을 호출한 결과를 사용해 components의 두 번째 요소를
대체합니다.
bbs-2023 암호화 스위트는 입력 문서를 받아 RDF 데이터셋 정규화 알고리즘
[RDF-CANON]을 사용하여 문서를 정규화한 다음,
여러 변환 및 암호화
연산을 적용하여 데이터 무결성 증명을 생성합니다. 이 절의 알고리즘에는
이러한 데이터 무결성 증명의 검증도 포함됩니다.
다음 알고리즘은 보안 처리되지 않은 데이터 문서가 주어졌을 때 데이터 무결성 증명을 생성하는 방법을 지정합니다. 필수 입력은 보안 처리되지 않은 데이터 문서 (맵 unsecuredDocument), 증명 옵션 집합(맵 options), 필수 JSON 포인터 배열 (mandatoryPointers), featureOption 표시자 매개변수 및 featureOption에 따라 commitment_with_proof 바이트 배열입니다. 데이터 무결성 증명 (맵) 또는 오류가 출력으로 생성됩니다.
featureOption 매개변수는 선택적 기능이 사용되는 경우
어떤 기능인지 나타내는 데 사용됩니다. 다음 값 중 하나를 사용할 수 있습니다. "baseline",
"anonymous_holder_binding", "pseudonym" 또는
"holder_binding_pseudonym". "baseline"은
선택적 기능이 없는 경우를 나타내는 데 사용된다는 점에 유의하십시오.
featureOption이
"anonymous_holder_binding", "pseudonym" 또는
"holder_binding_pseudonym"으로 설정되면
commitment_with_proof 입력을 제공해야 합니다(MUST).
featureOption이
"pseudonym" 또는 "holder_binding_pseudonym"으로 설정되면
signer_nym_entropy 입력을 제공해야 합니다(MUST).
다음 알고리즘은 BBS로 보호된 검증 가능한
자격 증명의 발급자가 호출하며, 기본 증명을 생성하는 방법을 지정합니다. 기본 증명은
보유자에게만 제공되어야 하며, 보유자는 이 증명에서 파생 증명을 생성하고
선택적으로 공개된 세부 정보만 증명에서 검증자에게 노출할 책임이 있습니다. 이
알고리즘은 데이터 무결성 [VC-DATA-INTEGRITY-1.1]
사양의
4절: 알고리즘에 정의된 알고리즘과 함께 사용하도록 설계되었습니다. 필수 입력은
암호화 해시 데이터(hashData),
featureOption 및 필요한 경우
commitment_with_proof입니다.
featureOption이 "anonymous_holder_binding",
"pseudonym" 또는 "holder_binding_pseudonym"으로 설정되면
commitment_with_proof 입력을 제공해야 하며(MUST), 제공되지 않으면
오류를 발생시켜야 하고(MUST) 오류
유형
PROOF_GENERATION_ERROR를
전달하는 것이 좋습니다(SHOULD).
featureOption이
"pseudonym" 또는 "holder_binding_pseudonym"으로 설정되면
signer_nym_entropy 입력을 제공해야 하며(MUST), 제공되지 않으면
오류를 발생시켜야 하고(MUST) 오류
유형
PROOF_GENERATION_ERROR를
전달하는 것이 좋습니다(SHOULD).
일련의 바이트로 표현되는 하나의 디지털 증명 값이
출력으로 생성됩니다.
proofHash, mandatoryPointers, mandatoryHash,
nonMandatory 및
hmacKey를 hashData에서 각 속성 이름과 연결된 값으로
초기화합니다.
bbsHeader를 proofHash와
mandatoryHash를 해당 순서로
연결한 값으로 초기화합니다.
bbsMessages를 UTF-8 문자 인코딩을 사용하여 인코딩된
nonMandatory 문자열 배열의 값을 포함하는 바이트 배열의 배열로 초기화합니다.
bbsSignature를 계산합니다.
"baseline"과 같으면
[CFRG-BBS-Signature]의 Sign 절차를 사용하여
적절한 키 자료, header로 bbsHeader,
messages로 bbsMessages를 사용해
bbsSignature를 계산합니다.
"anonymous_holder_binding"과 같으면,
[CFRG-Blind-BBS-Signature]의 BlindSign
절차를 사용하여
적절한 키 자료, commitment_with_proof로 commitment_with_proof,
header로 bbsHeader,
messages로 bbsMessages를 사용해
bbsSignature를 계산합니다. 이는
익명 보유자 바인딩 기능을 제공합니다.
"pseudonym" 또는
"holder_binding_pseudonym"과 같으면,
발급자는 signer_nym_entropy에 사용할
암호학적으로 무작위인 값을 생성하고
[CFRG-Pseudonym-BBS-Signature]의
"블라인드 발급" 연산을 사용하여
적절한 키 자료,
header로 bbsHeader,
messages로 bbsMessages,
commitment_with_proof로 commitment_with_proof 및
signer_nym_entropy 값을 사용해
bbsSignature를 계산합니다.
발급자가 나중에 동일한 nym_secret에 바인딩된 자격 증명을
이 보유자에게 재발급해야 할 가능성이 있다면
signer_nym_entropy 값을 보관하는 것이 좋습니다. 그렇지 않으면 이 값은 폐기할 수 있습니다.
publicKey는
[CFRG-BBS-SIGNATURE]에 따라 인코딩된 공개 키의 바이트 배열입니다.
proofValue를 디지털 증명으로 반환합니다.
다음 알고리즘은 bbs-2023로 보호된
검증
가능한
자격 증명의 보유자가 호출하며, 선택적 공개 파생 증명을 생성합니다.
파생 증명은 검증자에게 제공됩니다. 입력에는
JSON-LD 문서(document), BBS 기본 증명
(proof), 문장을 선택적으로 공개하는 데 사용할 JSON 포인터 배열
(selectivePointers), 선택 사항인(OPTIONAL) BBS
presentationHeader(바이트 배열), featureOption 매개변수, 선택된
featureOption을 지원하는 추가 매개변수(아래 참조),
및 문서 로더와 같은 사용자 지정 JSON-LD API 옵션이 포함됩니다.
객체로 표현되는 하나의 선택적으로 공개된 문서
값이 출력으로 생성됩니다.
featureOption이 "anonymous_holder_binding"과 같으면
필수(REQUIRED) 추가 입력은 holderSecret 및
proverBlind입니다. 이 값들은
보유자가 미리 계산했어야 합니다. 배경 정보는
익명 보유자 바인딩을
참조하십시오.
featureOption이 "pseudonym"과 같으면 필수(REQUIRED)
추가 입력은 보유자가 모두 알고 있는 prover_nym 및 proverBlind과,
보유자가 설정하거나 검증자가
보유자에게 전달하는 nym_dofmain입니다.
배경 정보는 자격 증명 바인딩 가명을
참조하십시오.
featureOption이 "holder_binding_pseudonym"과 같으면 필수(REQUIRED)
추가 입력은 holder_secret, prover_nym 및 proverBlind이며,
모두 보유자가 알고 있고, nym_dofmain은 보유자가 설정하거나
검증자가 보유자에게 전달합니다.
배경 정보는 보유자 바인딩 및 가명을
참조하십시오.
다음 알고리즘은 파생 증명을 생성합니다. 입력은 proofData 및 disclosureData 객체입니다.
"baseline"과 같으면
[CFRG-BBS-SIGNATURE]의
ProofGen 절차가 계산한 값으로 bbsProof를 설정합니다. 즉,
ProofGen(PK, signature, header, ph, messages, disclosed_indexes)이며,
여기서 PK는 원래 발급자의 공개 키이고, signature는
bbsSignature, header는 bbsHeader,
ph는 presentationHeader,
messages는 bbsMessages, disclosed_indexes는
selectiveIndexes입니다.
"anonymous_holder_binding"과 같으면,
[CFRG-Blind-BBS-Signature]의
BlindProofGen 절차가 계산한 값으로
bbsProof를 설정합니다. 여기서
PK는 원래 발급자의 공개 키이고,
signature는
bbsSignature, header는 bbsHeader, ph는
presentationHeader,
messages는 bbsMessages, disclosed_indexes는
selectiveIndexes이며
commitment_with_proof도 사용합니다. 보유자는 또한 자신의
holder_secret과 commitment_with_proof를 계산하는 데 사용된
proverBlind를 제공합니다. 이것은
익명 보유자 바인딩 기능 옵션입니다.
IETF API가 확정되면
업데이트할 예정입니다.
"pseudonym"과 같으면,
[CFRG-Pseudonym-BBS-Signature]의
"검증 및 마무리" 연산을
빈 committed_messages 배열과 함께 사용하여
bbsSignature를 검증하고
nym_secret 값을 계산합니다. 이 연산은 prover_nym,
signer_nym_entropy 및 secret_prover_blind를 사용합니다.
"holder_binding_pseudonym"과 같으면,
[CFRG-Pseudonym-BBS-Signature]의
"검증 및 마무리" 연산을
holder_secret을 유일한 값으로 포함하는
committed_messages 배열과 함께 사용하여
bbsSignature를 검증하고
nym_secret 값을 계산합니다. 이 연산은 prover_nym,
signer_nym_entropy 및 secret_prover_blind를 사용합니다.
"anonymous_holder_binding",
"pseudonym" 또는 "holder_binding_pseudonym"과 같으면
lengthBBSMessages
매개변수를 bbsMessages 배열의 길이로 설정합니다.
다음 알고리즘은 보안 처리된 데이터 문서가 주어졌을 때 데이터 무결성 증명을 검증하는 방법을 지정합니다. 필수 입력은 보안 처리된 데이터 문서 (맵 securedDocument)입니다. 이 알고리즘은 검증 결과를 반환하며, 이는 다음 항목을 갖는 구조체입니다.
true 또는 falsefalse이면 Null, 그렇지 않으면
보안 처리되지 않은
데이터 문서
파생 증명을 검증하려면 다음 단계를 수행합니다.
proof
값이 제거된 document의 복사본으로 둡니다.
"baseline"과 같으면
[CFRG-BBS-SIGNATURE]의
검증 알고리즘 ProofVerify(PK, proof, header, ph,
disclosed_messages, disclosed_indexes)을 적용한 결과로
verified를 초기화합니다. 이때
PK는 원래 발급자의 공개 키,
proof는
bbsProof, header는
bbsHeader, disclosed_messages는
disclosedMessages, ph는
presentationHeader, disclosed_indexes는
selectiveIndexes로 설정합니다.
"anonymous_holder_binding"과 같으면
[CFRG-Blind-BBS-Signature]의
ProofVerify 검증 알고리즘을
"L" 매개변수에 lengthBBSMessages를 사용하여
적용한 결과로 verified를 초기화합니다.
IETF API가 확정되면 업데이트할 예정입니다.
"pseudonym" 또는
"holder_binding_pseudonym"과 같으면
[CFRG-Pseudonym-BBS-Signature]의
"가명을 사용한 증명 검증" 연산을
"L" 매개변수에 lengthBBSMessages를 사용하고
빈 committed_messages 배열과 함께
적용한 결과로 verified를
초기화합니다.
IETF
API가 확정되면 업데이트할 예정입니다.
true이면 unsecuredDocument, 그렇지 않으면
Null
이 절은 비규범적입니다.
BBS 서명의 암호학적 속성은 고급 기능을 지원할 수 있는 변형을 허용합니다. 이 명세는 이러한 확장 기능 중 가장 관련성이 높은 기능만 지원하며, 다음 절에서 이를 설명합니다. 변수 commitment_with_proof, holder_secret, prover_nym, signer_nym_entropy 및 pseudonym은 이러한 기능과 관련되어 있으며, 그 외에는 BBS 서명 및 증명에 필요하지 않습니다.
이 절에서 설명되고 이 명세의 알고리즘에 포함된 선택적 BBS 기능은 위험 상태이며, 해당 IETF 명세가 동일한 일정 내에 RFC 상태에 도달하지 못하거나 각 선택적 기능에 대해 최소 두 개의 독립적인 구현이 존재하지 않는 경우 이 명세가 최종 확정되기 전에 제거됩니다.
이 기능은 발급 시점에 기본 증명이 있는 문서를 보유자만 알고 있는 비밀 값에 바인딩하여, 해당 보유자만 검증 가능한 파생 증명이 있는 공개 문서를 생성할 수 있도록 합니다. 예를 들어 공격자가 기본 증명이 있는 문서를 획득하더라도 검증 가능한 파생 증명이 있는 공개 문서를 생성할 수 없습니다.
이 기능을 제공하기 위해 보유자는 일반적으로 최소 32바이트 길이이며 암호학적으로 무작위로 생성되어야 하는 holder_secret 값을 생성합니다. 이 값은 보유자가 절대로 공유하지 않습니다. 대신 보유자는 [CFRG-Blind-BBS-Signature]의 "Commitment Computation" 연산을 사용하여 이 값에 대한 영지식 지식 증명과 함께 커밋먼트를 생성합니다. 이 계산에는 암호학적 난수 값이 사용되며 commitment_with_proof 및 secret_prover_blind 값을 계산합니다. commitment_with_proof는 발급자에게 전달되지만, secret_prover_blind는 비밀로 유지되며 파생 증명을 생성할 때 사용하기 위해 보유자가 보관합니다. 보유자는 "Commitment Computation" 연산을 여러 번 실행하여 서로 다른 발급자와 함께 사용할 연결 불가능한 commitment_with_proof 값을 생성할 수 있습니다.
발급자는 commitment_with_proof를 받으면 이 명세의 절차를 따르고 [CFRG-Blind-BBS-Signature]의 "Blind Signature Generation" 연산을 사용하여, 보유자가 제공한 commitment_with_proof와 함께 문서에 대한 기본 증명(서명)을 생성합니다.
보유자가 파생 증명이 포함된 선택적으로 공개된 문서를 생성하려는 경우 이 명세의 절차와 [CFRG-Blind-BBS-Signature]의 "Proof Generation" 연산을 사용합니다. 보유자는 holder_secret을 commited messages 배열의 유일한 "메시지"로 사용하고 secret_prover_blind를 제공합니다.
파생 증명이 있는 공개 문서의 검증에는 이 명세의 절차와 [CFRG-Blind-BBS-Signature]의 "Proof Verification" 연산을 사용합니다.
이 문서에 명시된 BBS 서명 검증 가능한 자격 증명은 선택적 공개와 연결 불가능한 암호학적 증명 산출물을 허용합니다. 여기서 "연결 불가능"이란 파생 증명의 암호학적 정보를 다른 증명이나 원본 서명에 연결할 수 없음을 의미합니다. 이는 검증자가 보유자가 이전에 동일한 자격 증명을 제시했는지(다른 증명 인스턴스를 사용했더라도) 판단할 수 없으며, 특정 유형의 신원을 단정할 수도 없음을 의미합니다. 자격 증명 바인딩 가명은 암호학적 가명의 제한된 연결 가능성을 허용하는 개인정보 보호 메커니즘을 제공합니다. 이러한 가명은 보유자가 단독으로 결정하거나 보유자와 검증자가 공동으로 결정할 수 있습니다.
이러한 유형의 암호학적 가명(암호학적 식별자/이름)은 두 부분으로 계산됩니다. 첫 번째 부분인 nym_secret은 보유자가 지정하며 보유자만 알게 됩니다. 두 번째 부분인 nym_domain은 보유자 또는 검증자가 지정할 수 있으며 보유자와 검증자 간에 공유됩니다. 발급자는 발급 과정에서 자격 증명을 nym_secret에 바인딩합니다. 그런 다음 보유자는 nym_secret으로부터 가명을 계산하고 해당 가명이 자신이 제시하는 자격 증명에 바인딩되어 있음을 검증자에게 증명할 수 있습니다. 동일한 nym_secret에서 계산되었지만 서로 다른 nym_domain 값을 사용하는 암호학적 가명은 서로 연결할 수 없습니다.
보유자는 특정 유형의 공개 포럼에서 자신에게 가명을 부여하기 위해
nym_domain을 선택할 수 있습니다. 예를 들어
nym_domain = "Mark Twain"을 선택할 수 있습니다.
보유자가 이 nym_domain과 자신의 nym_secret으로 계산한
암호학적 가명은 사실상 고유하며, nym_secret을 알고
해당 가명에 바인딩된 기본 검증 가능한 자격 증명을 보유한 엔터티가 아니라면
이 가명 신원을 주장할 수 없습니다.
이 가명 신원을 주장하려면
(nym_domain, pseudonym) 쌍을 파생 자격 증명과 함께 전송해야 한다는 점에 유의하십시오.
다른 상황에서는 보유자가 검증자의 서비스를 이용하고 있으며
검증자가 시간에 따른 방문을 추적하거나 보유자의 특정 리소스 사용을
모니터링하려 할 수 있습니다. 이 경우 검증자가
보유자가 파생 자격 증명을 제시할 때 사용해야 하는 nym_domain을 선택합니다.
예를 들어 검증자는 보유자가 사용할 수 있도록
자신의 DNS 도메인에 연결된 공개 nym_domain(예:
"www.nym.example")을 지정할 수 있습니다. 검증자는
nym_domain을 주기적으로 변경함으로써
일정 수준의 데이터 최소화를 지원한다는 것을 보여줄 수도 있습니다
(예: 날짜에 연결하여
"www.nym.example/2025-01-02"로 설정).
이 명세는 nym_domain의 값을 규정하지 않습니다.
마지막으로, 다른 보유자의 nym_secret을 획득한 악의적인 보유자가 해당 값에 바인딩된 자격 증명을 얻는 것을 방지하기 위해 [CFRG-Pseudonym-BBS-Signature]의 연산은 발급자가 난수화 요소 signer_nym_entropy를 추가하도록 합니다. 이 값은 서명 생성 중에 보유자 측 값인 prover_nym과 안전하게 "혼합"됩니다. 그 결과 발급자가 보유자가 사용할 값이 고유하다는 암호학적 보증을 제공할 수 있는 nym_secret이 생성됩니다.
자격 증명 바인딩 가명의 생성 및 사용 개요는 다음 단계와 같습니다.
Commitment" 연산을 빈 committed_messages 배열과 함께 사용하여
commitment_with_proof 및 secret_prover_blind를 계산합니다.
보유자는 자격 증명 요청과 함께
commitment_with_proof를 발급자에게 보내지만,
prover_nym과 secret_prover_blind는 절대로 공개하지 않고 나중에 사용하기 위해 보관합니다.
"pseudonym"과 같음)과
commitment_with_proof를 함께 받습니다.
발급자는 signer_nym_entropy에 사용할 암호학적 난수 값을 생성하고
[CFRG-Pseudonym-BBS-Signature]의 "Blind Issuance" 연산을 사용하여
기본 증명을 생성합니다. 다른 정보와 함께
기본 증명에는 signer_nym_entropy 값이 포함됩니다. 발급자가
동일한 nym_secret에 바인딩된 자격 증명을
이 보유자에게 다시 발급해야 할 가능성이 있다면 signer_nym_entropy 값을 보관해야 하며,
그렇지 않으면 이 값을 폐기할 수 있습니다.
익명 보유자 바인딩과 자격 증명 바인딩 가명은 어떤 의미에서는
서로 직교하는 기능이며, 보유자 및 자격 증명 생태계에서는 두 기능을
동시에 사용하려 할 수 있습니다. 예를 들어 보유자는 검증 가능한
자격 증명을 holder_secret에 바인딩하여 이 값을 아는 보유자만
기본 증명에서 파생 증명을 생성할 수 있도록 하고,
nym_secret을 기본 증명에 바인딩하여 가명을 파생 증명에
바인딩할 수 있도록 할 수 있습니다. 이는
featureOption이 "holder_binding_pseudonym"과 같은 경우에 해당합니다.
익명 보유자 바인딩과 자격 증명 바인딩 가명을 모두 생성하고 사용하는 방법의 개요는 다음 단계와 같습니다.
"pseudonym"과 같고
commitment_with_proof도 함께 받습니다.
발급자는 이 명세의 절차를 사용하고
signer_nym_entropy에 사용할 암호학적 난수 값을 생성한 다음
[CFRG-Pseudonym-BBS-Signature]의
"Blind Issuance" 연산을 사용하여 기본 증명을 생성합니다.
다른 정보와 함께 기본 증명에는
signer_nym_entropy 값이 포함됩니다. 발급자가 동일한
nym_secret에 바인딩된 자격 증명을 이 보유자에게 다시 발급해야 한다면
signer_nym_entropy 값을 보관해야 하며, 그렇지 않으면 이 값을 폐기할 수 있습니다.
이 절은 비규범적입니다.
이 절에서는 "baseline" BBS 증명과 선택적 기능에 대한 입력, 출력, 증명 직렬화, 작업 및 절차를 요약합니다. baseline BBS란 추가 기능이 없는 BBS 기본 증명 및 파생 증명을 의미합니다. 모든 선택적 기능은 "추가적"이며, "baseline" BBS 서명/증명의 입력, 작업 또는 출력에 추가로 일부 입력, 작업 또는 출력이 생성됩니다.
| 이름 | 작업 | 입력 | 서명 알고리즘 |
|---|---|---|---|
| 기준 BBS | baseline: VC에서 BBS 서명 생성 | baseline: 문서, 증명 옵션, 키 자료, 필수 포인터 | BBS |
| 익명 보유자 바인딩 | baseline | baseline + 보유자가 제공한 증명이 포함된 커밋먼트 | 블라인드 BBS |
| 자격 증명 바인딩 가명 | baseline + signer_nym_entropy 생성 | baseline + signer_nym_entropy, 보유자가 제공한 증명이 포함된 커밋먼트 | 가명 BBS |
| 보유자 바인딩 및 가명 | baseline + signer_nym_entropy 생성 | baseline + signer_nym_entropy, 보유자가 제공한 증명이 포함된 커밋먼트 | 가명 BBS |
| 이름 | 증명 헤더 바이트 | 직렬화된 출력 |
|---|---|---|
| 기준 BBS | 0xd9, 0x5d, 및 0x02 |
baseline: bbsSignature, bbsHeader, publicKey, hmacKey 및 mandatoryPointers |
| 익명 보유자 바인딩 | 0xd9, 0x5d, 및 0x04 |
baseline |
| 자격 증명 바인딩 가명 | 0xd9, 0x5d, 및 0x06 |
baseline + signer_nym_entropy |
| 보유자 바인딩 및 가명 | 0xd9, 0x5d, 및 0x08 |
baseline + signer_nym_entropy |
| 이름 | 작업 | 입력 | 증명 생성 알고리즘 |
|---|---|---|---|
| 기준 BBS | 기본 증명이 있는 VC에서 BBS 파생 증명 생성 | baseline: (기본 증명 직렬화에서) bbsSignature, bbsHeader, publicKey, hmacKey 및 mandatoryPointers; selectivePointers (보유자의 선택) | BBS |
| 익명 보유자 바인딩 | baseline | baseline + holder_secret, prover_blind (둘 다 보유자가 알고 있음) | 블라인드 BBS |
| 자격 증명 바인딩 가명 | baseline + nym_secret 계산, pseudonym 계산 | baseline + prover_nym, prover_blind (모두 보유자가 알고 있음), signer_nym_entropy (발급자의 기본 증명에 포함됨), nym_domain | 가명 BBS |
| 보유자 바인딩 및 가명 | baseline + nym_secret 계산, pseudonym 계산 | baseline + holder_secret, prover_nym, prover_blind (모두 보유자가 알고 있음), signer_nym_entropy (발급자의 기본 증명에 포함됨), nym_domain | 가명 BBS |
| 이름 | 증명 헤더 바이트 | 직렬화된 출력 |
|---|---|---|
| 기준 BBS | 0xd9, 0x5d, 및 0x03 |
baseline: bbsProof, compressedLabelMap, mandatoryIndexes, selectiveIndexes, presentationHeader |
| 익명 보유자 바인딩 | 0xd9, 0x5d, 및 0x05 |
baseline |
| 자격 증명 바인딩 가명 | 0xd9, 0x5d, 및 0x07 |
baseline + pseudonym, nym_domain |
| 보유자 바인딩 및 가명 | 0xd9, 0x5d, 및 0x09 |
baseline + pseudonym, nym_domain |
| 이름 | 입력 | 증명 검증 알고리즘 |
|---|---|---|
| BBS 기준 | baseline: (파생 증명 직렬화에서) bbsProof, compressedLabelMap, mandatoryIndexes, selectiveIndexes, presentationHeader | BBS |
| 익명 보유자 바인딩 | baseline | 블라인드 BBS |
| 자격 증명 바인딩 가명 | baseline + pseudonym (파생 증명에 포함됨), nym_domain | 가명 BBS |
| 보유자 바인딩 및 가명 | baseline + pseudonym (파생 증명에 포함됨), nym_domain | 가명 BBS |
이 절을 읽기 전에 독자는 데이터 무결성 명세의 보안 고려 사항 절에서 제공하는 일반적인 보안 지침을 숙지할 것을 권고합니다.
이 절은 비규범적입니다.
기본 증명의 보안은 관련 BBS 서명의 보안 속성에 따라 달라집니다. 디지털 서명은 여러 바람직한 암호학적 속성을 가질 수 있으며 [Taming_EdDSAs] 그중에는 다음이 있습니다:
EUF-CMA (선택 메시지 공격에 대한 존재적 위조 불가능성)는 일반적으로 서명 방식에 요구되는 최소한의 보안 속성입니다. 이는 서명자의 공개 키 를 가지고 있으며 자신이 선택한 메시지에 대한 임의 개수의 서명을 (적응적인 방식으로) 받은 효율적인 공격자가: , 새로운 메시지 에 대해 유효한 서명 을 출력할 수 없음을 보장합니다 (무시할 수 있을 정도로 작은 확률은 제외). 공격자가 새로운 메시지에 대한 유효한 서명을 출력하는 경우: , 이를 존재적 위조라고 합니다.
SUF-CMA (선택 메시지 공격에 대한 강한 위조 불가능성)는 EUF-CMA보다 더 강한 개념입니다. 이는 서명자의 공개 키 를 가지고 있으며 자신이 선택한 메시지에 대한 임의 개수의 서명을 받은 효율적인 공격자가: , 다음 조건을 만족하는 새로운 유효한 서명 쌍 , 을 출력할 수 없음을 보장합니다: (무시할 수 있을 정도로 작은 확률은 제외). 강한 위조 불가능성은 공격자가 새로운 메시지에 서명할 수 없을 뿐만 아니라 기존 메시지에 대해 새로운 서명을 찾을 수도 없음을 의미합니다.
[CDL2016]에서는 일부 합리적인 가정하에 BBS 서명이 EUF-CMA임이 증명되었습니다. 또한 [TZ2023]에서는 유사한 가정하에 BBS 서명이 SUF-CMA임이 증명되었습니다. 두 경우 모두 가정은 대규모 양자 컴퓨팅 이후에는 안전하다고 간주되지 않는 이산 로그 문제의 어려움과 관련되어 있습니다.
비양자 컴퓨팅 조건에서 [CFRG-BBS-SIGNATURE]은 BBS 서명 스위트 구현자에게 추가적인 보안 지침을 제공합니다. 페어링 친화적 곡선과 관련된 추가적인 보안 고려 사항은 [CFRG-PAIRING-FRIENDLY]에서 논의됩니다.
이 절은 비규범적입니다.
파생 증명의 보안은 관련 BBS 증명의 보안 속성에 따라 달라집니다.
[CDL2016] 및
[TZ2023] 모두
BBS 증명이 BBS 서명에 대한 지식의 영지식 증명
임을 증명합니다.
[CFRG-BBS-SIGNATURE]에서 설명한 바와 같이 이는 다음을 의미합니다:
증명을 받은 검증 당사자는 어떤 서명이 증명 생성에 사용되었는지 판단할 수 없으므로 일반적인 상관 관계의 원인이 제거됩니다. 일반적으로 동일한 서명에서 생성된 두 증명이라도 생성된 각 증명은 난수와 구별할 수 없습니다.
그리고
이 방식으로 생성된 증명은 증명을 생성한 당사자 (보유자/증명자 또는 그 대리인)가 서명을 공개하지 않고도 해당 서명을 보유하고 있었음을 검증자에게 증명합니다.
더 정확히 말하면 BBS 증명을 검증하려면 원래 발급자의 공개 키와 변경되지 않고 공개된 BBS 메시지가 올바른 순서로 필요합니다.
이 절은 비규범적입니다.
선택적 공개를 사용하면 보유자가 특정 목적을 달성하기 위해 검증자에게 공개하는 정보를 최소화할 수 있습니다. 선택적 공개를 지원하는 전체 시스템을 규정할 때는 검증자에게 공개하려 하지 않았던 추가 정보가 최소화되도록 주의해야 합니다. 이러한 유출은 시스템의 산출물을 통해 발생할 수 있습니다. 이러한 산출물은 데이터 구조와 같은 시스템의 상위 계층이나 하위 수준의 암호학적 기본 연산에서 발생할 수 있습니다.
예를 들어 BBS 서명 방식은 여러 메시지에 대한 서명을 생성하는 데 공간 효율성이 매우 높은 방식입니다. 즉, 보유자에게 전송되는 암호학적 서명의 크기는 메시지 수와 관계없이 일정합니다. 그런 다음 보유자는 이러한 메시지 중 원하는 것을 검증자에게 선택적으로 공개할 수 있습니다. 그러나 암호화 방식의 일부로서 발급자가 서명한 전체 메시지 수를 검증자에게 공개해야 합니다. 이러한 정보 유출을 피해야 한다면 [CFRG-BBS-SIGNATURE]의 개인정보 보호 고려 사항 절에서 제안하는 대로 메시지 수를 공통 길이에 맞게 패딩하는 것이 권장됩니다.
상위 수준에서는 데이터를 선택적 공개에 적합한 개별 문장, 즉 BBS 메시지로 매핑하는 방식이 데이터 유출의 잠재적인 원인이 됩니다. 이 암호화 스위트는 JSON-LD 처리를 사용하여 입력을 RDF로 변환함으로써 JSON 데이터를 표현하는 데 사용되며 정보를 유출할 수 있는 많은 구조적 산출물(중첩, 맵 또는 배열 위치 등)을 제거할 수 있습니다. 그런 다음 RDF는 단순한 주어, 속성, 값 문장으로 이루어진 정규화된 평면 형식으로 표현할 수 있습니다(검증 가능한 자격 증명 데이터 모델 [VC-DATA-MODEL-2.0]에서는 이를 클레임이라고 합니다). 다음에서는 선택적 공개를 위해 JSON-LD 형식의 검증 가능한 자격 증명을 문장(BBS 메시지) 집합으로 매핑하는 일반적인 방식인 RDF 정규화를 살펴봅니다. 이 과정이 수행된 후에도 정보 유출의 잠재적인 원인이 남아 있음을 보여주고, 키 기반 의사 난수 함수(PRF)를 사용하여 이러한 유출을 완화하는 방법을 보여줍니다.
RDF 정규화를 사용하여 JSON-LD VC를 문장 집합으로
평탄화
할 수 있습니다. 이 알고리즘은 VC의 내용에 따라 달라지며
문장의 순서를 지정하는 데 도움을 주기 위해
암호학적 해시 함수도 사용합니다. 본질적으로 JSON-LD 문서 내에서
클레임의 주체를 나타내는 각 JSON 객체는 @id 필드가
정의되어 있지 않은 경우 id가 할당됩니다. 이러한 id를
빈 노드 id라고 합니다. 이러한 id는 각 클레임의 주체를
구별할 수 있도록 클레임을 단순한 주어, 속성, 값 문장으로 표현하는 데 필요합니다.
id 값은 [RDF-CANON]에 따라 결정론적으로 설정되며
문서의 데이터와 SHA-256 같은 암호학적 해시 함수의 출력을 기반으로 합니다.
아래에서는 윈드서핑 돛 집합에 대한 약간 서로 다른 두 VC와 선택적 공개에 사용할 수 있는 문장 집합으로의 정규화를 보여줍니다. 6.1 크기 돛의 연도를 변경하면 두 VC 간 문장 순서가 크게 변경되는 것을 확인할 수 있습니다. 보유자가 더 큰 돛 (7.0 및 7.8)에 대한 정보만 공개하는 경우 검증자는 돛 집합에서 무언가 변경되었다는 사실을 알아낼 수 있으며, 이는 정보 유출에 해당합니다.
{
"@context": [
"https://www.w3.org/ns/credentials/v2",
{
"@vocab": "https://windsurf.grotto-networking.com/selective#"
}
],
"type": [
"VerifiableCredential"
],
"credentialSubject": {
"sails": [
{
"size": 5.5,
"sailName": "Kihei",
"year": 2023
},
{
"size": 6.1,
"sailName": "Lahaina",
"year": 2023 // 정규화에 미치는 영향을 확인하기 위해 이 값을 변경합니다
},
{
"size": 7.0,
"sailName": "Lahaina",
"year": 2020
},
{
"size": 7.8,
"sailName": "Lahaina",
"year": 2023
}
]
}
}
위 VC의 정규형입니다. 빈 노드 id의 할당, 즉
_:c14nX
레이블은 VC의 내용에 따라 달라지며
이는 문장의 순서에도 영향을 줍니다.
_:c14n0 <https://windsurf.grotto-networking.com/selective#sailName> "Lahaina" . _:c14n0 <https://windsurf.grotto-networking.com/selective#size> "7.8E0"^^<http://www.w3.org/2001/XMLSchema#double> . _:c14n0 <https://windsurf.grotto-networking.com/selective#year> "2023"^^<http://www.w3.org/2001/XMLSchema#integer> . _:c14n1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://www.w3.org/2018/credentials#VerifiableCredential> . _:c14n1 <https://www.w3.org/2018/credentials#credentialSubject> _:c14n4 . _:c14n2 <https://windsurf.grotto-networking.com/selective#sailName> "Lahaina" . _:c14n2 <https://windsurf.grotto-networking.com/selective#size> "7"^^<http://www.w3.org/2001/XMLSchema#integer> . _:c14n2 <https://windsurf.grotto-networking.com/selective#year> "2020"^^<http://www.w3.org/2001/XMLSchema#integer> . _:c14n3 <https://windsurf.grotto-networking.com/selective#sailName> "Kihei" . _:c14n3 <https://windsurf.grotto-networking.com/selective#size> "5.5E0"^^<http://www.w3.org/2001/XMLSchema#double> . _:c14n3 <https://windsurf.grotto-networking.com/selective#year> "2023"^^<http://www.w3.org/2001/XMLSchema#integer> . _:c14n4 <https://windsurf.grotto-networking.com/selective#sails> _:c14n0 . _:c14n4 <https://windsurf.grotto-networking.com/selective#sails> _:c14n2 . _:c14n4 <https://windsurf.grotto-networking.com/selective#sails> _:c14n3 . _:c14n4 <https://windsurf.grotto-networking.com/selective#sails> _:c14n5 . _:c14n5 <https://windsurf.grotto-networking.com/selective#sailName> "Lahaina" . _:c14n5 <https://windsurf.grotto-networking.com/selective#size> "6.1E0"^^<http://www.w3.org/2001/XMLSchema#double> . _:c14n5 <https://windsurf.grotto-networking.com/selective#year> "2023"^^<http://www.w3.org/2001/XMLSchema#integer> .
업데이트된 윈드서핑 돛 컬렉션으로, 6.1 크기 돛이 2024년 모델로 업데이트되었습니다. 이로 인해 빈 노드 id 할당을 통해 문장의 순서가 변경됩니다.
{
"@context": [
"https://www.w3.org/ns/credentials/v2",
{
"@vocab": "https://windsurf.grotto-networking.com/selective#"
}
],
"type": [
"VerifiableCredential"
],
"credentialSubject": {
"sails": [
{
"size": 5.5,
"sailName": "Kihei",
"year": 2023
},
{
"size": 6.1,
"sailName": "Lahaina",
"year": 2024 // 기존 모델을 업데이트하는 새 돛으로, 정규화가 변경됩니다
},
{
"size": 7.0,
"sailName": "Lahaina",
"year": 2020
},
{
"size": 7.8,
"sailName": "Lahaina",
"year": 2023
}
]
}
}
이전 VC의 정규형입니다. 빈 노드 id 할당과 문장 순서의 차이에 유의하십시오.
_:c14n0 <https://windsurf.grotto-networking.com/selective#sailName> "Lahaina" . _:c14n0 <https://windsurf.grotto-networking.com/selective#size> "6.1E0"^^<http://www.w3.org/2001/XMLSchema#double> . _:c14n0 <https://windsurf.grotto-networking.com/selective#year> "2024"^^<http://www.w3.org/2001/XMLSchema#integer> . _:c14n1 <https://windsurf.grotto-networking.com/selective#sailName> "Lahaina" . _:c14n1 <https://windsurf.grotto-networking.com/selective#size> "7.8E0"^^<http://www.w3.org/2001/XMLSchema#double> . _:c14n1 <https://windsurf.grotto-networking.com/selective#year> "2023"^^<http://www.w3.org/2001/XMLSchema#integer> . _:c14n2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://www.w3.org/2018/credentials#VerifiableCredential> . _:c14n2 <https://www.w3.org/2018/credentials#credentialSubject> _:c14n5 . _:c14n3 <https://windsurf.grotto-networking.com/selective#sailName> "Lahaina" . _:c14n3 <https://windsurf.grotto-networking.com/selective#size> "7"^^<http://www.w3.org/2001/XMLSchema#integer> . _:c14n3 <https://windsurf.grotto-networking.com/selective#year> "2020"^^<http://www.w3.org/2001/XMLSchema#integer> . _:c14n4 <https://windsurf.grotto-networking.com/selective#sailName> "Kihei" . _:c14n4 <https://windsurf.grotto-networking.com/selective#size> "5.5E0"^^<http://www.w3.org/2001/XMLSchema#double> . _:c14n4 <https://windsurf.grotto-networking.com/selective#year> "2023"^^<http://www.w3.org/2001/XMLSchema#integer> . _:c14n5 <https://windsurf.grotto-networking.com/selective#sails> _:c14n0 . _:c14n5 <https://windsurf.grotto-networking.com/selective#sails> _:c14n1 . _:c14n5 <https://windsurf.grotto-networking.com/selective#sails> _:c14n3 . _:c14n5 <https://windsurf.grotto-networking.com/selective#sails> _:c14n4 .
이러한 빈 노드 id의 할당과 이로 인해 문장에 부여되는
순서에서 발생하는 정보 유출을 방지하기 위해 HMAC 기반 PRF를
빈 노드 id에 실행합니다. HMAC 비밀 키는
발급자와 보유자 사이에서만 공유되며,
발급자가 생성하는 각 기본 증명은 새로운 HMAC 키를 사용합니다.
이에 대한 예는 [DI-ECDSA]의
정규 HMAC 테스트 벡터에서 확인할 수 있습니다.
다음 절에서 설명하듯이 BBS가 연결 불가능성을 유지하도록 하기 위해
HMAC 기반 빈 노드 id를 사용하지 않고, 테스트 벡터
예제 12에 표시된 것처럼 HMAC을 기반으로
순서의 셔플된
버전을 생성합니다.
이는 빈 노드 id의 수에 관한 정보가
유출될 수 있으므로 ECDSA-SD 방식보다 빈 노드 id에 관한
정보 은닉 수준이 낮지만, 빈 노드 id에 HMAC을 적용하여 생성된
사실상 고유한 식별자를 통한 연결 공격은 방지합니다.
VC의 일부 사용 사례에서는 여러 서로 다른 검증자와의 상호작용이 추적되거나 연결되는 것을 방지하는 것이 보유자의 개인정보 보호에 중요할 수 있습니다. 특히 두 가지 중요한 경우, (i) 검증자와 발급자의 공모 및 (ii) 검증자 간 공모를 고려합니다. 첫 번째 경우는 그림 1에 표시되어 있으며, 검증자가 보유자와의 상호작용에 관한 정보를 자격 증명의 원래 발급자에게 다시 보고합니다. 이 상황에서 발급자는 발급된 VC를 사용하여 다양한 검증자와 이루어진 모든 보유자 상호작용을 추적할 수 있습니다. 두 번째 상황은 그림 2에 표시되어 있으며, 여러 검증자가 공모하여 자신들과 상호작용한 보유자에 관한 정보를 공유합니다.
VC 시스템이 보유자의 개인정보에 대한 이러한 "연결 공격"을
방지하는 속성을 설명하기 위해 연결 불가능성이라는 용어를 사용합니다.
연결 불가능성이라는 용어는 비교적 새롭지만
[NISTIR8053]의 3.3절에서는
연결 공격을 통한 재식별
을 논의하고 사례 연구를 제공합니다.
데이터 개인정보에 대한 연결 공격
에 관한 지식의 체계화는
[Powar2023]에서 확인할 수 있습니다.
사용자 개인정보에 대한 연결 공격의 가장 널리 사용되는 형태는
웹 브라우저 핑거프린팅이며, 이에 관한 조사는
[Pugliese2020]에서 확인할 수 있습니다.
연결이라는 개념을 정량화하기 위해 [Powar2023]에서는 익명성 집합이라는 개념을 도입합니다. 여기서 다루는 VC의 경우 익명성 집합에는 특정 VC의 보유자와 특정 발급자와 관련된 다른 보유자가 포함됩니다. 익명성 집합이 작을수록 여러 검증자에 걸쳐 보유자를 추적할 가능성이 커집니다. 서명된 VC에는 발급자의 공개 키에 대한 참조가 포함되므로 특정 발급자의 VC를 보유한 보유자에 대한 익명성 집합의 초기 크기는 해당 발급자가 특정 공개/비공개 키 쌍으로 발급한 VC의 수입니다. 악의적이지 않은 발급자는 VC 발급에 사용하는 공개/비공개 키 쌍의 수를 최소화할 것으로 기대됩니다. 익명성 집합 개념은 [vc-bitstring-status-list]의 그룹 개인정보 보호 개념과 유사하다는 점에 유의하십시오. 여기서 연결이라는 용어를 사용할 때는 일반적으로 익명성 집합의 크기를 감소시키는 모든 메커니즘을 의미합니다.
선택적 공개를 지원하는 VC 시스템에서 연결의 원인은 다음과 같습니다:
아래에서 각각을 논의합니다.
암호학적 해시, HMAC 및 디지털 서명은 그 특성상 매우 고유한 식별자를 생성합니다. SHA-256 같은 해시 함수의 출력은 충돌 저항성 속성으로 인해 서로 다른 입력에 대해 사실상 고유함이 보장되며 강한 연결을 초래합니다. 즉, 익명성 집합의 크기를 1로 줄입니다. 마찬가지로 Ed25519 및 결정론적 ECDSA 같은 결정론적 서명 알고리즘은 서로 다른 입력에 대해 사실상 고유한 출력을 생성하고 강한 연결을 초래합니다.
이는 VC 내부의 디지털 서명, HMAC 또는 해시 산출물을 통해 보유자가 여러 검증자에 걸쳐 쉽게 추적될 수 있음을 의미하며, 따라서 검증자 간 공모 및 검증자와 발급자 간 공모에 취약합니다. 일부 형태의 ECDSA와 같은 무작위화된 서명 알고리즘을 사용하면 발급자가 동일한 입력에 대해 여러 개의 서로 다른 서명을 생성하고, 서로 다른 검증자와 함께 사용하도록 이를 보유자에게 전송할 수 있습니다. 이러한 방식은 검증자 간 공모에 기반한 추적을 방지하는 데 사용할 수 있지만 검증자와 발급자 간 공모에는 도움이 되지 않습니다.
연결 불가능성을 달성하려면 보유자가
서명에 대한 지식의 영지식 증명
(ZKPKS)을 생성할 수 있도록
특별히 설계된 암호학적 서명 방식이 필요합니다. 이는
보유자가 이러한 방식에서 발급자의 서명을 받아
검증자에게 전송할 ZKPKS를 계산할 수 있음을 의미합니다.
이 ZKPKS는 원본 서명으로 다시 연결할 수 없지만 서명의 모든
바람직한 속성을 갖습니다. 즉, 검증자는 이를 사용하여
메시지가 발급자의 공개 키로 서명되었고 메시지가
변경되지 않았음을 검증할 수 있습니다. 또한 보유자는
서로 다른 검증자를 위해 원하는 만큼 ZKPKS를 생성할 수 있으며
이들은 사실상 서로 독립적이고 연결할 수 없습니다.
BBS는 이러한 기능을 지원하는 서명 방식 중 하나입니다.
이 문서에서 BBS 증명이라고 하는 ZKPKS에는 보장된 연결 불가능성 속성이 있습니다. 그러나 BBS를 선택적 공개와 함께 사용할 때는 연결 가능성에 영향을 줄 수 있는 두 가지 산출물이 있습니다. 원래 서명된 전체 메시지 수와 공개된 문장의 인덱스 값입니다. 이에 대한 논의 및 완화 기법은 [CFRG-BBS-SIGNATURE]의 개인정보 보호 고려 사항을 참조하십시오.
[CFRG-BBS-SIGNATURE]의
발급자의 공개 키
절에서 언급했듯이,
발급자가 여러 공개 키를 사용하고 그중 일부를
검증자와 발급자 간 공모를 통해 특정 사용자 하위 집합을
추적하는 데 사용할 수 있는 잠재적 위협이 있습니다.
발급자의 공개 키는 검증자에게 보여야 하므로,
즉 BBS 증명(파생 증명)에서 참조되므로, 발급자가
많은 서로 다른 공개 키를 사용하고 특히 그 키 중 일부를
소수의 사용자(보유자)에게 사용하는 경우 연결 지점으로
사용될 수 있습니다.
정보 유출에 관한 절에서 보았듯이 RDF 정규화는 해시 함수를 사용하여
문장의 순서를 지정하며, HMAC을 기반으로 문장 순서를 추가로
셔플
합니다. 이로 인해 일부 연결을 가능하게 하는 핑거프린트가
남을 수 있습니다. 연결의 강도는 빈 노드의 수, 즉 VC 내 JSON 객체의 수와
공개되는 인덱스의 수에 따라 달라집니다. n개의 빈 노드와
k개의 공개된 인덱스가 있을 때 최악의 경우 익명성 집합의 크기는
C(n, k)배 감소할 수 있습니다. 즉,
n개 요소 집합에서 선택한 크기 k의 조합 수입니다.
VC의 빈 노드 수를 줄이는 방법, 예를 들어 VC를 짧고 간단하게
유지하는 방법으로 이 값을 상당히 낮게 유지할 수 있습니다.
JSON-LD는 연결 데이터를 직렬화하기 위한 JSON 기반 형식입니다. 따라서
문서 내 각 객체(JSON-LD 용어로 "노드")에 전역적으로 모호하지 않은
@id 속성(노드 식별자)을 할당하는 기능을 지원합니다.
이를 통해 연결 데이터의 연결
이 가능해지고,
동일한 엔터티에 관한 정보를 서로 연관시킬 수 있습니다.
이러한 상관 관계는 사용 사례에 따라 바람직할 수도, 바람직하지 않을 수도 있습니다.
BBS의 연결 불가능성 기능을 사용할 때는 전역적으로 모호하지 않은 노드
식별자를 개인이나 개인 식별 가능 정보에 사용할 수 없습니다.
이들이 제공하는 강한 연결은 바람직하지 않기 때문입니다.
이러한 식별자는 비개인 정보에 관한 문장을 표현할 때는 사용할 수 있다는 점에
유의하십시오(예: 큰 국가나 콘서트 이벤트를 식별하기 위해
전역적으로 모호하지 않은 식별자를 사용하는 경우).
또한 용어를 IRI에 매핑하는 JSON-LD의 @context 사용은
일반적으로 연결 불가능성에 영향을 주지 않는다는 점에 유의하십시오.
[VC-DATA-INTEGRITY-1.1]
사양에서는 VC의
proof 속성에 관한 여러 속성이 제시됩니다. 선택적 필드가
검증자 간에 강한 연결성을 제공하지 않도록 주의해야 합니다. 선택적 필드에는 다음이 포함됩니다.
id, created, expires, domain,
challenge 및 nonce. 예를 들어 선택적
created 필드는 증명의
생성 날짜를 임의의 1초 미만 정밀도까지 지정할 수 있는 dateTimeStamp 객체입니다. 이러한
정보가 존재하면 익명성 집합의 크기가 크게 줄어들 수 있습니다.
발급자가 이러한 정보를 포함하려는 경우 시간 경과에 따라 발급되는 VC 수에 비례하여 가능한 한
거친 단위로 만들어야 합니다.
발급자는 또한 기본 증명 생성에 사용되는
mandatoryPointers 입력을 통해 보유자가 특정 문장을
검증자에게 공개하도록 강제할 수도 있습니다. 다음 절을 참조하십시오.
예제 9 및
예제 10. 여기서
강제한다
는 것은
이러한 문장이 검증자에게 공개되지 않으면 생성된 파생 증명이 검증되지 않는다는
의미입니다. 이러한 정보를 공개해야 하는 경우에도 익명성 집합이 충분히 크게
유지되도록 주의해야 합니다.
[Powar2023]에서 논의한 것처럼 연결 공격을 통해 개인이 재식별된 많은 사례가 문서화되어 있습니다. 따라서 보유자는 익명성 집합을 크게 유지하는 데 도움이 되도록 가능한 한 적은 정보만 공개할 것을 권고합니다. 또한 겉보기에는 무해한 정보도 매우 고유할 수 있으며, 따라서 재식별이나 추적으로 이어질 수 있음이 여러 차례 입증되었습니다. 특히 유명한 전 매사추세츠 주지사 사례의 자세한 설명은 [NISTIR8053]을 참조하고, 이러한 공개 사례 94건에 대한 추가 분석 및 분류는 [Powar2023]을 참조하십시오.
연결 불가능성, 즉 익명성을 유지하려면 VC를 보관하고 통신하는 시스템에서도 주의가 필요하다는 점을 지적해야 합니다. IP 주소(계층 3)나 이더넷/MAC 주소(계층 2) 같은 네트워크 산출물은 잘 알려진 연결의 원인입니다. 예를 들어 휴대전화 MAC 주소는 사용자가 특정 액세스 포인트를 다시 방문하는 경우 사용자를 추적하는 데 사용될 수 있으며, 이로 인해 휴대전화 제조업체가 MAC 주소 무작위화 기능을 제공하게 되었습니다. 공인 IP 주소는 일반적으로 개인의 위치를 한 국가 내 도시나 지역 수준까지 파악할 수 있는 충분한 정보를 제공하므로 익명성 집합을 크게 줄일 수 있습니다.
이 절은 비규범적입니다.
문서 테스트 벡터는 완전히 가상의 영주권 카드를 기반으로 하며, 두 그룹, 즉 발급자가 생성하는 것("기본 증명")과 보유자가 생성하는 것("파생 증명")으로 나뉩니다.
문서에 선택적 공개 기본 증명을 추가하려면 발급자에게 다음 암호학적 키 자료가 필요합니다:
기본 증명 추가 테스트를 위한 테스트 벡터 생성에 사용된 키 자료는 아래와 같습니다. BBS 키 쌍과 HMAC 키에는 16진수 표현을 사용합니다.
{
"publicKeyHex": "a4ef1afa3da575496f122b9b78b8c24761531a8a093206ae7c45b80759c168ba4f7a260f9c3367b6c019b4677841104b10665edbe70ba3ebe7d9cfbffbf71eb016f70abfbb163317f372697dc63efd21fc55764f63926a8f02eaea325a2a888f",
"privateKeyHex": "66d36e118832af4c5e28b2dfe1b9577857e57b042a33e06bdea37b811ed09ee0",
"hmacKeyString": "00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF"
}
이 시나리오에서는 영주권 자격 증명을 발급합니다. 서명되지 않은 영주권 문서는 아래와 같습니다.
{
"@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 포인터 배열을 통해 지정됩니다.
["/issuer"]
위의 JSON 포인터를 문서에 적용한 결과는 아래와 같습니다.
[
{
"pointer": "/issuer",
"value": {
"id": "did:key:zDnaeTHxNEBZoKaEo6PdA83fq98ebiFvo3X273Ydu4YmV96rg",
"image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2P4z/DiPwAG0ALnwgz64QAAAABJRU5ErkJggg=="
}
}
]
서명되지 않은 문서의 변환은 아래와 같이 문서를 정규화하는 것부터 시작합니다.
[ "<did:key:zDnaeTHxNEBZoKaEo6PdA83fq98ebiFvo3X273Ydu4YmV96rg> <https://schema.org/image> <data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2P4z/DiPwAG0ALnwgz64QAAAABJRU5ErkJggg==> .\n", "_:c14n0 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/citizenship#PermanentResidentCard> .\n", "_:c14n0 <https://schema.org/identifier> \"83627465\" .\n", "_:c14n0 <https://w3id.org/citizenship#lprCategory> \"C09\" .\n", "_:c14n0 <https://w3id.org/citizenship#lprNumber> \"999-999-999\" .\n", "_:c14n1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://schema.org/Person> .\n", "_:c14n1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/citizenship#PermanentResident> .\n", "_:c14n1 <https://schema.org/birthDate> \"1978-07-17\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n", "_:c14n1 <https://schema.org/familyName> \"SMITH\" .\n", "_:c14n1 <https://schema.org/gender> \"Female\" .\n", "_:c14n1 <https://schema.org/givenName> \"JANE\" .\n", "_:c14n1 <https://schema.org/image> <data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2P4v43hPwAHIgK1v4tX6wAAAABJRU5ErkJggg==> .\n", "_:c14n1 <https://w3id.org/citizenship#birthCountry> \"Arcadia\" .\n", "_:c14n1 <https://w3id.org/citizenship#commuterClassification> \"C1\" .\n", "_:c14n1 <https://w3id.org/citizenship#permanentResidentCard> _:c14n0 .\n", "_:c14n1 <https://w3id.org/citizenship#residentSince> \"2015-01-01\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n", "_:c14n2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/citizenship#PermanentResidentCardCredential> .\n", "_:c14n2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://www.w3.org/2018/credentials#VerifiableCredential> .\n", "_:c14n2 <https://schema.org/description> \"Permanent Resident Card from Government of Utopia.\" .\n", "_:c14n2 <https://schema.org/name> \"Permanent Resident Card\" .\n", "_:c14n2 <https://www.w3.org/2018/credentials#credentialSubject> _:c14n1 .\n", "_:c14n2 <https://www.w3.org/2018/credentials#issuer> <did:key:zDnaeTHxNEBZoKaEo6PdA83fq98ebiFvo3X273Ydu4YmV96rg> .\n", "_:c14n2 <https://www.w3.org/2018/credentials#validFrom> \"2024-12-16T00:00:00Z\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n", "_:c14n2 <https://www.w3.org/2018/credentials#validUntil> \"2025-12-16T23:59:59Z\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n" ]
빈 노드 ID의 순서를 통한 잠재적인 정보 유출을 방지하기 위해, 이러한 ID를 PRF(즉, HMAC)를 통해 처리하여 아래에 표시된 정규화된 HMAC 문서를 생성합니다. 이는 "필수" 및 "선택적"(또는 "비필수") 공개의 대상이 되는 문장들의 순서 있는 목록을 나타냅니다. 즉, 이러한 문장을 공개 요구 사항에 따라 그룹화하더라도 이 목록과 동일한 순서가 유지됩니다.
[ "<did:key:zDnaeTHxNEBZoKaEo6PdA83fq98ebiFvo3X273Ydu4YmV96rg> <https://schema.org/image> <data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2P4z/DiPwAG0ALnwgz64QAAAABJRU5ErkJggg==> .\n", "_:b0 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://schema.org/Person> .\n", "_:b0 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/citizenship#PermanentResident> .\n", "_:b0 <https://schema.org/birthDate> \"1978-07-17\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n", "_:b0 <https://schema.org/familyName> \"SMITH\" .\n", "_:b0 <https://schema.org/gender> \"Female\" .\n", "_:b0 <https://schema.org/givenName> \"JANE\" .\n", "_:b0 <https://schema.org/image> <data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2P4v43hPwAHIgK1v4tX6wAAAABJRU5ErkJggg==> .\n", "_:b0 <https://w3id.org/citizenship#birthCountry> \"Arcadia\" .\n", "_:b0 <https://w3id.org/citizenship#commuterClassification> \"C1\" .\n", "_:b0 <https://w3id.org/citizenship#permanentResidentCard> _:b1 .\n", "_:b0 <https://w3id.org/citizenship#residentSince> \"2015-01-01\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n", "_:b1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/citizenship#PermanentResidentCard> .\n", "_:b1 <https://schema.org/identifier> \"83627465\" .\n", "_:b1 <https://w3id.org/citizenship#lprCategory> \"C09\" .\n", "_:b1 <https://w3id.org/citizenship#lprNumber> \"999-999-999\" .\n", "_:b2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/citizenship#PermanentResidentCardCredential> .\n", "_:b2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://www.w3.org/2018/credentials#VerifiableCredential> .\n", "_:b2 <https://schema.org/description> \"Permanent Resident Card from Government of Utopia.\" .\n", "_:b2 <https://schema.org/name> \"Permanent Resident Card\" .\n", "_:b2 <https://www.w3.org/2018/credentials#credentialSubject> _:b0 .\n", "_:b2 <https://www.w3.org/2018/credentials#issuer> <did:key:zDnaeTHxNEBZoKaEo6PdA83fq98ebiFvo3X273Ydu4YmV96rg> .\n", "_:b2 <https://www.w3.org/2018/credentials#validFrom> \"2024-12-16T00:00:00Z\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n", "_:b2 <https://www.w3.org/2018/credentials#validUntil> \"2025-12-16T23:59:59Z\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n" ]
위 정규 문서의 목록은 필수 및 비필수 문장으로 그룹화됩니다. 선택적 공개 변환 과정의 최종 출력은 아래와 같습니다. 이제 문장은 필수 또는 비필수 공개로 그룹화되며, 이전 목록에서 각 문장의 인덱스가 기억됩니다.
{
"mandatoryPointers": [
"/issuer"
],
"mandatory": {
"dataType": "Map",
"value": [
[
0,
"<did:key:zDnaeTHxNEBZoKaEo6PdA83fq98ebiFvo3X273Ydu4YmV96rg> <https://schema.org/image> <data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2P4z/DiPwAG0ALnwgz64QAAAABJRU5ErkJggg==> .\n"
],
[
16,
"_:b2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/citizenship#PermanentResidentCardCredential> .\n"
],
[
17,
"_:b2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://www.w3.org/2018/credentials#VerifiableCredential> .\n"
],
[
21,
"_:b2 <https://www.w3.org/2018/credentials#issuer> <did:key:zDnaeTHxNEBZoKaEo6PdA83fq98ebiFvo3X273Ydu4YmV96rg> .\n"
]
]
},
"nonMandatory": {
"dataType": "Map",
"value": [
[
1,
"_:b0 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://schema.org/Person> .\n"
],
[
2,
"_:b0 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/citizenship#PermanentResident> .\n"
],
[
3,
"_:b0 <https://schema.org/birthDate> \"1978-07-17\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n"
],
[
4,
"_:b0 <https://schema.org/familyName> \"SMITH\" .\n"
],
[
5,
"_:b0 <https://schema.org/gender> \"Female\" .\n"
],
[
6,
"_:b0 <https://schema.org/givenName> \"JANE\" .\n"
],
[
7,
"_:b0 <https://schema.org/image> <data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2P4v43hPwAHIgK1v4tX6wAAAABJRU5ErkJggg==> .\n"
],
[
8,
"_:b0 <https://w3id.org/citizenship#birthCountry> \"Arcadia\" .\n"
],
[
9,
"_:b0 <https://w3id.org/citizenship#commuterClassification> \"C1\" .\n"
],
[
10,
"_:b0 <https://w3id.org/citizenship#permanentResidentCard> _:b1 .\n"
],
[
11,
"_:b0 <https://w3id.org/citizenship#residentSince> \"2015-01-01\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n"
],
[
12,
"_:b1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/citizenship#PermanentResidentCard> .\n"
],
[
13,
"_:b1 <https://schema.org/identifier> \"83627465\" .\n"
],
[
14,
"_:b1 <https://w3id.org/citizenship#lprCategory> \"C09\" .\n"
],
[
15,
"_:b1 <https://w3id.org/citizenship#lprNumber> \"999-999-999\" .\n"
],
[
18,
"_:b2 <https://schema.org/description> \"Permanent Resident Card from Government of Utopia.\" .\n"
],
[
19,
"_:b2 <https://schema.org/name> \"Permanent Resident Card\" .\n"
],
[
20,
"_:b2 <https://www.w3.org/2018/credentials#credentialSubject> _:b0 .\n"
],
[
22,
"_:b2 <https://www.w3.org/2018/credentials#validFrom> \"2024-12-16T00:00:00Z\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n"
],
[
23,
"_:b2 <https://www.w3.org/2018/credentials#validUntil> \"2025-12-16T23:59:59Z\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n"
]
]
},
"hmacKeyString": "00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF"
}
다음 단계는 기본 증명 구성을 생성하고 이를 정규화하는 것입니다. 이는 다음 두 예제에 표시되어 있습니다.
{
"type": "DataIntegrityProof",
"cryptosuite": "bbs-2023",
"created": "2023-08-15T23:36:38Z",
"verificationMethod": "did:key:zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ#zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ",
"proofPurpose": "assertionMethod",
"@context": [
"https://www.w3.org/ns/credentials/v2",
"https://w3id.org/citizenship/v4rc1"
]
}
_:c14n0 <http://purl.org/dc/terms/created> "2023-08-15T23:36:38Z"^^<http://www.w3.org/2001/XMLSchema#dateTime> . _:c14n0 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/security#DataIntegrityProof> . _:c14n0 <https://w3id.org/security#cryptosuite> "bbs-2023"^^<https://w3id.org/security#cryptosuiteString> . _:c14n0 <https://w3id.org/security#proofPurpose> <https://w3id.org/security#assertionMethod> . _:c14n0 <https://w3id.org/security#verificationMethod> <did:key:zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ#zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ> .
해싱 단계에서는 정규화된 증명 옵션의 SHA-256 해시를 계산하여
proofHash를 생성하고, 모든 필수 N-Quads의
JOIN에 대한 SHA-256 해시를 계산하여 mandatoryHash를 생성합니다. 이는
아래에 16진수 형식으로 표시되어 있습니다.
{
"proofHash": "3a5bbf25d34d90b18c35cd2357be6a6f42301e94fc9e52f77e93b773c5614bdf",
"mandatoryHash": "8e7cc22c318dd2094e02d0bf06c5d73a5dba717611a40f6d1bedc5ea7c300fd6"
}
아래에는 계산된 bbsSignature가 16진수로 표시되어 있으며,
mandatoryPointers도 함께 표시되어 있습니다. 이들은
hmacKey와 함께 최종 직렬화 단계에 입력됩니다.
{
"bbsSignature": "86168dd2b5d0c7c6a56a30f4212ed116a53def05d0d6708207d483c7ff2053aefa22d24ba7659d60852694f8d85be0fa2adc3974c7dc4cc68b3db17b2423975047104162c24502b41591879ac24f1bb1",
"mandatoryPointers": [
"/issuer"
]
}
마지막으로 위의 값들을
3.2.1
serializeBaseProofValue 절의 알고리즘에 적용하여
서명된 기본 문서에서 사용되는 proofValue를 생성하며,
그 결과는 아래와 같습니다.
{
"@context": [
"https://www.w3.org/ns/credentials/v2",
"https://w3id.org/citizenship/v4rc1"
],
"type": [
"VerifiableCredential",
"PermanentResidentCardCredential"
],
"issuer": {
"id": "did:key:zDnaeTHxNEBZoKaEo6PdA83fq98ebiFvo3X273Ydu4YmV96rg",
"image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2P4z/DiPwAG0ALnwgz64QAAAABJRU5ErkJggg=="
},
"name": "Permanent Resident Card",
"description": "Permanent Resident Card from Government of Utopia.",
"credentialSubject": {
"type": [
"PermanentResident",
"Person"
],
"givenName": "JANE",
"familyName": "SMITH",
"gender": "Female",
"image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2P4v43hPwAHIgK1v4tX6wAAAABJRU5ErkJggg==",
"residentSince": "2015-01-01",
"commuterClassification": "C1",
"birthCountry": "Arcadia",
"birthDate": "1978-07-17",
"permanentResidentCard": {
"type": [
"PermanentResidentCard"
],
"identifier": "83627465",
"lprCategory": "C09",
"lprNumber": "999-999-999"
}
},
"validFrom": "2024-12-16T00:00:00Z",
"validUntil": "2025-12-16T23:59:59Z",
"proof": {
"type": "DataIntegrityProof",
"cryptosuite": "bbs-2023",
"created": "2023-08-15T23:36:38Z",
"verificationMethod": "did:key:zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ#zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ",
"proofPurpose": "assertionMethod",
"proofValue": "u2V0ChVhQhhaN0rXQx8alajD0IS7RFqU97wXQ1nCCB9SDx_8gU676ItJLp2WdYIUmlPjYW-D6Ktw5dMfcTMaLPbF7JCOXUEcQQWLCRQK0FZGHmsJPG7FYQDpbvyXTTZCxjDXNI1e-am9CMB6U_J5S936Tt3PFYUvfjnzCLDGN0glOAtC_BsXXOl26cXYRpA9tG-3F6nwwD9ZYYKTvGvo9pXVJbxIrm3i4wkdhUxqKCTIGrnxFuAdZwWi6T3omD5wzZ7bAGbRneEEQSxBmXtvnC6Pr59nPv_v3HrAW9wq_uxYzF_NyaX3GPv0h_FV2T2OSao8C6uoyWiqIj1ggABEiM0RVZneImaq7zN3u_wARIjNEVWZ3iJmqu8zd7v-BZy9pc3N1ZXI"
}
}
BBS 증명
을 생성할 때 난수를 사용하며,
선택적 presentationHeader를 추가 입력으로 사용할 수 있습니다.
결정론적인 테스트 벡터 집합을 제공하기 위해
[CFRG-BBS-SIGNATURE]의
Mocked Random Scalars
절차를 사용했습니다.
파생 증명 테스트 벡터 생성에 사용한 seed 및
presentationHeader 값은 아래에 16진수로 표시되어 있습니다.
{
"presentationHeaderHex": "113377aa",
"pseudoRandSeedHex": "332e313431353932363533353839373933323338343632363433333833323739"
}
파생 증명을 생성하려면 보유자는 기본 증명을 포함하는
서명된 문서에서 시작합니다. 이 테스트 벡터에 사용할 기본 문서는
위 A.1.1
기본 증명 절의 마지막 예제입니다. 첫 번째 단계는
3.2.2
parseBaseProofValue 절의 알고리즘을 실행하여
아래와 같이 bbsSignature, hmacKey,
mandatoryPointers를 복구하는 것입니다.
{
"bbsSignature": "86168dd2b5d0c7c6a56a30f4212ed116a53def05d0d6708207d483c7ff2053aefa22d24ba7659d60852694f8d85be0fa2adc3974c7dc4cc68b3db17b2423975047104162c24502b41591879ac24f1bb1",
"hmacKey": "00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff",
"mandatoryPointers": [
"/issuer"
]
}
다음으로 보유자는 선택적 공개를 위한 JSON 포인터를 지정하여 검증자에게 공개하려는 비필수 문장이 있다면 어떤 것인지 나타내야 합니다. 이는 아래와 같습니다.
["/validFrom", "/validUntil", "/credentialSubject/birthCountry"]
revealDocument(즉, 최종적으로 서명되어
검증자에게 전송될 서명되지 않은 문서)를 생성하기 위해 선택적 포인터를
필수 포인터에 이어 붙이고, 이 결합된 포인터와 증명을 제거한
문서를 [DI-ECDSA]의
selectJsonLd 알고리즘에 입력합니다.
그러면 아래와 같은 결과를 얻습니다.
{
"@context": [
"https://www.w3.org/ns/credentials/v2",
"https://w3id.org/citizenship/v4rc1"
],
"type": [
"VerifiableCredential",
"PermanentResidentCardCredential"
],
"issuer": {
"id": "did:key:zDnaeTHxNEBZoKaEo6PdA83fq98ebiFvo3X273Ydu4YmV96rg",
"image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2P4z/DiPwAG0ALnwgz64QAAAABJRU5ErkJggg=="
},
"validFrom": "2024-12-16T00:00:00Z",
"validUntil": "2025-12-16T23:59:59Z",
"credentialSubject": {
"type": [
"PermanentResident",
"Person"
],
"birthCountry": "Arcadia"
}
}
이제 공개 문서가 어떤 형태인지 알았으므로, 어떤 문장이 필수인지와 선택된 비필수 문장의 인덱스에 관한 적절히 갱신된 정보를 검증자에게 제공해야 합니다. § 4.4.3 CreateDisclosureData를 실행하면 원본 문서를 기준으로 여러 문장 그룹에 관한 풍부한 정보를 얻을 수 있습니다. 아래에서는 이러한 그룹에 대한 인덱스의 일부를 보여 줍니다.
{"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를 기준으로 한 위치)을 제공하며,
selectiveIndexes는
nonMandatoryIndexes 내 위치를 기준으로 조정됩니다.
이러한 "조정된" 인덱스는 아래와 같습니다.
{"adjMandatoryIndexes":[0,4,5,7],"adjSelectiveIndexes":[0,1,7,17,18,19]}
마지막으로 중요한 공개 데이터는 labelMap이며, 이는 정규화된
빈 노드 ID를 HMAC 기반으로 섞인 ID에 매핑한 것으로,
§ 4.4.3 CreateDisclosureData에 따라 계산됩니다. 이는
아래에 공개 문서를 제외한
나머지 공개 데이터와 함께 표시됩니다.
{"bbsProof":"96ac5ff7b89bf2d8b0f3cc51c547f1a22b01e24e246579d212362cdf6bf0fabe18be0c9d1f84c904bb4c6c613fd0ecabb7ad92e615341da97a45a918721626cc859c455b473a36e39572561d5fc483c637424717a43dcffb3b130d8fe11f88a8802f3b231efe2444f8b47feded0b621e3d5cd22cb3ec23ebc4f6dca745b5c1ce2f42a710b92510a71225a7d39e00e0c26da2fae242cdf154e93de42017270b99023fe95b42c42a461a2eab19e04aa44839af39aa71f830162cb424a5aa0acc046dc7e7b8bdfc73cf3641c76aeeb7fbb56cd936776050dbd632bf7fc80d33c621dc6b837184ade619630f72bd25d8aea626ba994d15a65def1b0dc8af09c54a0cf5e5b54d1b1b28047aa2dbf63805fec9533bab46d12349ca47dfd83ff30454cedacd23da4eb9a3ebe198c80ac1992e2a203ffcf46afaa3482a63b7b00033df1a2da361d600a1cfd5139be010ca302e082af7ee34a5ff3d24cc7062f57fa36d47846edd5219e59bd438576bff709bfd7920d6bad8367b0fe8c749318ef8726beda9c1d9095bed738e4fd1c38333a27f4f2071a21a863671b43fe521f737444be865e887cbf33caa39226fb8013003721e37c6d949867befba1c8b7bf641bd647851ad92aed3da91af52f17d058a9f74eb30744304c05813840be6a528f54cd5a24b73ae2f42dec1bfc2e1354fb061a96c0df3ab96ddc9ada96cb882571cccb89774fcf0326e1c8b2b87cc4cf4eafbd75632518919cbe58a9f86ade12b0f6989c0886e358d801b99b1dd32c7e6e56a653c0e264a84b51d2d23679c75e282451af3bcaa6f19ec7bc3aa603fec87db5a57d42961e2907d899a8fd5d1ce17dde8a75cd1192494cd93b112da7774c2bb2f679f5b4b404dabe485d78a017b2be81e5ff8bacf90d5f24b2e83ab4169f8f55ca6f703141f91565abbec7445e6cf4663f5e34b9188283d57cedf36c586b18a130b83652436bf6862673ddeebd9aefdc2fbfc97dde80e36483491c4357ccd2fc131fb","labelMap":{"dataType":"Map","value":[["c14n0","b0"],["c14n1","b2"]]},"mandatoryIndexes":[0,4,5,7],"adjSelectiveIndexes":[0,1,7,17,18,19],"presentationHeader":{"0":17,"1":51,"2":119,"3":170}}
마지막으로 위의 공개 데이터를 다음 절의 알고리즘과 함께 사용하면 3.2.3 serializeDerivedProofValue, 아래에 표시된 서명된 파생(공개) 문서를 얻습니다.
{
"@context": [
"https://www.w3.org/ns/credentials/v2",
"https://w3id.org/citizenship/v4rc1"
],
"type": [
"VerifiableCredential",
"PermanentResidentCardCredential"
],
"issuer": {
"id": "did:key:zDnaeTHxNEBZoKaEo6PdA83fq98ebiFvo3X273Ydu4YmV96rg",
"image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2P4z/DiPwAG0ALnwgz64QAAAABJRU5ErkJggg=="
},
"validFrom": "2024-12-16T00:00:00Z",
"validUntil": "2025-12-16T23:59:59Z",
"credentialSubject": {
"type": [
"PermanentResident",
"Person"
],
"birthCountry": "Arcadia"
},
"proof": {
"type": "DataIntegrityProof",
"cryptosuite": "bbs-2023",
"created": "2023-08-15T23:36:38Z",
"verificationMethod": "did:key:zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ#zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ",
"proofPurpose": "assertionMethod",
"proofValue": "u2V0DhVkC0JasX_e4m_LYsPPMUcVH8aIrAeJOJGV50hI2LN9r8Pq-GL4MnR-EyQS7TGxhP9Dsq7etkuYVNB2pekWpGHIWJsyFnEVbRzo245VyVh1fxIPGN0JHF6Q9z_s7Ew2P4R-IqIAvOyMe_iRE-LR_7e0LYh49XNIss-wj68T23KdFtcHOL0KnELklEKcSJafTngDgwm2i-uJCzfFU6T3kIBcnC5kCP-lbQsQqRhouqxngSqRIOa85qnH4MBYstCSlqgrMBG3H57i9_HPPNkHHau63-7Vs2TZ3YFDb1jK_f8gNM8Yh3GuDcYSt5hljD3K9Jdiupia6mU0Vpl3vGw3IrwnFSgz15bVNGxsoBHqi2_Y4Bf7JUzurRtEjScpH39g_8wRUztrNI9pOuaPr4ZjICsGZLiogP_z0avqjSCpjt7AAM98aLaNh1gChz9UTm-AQyjAuCCr37jSl_z0kzHBi9X-jbUeEbt1SGeWb1DhXa_9wm_15INa62DZ7D-jHSTGO-HJr7anB2Qlb7XOOT9HDgzOif08gcaIahjZxtD_lIfc3REvoZeiHy_M8qjkib7gBMANyHjfG2UmGe--6HIt79kG9ZHhRrZKu09qRr1LxfQWKn3TrMHRDBMBYE4QL5qUo9UzVoktzri9C3sG_wuE1T7BhqWwN86uW3cmtqWy4glcczLiXdPzwMm4ciyuHzEz06vvXVjJRiRnL5Yqfhq3hKw9picCIbjWNgBuZsd0yx-blamU8DiZKhLUdLSNnnHXigkUa87yqbxnse8OqYD_sh9taV9QpYeKQfYmaj9XRzhfd6Kdc0RkklM2TsRLad3TCuy9nn1tLQE2r5IXXigF7K-geX_i6z5DV8ksug6tBafj1XKb3AxQfkVZau-x0RebPRmP140uRiCg9V87fNsWGsYoTC4NlJDa_aGJnPd7r2a79wvv8l93oDjZINJHENXzNL8Ex-6IAAAEChAAEBQeGAAEHERITRBEzd6o"
}
}
필수 공개, 선택적 공개 및 이들 간의 중첩을 포함한 선택적 공개 기능을 시연하려면 이전 테스트 벡터보다 더 많은 내용을 포함하는 입력 자격 증명 문서가 필요합니다. 지나치게 긴 테스트 벡터를 피하기 위해 시작 문서 테스트 벡터는 완전히 가상의 윈드서핑(요트) 경기 시나리오를 기반으로 합니다. 또한 테스트 벡터를 발급자가 생성하는 것(기본 증명)과 보유자가 생성하는 것(파생 증명)에 따라 두 그룹으로 나눕니다.
문서에 선택적 공개 기본 증명을 추가하려면 발급자에게 다음 암호학적 키 자료가 필요합니다:
기본 증명 추가 테스트를 위한 테스트 벡터 생성에 사용된 키 자료는 아래와 같습니다. BBS 키 쌍과 HMAC 키에는 16진수 표현을 사용합니다.
{
"publicKeyHex": "a4ef1afa3da575496f122b9b78b8c24761531a8a093206ae7c45b80759c168ba4f7a260f9c3367b6c019b4677841104b10665edbe70ba3ebe7d9cfbffbf71eb016f70abfbb163317f372697dc63efd21fc55764f63926a8f02eaea325a2a888f",
"privateKeyHex": "66d36e118832af4c5e28b2dfe1b9577857e57b042a33e06bdea37b811ed09ee0",
"hmacKeyString": "00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF"
}
이 시나리오에서는 한 선수가 마우이에서 여러 날에 걸쳐 열리는 일련의 윈드서핑 경기에 참가하기 위해 경기 주최자에게 등록합니다. 주최자는 선수가 신고한 내용이 정확한지 인증하기 위해 장비를 검사합니다. 선수의 서명되지 않은 장비 목록은 아래와 같습니다.
{
"@context": [
"https://www.w3.org/ns/credentials/v2",
{
"@vocab": "https://windsurf.grotto-networking.com/selective#"
}
],
"type": [
"VerifiableCredential"
],
"issuer": "https://vc.example/windsurf/racecommittee",
"credentialSubject": {
"sailNumber": "Earth101",
"sails": [
{
"size": 5.5,
"sailName": "Kihei",
"year": 2023
},
{
"size": 6.1,
"sailName": "Lahaina",
"year": 2023
},
{
"size": 7.0,
"sailName": "Lahaina",
"year": 2020
},
{
"size": 7.8,
"sailName": "Lahaina",
"year": 2023
}
],
"boards": [
{
"boardName": "CompFoil170",
"brand": "Wailea",
"year": 2022
},
{
"boardName": "Kanaha Custom",
"brand": "Wailea",
"year": 2019
}
]
}
}
다른 선수들에게 경쟁자들이 어떤 종류의 장비를 사용할 수 있는지 알려주는 것 외에도, 각 선수는 가장 최근 윈드서핑 보드의 연도와 돛 두 개에 대한 전체 세부 정보를 반드시 공개해야 합니다. 모든 선수는 모든 장비에 인쇄된 돛 번호로 식별된다는 점에 유의하십시오. 이 필수 정보는 아래와 같이 JSON 포인터 배열을 통해 지정됩니다.
["/issuer", "/credentialSubject/sailNumber", "/credentialSubject/sails/1", "/credentialSubject/boards/0/year", "/credentialSubject/sails/2"]
위의 JSON 포인터를 선수의 장비 문서에 적용한 결과는 아래와 같습니다.
[
{
"pointer": "/sailNumber",
"value": "Earth101"
},
{
"pointer": "/sails/1",
"value": {
"size": 6.1,
"sailName": "Lahaina",
"year": 2023
}
},
{
"pointer": "/boards/0/year",
"value": 2022
},
{
"pointer": "/sails/2",
"value": {
"size": 7,
"sailName": "Lahaina",
"year": 2020
}
}
]
서명되지 않은 문서의 변환은 아래와 같이 문서를 정규화하는 것부터 시작합니다.
[ "_:c14n0 <https://windsurf.grotto-networking.com/selective#boardName> \"CompFoil170\" .\n", "_:c14n0 <https://windsurf.grotto-networking.com/selective#brand> \"Wailea\" .\n", "_:c14n0 <https://windsurf.grotto-networking.com/selective#year> \"2022\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n", "_:c14n1 <https://windsurf.grotto-networking.com/selective#sailName> \"Lahaina\" .\n", "_:c14n1 <https://windsurf.grotto-networking.com/selective#size> \"7.8E0\"^^<http://www.w3.org/2001/XMLSchema#double> .\n", "_:c14n1 <https://windsurf.grotto-networking.com/selective#year> \"2023\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n", "_:c14n2 <https://windsurf.grotto-networking.com/selective#boardName> \"Kanaha Custom\" .\n", "_:c14n2 <https://windsurf.grotto-networking.com/selective#brand> \"Wailea\" .\n", "_:c14n2 <https://windsurf.grotto-networking.com/selective#year> \"2019\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n", "_:c14n3 <https://windsurf.grotto-networking.com/selective#sailName> \"Lahaina\" .\n", "_:c14n3 <https://windsurf.grotto-networking.com/selective#size> \"7\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n", "_:c14n3 <https://windsurf.grotto-networking.com/selective#year> \"2020\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n", "_:c14n4 <https://windsurf.grotto-networking.com/selective#sailName> \"Kihei\" .\n", "_:c14n4 <https://windsurf.grotto-networking.com/selective#size> \"5.5E0\"^^<http://www.w3.org/2001/XMLSchema#double> .\n", "_:c14n4 <https://windsurf.grotto-networking.com/selective#year> \"2023\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n", "_:c14n5 <https://windsurf.grotto-networking.com/selective#boards> _:c14n0 .\n", "_:c14n5 <https://windsurf.grotto-networking.com/selective#boards> _:c14n2 .\n", "_:c14n5 <https://windsurf.grotto-networking.com/selective#sailNumber> \"Earth101\" .\n", "_:c14n5 <https://windsurf.grotto-networking.com/selective#sails> _:c14n1 .\n", "_:c14n5 <https://windsurf.grotto-networking.com/selective#sails> _:c14n3 .\n", "_:c14n5 <https://windsurf.grotto-networking.com/selective#sails> _:c14n4 .\n", "_:c14n5 <https://windsurf.grotto-networking.com/selective#sails> _:c14n6 .\n", "_:c14n6 <https://windsurf.grotto-networking.com/selective#sailName> \"Lahaina\" .\n", "_:c14n6 <https://windsurf.grotto-networking.com/selective#size> \"6.1E0\"^^<http://www.w3.org/2001/XMLSchema#double> .\n", "_:c14n6 <https://windsurf.grotto-networking.com/selective#year> \"2023\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n", "_:c14n7 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://www.w3.org/2018/credentials#VerifiableCredential> .\n", "_:c14n7 <https://www.w3.org/2018/credentials#credentialSubject> _:c14n5 .\n", "_:c14n7 <https://www.w3.org/2018/credentials#issuer> <https://vc.example/windsurf/racecommittee> .\n" ]
빈 노드 ID의 순서에서 발생할 수 있는 정보 유출을 방지하기 위해 이를 PRF(즉, HMAC)를 통해 처리하여 아래에 표시된 정규화된 HMAC 문서를 생성합니다. 이는 필수 및 선택적 공개의 대상이 되는 문장들의 순서 있는 목록을 나타내며, 즉 이 목록을 기준으로 문장이 그룹화됩니다.
[ "_:b0 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://www.w3.org/2018/credentials#VerifiableCredential> .\n", "_:b0 <https://www.w3.org/2018/credentials#credentialSubject> _:b3 .\n", "_:b0 <https://www.w3.org/2018/credentials#issuer> <https://vc.example/windsurf/racecommittee> .\n", "_:b1 <https://windsurf.grotto-networking.com/selective#sailName> \"Lahaina\" .\n", "_:b1 <https://windsurf.grotto-networking.com/selective#size> \"7.8E0\"^^<http://www.w3.org/2001/XMLSchema#double> .\n", "_:b1 <https://windsurf.grotto-networking.com/selective#year> \"2023\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n", "_:b2 <https://windsurf.grotto-networking.com/selective#boardName> \"CompFoil170\" .\n", "_:b2 <https://windsurf.grotto-networking.com/selective#brand> \"Wailea\" .\n", "_:b2 <https://windsurf.grotto-networking.com/selective#year> \"2022\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n", "_:b3 <https://windsurf.grotto-networking.com/selective#boards> _:b2 .\n", "_:b3 <https://windsurf.grotto-networking.com/selective#boards> _:b4 .\n", "_:b3 <https://windsurf.grotto-networking.com/selective#sailNumber> \"Earth101\" .\n", "_:b3 <https://windsurf.grotto-networking.com/selective#sails> _:b1 .\n", "_:b3 <https://windsurf.grotto-networking.com/selective#sails> _:b5 .\n", "_:b3 <https://windsurf.grotto-networking.com/selective#sails> _:b6 .\n", "_:b3 <https://windsurf.grotto-networking.com/selective#sails> _:b7 .\n", "_:b4 <https://windsurf.grotto-networking.com/selective#boardName> \"Kanaha Custom\" .\n", "_:b4 <https://windsurf.grotto-networking.com/selective#brand> \"Wailea\" .\n", "_:b4 <https://windsurf.grotto-networking.com/selective#year> \"2019\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n", "_:b5 <https://windsurf.grotto-networking.com/selective#sailName> \"Kihei\" .\n", "_:b5 <https://windsurf.grotto-networking.com/selective#size> \"5.5E0\"^^<http://www.w3.org/2001/XMLSchema#double> .\n", "_:b5 <https://windsurf.grotto-networking.com/selective#year> \"2023\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n", "_:b6 <https://windsurf.grotto-networking.com/selective#sailName> \"Lahaina\" .\n", "_:b6 <https://windsurf.grotto-networking.com/selective#size> \"6.1E0\"^^<http://www.w3.org/2001/XMLSchema#double> .\n", "_:b6 <https://windsurf.grotto-networking.com/selective#year> \"2023\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n", "_:b7 <https://windsurf.grotto-networking.com/selective#sailName> \"Lahaina\" .\n", "_:b7 <https://windsurf.grotto-networking.com/selective#size> \"7\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n", "_:b7 <https://windsurf.grotto-networking.com/selective#year> \"2020\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n" ]
위 정규 문서는 필수 및 비필수 문장으로 그룹화됩니다. 선택적 공개 변환 과정의 최종 출력은 아래와 같습니다. 이제 각 문장은 필수 또는 비필수로 그룹화되고, 이전 문장 목록에서의 인덱스가 기억됩니다.
{
"mandatoryPointers": [
"/issuer",
"/credentialSubject/sailNumber",
"/credentialSubject/sails/1",
"/credentialSubject/boards/0/year",
"/credentialSubject/sails/2"
],
"mandatory": {
"dataType": "Map",
"value": [
[
0,
"_:b0 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://www.w3.org/2018/credentials#VerifiableCredential> .\n"
],
[
1,
"_:b0 <https://www.w3.org/2018/credentials#credentialSubject> _:b3 .\n"
],
[
2,
"_:b0 <https://www.w3.org/2018/credentials#issuer> <https://vc.example/windsurf/racecommittee> .\n"
],
[
8,
"_:b2 <https://windsurf.grotto-networking.com/selective#year> \"2022\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n"
],
[
9,
"_:b3 <https://windsurf.grotto-networking.com/selective#boards> _:b2 .\n"
],
[
11,
"_:b3 <https://windsurf.grotto-networking.com/selective#sailNumber> \"Earth101\" .\n"
],
[
14,
"_:b3 <https://windsurf.grotto-networking.com/selective#sails> _:b6 .\n"
],
[
15,
"_:b3 <https://windsurf.grotto-networking.com/selective#sails> _:b7 .\n"
],
[
22,
"_:b6 <https://windsurf.grotto-networking.com/selective#sailName> \"Lahaina\" .\n"
],
[
23,
"_:b6 <https://windsurf.grotto-networking.com/selective#size> \"6.1E0\"^^<http://www.w3.org/2001/XMLSchema#double> .\n"
],
[
24,
"_:b6 <https://windsurf.grotto-networking.com/selective#year> \"2023\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n"
],
[
25,
"_:b7 <https://windsurf.grotto-networking.com/selective#sailName> \"Lahaina\" .\n"
],
[
26,
"_:b7 <https://windsurf.grotto-networking.com/selective#size> \"7\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n"
],
[
27,
"_:b7 <https://windsurf.grotto-networking.com/selective#year> \"2020\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n"
]
]
},
"nonMandatory": {
"dataType": "Map",
"value": [
[
3,
"_:b1 <https://windsurf.grotto-networking.com/selective#sailName> \"Lahaina\" .\n"
],
[
4,
"_:b1 <https://windsurf.grotto-networking.com/selective#size> \"7.8E0\"^^<http://www.w3.org/2001/XMLSchema#double> .\n"
],
[
5,
"_:b1 <https://windsurf.grotto-networking.com/selective#year> \"2023\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n"
],
[
6,
"_:b2 <https://windsurf.grotto-networking.com/selective#boardName> \"CompFoil170\" .\n"
],
[
7,
"_:b2 <https://windsurf.grotto-networking.com/selective#brand> \"Wailea\" .\n"
],
[
10,
"_:b3 <https://windsurf.grotto-networking.com/selective#boards> _:b4 .\n"
],
[
12,
"_:b3 <https://windsurf.grotto-networking.com/selective#sails> _:b1 .\n"
],
[
13,
"_:b3 <https://windsurf.grotto-networking.com/selective#sails> _:b5 .\n"
],
[
16,
"_:b4 <https://windsurf.grotto-networking.com/selective#boardName> \"Kanaha Custom\" .\n"
],
[
17,
"_:b4 <https://windsurf.grotto-networking.com/selective#brand> \"Wailea\" .\n"
],
[
18,
"_:b4 <https://windsurf.grotto-networking.com/selective#year> \"2019\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n"
],
[
19,
"_:b5 <https://windsurf.grotto-networking.com/selective#sailName> \"Kihei\" .\n"
],
[
20,
"_:b5 <https://windsurf.grotto-networking.com/selective#size> \"5.5E0\"^^<http://www.w3.org/2001/XMLSchema#double> .\n"
],
[
21,
"_:b5 <https://windsurf.grotto-networking.com/selective#year> \"2023\"^^<http://www.w3.org/2001/XMLSchema#integer> .\n"
]
]
},
"hmacKeyString": "00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF"
}
다음 단계는 기본 증명 구성을 생성하고 이를 정규화하는 것입니다. 이는 다음 두 예제에 표시되어 있습니다.
{
"type": "DataIntegrityProof",
"cryptosuite": "bbs-2023",
"created": "2023-08-15T23:36:38Z",
"verificationMethod": "did:key:zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ#zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ",
"proofPurpose": "assertionMethod",
"@context": [
"https://www.w3.org/ns/credentials/v2",
{
"@vocab": "https://windsurf.grotto-networking.com/selective#"
}
]
}
_:c14n0 <http://purl.org/dc/terms/created> "2023-08-15T23:36:38Z"^^<http://www.w3.org/2001/XMLSchema#dateTime> . _:c14n0 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/security#DataIntegrityProof> . _:c14n0 <https://w3id.org/security#cryptosuite> "bbs-2023"^^<https://w3id.org/security#cryptosuiteString> . _:c14n0 <https://w3id.org/security#proofPurpose> <https://w3id.org/security#assertionMethod> . _:c14n0 <https://w3id.org/security#verificationMethod> <did:key:zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ#zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ> .
해싱 단계에서는 정규화된 증명 옵션의 SHA-256 해시를 계산하여
proofHash를 생성하고, 모든 필수 N-Quads를
결합한 값의 SHA-256 해시를 계산하여 mandatoryHash를 생성합니다.
이는 아래에 16진수 형식으로 표시되어 있습니다.
{
"proofHash": "3a5bbf25d34d90b18c35cd2357be6a6f42301e94fc9e52f77e93b773c5614bdf",
"mandatoryHash": "555de05f898817e31301bac187d0c3ff2b03e2cbdb4adb4d568c17de961f9a18"
}
아래에는 계산된 bbsSignature가 16진수로 표시되어 있으며,
mandatoryPointers도 함께 표시되어 있습니다. 이들은
hmacKey와 함께 최종 직렬화 단계에 입력됩니다.
{
"bbsSignature": "8331f55ad458fe5c322420b2cb806f9a20ea6b2b8a29d51710026d71ace5da080064b488818efc75a439525bd031450822a6a332da781926e19360b90166431124efcf3d060fbc750c6122c714c07f71",
"mandatoryPointers": [
"/issuer",
"/credentialSubject/sailNumber",
"/credentialSubject/sails/1",
"/credentialSubject/boards/0/year",
"/credentialSubject/sails/2"
]
}
마지막으로 위의 값들을
3.2.1
serializeBaseProofValue 절의 알고리즘에 적용하여,
아래에 표시된 서명된 기본 문서에서 사용되는
proofValue를 생성합니다.
{
"@context": [
"https://www.w3.org/ns/credentials/v2",
{
"@vocab": "https://windsurf.grotto-networking.com/selective#"
}
],
"type": [
"VerifiableCredential"
],
"issuer": "https://vc.example/windsurf/racecommittee",
"credentialSubject": {
"sailNumber": "Earth101",
"sails": [
{
"size": 5.5,
"sailName": "Kihei",
"year": 2023
},
{
"size": 6.1,
"sailName": "Lahaina",
"year": 2023
},
{
"size": 7,
"sailName": "Lahaina",
"year": 2020
},
{
"size": 7.8,
"sailName": "Lahaina",
"year": 2023
}
],
"boards": [
{
"boardName": "CompFoil170",
"brand": "Wailea",
"year": 2022
},
{
"boardName": "Kanaha Custom",
"brand": "Wailea",
"year": 2019
}
]
},
"proof": {
"type": "DataIntegrityProof",
"cryptosuite": "bbs-2023",
"created": "2023-08-15T23:36:38Z",
"verificationMethod": "did:key:zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ#zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ",
"proofPurpose": "assertionMethod",
"proofValue": "u2V0ChVhQgzH1WtRY_lwyJCCyy4BvmiDqayuKKdUXEAJtcazl2ggAZLSIgY78daQ5UlvQMUUIIqajMtp4GSbhk2C5AWZDESTvzz0GD7x1DGEixxTAf3FYQDpbvyXTTZCxjDXNI1e-am9CMB6U_J5S936Tt3PFYUvfVV3gX4mIF-MTAbrBh9DD_ysD4svbSttNVowX3pYfmhhYYKTvGvo9pXVJbxIrm3i4wkdhUxqKCTIGrnxFuAdZwWi6T3omD5wzZ7bAGbRneEEQSxBmXtvnC6Pr59nPv_v3HrAW9wq_uxYzF_NyaX3GPv0h_FV2T2OSao8C6uoyWiqIj1ggABEiM0RVZneImaq7zN3u_wARIjNEVWZ3iJmqu8zd7v-FZy9pc3N1ZXJ4HS9jcmVkZW50aWFsU3ViamVjdC9zYWlsTnVtYmVyeBovY3JlZGVudGlhbFN1YmplY3Qvc2FpbHMvMXggL2NyZWRlbnRpYWxTdWJqZWN0L2JvYXJkcy8wL3llYXJ4Gi9jcmVkZW50aWFsU3ViamVjdC9zYWlscy8y"
}
}
BBS 증명
을 생성할 때 난수를 사용하며,
선택적 presentationHeader를 입력으로 사용할 수 있습니다.
결정론적인 테스트 벡터 집합을 제공하기 위해
[CFRG-BBS-SIGNATURE]의
Mocked Random Scalars
절차를 사용했습니다.
파생 증명 테스트 벡터 생성에 사용한 seed 및
presentationHeader 값은 아래에 16진수로 표시되어 있습니다.
{
"presentationHeaderHex": "113377aa",
"pseudoRandSeedHex": "332e313431353932363533353839373933323338343632363433333833323739"
}
파생 증명을 생성하려면 보유자는 기본 증명을 포함하는
서명된 문서에서 시작합니다. 이 테스트 벡터에 사용할 기본 문서는
위 A.1.1
기본 증명 절의 마지막 예제입니다. 첫 번째 단계는
3.2.2
parseBaseProofValue 절의 알고리즘을 실행하여
아래와 같이 bbsSignature, hmacKey,
mandatoryPointers를 복구하는 것입니다.
{
"bbsSignature": "8331f55ad458fe5c322420b2cb806f9a20ea6b2b8a29d51710026d71ace5da080064b488818efc75a439525bd031450822a6a332da781926e19360b90166431124efcf3d060fbc750c6122c714c07f71",
"hmacKey": "00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff",
"mandatoryPointers": [
"/issuer",
"/credentialSubject/sailNumber",
"/credentialSubject/sails/1",
"/credentialSubject/boards/0/year",
"/credentialSubject/sails/2"
]
}
다음으로 보유자는 선택적 공개를 위한 JSON 포인터를 지정하여, 추가로 공개하려는 내용이 있다면 무엇인지 검증자에게 나타내야 합니다. 이 윈드서핑 경기 시나리오에서 선수(보유자)는 경기 첫날을 막 마쳤으며, 경기에서 사용한 모든 윈드서핑 보드의 세부 정보를 일반 대중(검증자)에게 공개하려고 합니다. 이는 아래와 같습니다. 이 정보는 가장 최근 보드의 연도만 포함했던 필수 공개 정보와 일부 중첩된다는 점에 유의하십시오.
["/credentialSubject/boards/0", "/credentialSubject/boards/1"]
revealDocument(즉, 최종적으로 서명되어
검증자에게 전송될 서명되지 않은 문서)를 생성하기 위해 선택적 포인터를
필수 포인터에 이어 붙이고, 이 결합된 포인터와 증명을 제거한
문서를 [DI-ECDSA]의
selectJsonLd 알고리즘에 입력하여
아래와 같은 결과를 얻습니다.
{
"@context": [
"https://www.w3.org/ns/credentials/v2",
{
"@vocab": "https://windsurf.grotto-networking.com/selective#"
}
],
"type": [
"VerifiableCredential"
],
"issuer": "https://vc.example/windsurf/racecommittee",
"credentialSubject": {
"sailNumber": "Earth101",
"sails": [
{
"size": 6.1,
"sailName": "Lahaina",
"year": 2023
},
{
"size": 7,
"sailName": "Lahaina",
"year": 2020
}
],
"boards": [
{
"year": 2022,
"boardName": "CompFoil170",
"brand": "Wailea"
},
{
"boardName": "Kanaha Custom",
"brand": "Wailea",
"year": 2019
}
]
}
}
이제 공개된 문서가 어떤 형태인지 알았으므로, 어떤 문장이 필수인지와 선택된 비필수 문장의 인덱스에 관한 적절히 갱신된 정보를 검증자에게 제공해야 합니다. § 4.4.3 CreateDisclosureData를 실행하면 원본 문서를 기준으로 여러 문장 그룹에 관한 풍부한 정보를 얻을 수 있습니다. 아래에서는 이러한 그룹에 대한 인덱스의 일부를 보여 줍니다.
{
"combinedIndexes":[0,1,2,6,7,8,9,10,11,14,15,16,17,18,22,23,24,25,26,27],
"mandatoryIndexes":[0,1,2,8,9,11,14,15,22,23,24,25,26,27],
"nonMandatoryIndexes":[3,4,5,6,7,10,12,13,16,17,18,19,20,21],
"selectiveIndexes":[0,1,6,7,8,9,10,16,17,18]
}
검증자는 필수 문장을 모아 해싱할 수 있어야 합니다. 이를 위해
필수 문장의 인덱스를 공개 문서에서의 위치에 맞게 조정한 목록
(즉, combinedIndexes를 기준으로 한 위치)을 제공하며,
selectiveIndexes는
nonMandatoryIndexes 내 위치를 기준으로 조정해야 합니다.
이러한 "조정된" 인덱스는 아래와 같습니다.
{
"adjMandatoryIndexes":[0,1,2,5,6,8,9,10,14,15,16,17,18,19],
"adjSelectiveIndexes":[3,4,5,8,9,10]
}
마지막으로 중요한 공개 데이터는 정규화된 빈 노드
ID를 HMAC 기반으로 섞인 ID에 매핑한 labelMap이며, 다음 절에 따라 계산됩니다.
§ 4.4.3 CreateDisclosureData. 이는
아래에 공개 문서를 제외한
나머지 공개 데이터와 함께 표시됩니다.
{
"bbsProof":"9831ba06852694fb44eb56cd9f66581330d9493671a3ad5ed28610c2550c5bfda6cada7cbaf37e9af0c873a4ec6813bf857d539543bc45ba1349fe3233b446f6c46190c40aa8456d98312ed7535c3003e3a77af752ed6f7ee162df4e38a268ad87cc5a10ff38dcc6633810e08ac5a80dacfe6e7dec3ca65fb1dab8d1b0da22b8f26040238c700b8310de92c9c2ec118b2de6b0ccdc72fbdd3329ccf7bc729829e8492d0a796f6e09131884f6fdd0df8028d5ef8f05d9aa9817872598c56421526dbe5db40586cd2b83a454652f71637e57917abd22f45bb67d48fcebdf5464671aec2e845f87f87c1d0eb934db3fb9e2310d483d67110b5f64127827888e8cd9259ea78f6683184ca4e71845b803d93a3554f4577716f939bd36f26eb740771bd5c35247ef4abc2b0e701721a6e8edf62a63af3a032df895cde06d0b15ca8c1a7507249118f9d096fcc5a3f9a39ec1a870ef619efa6af61fd93b74b82b24317def59f981fc8ec2b5633d8eb8711b108552b7b6e748648503fecdf52ac0a76eca89306361262cc4767bbb84e904d1a7523bc19d67bc501c78949616bef65470b067f81759d9a29f9c2775c0888a4617b57018ece111e62cd8365b4783fbe53bcec846bf724bdddc196fced05c59c35ebb735aea9a83f0e5233cdb9fbb8fd2e3b007ee7f69cafc37c4993ddfc747d7793b48ea48213154b459260c29da6dd41de9539a3352855afa398b2bafd47d07d765",
"labelMap":{"dataType":"Map","value":[["c14n0","b2"],["c14n1","b4"],["c14n2","b3"],["c14n3","b7"],["c14n4","b6"],["c14n5","b0"]]},
"mandatoryIndexes":[0,1,2,5,6,8,9,10,14,15,16,17,18,19],
"adjSelectiveIndexes":[3,4,5,8,9,10],
"presentationHeader":{"0":17,"1":51,"2":119,"3":170}
}
마지막으로 위의 공개 데이터를 다음 절의 알고리즘과 함께 사용하면 3.2.3 serializeDerivedProofValue, 아래에 표시된 서명된 파생(공개) 문서를 얻습니다.
{
"@context": [
"https://www.w3.org/ns/credentials/v2",
{
"@vocab": "https://windsurf.grotto-networking.com/selective#"
}
],
"type": [
"VerifiableCredential"
],
"issuer": "https://vc.example/windsurf/racecommittee",
"credentialSubject": {
"sailNumber": "Earth101",
"sails": [
{
"size": 6.1,
"sailName": "Lahaina",
"year": 2023
},
{
"size": 7,
"sailName": "Lahaina",
"year": 2020
}
],
"boards": [
{
"year": 2022,
"boardName": "CompFoil170",
"brand": "Wailea"
},
{
"boardName": "Kanaha Custom",
"brand": "Wailea",
"year": 2019
}
]
},
"proof": {
"type": "DataIntegrityProof",
"cryptosuite": "bbs-2023",
"created": "2023-08-15T23:36:38Z",
"verificationMethod": "did:key:zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ#zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ",
"proofPurpose": "assertionMethod",
"proofValue": "u2V0DhVkCEJgxugaFJpT7ROtWzZ9mWBMw2Uk2caOtXtKGEMJVDFv9psrafLrzfprwyHOk7GgTv4V9U5VDvEW6E0n-MjO0RvbEYZDECqhFbZgxLtdTXDAD46d691Ltb37hYt9OOKJorYfMWhD_ONzGYzgQ4IrFqA2s_m597DymX7HauNGw2iK48mBAI4xwC4MQ3pLJwuwRiy3msMzccvvdMynM97xymCnoSS0KeW9uCRMYhPb90N-AKNXvjwXZqpgXhyWYxWQhUm2-XbQFhs0rg6RUZS9xY35XkXq9IvRbtn1I_OvfVGRnGuwuhF-H-HwdDrk02z-54jENSD1nEQtfZBJ4J4iOjNklnqePZoMYTKTnGEW4A9k6NVT0V3cW-Tm9NvJut0B3G9XDUkfvSrwrDnAXIabo7fYqY686Ay34lc3gbQsVyowadQckkRj50Jb8xaP5o57BqHDvYZ76avYf2Tt0uCskMX3vWfmB_I7CtWM9jrhxGxCFUre250hkhQP-zfUqwKduyokwY2EmLMR2e7uE6QTRp1I7wZ1nvFAceJSWFr72VHCwZ_gXWdmin5wndcCIikYXtXAY7OER5izYNltHg_vlO87IRr9yS93cGW_O0FxZw167c1rqmoPw5SM825-7j9LjsAfuf2nK_DfEmT3fx0fXeTtI6kghMVS0WSYMKdpt1B3pU5ozUoVa-jmLK6_UfQfXZaYAAgEEAgMDBwQGBQCOAAECBQYICQoODxAREhOGAwQFCAkKRBEzd6o"
}
}
익명 보유자 바인딩 기능을 사용하는 첫 단계는 보유자가 자신의 holderSecret 값을 생성한 다음 [CFRG-Blind-BBS-Signature]의 커밋먼트 계산 절차에 따라 이 값에 대한 증명이 포함된 커밋먼트를 계산하는 것입니다. 이 절차의 예제 값과 출력은 아래와 같습니다.
{
"holderSecretHex": "8fc6cc3f65db4ba5e3ed63fe9d2bd57a9c7df9c7f6bf2b898b308d5493b07eb6"
}
{
"secretProverBlind": "12901a77b3906af68d9e4214dce887d127b2a51d6311bbe7d087d45737acd2db",
"commitmentWithProof": "ab77a14fddfafc7ae6ea82b0ef6048059225f96c9206903a34c6ec6beba702652e9d64fac1917e372853867d944e4a8059e0c26bc871cac14736e73685cd3006299539b93df64cdf661af2bc6300976528c5092c6dc842abaaa624f2184d3d5b75be0ede9c4822161149ef51a965ddda260e10b9246ecaea020ef952e3b3ed6e724bcb5d1a9c4004f0aea2cba030c27c"
}
holderSecret 및 secretProverBlind는 보유자가 보관하고 비밀로 유지해야 합니다. commitmentWithProof 값은 발급자에게 전달해야 합니다.
익명 보유자 바인딩 옵션에 따라 기본 증명을 추가하는 절차는 발급자가 보유자로부터 commitmentWithProof 값을 받은 다음 [CFRG-Blind-BBS-Signature]의 커밋먼트 검증 절차를 사용하여 해당 값을 검증하는 것부터 시작합니다. 기본 증명 절에서 설명하고 사용한 암호학적 키 자료도 여기에서 사용하며, 아래에 다시 표시합니다.
{
"publicKeyHex": "a4ef1afa3da575496f122b9b78b8c24761531a8a093206ae7c45b80759c168ba4f7a260f9c3367b6c019b4677841104b10665edbe70ba3ebe7d9cfbffbf71eb016f70abfbb163317f372697dc63efd21fc55764f63926a8f02eaea325a2a888f",
"privateKeyHex": "66d36e118832af4c5e28b2dfe1b9577857e57b042a33e06bdea37b811ed09ee0",
"hmacKeyString": "00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF"
}
이 시나리오에서는 운전면허증의 전자 버전을 고려합니다.
{
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://w3id.org/security/data-integrity/v2",
"https://w3id.org/vdl/v1",
"https://w3id.org/vdl/aamva/v1"
],
"type": [
"VerifiableCredential",
"Iso18013DriversLicenseCredential"
],
"issuer": {
"id": "did:key:z6MkjxvA4FNrQUhr8f7xhdQuP1VPzErkcnfxsRaU5oFgy2E5",
"name": "Utopia Department of Motor Vehicles",
"url": "https://dmv.utopia.example/",
"image": "https://dmv.utopia.example/logo.png"
},
"issuanceDate": "2023-11-15T10:00:00-07:00",
"expirationDate": "2028-11-15T12:00:00-06:00",
"name": "Utopia Driver's License",
"image": "data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUg...kSuQmCC",
"description": "A license granting driving privileges in Utopia.",
"credentialSubject": {
"type": "LicensedDriver",
"driversLicense": {
"type": "Iso18013DriversLicense",
"document_number": "542426814",
"family_name": "TURNER",
"given_name": "SUSAN",
"portrait": "data:image/jpeg;base64,/9j/4AAQSkZJR...RSClooooP/2Q==",
"birth_date": "1998-08-28",
"issue_date": "2023-01-15T10:00:00-07:00",
"expiry_date": "2028-08-27T12:00:00-06:00",
"issuing_country": "UA",
"issuing_authority": "UADMV",
"driving_privileges": [
{
"codes": [
{
"code": "D"
}
],
"vehicle_category_code": "D",
"issue_date": "2019-01-01",
"expiry_date": "2027-01-01"
},
{
"codes": [
{
"code": "C"
}
],
"vehicle_category_code": "C",
"issue_date": "2019-01-01",
"expiry_date": "2017-01-01"
}
],
"un_distinguishing_sign": "UTA",
"aamva_aka_suffix": "1ST",
"sex": 2,
"aamva_family_name_truncation": "N",
"aamva_given_name_truncation": "N"
}
}
}
보유자의 개인정보를 보호하기 위해 아래에 제시된 필수 포인터에서 구현된 것처럼 유일한 필수 필드는 "issuer" 및 "expirationDate"입니다.
["/issuer", "/expirationDate"]
서명되지 않은 문서의 변환은 아래와 같이 문서를 정규화하는 것부터 시작합니다.
[
"<did:key:z6MkjxvA4FNrQUhr8f7xhdQuP1VPzErkcnfxsRaU5oFgy2E5> <https://schema.org/image> <https://dmv.utopia.example/logo.png> .\n",
"<did:key:z6MkjxvA4FNrQUhr8f7xhdQuP1VPzErkcnfxsRaU5oFgy2E5> <https://schema.org/name> \"Utopia Department of Motor Vehicles\" .\n",
"<did:key:z6MkjxvA4FNrQUhr8f7xhdQuP1VPzErkcnfxsRaU5oFgy2E5> <https://schema.org/url> <https://dmv.utopia.example/> .\n",
"_:c14n0 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/vdl#Iso18013DriversLicenseCredential> .\n",
"_:c14n0 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://www.w3.org/2018/credentials#VerifiableCredential> .\n",
"_:c14n0 <https://schema.org/description> \"A license granting driving privileges in Utopia.\" .\n",
"_:c14n0 <https://schema.org/image> <data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUg...kSuQmCC> .\n",
"_:c14n0 <https://schema.org/name> \"Utopia Driver's License\" .\n",
"_:c14n0 <https://www.w3.org/2018/credentials#credentialSubject> _:c14n1 .\n",
"_:c14n0 <https://www.w3.org/2018/credentials#expirationDate> \"2028-11-15T12:00:00-06:00\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n",
"_:c14n0 <https://www.w3.org/2018/credentials#issuanceDate> \"2023-11-15T10:00:00-07:00\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n",
"_:c14n0 <https://www.w3.org/2018/credentials#issuer> <did:key:z6MkjxvA4FNrQUhr8f7xhdQuP1VPzErkcnfxsRaU5oFgy2E5> .\n",
"_:c14n1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/vdl#LicensedDriver> .\n",
"_:c14n1 <https://w3id.org/vdl#license> _:c14n2 .\n",
"_:c14n2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/vdl#Iso18013DriversLicense> .\n",
"_:c14n2 <https://w3id.org/vdl#birthDate> \"1998-08-28\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n",
"_:c14n2 <https://w3id.org/vdl#documentNumber> \"542426814\" .\n",
"_:c14n2 <https://w3id.org/vdl#drivingPrivileges> \"[{\\\"codes\\\":[{\\\"code\\\":\\\"D\\\"}],\\\"expiry_date\\\":\\\"2027-01-01\\\",\\\"issue_date\\\":\\\"2019-01-01\\\",\\\"vehicle_category_code\\\":\\\"D\\\"},{\\\"codes\\\":[{\\\"code\\\":\\\"C\\\"}],\\\"expiry_date\\\":\\\"2017-01-01\\\",\\\"issue_date\\\":\\\"2019-01-01\\\",\\\"vehicle_category_code\\\":\\\"C\\\"}]\"^^<http://www.w3.org/1999/02/22-rdf-syntax-ns#JSON> .\n",
"_:c14n2 <https://w3id.org/vdl#expiryDate> \"2028-08-27T12:00:00-06:00\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n",
"_:c14n2 <https://w3id.org/vdl#familyName> \"TURNER\" .\n",
"_:c14n2 <https://w3id.org/vdl#givenName> \"SUSAN\" .\n",
"_:c14n2 <https://w3id.org/vdl#issueDate> \"2023-01-15T10:00:00-07:00\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n",
"_:c14n2 <https://w3id.org/vdl#issuingAuthority> \"UADMV\" .\n",
"_:c14n2 <https://w3id.org/vdl#issuingCountry> \"UA\" .\n",
"_:c14n2 <https://w3id.org/vdl#portrait> <data:image/jpeg;base64,/9j/4AAQSkZJR...RSClooooP/2Q==> .\n",
"_:c14n2 <https://w3id.org/vdl#sex> \"2\"^^<http://www.w3.org/2001/XMLSchema#unsignedInt> .\n",
"_:c14n2 <https://w3id.org/vdl#unDistinguishingSign> \"UTA\" .\n",
"_:c14n2 <https://w3id.org/vdl/aamva#akaSuffix> \"1ST\" .\n",
"_:c14n2 <https://w3id.org/vdl/aamva#familyNameTruncation> \"N\" .\n",
"_:c14n2 <https://w3id.org/vdl/aamva#givenNameTruncation> \"N\" .\n"
]
빈 노드 ID의 순서에서 발생할 수 있는 정보 유출을 방지하기 위해 이를 PRF(즉, HMAC)를 통해 처리하여 아래에 표시된 정규화된 HMAC 문서를 생성합니다. 이는 필수 및 선택적 공개의 대상이 되는 문장들의 순서 있는 목록을 나타내며, 즉 이 목록을 기준으로 문장이 그룹화됩니다.
[
"<did:key:z6MkjxvA4FNrQUhr8f7xhdQuP1VPzErkcnfxsRaU5oFgy2E5> <https://schema.org/image> <https://dmv.utopia.example/logo.png> .\n",
"<did:key:z6MkjxvA4FNrQUhr8f7xhdQuP1VPzErkcnfxsRaU5oFgy2E5> <https://schema.org/name> \"Utopia Department of Motor Vehicles\" .\n",
"<did:key:z6MkjxvA4FNrQUhr8f7xhdQuP1VPzErkcnfxsRaU5oFgy2E5> <https://schema.org/url> <https://dmv.utopia.example/> .\n",
"_:b0 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/vdl#LicensedDriver> .\n",
"_:b0 <https://w3id.org/vdl#license> _:b2 .\n",
"_:b1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/vdl#Iso18013DriversLicenseCredential> .\n",
"_:b1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://www.w3.org/2018/credentials#VerifiableCredential> .\n",
"_:b1 <https://schema.org/description> \"A license granting driving privileges in Utopia.\" .\n",
"_:b1 <https://schema.org/image> <data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUg...kSuQmCC> .\n",
"_:b1 <https://schema.org/name> \"Utopia Driver's License\" .\n",
"_:b1 <https://www.w3.org/2018/credentials#credentialSubject> _:b0 .\n",
"_:b1 <https://www.w3.org/2018/credentials#expirationDate> \"2028-11-15T12:00:00-06:00\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n",
"_:b1 <https://www.w3.org/2018/credentials#issuanceDate> \"2023-11-15T10:00:00-07:00\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n",
"_:b1 <https://www.w3.org/2018/credentials#issuer> <did:key:z6MkjxvA4FNrQUhr8f7xhdQuP1VPzErkcnfxsRaU5oFgy2E5> .\n",
"_:b2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/vdl#Iso18013DriversLicense> .\n",
"_:b2 <https://w3id.org/vdl#birthDate> \"1998-08-28\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n",
"_:b2 <https://w3id.org/vdl#documentNumber> \"542426814\" .\n",
"_:b2 <https://w3id.org/vdl#drivingPrivileges> \"[{\\\"codes\\\":[{\\\"code\\\":\\\"D\\\"}],\\\"expiry_date\\\":\\\"2027-01-01\\\",\\\"issue_date\\\":\\\"2019-01-01\\\",\\\"vehicle_category_code\\\":\\\"D\\\"},{\\\"codes\\\":[{\\\"code\\\":\\\"C\\\"}],\\\"expiry_date\\\":\\\"2017-01-01\\\",\\\"issue_date\\\":\\\"2019-01-01\\\",\\\"vehicle_category_code\\\":\\\"C\\\"}]\"^^<http://www.w3.org/1999/02/22-rdf-syntax-ns#JSON> .\n",
"_:b2 <https://w3id.org/vdl#expiryDate> \"2028-08-27T12:00:00-06:00\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n",
"_:b2 <https://w3id.org/vdl#familyName> \"TURNER\" .\n",
"_:b2 <https://w3id.org/vdl#givenName> \"SUSAN\" .\n",
"_:b2 <https://w3id.org/vdl#issueDate> \"2023-01-15T10:00:00-07:00\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n",
"_:b2 <https://w3id.org/vdl#issuingAuthority> \"UADMV\" .\n",
"_:b2 <https://w3id.org/vdl#issuingCountry> \"UA\" .\n",
"_:b2 <https://w3id.org/vdl#portrait> <data:image/jpeg;base64,/9j/4AAQSkZJR...RSClooooP/2Q==> .\n",
"_:b2 <https://w3id.org/vdl#sex> \"2\"^^<http://www.w3.org/2001/XMLSchema#unsignedInt> .\n",
"_:b2 <https://w3id.org/vdl#unDistinguishingSign> \"UTA\" .\n",
"_:b2 <https://w3id.org/vdl/aamva#akaSuffix> \"1ST\" .\n",
"_:b2 <https://w3id.org/vdl/aamva#familyNameTruncation> \"N\" .\n",
"_:b2 <https://w3id.org/vdl/aamva#givenNameTruncation> \"N\" .\n"
]
위 정규 문서는 필수 및 비필수 문장으로 그룹화됩니다. 선택적 공개 변환 과정의 최종 출력은 아래와 같습니다. 이제 각 문장은 필수 또는 비필수로 그룹화되며, 이전 문장 목록에서의 인덱스가 기억됩니다.
{
"mandatoryPointers": [
"/issuer",
"/expirationDate"
],
"mandatory": {
"dataType": "Map",
"value": [
[
0,
"<did:key:z6MkjxvA4FNrQUhr8f7xhdQuP1VPzErkcnfxsRaU5oFgy2E5> <https://schema.org/image> <https://dmv.utopia.example/logo.png> .\n"
],
[
1,
"<did:key:z6MkjxvA4FNrQUhr8f7xhdQuP1VPzErkcnfxsRaU5oFgy2E5> <https://schema.org/name> \"Utopia Department of Motor Vehicles\" .\n"
],
[
2,
"<did:key:z6MkjxvA4FNrQUhr8f7xhdQuP1VPzErkcnfxsRaU5oFgy2E5> <https://schema.org/url> <https://dmv.utopia.example/> .\n"
],
[
5,
"_:b1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/vdl#Iso18013DriversLicenseCredential> .\n"
],
[
6,
"_:b1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://www.w3.org/2018/credentials#VerifiableCredential> .\n"
],
[
11,
"_:b1 <https://www.w3.org/2018/credentials#expirationDate> \"2028-11-15T12:00:00-06:00\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n"
],
[
13,
"_:b1 <https://www.w3.org/2018/credentials#issuer> <did:key:z6MkjxvA4FNrQUhr8f7xhdQuP1VPzErkcnfxsRaU5oFgy2E5> .\n"
]
]
},
"nonMandatory": {
"dataType": "Map",
"value": [
[
3,
"_:b0 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/vdl#LicensedDriver> .\n"
],
[
4,
"_:b0 <https://w3id.org/vdl#license> _:b2 .\n"
],
[
7,
"_:b1 <https://schema.org/description> \"A license granting driving privileges in Utopia.\" .\n"
],
[
8,
"_:b1 <https://schema.org/image> <data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUg...kSuQmCC> .\n"
],
[
9,
"_:b1 <https://schema.org/name> \"Utopia Driver's License\" .\n"
],
[
10,
"_:b1 <https://www.w3.org/2018/credentials#credentialSubject> _:b0 .\n"
],
[
12,
"_:b1 <https://www.w3.org/2018/credentials#issuanceDate> \"2023-11-15T10:00:00-07:00\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n"
],
[
14,
"_:b2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/vdl#Iso18013DriversLicense> .\n"
],
[
15,
"_:b2 <https://w3id.org/vdl#birthDate> \"1998-08-28\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n"
],
[
16,
"_:b2 <https://w3id.org/vdl#documentNumber> \"542426814\" .\n"
],
[
17,
"_:b2 <https://w3id.org/vdl#drivingPrivileges> \"[{\\\"codes\\\":[{\\\"code\\\":\\\"D\\\"}],\\\"expiry_date\\\":\\\"2027-01-01\\\",\\\"issue_date\\\":\\\"2019-01-01\\\",\\\"vehicle_category_code\\\":\\\"D\\\"},{\\\"codes\\\":[{\\\"code\\\":\\\"C\\\"}],\\\"expiry_date\\\":\\\"2017-01-01\\\",\\\"issue_date\\\":\\\"2019-01-01\\\",\\\"vehicle_category_code\\\":\\\"C\\\"}]\"^^<http://www.w3.org/1999/02/22-rdf-syntax-ns#JSON> .\n"
],
[
18,
"_:b2 <https://w3id.org/vdl#expiryDate> \"2028-08-27T12:00:00-06:00\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n"
],
[
19,
"_:b2 <https://w3id.org/vdl#familyName> \"TURNER\" .\n"
],
[
20,
"_:b2 <https://w3id.org/vdl#givenName> \"SUSAN\" .\n"
],
[
21,
"_:b2 <https://w3id.org/vdl#issueDate> \"2023-01-15T10:00:00-07:00\"^^<http://www.w3.org/2001/XMLSchema#dateTime> .\n"
],
[
22,
"_:b2 <https://w3id.org/vdl#issuingAuthority> \"UADMV\" .\n"
],
[
23,
"_:b2 <https://w3id.org/vdl#issuingCountry> \"UA\" .\n"
],
[
24,
"_:b2 <https://w3id.org/vdl#portrait> <data:image/jpeg;base64,/9j/4AAQSkZJR...RSClooooP/2Q==> .\n"
],
[
25,
"_:b2 <https://w3id.org/vdl#sex> \"2\"^^<http://www.w3.org/2001/XMLSchema#unsignedInt> .\n"
],
[
26,
"_:b2 <https://w3id.org/vdl#unDistinguishingSign> \"UTA\" .\n"
],
[
27,
"_:b2 <https://w3id.org/vdl/aamva#akaSuffix> \"1ST\" .\n"
],
[
28,
"_:b2 <https://w3id.org/vdl/aamva#familyNameTruncation> \"N\" .\n"
],
[
29,
"_:b2 <https://w3id.org/vdl/aamva#givenNameTruncation> \"N\" .\n"
]
]
},
"hmacKeyString": "00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF"
}
다음 단계에서는 기본 증명 구성을 생성하고 이를 정규화합니다. 이는 다음 두 예제에 표시되어 있습니다.
{
"type": "DataIntegrityProof",
"cryptosuite": "bbs-2023",
"created": "2023-08-15T23:36:38Z",
"verificationMethod": "did:key:zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ#zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ",
"proofPurpose": "assertionMethod",
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://w3id.org/security/data-integrity/v2",
"https://w3id.org/vdl/v1",
"https://w3id.org/vdl/aamva/v1"
]
}
_:c14n0 <http://purl.org/dc/terms/created> "2023-08-15T23:36:38Z"^^<http://www.w3.org/2001/XMLSchema#dateTime> . _:c14n0 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://w3id.org/security#DataIntegrityProof> . _:c14n0 <https://w3id.org/security#cryptosuite> "bbs-2023"^^<https://w3id.org/security#cryptosuiteString> . _:c14n0 <https://w3id.org/security#proofPurpose> <https://w3id.org/security#assertionMethod> . _:c14n0 <https://w3id.org/security#verificationMethod> <did:key:zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ#zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ> .
해싱 단계에서는 정규화된 증명 옵션의 SHA-256 해시를 계산하여
proofHash를 생성하고, 모든 필수 N-Quads를 결합한 값의
SHA-256 해시를 계산하여 mandatoryHash를 생성합니다. 이는
아래에 16진수 형식으로 표시되어 있습니다.
{
"proofHash": "3a5bbf25d34d90b18c35cd2357be6a6f42301e94fc9e52f77e93b773c5614bdf",
"mandatoryHash": "8eea112c04d89e133880f96766ebae73693f75f1bbcbbaa473dc06254bdec4fb"
}
이제 [CFRG-Blind-BBS-Signature]의 블라인드 서명 생성 절차를 3.3.2 기본 증명 직렬화 (bbs-2023) 절차에서 사용합니다. 아래에는 계산된 bbsSignature, bbsHeader, publicKey, hmacKey, mandatoryPointers 및 featureOption이 표시되어 있으며, 바이트 데이터는 16진수로 표시됩니다.
{
"bbsSignature": "90eadd70a16661f3d596f3560fc485f7c23ba969eb7c237d481b3596b2f66279bd5a62fa523777eb73b5cfa361885f1a00864b960baf1b92d2b55c0652ebe39024f88e1377911c40bf14cb5fbc808ee1",
"bbsHeader": "3a5bbf25d34d90b18c35cd2357be6a6f42301e94fc9e52f77e93b773c5614bdf8eea112c04d89e133880f96766ebae73693f75f1bbcbbaa473dc06254bdec4fb",
"publicKey": "a4ef1afa3da575496f122b9b78b8c24761531a8a093206ae7c45b80759c168ba4f7a260f9c3367b6c019b4677841104b10665edbe70ba3ebe7d9cfbffbf71eb016f70abfbb163317f372697dc63efd21fc55764f63926a8f02eaea325a2a888f",
"hmacKey": "00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff",
"mandatoryPointers": [
"/issuer",
"/expirationDate"
],
"featureOption": "anonymous_holder_binding"
}
마지막으로 위의 값들을 3.2.1 serializeBaseProofValue 절의 알고리즘에 적용하여 아래에 표시된 서명된 기본 문서에서 사용되는 proofValue를 생성합니다.
{
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://w3id.org/security/data-integrity/v2",
"https://w3id.org/vdl/v1",
"https://w3id.org/vdl/aamva/v1"
],
"type": [
"VerifiableCredential",
"Iso18013DriversLicenseCredential"
],
"issuer": {
"id": "did:key:z6MkjxvA4FNrQUhr8f7xhdQuP1VPzErkcnfxsRaU5oFgy2E5",
"name": "Utopia Department of Motor Vehicles",
"url": "https://dmv.utopia.example/",
"image": "https://dmv.utopia.example/logo.png"
},
"issuanceDate": "2023-11-15T10:00:00-07:00",
"expirationDate": "2028-11-15T12:00:00-06:00",
"name": "Utopia Driver's License",
"image": "data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUg...kSuQmCC",
"description": "A license granting driving privileges in Utopia.",
"credentialSubject": {
"type": "LicensedDriver",
"driversLicense": {
"type": "Iso18013DriversLicense",
"document_number": "542426814",
"family_name": "TURNER",
"given_name": "SUSAN",
"portrait": "data:image/jpeg;base64,/9j/4AAQSkZJR...RSClooooP/2Q==",
"birth_date": "1998-08-28",
"issue_date": "2023-01-15T10:00:00-07:00",
"expiry_date": "2028-08-27T12:00:00-06:00",
"issuing_country": "UA",
"issuing_authority": "UADMV",
"driving_privileges": [
{
"codes": [
{
"code": "D"
}
],
"vehicle_category_code": "D",
"issue_date": "2019-01-01",
"expiry_date": "2027-01-01"
},
{
"codes": [
{
"code": "C"
}
],
"vehicle_category_code": "C",
"issue_date": "2019-01-01",
"expiry_date": "2017-01-01"
}
],
"un_distinguishing_sign": "UTA",
"aamva_aka_suffix": "1ST",
"sex": 2,
"aamva_family_name_truncation": "N",
"aamva_given_name_truncation": "N"
}
},
"proof": {
"type": "DataIntegrityProof",
"cryptosuite": "bbs-2023",
"created": "2023-08-15T23:36:38Z",
"verificationMethod": "did:key:zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ#zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ",
"proofPurpose": "assertionMethod",
"proofValue": "u2V0EhVhQkOrdcKFmYfPVlvNWD8SF98I7qWnrfCN9SBs1lrL2Ynm9WmL6Ujd363O1z6NhiF8aAIZLlguvG5LStVwGUuvjkCT4jhN3kRxAvxTLX7yAjuFYQDpbvyXTTZCxjDXNI1e-am9CMB6U_J5S936Tt3PFYUvfjuoRLATYnhM4gPlnZuuuc2k_dfG7y7qkc9wGJUvexPtYYKTvGvo9pXVJbxIrm3i4wkdhUxqKCTIGrnxFuAdZwWi6T3omD5wzZ7bAGbRneEEQSxBmXtvnC6Pr59nPv_v3HrAW9wq_uxYzF_NyaX3GPv0h_FV2T2OSao8C6uoyWiqIj1ggABEiM0RVZneImaq7zN3u_wARIjNEVWZ3iJmqu8zd7v-CZy9pc3N1ZXJvL2V4cGlyYXRpb25EYXRl"
}
}
절에서 설명했듯이 모의 난수 생성 절차를 사용하고 presentationHeader의 사용을 보여줍니다. 여기에서도 동일한 seed 및 presentationHeader를 사용하며 아래에 다시 표시합니다.
{
"presentationHeaderHex": "113377aa",
"pseudoRandSeedHex": "332e313431353932363533353839373933323338343632363433333833323739"
}
파생 증명을 생성하려면 보유자는 기본 증명을 포함하는 서명된 문서에서 시작합니다. 이 테스트 벡터에 사용할 기본 문서는 위 A.3.2 보유자 바인딩 기본 증명 절의 마지막 예제입니다. 첫 번째 단계는 3.2.2 parseBaseProofValue 절의 알고리즘을 실행하여 아래와 같이 bbsSignature, bbsHeader, publicKey, hmacKey, mandatoryPointers 및 featureOption을 복구하는 것입니다.
{
"bbsSignature": "90eadd70a16661f3d596f3560fc485f7c23ba969eb7c237d481b3596b2f66279bd5a62fa523777eb73b5cfa361885f1a00864b960baf1b92d2b55c0652ebe39024f88e1377911c40bf14cb5fbc808ee1",
"bbsHeader": "3a5bbf25d34d90b18c35cd2357be6a6f42301e94fc9e52f77e93b773c5614bdf8eea112c04d89e133880f96766ebae73693f75f1bbcbbaa473dc06254bdec4fb",
"publicKey": "a4ef1afa3da575496f122b9b78b8c24761531a8a093206ae7c45b80759c168ba4f7a260f9c3367b6c019b4677841104b10665edbe70ba3ebe7d9cfbffbf71eb016f70abfbb163317f372697dc63efd21fc55764f63926a8f02eaea325a2a888f",
"hmacKey": "00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff",
"mandatoryPointers": [
"/issuer",
"/expirationDate"
],
"featureOption": "anonymous_holder_binding"
}
다음으로 보유자는 선택적 공개를 위한 JSON 포인터를 지정하여 추가로 공개하려는 내용이 있다면 무엇인지 검증자에게 알려야 합니다. 이 경우 보유자는 자신의 운전 권한만 공개하려고 합니다.
["/credentialSubject/driversLicense/issuing_country", "/credentialSubject/driversLicense/driving_privileges"]
revealDocument(즉, 최종적으로 서명되어
검증자에게 전송될 서명되지 않은 문서)를 생성하기 위해 선택적 포인터를
필수 포인터에 이어 붙이고, 이 결합된 포인터와 증명을 제거한
문서를 [DI-ECDSA]의
selectJsonLd 알고리즘에 입력하여
아래와 같은 결과를 얻습니다.
{
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://w3id.org/security/data-integrity/v2",
"https://w3id.org/vdl/v1",
"https://w3id.org/vdl/aamva/v1"
],
"type": [
"VerifiableCredential",
"Iso18013DriversLicenseCredential"
],
"issuer": {
"id": "did:key:z6MkjxvA4FNrQUhr8f7xhdQuP1VPzErkcnfxsRaU5oFgy2E5",
"name": "Utopia Department of Motor Vehicles",
"url": "https://dmv.utopia.example/",
"image": "https://dmv.utopia.example/logo.png"
},
"expirationDate": "2028-11-15T12:00:00-06:00",
"credentialSubject": {
"type": "LicensedDriver",
"driversLicense": {
"type": "Iso18013DriversLicense",
"issuing_country": "UA",
"driving_privileges": [
{
"codes": [
{
"code": "D"
}
],
"vehicle_category_code": "D",
"issue_date": "2019-01-01",
"expiry_date": "2027-01-01"
},
{
"codes": [
{
"code": "C"
}
],
"vehicle_category_code": "C",
"issue_date": "2019-01-01",
"expiry_date": "2017-01-01"
}
]
}
}
}
이제 공개된 문서가 어떤 형태인지 알았으므로, 어떤 문장이 필수인지와 선택된 비필수 문장의 인덱스에 관한 적절히 갱신된 정보를 검증자에게 제공해야 합니다. § 4.4.3 CreateDisclosureData를 실행하면 원본 문서를 기준으로 여러 문장 그룹에 관한 풍부한 정보를 얻을 수 있습니다. 아래에서는 이러한 그룹에 대한 인덱스의 일부를 보여 줍니다.
{"combinedIndexes":[0,1,2,3,4,5,6,10,11,13,14,17,23],"mandatoryIndexes":[0,1,2,5,6,11,13],"nonMandatoryIndexes":[3,4,7,8,9,10,12,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29],"selectiveIndexes":[3,4,5,6,10,14,17,23]}
검증자는 필수 문장을 모아 해싱할 수 있어야 합니다. 이를 위해
필수 문장의 인덱스를 공개 문서에서의 위치에 맞게 조정한 목록
(즉, combinedIndexes를 기준으로 한 위치)을 제공하며,
selectiveIndexes는
nonMandatoryIndexes 내 위치를 기준으로 조정해야 합니다. 이러한 "조정된" 인덱스는
아래와 같습니다.
{"adjMandatoryIndexes":[0,1,2,5,6,8,9],"adjSelectiveIndexes":[0,1,5,7,10,16]}
마지막으로 중요한 공개 데이터는 정규화된 빈 노드
ID를 HMAC 기반으로 섞인 ID에 매핑한 labelMap이며, 다음 절에 따라 계산됩니다.
§ 4.4.3 CreateDisclosureData. 이는
아래에 공개 문서를 제외한
나머지 공개 데이터와 함께 표시됩니다. 여기서는
featureOption이
"anonymous_holder_binding"과 같은 경우에 적합한 결과를 보여 주며, 이는
[CFRG-Blind-BBS-Signature]의 블라인드 증명 생성
절차를 사용합니다. blindAdjDisclosedIdxs는
증명 직렬화 프로세스에서 사용되는 최종 BBS 선택적 인덱스 집합이며,
adjSelectiveIndexes를 입력으로 받는 블라인드 BBS 증명 생성 함수에서
가져온다는 점에 유의하십시오.
{"bbsProof":"a19db05cca1237d9965b0bb3197c4962a7fb49c97af131c80ea2d8f949078ff5642acdb33d27d06b97f87ff906a2a23bb0c3dd778572b892785faefdc25811318b0b46e25b8863898b0600701a71c256ee9a7347a1a577fe2e3793b1c0390e4d8f9fff9161074eebba852bcca8089eed76416ac9f178b850e7688c26cfbdee344fa75d9ba2cf22417e3c70be7891f6de040928d4a665005ddbe3b7372ecb87baad726f1535d4600a0198d3a36a17ad673160f8ef5e5fd74f2542b214cc4534ee82b0a90c0501ca9749c8327afcb97e14220f2e516dfc3cb2ed2ffdd3845a25cb64e1a2aa9987bbc122755158d787a2356e28f2affff31b83a2cdff26d5ac1aa72f4d6c40fe96ad230ce09fd4e9b8998357c2964da031e59c3b8c2241da00bc66a6216af7cd02b535577fa3b54bf9a0d230183b03aa145dbabc7fed3710d879c6b8d4273e6e377bed382de985f561ff9b2b3445f29957655600cbd1b29714f52c55ff05bc204203e65bdf6f818e976c690becfed9284b27c2dead96803efad949ffb519b7024530b08b5ed4c8e7472ed20c3866b79658e1b2d2c5b88a60da07614afa4906c73a6e5ad9113282288173e265236fa57d72c97f85c86b43349516f8e2f52f756d43cd2d9cf8c673db404d14007706ebbd4f7b5bbd19cdce9f48b2dac2db7f0f0c3fb18bd8e66e28fe46dafc3961e5945779faf5407190a33ce00efd07222cc142d40cab9b9d591589a30d056dae47d376d3ac5fab3201bbada604dd8e5e292185f38e2bcd58e81b2fec1e7b5754b7b28bd127abc929e950cb75100e94695f1ad13c09c1d394664029b66bdd49304df3ae1e2a90a6309f07c47555ccaea9cd17d80eaad6b7c29e9335a69338446ff666ac5802cfe36057c449d392bda99d2657fb8b6cf02d7ce4d9dccd8e97033accc5c10f092ec7bf0b3c0b2afc64a1a429d81cc485388f6f390dd97f648c3712ee0b93a7e96b268437e6e3537fb7918cee2a4ac3f895c7945988d7d3880238b8cf6062da171aa87545cf62072b20e698eb4ac12450c0b95a77e946fada8d46102abfa9a5a12d2a71380dedb51e2a57c97514813c17ea93e6ca19077c2a2511bf8fd158c4ed7361590b040915a3cb76f323300111303d8dd31c55474d514209bf01ed6639d4d81a1b30be54444e523e2ddef9a0a6bfe792d3037944aec29154c02bb79d09bd53856797dceb6c599f4103ff7f13dfdb8b2d18477832e5fe21","labelMap":{"dataType":"Map","value":[["c14n0","b1"],["c14n1","b2"],["c14n2","b0"]]},"mandatoryIndexes":[0,1,2,5,6,8,9],"adjSelectiveIndexes":[0,1,5,7,10,16],"presentationHeader":{"0":17,"1":51,"2":119,"3":170},"featureOption":"anonymous_holder_binding","lengthBBSMessages":23}
마지막으로 위의 공개 데이터를 다음 절의 알고리즘과 함께 사용하면 3.2.3 serializeDerivedProofValue, 아래에 표시된 서명된 파생 (공개) 문서를 얻습니다.
{
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://w3id.org/security/data-integrity/v2",
"https://w3id.org/vdl/v1",
"https://w3id.org/vdl/aamva/v1"
],
"type": [
"VerifiableCredential",
"Iso18013DriversLicenseCredential"
],
"issuer": {
"id": "did:key:z6MkjxvA4FNrQUhr8f7xhdQuP1VPzErkcnfxsRaU5oFgy2E5",
"name": "Utopia Department of Motor Vehicles",
"url": "https://dmv.utopia.example/",
"image": "https://dmv.utopia.example/logo.png"
},
"expirationDate": "2028-11-15T12:00:00-06:00",
"credentialSubject": {
"type": "LicensedDriver",
"driversLicense": {
"type": "Iso18013DriversLicense",
"issuing_country": "UA",
"driving_privileges": [
{
"codes": [
{
"code": "D"
}
],
"vehicle_category_code": "D",
"issue_date": "2019-01-01",
"expiry_date": "2027-01-01"
},
{
"codes": [
{
"code": "C"
}
],
"vehicle_category_code": "C",
"issue_date": "2019-01-01",
"expiry_date": "2017-01-01"
}
]
}
},
"proof": {
"type": "DataIntegrityProof",
"cryptosuite": "bbs-2023",
"created": "2023-08-15T23:36:38Z",
"verificationMethod": "did:key:zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ#zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ",
"proofPurpose": "assertionMethod",
"proofValue": "u2V0FhlkDcKGdsFzKEjfZllsLsxl8SWKn-0nJevExyA6i2PlJB4_1ZCrNsz0n0GuX-H_5BqKiO7DD3XeFcriSeF-u_cJYETGLC0biW4hjiYsGAHAaccJW7ppzR6Gld_4uN5OxwDkOTY-f_5FhB07ruoUrzKgInu12QWrJ8Xi4UOdojCbPve40T6ddm6LPIkF-PHC-eJH23gQJKNSmZQBd2-O3Ny7Lh7qtcm8VNdRgCgGY06NqF61nMWD4715f108lQrIUzEU07oKwqQwFAcqXScgyevy5fhQiDy5Rbfw8su0v_dOEWiXLZOGiqpmHu8EidVFY14eiNW4o8q__8xuDos3_JtWsGqcvTWxA_patIwzgn9TpuJmDV8KWTaAx5Zw7jCJB2gC8ZqYhavfNArU1V3-jtUv5oNIwGDsDqhRdurx_7TcQ2HnGuNQnPm43e-04LemF9WH_mys0RfKZV2VWAMvRspcU9SxV_wW8IEID5lvfb4GOl2xpC-z-2ShLJ8LerZaAPvrZSf-1GbcCRTCwi17UyOdHLtIMOGa3lljhstLFuIpg2gdhSvpJBsc6blrZETKCKIFz4mUjb6V9csl_hchrQzSVFvji9S91bUPNLZz4xnPbQE0UAHcG671Pe1u9Gc3On0iy2sLbfw8MP7GL2OZuKP5G2vw5YeWUV3n69UBxkKM84A79ByIswULUDKubnVkViaMNBW2uR9N206xfqzIBu62mBN2OXikhhfOOK81Y6Bsv7B57V1S3sovRJ6vJKelQy3UQDpRpXxrRPAnB05RmQCm2a91JME3zrh4qkKYwnwfEdVXMrqnNF9gOqta3wp6TNaaTOERv9masWALP42BXxEnTkr2pnSZX-4ts8C185NnczY6XAzrMxcEPCS7Hvws8Cyr8ZKGkKdgcxIU4j285Ddl_ZIw3Eu4Lk6fpayaEN-bjU3-3kYzuKkrD-JXHlFmI19OIAji4z2Bi2hcaqHVFz2IHKyDmmOtKwSRQwLlad-lG-tqNRhAqv6mloS0qcTgN7bUeKlfJdRSBPBfqk-bKGQd8KiURv4_RWMTtc2FZCwQJFaPLdvMjMAERMD2N0xxVR01RQgm_Ae1mOdTYGhswvlRETlI-Ld75oKa_55LTA3lErsKRVMArt50JvVOFZ5fc62xZn0ED_38T39uLLRhHeDLl_iGjAAEBAgIAhwABAgUGCAmGAAEFBwoQRBEzd6oX"
}
}
자격 증명 바인딩 가명 기능을 사용하는 첫 단계는 보유자가 자신의 비밀 prover_nym 값을 생성한 다음 [CFRG-Pseudonym-BBS-Signature]의 "Commitment" 연산에 따라 이 값에 대한 증명이 포함된 커밋먼트를 계산하는 것입니다. 이 절차의 예제 값과 출력은 아래와 같습니다.
{
"proverNymHex": "5e2087638f71057ef108f83923189a71cea1f7c4b4ef69afb473c9a7074ddf49"
}
{
"secretProverBlind": "2df3cd3d451b21069b72269f9984df449219c41273b19b1a8487d836fbb8baa1",
"commitmentWithProof": "a80f61f9470cb8ab88644fbef3616eaf5d3b147c4dc1dcad810148a5f2e73186cb3ffa27ea55728a6df470d0c3928be1408b95f5d261cee4d66992ecacf5ca2d6348c33bb7f90c2cef513cdc88be536550e9701d9a466320f49ce097551f8097317c530e2b80710748362b03f5a74280669c00eb29145eb3ec51975d8189fdf2c810d7fadefe36f93b0d2068a494175c"
}
prover_nym 및 secretProverBlind는 보유자가 보관하고 비밀로 유지해야 합니다. commitmentWithProof 값은 발급자에게 전달해야 합니다.
가명 기능 옵션에 따라 기본 증명을 추가하는 절차는 발급자가 보유자로부터 commitmentWithProof 값을 받고 signer_nym_entropy에 사용할 암호학적 난수 값을 생성하는 것부터 시작합니다.
{
"signerNymEntropyHex": "25555cf635188a1c33989056f5129e6ab4be0e7c5cc588c48d308e0254eed140"
}
이 예제에서는 예제 27에 표시된 것과 동일한 키 자료, 예제 50에 표시된 것과 동일한 서명되지 않은 문서, 그리고 예제 51에 표시된 것과 동일한 필수 포인터를 사용합니다. 그 결과 예제 52와 동일한 정규 문서, 예제 53과 동일한 정규 HMAC 문서, 그리고 예제 54와 동일한 "기본 변환 추가" 결과가 생성됩니다.
이 예제에서는 예제 55와 동일한 증명 구성을 사용합니다. 그 결과 예제 56과 동일한 정규 기본 증명이 생성됩니다. 이를 위의 가정과 결합하면 예제 57과 동일한 기본 해시가 생성됩니다.
featureOption이 "pseudonym"과 같으므로
3.3.2
기본 증명 직렬화 (bbs-2023) 절의 절차는
아래와 같은 출력을 생성합니다. 여기서는
[CFRG-Pseudonym-BBS-Signature]의 서명 생성
알고리즘을 사용합니다. signer_nym_entropy 및 featureOption 값이 포함되어 있다는 점에 유의하십시오.
이 값들은 보유자에게 전달해야 합니다.
{
"bbsSignature": "b9389149bab1b5a6032c20781732105a5cbc209592e712e182eec5c055f2072877683dee2949af32290d350ed9e9ffa246f65b8c3f6f199c4d29009d2ce6dff374ed4f22f2f9a7e12dc3c342e8c18107",
"bbsHeader": "3a5bbf25d34d90b18c35cd2357be6a6f42301e94fc9e52f77e93b773c5614bdf8eea112c04d89e133880f96766ebae73693f75f1bbcbbaa473dc06254bdec4fb",
"publicKey": "a4ef1afa3da575496f122b9b78b8c24761531a8a093206ae7c45b80759c168ba4f7a260f9c3367b6c019b4677841104b10665edbe70ba3ebe7d9cfbffbf71eb016f70abfbb163317f372697dc63efd21fc55764f63926a8f02eaea325a2a888f",
"hmacKey": "00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff",
"mandatoryPointers": [
"/issuer",
"/expirationDate"
],
"signerNymEntropyHex": "25555cf635188a1c33989056f5129e6ab4be0e7c5cc588c48d308e0254eed140",
"featureOption": "pseudonym"
}
마지막으로 위의 값들을
3.2.1
serializeBaseProofValue 절의 알고리즘에 적용하여
아래에 표시된 서명된 기본 문서에서 사용되는 proofValue를
생성합니다.
{
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://w3id.org/security/data-integrity/v2",
"https://w3id.org/vdl/v1",
"https://w3id.org/vdl/aamva/v1"
],
"type": [
"VerifiableCredential",
"Iso18013DriversLicenseCredential"
],
"issuer": {
"id": "did:key:z6MkjxvA4FNrQUhr8f7xhdQuP1VPzErkcnfxsRaU5oFgy2E5",
"name": "Utopia Department of Motor Vehicles",
"url": "https://dmv.utopia.example/",
"image": "https://dmv.utopia.example/logo.png"
},
"issuanceDate": "2023-11-15T10:00:00-07:00",
"expirationDate": "2028-11-15T12:00:00-06:00",
"name": "Utopia Driver's License",
"image": "data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUg...kSuQmCC",
"description": "A license granting driving privileges in Utopia.",
"credentialSubject": {
"type": "LicensedDriver",
"driversLicense": {
"type": "Iso18013DriversLicense",
"document_number": "542426814",
"family_name": "TURNER",
"given_name": "SUSAN",
"portrait": "data:image/jpeg;base64,/9j/4AAQSkZJR...RSClooooP/2Q==",
"birth_date": "1998-08-28",
"issue_date": "2023-01-15T10:00:00-07:00",
"expiry_date": "2028-08-27T12:00:00-06:00",
"issuing_country": "UA",
"issuing_authority": "UADMV",
"driving_privileges": [
{
"codes": [
{
"code": "D"
}
],
"vehicle_category_code": "D",
"issue_date": "2019-01-01",
"expiry_date": "2027-01-01"
},
{
"codes": [
{
"code": "C"
}
],
"vehicle_category_code": "C",
"issue_date": "2019-01-01",
"expiry_date": "2017-01-01"
}
],
"un_distinguishing_sign": "UTA",
"aamva_aka_suffix": "1ST",
"sex": 2,
"aamva_family_name_truncation": "N",
"aamva_given_name_truncation": "N"
}
},
"proof": {
"type": "DataIntegrityProof",
"cryptosuite": "bbs-2023",
"created": "2023-08-15T23:36:38Z",
"verificationMethod": "did:key:zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ#zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ",
"proofPurpose": "assertionMethod",
"proofValue": "u2V0IhlhQuTiRSbqxtaYDLCB4FzIQWly8IJWS5xLhgu7FwFXyByh3aD3uKUmvMikNNQ7Z6f-iRvZbjD9vGZxNKQCdLObf83TtTyLy-afhLcPDQujBgQdYQDpbvyXTTZCxjDXNI1e-am9CMB6U_J5S936Tt3PFYUvfjuoRLATYnhM4gPlnZuuuc2k_dfG7y7qkc9wGJUvexPtYYKTvGvo9pXVJbxIrm3i4wkdhUxqKCTIGrnxFuAdZwWi6T3omD5wzZ7bAGbRneEEQSxBmXtvnC6Pr59nPv_v3HrAW9wq_uxYzF_NyaX3GPv0h_FV2T2OSao8C6uoyWiqIj1ggABEiM0RVZneImaq7zN3u_wARIjNEVWZ3iJmqu8zd7v-CZy9pc3N1ZXJvL2V4cGlyYXRpb25EYXRlwlggJVVc9jUYihwzmJBW9RKearS-DnxcxYjEjTCOAlTu0UA"
}
}
A.1.2 파생 증명 절에서 설명했듯이 presentationHeader의 사용을 보여주기 위해 모의 난수 생성 절차를 사용했습니다. 예제 19에 제시된 것과 동일한 seed 및 presentationHeader를 여기에서 사용합니다.
파생 증명을 생성하려면 보유자는 기본 증명을 포함하는 서명된 문서에서 시작합니다. 이 테스트 벡터에 사용할 기본 문서는 위 예제 72에서 가져옵니다. 첫 번째 단계는 3.2.2 parseBaseProofValue 절의 알고리즘을 실행하여 아래와 같이 bbsSignature, bbsHeader, publicKey, hmacKey, mandatoryPointers, signer_nym_entropy 및 featureOption을 복구하는 것입니다.
{
"bbsSignature": "b9389149bab1b5a6032c20781732105a5cbc209592e712e182eec5c055f2072877683dee2949af32290d350ed9e9ffa246f65b8c3f6f199c4d29009d2ce6dff374ed4f22f2f9a7e12dc3c342e8c18107",
"bbsHeader": "3a5bbf25d34d90b18c35cd2357be6a6f42301e94fc9e52f77e93b773c5614bdf8eea112c04d89e133880f96766ebae73693f75f1bbcbbaa473dc06254bdec4fb",
"publicKey": "a4ef1afa3da575496f122b9b78b8c24761531a8a093206ae7c45b80759c168ba4f7a260f9c3367b6c019b4677841104b10665edbe70ba3ebe7d9cfbffbf71eb016f70abfbb163317f372697dc63efd21fc55764f63926a8f02eaea325a2a888f",
"hmacKey": "00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff",
"mandatoryPointers": [
"/issuer",
"/expirationDate"
],
"signerNymEntropy": "25555cf635188a1c33989056f5129e6ab4be0e7c5cc588c48d308e0254eed140",
"featureOption": "pseudonym"
}
다음으로 보유자는 [CFRG-Pseudonym-BBS-Signature]의 "Verification and Finalization" 연산을 사용하여 서명을 검증하는 동시에 nym_secret 값을 계산합니다. 이 연산은 다른 값들과 함께 prover_nym, signer_nym_entropy 및 secret_prover_blind 값을 사용합니다.
{
"nymSecretHex": "f883d069aec1252f167b0880e8960d72fa2623e11b6967541a457aa5c3cb088"
}
다음으로 보유자는 선택적 공개를 위한 JSON 포인터를 지정하여 검증자에게 공개하려는 비필수 문장이 있다면 무엇인지 나타내야 합니다. 이 경우 보유자는 예제 62에 제시된 것과 동일한 정보를 공개합니다. 그 결과 예제 63에 표시된 것과 동일한 revealDocument가 생성됩니다.
§ 4.4.3 CreateDisclosureData를 실행하면 예제 64에 표시된 것과 동일한 파생 그룹 인덱스 정보와 예제 65에 표시된 것과 동일한 조정된 필수 및 선택적 인덱스를 얻습니다.
3.2.3 serializeDerivedProofValue 내에서, 에 표시된 것과 동일한 verfifier_id를 기반으로 pseudonym을 계산합니다. § 4.4.3 CreateDisclosureData의 최종 출력은 아래에 표시되어 있습니다. featureOption과 계산된 pseudonym 값이 포함되어 있다는 점에 유의하십시오.
{
"bbsProof":"b394693d54d67937aae0e4175ecf4331200c23470171188ac5513b30d27d9bd2e06173d44e1aca7c743ba30b3f59af0595965bf8256437bce6bef824fe243183af6aa14a1e8224ed7e4eeb16445594df13a46e75d8dfbae0a3e2e1e0871260e68f71de7be4309eb53523a446b8189446b8d5c60892bdd855b5067e0433b46d5b9ffc4dc54b712ff97ec9d7c44cff648929d826bf9e3a7f873c9bcd07c6a3747fc6befceaf892c4d8d38d385c19c399ab342a76c000a3ff9050fa9223e20acfdf4404f43605a24c44622ebcaaf144b161226a6cbe7c08474f9fb80a736be3a818e4e62aa738e701007871859bea36e062324ff3afd8670a5de8b69911fae58aa40e48e29a046c37b9f9cc3868c30482d2339746955c3deaf6f1d4c8cf8be8e503f3ea4715d11e385eb7ed9de6379b7de8436a4e89cf4427d53358b1882e27c6e1e3ba2e81cf10fbc792cf3461a0fdd63f35a151b8c8350505a9b6d612e9adc1dca11b2698a3d0a9f0df6e9bc0ece7aa462afab02d93a87fd5bebb0eee058770c81c5f2fe6eeefcb0a657d9f116b96e2b04b4cc7f4baad4fe784bd9563aea20272138f2dbe94a5e25d30633b5f83eac4b42af25f144bddb631738bf3d54206e8d8b5172c8d52d3c272f799b782c73d480e1289e262ddbb70ab29491cf85a8428c4672437677407524a6dacb53332565dab5d056dbc5451becb123f91d173f6a7c785b7d9f19c43864a785bd941db248322539a097e9ac06244308a3b8df88b5213724cf09715b09e06425448c400680b943ba4711f14a719920b06ec2c6aff908ecf4f5793afd233d270a5ef92131606035517a89e4118dc65dbeb9051f92797036f54f8400910fa56cdd7b87b122e39e41233ea493239fab55c4c836a0a38732a68e6a9f9e11d32b991599e19edbb386f0d364b91e10dd9bf82898f79e90045a0c4987a0cf365d37d8380539a794284841c50c83f2bc3ee9cf7432f44dbfca897ff99feabf224e51137313630c5000d39429d9ea69a2a8237fe3a1857121c14ebb00d57b90db39e2e11bfa37858187d183027c45e317a72e5334681de26788e3176bd48d5761d54c1f2af0a6c3549a0de05b21d0a066c732a540072ae7676b867027b18323e08fcbfaf38ec22aeccd3375bb7b6965d9f6ab3ac4adc2a0700a4bc82fe58afbdd035af48fb85fcd8bf14f81d5ca3f2626be8962cbea13da31ff3cc6c6ebfeeef42f25708af872a14019f83",
"labelMap":{"dataType":"Map","value":[["c14n0","b1"],["c14n1","b2"],["c14n2","b0"]]},
"mandatoryIndexes":[0,1,2,5,6,8,9],
"adjSelectiveIndexes":[0,1,5,7,10,16],
"presentationHeader":{"0":17,"1":51,"2":119,"3":170},
"pseudonym":"838607ff2c8dcb2a0740ef13c2c87418efb57559243232a69daf1e294dd092af833ad4df1e99e0034c737b932916f378",
"featureOption":"pseudonym",
"lengthBBSMessages":23
}
마지막으로 위의 공개 데이터를 다음 절의 알고리즘과 함께 사용하면 3.2.3 serializeDerivedProofValue, 아래에 표시된 서명된 파생(공개) 문서를 얻습니다.
{
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://w3id.org/security/data-integrity/v2",
"https://w3id.org/vdl/v1",
"https://w3id.org/vdl/aamva/v1"
],
"type": [
"VerifiableCredential",
"Iso18013DriversLicenseCredential"
],
"issuer": {
"id": "did:key:z6MkjxvA4FNrQUhr8f7xhdQuP1VPzErkcnfxsRaU5oFgy2E5",
"name": "Utopia Department of Motor Vehicles",
"url": "https://dmv.utopia.example/",
"image": "https://dmv.utopia.example/logo.png"
},
"expirationDate": "2028-11-15T12:00:00-06:00",
"credentialSubject": {
"type": "LicensedDriver",
"driversLicense": {
"type": "Iso18013DriversLicense",
"issuing_country": "UA",
"driving_privileges": [
{
"codes": [
{
"code": "D"
}
],
"vehicle_category_code": "D",
"issue_date": "2019-01-01",
"expiry_date": "2027-01-01"
},
{
"codes": [
{
"code": "C"
}
],
"vehicle_category_code": "C",
"issue_date": "2019-01-01",
"expiry_date": "2017-01-01"
}
]
}
},
"proof": {
"type": "DataIntegrityProof",
"cryptosuite": "bbs-2023",
"created": "2023-08-15T23:36:38Z",
"verificationMethod": "did:key:zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ#zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ",
"proofPurpose": "assertionMethod",
"proofValue": "u2V0Jh1kDcLOUaT1U1nk3quDkF17PQzEgDCNHAXEYisVROzDSfZvS4GFz1E4aynx0O6MLP1mvBZWWW_glZDe85r74JP4kMYOvaqFKHoIk7X5O6xZEVZTfE6RuddjfuuCj4uHghxJg5o9x3nvkMJ61NSOkRrgYlEa41cYIkr3YVbUGfgQztG1bn_xNxUtxL_l-ydfETP9kiSnYJr-eOn-HPJvNB8ajdH_Gvvzq-JLE2NONOFwZw5mrNCp2wACj_5BQ-pIj4grP30QE9DYFokxEYi68qvFEsWEiamy-fAhHT5-4CnNr46gY5OYqpzjnAQB4cYWb6jbgYjJP86_YZwpd6LaZEfrliqQOSOKaBGw3ufnMOGjDBILSM5dGlVw96vbx1MjPi-jlA_PqRxXRHjhet-2d5jebfehDak6Jz0Qn1TNYsYguJ8bh47ougc8Q-8eSzzRhoP3WPzWhUbjINQUFqbbWEumtwdyhGyaYo9Cp8N9um8Ds56pGKvqwLZOof9W-uw7uBYdwyBxfL-bu78sKZX2fEWuW4rBLTMf0uq1P54S9lWOuogJyE48tvpSl4l0wYztfg-rEtCryXxRL3bYxc4vz1UIG6Ni1FyyNUtPCcveZt4LHPUgOEoniYt27cKspSRz4WoQoxGckN2d0B1JKbay1MzJWXatdBW28VFG-yxI_kdFz9qfHhbfZ8ZxDhkp4W9lB2ySDIlOaCX6awGJEMIo7jfiLUhNyTPCXFbCeBkJUSMQAaAuUO6RxHxSnGZILBuwsav-Qjs9PV5Ov0jPScKXvkhMWBgNVF6ieQRjcZdvrkFH5J5cDb1T4QAkQ-lbN17h7Ei455BIz6kkyOfq1XEyDago4cypo5qn54R0yuZFZnhntuzhvDTZLkeEN2b-CiY956QBFoMSYegzzZdN9g4BTmnlChIQcUMg_K8PunPdDL0Tb_KiX_5n-q_Ik5RE3MTYwxQANOUKdnqaaKoI3_joYVxIcFOuwDVe5DbOeLhG_o3hYGH0YMCfEXjF6cuUzRoHeJniOMXa9SNV2HVTB8q8KbDVJoN4Fsh0KBmxzKlQAcq52drhnAnsYMj4I_L-vOOwirszTN1u3tpZdn2qzrErcKgcApLyC_livvdA1r0j7hfzYvxT4HVyj8mJr6JYsvqE9ox_zzGxuv-7vQvJXCK-HKhQBn4OjAAEBAgIAhwABAgUGCAmGAAEFBwoQRBEzd6pYMIOGB_8sjcsqB0DvE8LIdBjvtXVZJDIypp2vHilN0JKvgzrU3x6Z4ANMc3uTKRbzeBc"
}
}
보유자 바인딩 및 가명 기능을 사용하는 첫 단계는 보유자가 자신의 holder_secret 및 prover_nym 값을 생성한 다음 [CFRG-Pseudonym-BBS-Signature]의 "Commitment" 연산에 따라 이러한 값에 대한 증명이 포함된 커밋먼트를 계산하는 것입니다. 이 절차의 예제 값과 출력은 아래와 같습니다.
{
"holderSecretHex": "8fc6cc3f65db4ba5e3ed63fe9d2bd57a9c7df9c7f6bf2b898b308d5493b07eb6"
}
{
"proverNymHex": "5e2087638f71057ef108f83923189a71cea1f7c4b4ef69afb473c9a7074ddf49"
}
{
"secretProverBlind": "0d215067232c77c94a7572eb80794592090da8aff35cca53d2d528d059e70fce",
"commitmentWithProof": "ab72f3e6d7a4185d100ede6ce7dde1c69db9a2128ad11d1b6991a018c340ca2672d7be636f153398be50f44ee434edf14322dd115f7527e770a0f0c41d8aeb2088d004f2703548db6ce15e2505368a1f686f20702aa9ff46bce301330ea0c4c16ef4d8bbf624064a60df3a563142d7b236cad6cf6bcf1f3694d0bf4c2b5ffce55bb26abc05e31f9aaf8b60674fefe02666f89c150c479694f4a89a9088b28a1e6e2cf0c2caaa01810d2e3a52853f3a2a"
}
holder_secret, prover_nym 및 secretProverBlind는 보유자가 보관하고 비밀로 유지해야 합니다. commitmentWithProof 값은 발급자에게 전달해야 합니다.
가명 기능 옵션에 따라 기본 증명을 추가하는 절차는 발급자가 보유자로부터 commitmentWithProof 값을 받고 signer_nym_entropy에 사용할 암호학적 난수 값을 생성하는 것부터 시작합니다.
{
"signerNymEntropyHex": "25555cf635188a1c33989056f5129e6ab4be0e7c5cc588c48d308e0254eed140"
}
이 예제에서는 예제 27에 표시된 것과 동일한 키 자료, 예제 50에 표시된 것과 동일한 서명되지 않은 문서 및 예제 51에 표시된 것과 동일한 필수 포인터를 사용합니다. 그 결과 예제 52에 표시된 것과 동일한 정규 문서, 예제 53에 표시된 것과 동일한 정규 HMAC 문서, 그리고 예제 54에 표시된 것과 동일한 "기본 변환 추가" 결과가 생성됩니다.
이 예제에서는 예제 55와 동일한 증명 구성을 사용합니다. 그 결과 예제 56과 동일한 정규 기본 증명이 생성됩니다. 이를 위의 가정과 결합하면 예제 57과 동일한 기본 해시가 생성됩니다.
featureOption이 "holder_binding_pseudonym"과 같으므로
3.3.2
기본 증명 직렬화 (bbs-2023) 절의 절차는
아래와 같은 출력을 생성합니다. 여기서는
[CFRG-Pseudonym-BBS-Signature]의 서명 생성
알고리즘을 사용합니다. signer_nym_entropy 및 featureOption 값이 포함되어 있다는 점에
유의하십시오. 이 값들은 보유자에게 전달해야 합니다.
{
"bbsSignature": "9251f497cb002c19f959a760fa24c5e961df9cb8ff5fbaaef14f2b7f1f41649990c30bd8c1d373e878a5d120123d658a326141275eee7833352d611cc1c05175c9c0f0ddeb0fdec09ad1bfad8796e410",
"bbsHeader": "3a5bbf25d34d90b18c35cd2357be6a6f42301e94fc9e52f77e93b773c5614bdf8eea112c04d89e133880f96766ebae73693f75f1bbcbbaa473dc06254bdec4fb",
"publicKey": "a4ef1afa3da575496f122b9b78b8c24761531a8a093206ae7c45b80759c168ba4f7a260f9c3367b6c019b4677841104b10665edbe70ba3ebe7d9cfbffbf71eb016f70abfbb163317f372697dc63efd21fc55764f63926a8f02eaea325a2a888f",
"hmacKey": "00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff",
"mandatoryPointers": [
"/issuer",
"/expirationDate"
],
"signerNymEntropyHex": "25555cf635188a1c33989056f5129e6ab4be0e7c5cc588c48d308e0254eed140",
"featureOption": "holder_binding_pseudonym"
}
마지막으로 위의 값들을
3.2.1
serializeBaseProofValue 절의 알고리즘에 적용하여,
아래에 표시된 서명된 기본 문서에서 사용되는 proofValue를
생성합니다.
{
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://w3id.org/security/data-integrity/v2",
"https://w3id.org/vdl/v1",
"https://w3id.org/vdl/aamva/v1"
],
"type": [
"VerifiableCredential",
"Iso18013DriversLicenseCredential"
],
"issuer": {
"id": "did:key:z6MkjxvA4FNrQUhr8f7xhdQuP1VPzErkcnfxsRaU5oFgy2E5",
"name": "유토피아 자동차 관리국",
"url": "https://dmv.utopia.example/",
"image": "https://dmv.utopia.example/logo.png"
},
"issuanceDate": "2023-11-15T10:00:00-07:00",
"expirationDate": "2028-11-15T12:00:00-06:00",
"name": "유토피아 운전면허증",
"image": "data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUg...kSuQmCC",
"description": "유토피아에서 운전 권한을 부여하는 면허증입니다.",
"credentialSubject": {
"type": "LicensedDriver",
"driversLicense": {
"type": "Iso18013DriversLicense",
"document_number": "542426814",
"family_name": "TURNER",
"given_name": "SUSAN",
"portrait": "data:image/jpeg;base64,/9j/4AAQSkZJR...RSClooooP/2Q==",
"birth_date": "1998-08-28",
"issue_date": "2023-01-15T10:00:00-07:00",
"expiry_date": "2028-08-27T12:00:00-06:00",
"issuing_country": "UA",
"issuing_authority": "UADMV",
"driving_privileges": [
{
"codes": [
{
"code": "D"
}
],
"vehicle_category_code": "D",
"issue_date": "2019-01-01",
"expiry_date": "2027-01-01"
},
{
"codes": [
{
"code": "C"
}
],
"vehicle_category_code": "C",
"issue_date": "2019-01-01",
"expiry_date": "2017-01-01"
}
],
"un_distinguishing_sign": "UTA",
"aamva_aka_suffix": "1ST",
"sex": 2,
"aamva_family_name_truncation": "N",
"aamva_given_name_truncation": "N"
}
},
"proof": {
"type": "DataIntegrityProof",
"cryptosuite": "bbs-2023",
"created": "2023-08-15T23:36:38Z",
"verificationMethod": "did:key:zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ#zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ",
"proofPurpose": "assertionMethod",
"proofValue": "u2V0IhlhQklH0l8sALBn5Wadg-iTF6WHfnLj_X7qu8U8rfx9BZJmQwwvYwdNz6Hil0SASPWWKMmFBJ17ueDM1LWEcwcBRdcnA8N3rD97AmtG_rYeW5BBYQDpbvyXTTZCxjDXNI1e-am9CMB6U_J5S936Tt3PFYUvfjuoRLATYnhM4gPlnZuuuc2k_dfG7y7qkc9wGJUvexPtYYKTvGvo9pXVJbxIrm3i4wkdhUxqKCTIGrnxFuAdZwWi6T3omD5wzZ7bAGbRneEEQSxBmXtvnC6Pr59nPv_v3HrAW9wq_uxYzF_NyaX3GPv0h_FV2T2OSao8C6uoyWiqIj1ggABEiM0RVZneImaq7zN3u_wARIjNEVWZ3iJmqu8zd7v-CZy9pc3N1ZXJvL2V4cGlyYXRpb25EYXRlwlggJVVc9jUYihwzmJBW9RKearS-DnxcxYjEjTCOAlTu0UA"
}
}
A.1.2 파생 증명 절에서 설명했듯이, 모의 난수 생성 절차를 사용하고 presentationHeader의 사용을 보여줍니다. 예제 19에 제시된 것과 동일한 seed 및 presentationHeader를 여기에서 사용합니다.
파생 증명을 생성하려면 보유자는 기본 증명을 포함하는 서명된 문서에서 시작합니다. 이 테스트 벡터에 사용할 기본 문서는 위 예제 72에서 가져옵니다. 첫 번째 단계는 3.2.2 parseBaseProofValue 절의 알고리즘을 실행하여 아래와 같이 bbsSignature, bbsHeader, publicKey, hmacKey, mandatoryPointers, signer_nym_entropy 및 featureOption을 복구하는 것입니다.
{
"bbsSignature": "9251f497cb002c19f959a760fa24c5e961df9cb8ff5fbaaef14f2b7f1f41649990c30bd8c1d373e878a5d120123d658a326141275eee7833352d611cc1c05175c9c0f0ddeb0fdec09ad1bfad8796e410",
"bbsHeader": "3a5bbf25d34d90b18c35cd2357be6a6f42301e94fc9e52f77e93b773c5614bdf8eea112c04d89e133880f96766ebae73693f75f1bbcbbaa473dc06254bdec4fb",
"publicKey": "a4ef1afa3da575496f122b9b78b8c24761531a8a093206ae7c45b80759c168ba4f7a260f9c3367b6c019b4677841104b10665edbe70ba3ebe7d9cfbffbf71eb016f70abfbb163317f372697dc63efd21fc55764f63926a8f02eaea325a2a888f",
"hmacKey": "00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff",
"mandatoryPointers": [
"/issuer",
"/expirationDate"
],
"signerNymEntropy": "25555cf635188a1c33989056f5129e6ab4be0e7c5cc588c48d308e0254eed140",
"featureOption": "holder_binding_pseudonym"
}
다음으로 보유자는 [CFRG-Pseudonym-BBS-Signature]의 "Verification and Finalization" 연산을 사용하여 서명을 검증하는 동시에 nym_secret 값을 계산합니다. 이 연산은 다른 값들과 함께 holder_secret, prover_nym, signer_nym_entropy 및 secret_prover_blind 값을 사용합니다.
{"nymSecretHex":"f883d069aec1252f167b0880e8960d72fa2623e11b6967541a457aa5c3cb088"}
다음으로 보유자는 선택적 공개를 위한 JSON 포인터를 지정하여 검증자에게 공개하려는 비필수 문장이 있다면 무엇인지 나타내야 합니다. 이 경우 보유자는 예제 62에 제시된 것과 동일한 정보를 공개합니다. 그 결과 예제 63에 표시된 것과 동일한 revealDocument가 생성됩니다.
§ 4.4.3 CreateDisclosureData를 실행하면 예제 64에 표시된 것과 동일한 파생 그룹 인덱스 정보와 예제 65에 표시된 것과 동일한 조정된 필수 및 선택적 인덱스를 얻습니다.
3.2.3 serializeDerivedProofValue 내에서, 에 표시된 것과 동일한 verfifier_id를 기반으로 pseudonym을 계산합니다. 3.2.3 serializeDerivedProofValue의 최종 출력은 아래에 표시되어 있습니다. featureOption과 계산된 pseudonym 값이 포함되어 있다는 점에 유의하십시오.
{
"bbsProof":"94752c678297191b42617aca412377d4a5b3d7872779ffea31e0b418f50e95056d923a97e8dc156edc2a3a3a54e7b27cafa26a989fc3e8a8bc7a08b84e706a1863bd06c396b973b1af0da4f6c20ea463e124d2ad97060a25ccc3ff695c71977ba2e83a6468205d9e0bfb756089ad40dededab480eeb13cf00265f49824c5f89e23ac48d07fa3164823741df5c066bdc31a231a7d4fecb75c912adb800b1efe8da3cd26805ffa56775b1c32da34e36e9716a4da909fa6803ca0aa2df2d82f697229ccb210503274d4d61c7386a44e9fb459c020fbcd62c7f437da8ffd5ea7e56d2c4e7d9c3f593b2a964346f24f71bec30a2c3ededa0bd3707e2e06cac2dddb66762135a229dc09b67fa61d690d33be78150bc60f3655ac1063f96d6fe95a260004c7bf9e924cc7439c6426f951d0cee963985557097788d2387b72c9aeb390f9a4fa4b519bc11ca81dfca8a4fd3c77805e1a0ef5c165b16c3cdc564e7a5593f0ddd0560f3514393c1b305d3950c29fbb72cc8b58979843cec768e9a77b14f70704771f877c49fc0d0d4ffbe3f0aaf8e472a83b14e32e46207d5012e79b9bcfc6197c858eb18ad97f589dddb5dc45e9ef65f482d3c07fbcbfef92bf293643539fffc94a8bc98b3b4dd3335bb8b248aa606a751330516f148211d5f2d513e02d45ec5a51add1f878948a673a0349d7cb4417b1f9c16945e1f607bdecf6ca3b96a64fb14ee1fc5dbecf751be23041df32842367285f2b3b02c13512c28c0e7671874699b9ff169e35f91debc796fd487d3e41dcc5f12949558f2705be3e8195d4c93a6c149dcb5f63e62d3ce0bf51034021251b74ed2a1186fd77741ce3bf51f57f19a9d4a9e6315a88024062269a9fec426a73199882113168573da451ca38aeacf28f7eef3892181f0bc511562fba00d035f608c4f85579fc9614618763fa4e6c2210184e12f83e1c22078dd4ca488de41dbf2c146a2e0c47137be7f006c6810f44746a819229349b50ca59a51f7c51bb62cacc1a1cc4a6f089680514d41800da57470ef275f390eb4a08db78789e71bd32bd8929961c9f79d1ca071a2608a393f162c2f644584473f11b41cc35c838f11fbd2adf47051829d378ac9dc151e64bc70cd21b2ea6bca3f77b9c2b35abcebb0ecbf1c09365a8e372a2fce74b97088c9e9505c5c0272a4d6959bec54911a99b6c8a1654395f0cd4e7d38d695ab45875ecc535439dde3fb3d4658d9ff9427d8e36d7bd19ea53fb875c4b138f6ffc06bfd496b1a744a63283ebc0fa34ea828d98",
"labelMap":{"dataType":"Map","value":[["c14n0","b1"],["c14n1","b2"],["c14n2","b0"]]},
"mandatoryIndexes":[0,1,2,5,6,8,9],"adjSelectiveIndexes":[0,1,5,7,10,16],
"presentationHeader":{"0":17,"1":51,"2":119,"3":170},
"pseudonym":"838607ff2c8dcb2a0740ef13c2c87418efb57559243232a69daf1e294dd092af833ad4df1e99e0034c737b932916f378",
"featureOption":"holder_binding_pseudonym",
"lengthBBSMessages":23
}
마지막으로 위의 공개 데이터를 다음 절의 알고리즘과 함께 사용하면 3.2.3 serializeDerivedProofValue, 아래에 표시된 서명된 파생(공개) 문서를 얻습니다.
{
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://w3id.org/security/data-integrity/v2",
"https://w3id.org/vdl/v1",
"https://w3id.org/vdl/aamva/v1"
],
"type": [
"VerifiableCredential",
"Iso18013DriversLicenseCredential"
],
"issuer": {
"id": "did:key:z6MkjxvA4FNrQUhr8f7xhdQuP1VPzErkcnfxsRaU5oFgy2E5",
"name": "유토피아 자동차 관리국",
"url": "https://dmv.utopia.example/",
"image": "https://dmv.utopia.example/logo.png"
},
"expirationDate": "2028-11-15T12:00:00-06:00",
"credentialSubject": {
"type": "LicensedDriver",
"driversLicense": {
"type": "Iso18013DriversLicense",
"issuing_country": "UA",
"driving_privileges": [
{
"codes": [
{
"code": "D"
}
],
"vehicle_category_code": "D",
"issue_date": "2019-01-01",
"expiry_date": "2027-01-01"
},
{
"codes": [
{
"code": "C"
}
],
"vehicle_category_code": "C",
"issue_date": "2019-01-01",
"expiry_date": "2017-01-01"
}
]
}
},
"proof": {
"type": "DataIntegrityProof",
"cryptosuite": "bbs-2023",
"created": "2023-08-15T23:36:38Z",
"verificationMethod": "did:key:zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ#zUC7DerdEmfZ8f4pFajXgGwJoMkV1ofMTmEG5UoNvnWiPiLuGKNeqgRpLH2TV4Xe5mJ2cXV76gRN7LFQwapF1VFu6x2yrr5ci1mXqC1WNUrnHnLgvfZfMH7h6xP6qsf9EKRQrPQ",
"proofPurpose": "assertionMethod",
"proofValue": "u2V0Jh1kDkJR1LGeClxkbQmF6ykEjd9Sls9eHJ3n_6jHgtBj1DpUFbZI6l-jcFW7cKjo6VOeyfK-iapifw-iovHoIuE5wahhjvQbDlrlzsa8NpPbCDqRj4STSrZcGCiXMw_9pXHGXe6LoOmRoIF2eC_t1YImtQN7e2rSA7rE88AJl9JgkxfieI6xI0H-jFkgjdB31wGa9wxojGn1P7LdckSrbgAse_o2jzSaAX_pWd1scMto0426XFqTakJ-mgDygqi3y2C9pcinMshBQMnTU1hxzhqROn7RZwCD7zWLH9Dfaj_1ep-VtLE59nD9ZOyqWQ0byT3G-wwosPt7aC9Nwfi4GysLd22Z2ITWiKdwJtn-mHWkNM754FQvGDzZVrBBj-W1v6VomAATHv56STMdDnGQm-VHQzuljmFVXCXeI0jh7csmus5D5pPpLUZvBHKgd_Kik_Tx3gF4aDvXBZbFsPNxWTnpVk_Dd0FYPNRQ5PBswXTlQwp-7csyLWJeYQ87HaOmnexT3BwR3H4d8SfwNDU_74_Cq-ORyqDsU4y5GIH1QEuebm8_GGXyFjrGK2X9Ynd213EXp72X0gtPAf7y_75K_KTZDU5__yUqLyYs7TdMzW7iySKpganUTMFFvFIIR1fLVE-AtRexaUa3R-HiUimc6A0nXy0QXsfnBaUXh9ge97PbKO5amT7FO4fxdvs91G-IwQd8yhCNnKF8rOwLBNRLCjA52cYdGmbn_Fp41-R3rx5b9SH0-QdzF8SlJVY8nBb4-gZXUyTpsFJ3LX2PmLTzgv1EDQCElG3TtKhGG_Xd0HOO_UfV_GanUqeYxWogCQGImmp_sQmpzGZiCETFoVz2kUco4rqzyj37vOJIYHwvFEVYvugDQNfYIxPhVefyWFGGHY_pObCIQGE4S-D4cIgeN1MpIjeQdvywUai4MRxN75_AGxoEPRHRqgZIpNJtQylmlH3xRu2LKzBocxKbwiWgFFNQYANpXRw7ydfOQ60oI23h4nnG9Mr2JKZYcn3nRygcaJgijk_FiwvZEWERz8RtBzDXIOPEfvSrfRwUYKdN4rJ3BUeZLxwzSGy6mvKP3e5wrNavOuw7L8cCTZajjcqL850uXCIyelQXFwCcqTWlZvsVJEambbIoWVDlfDNTn041pWrRYdezFNUOd3j-z1GWNn_lCfY42170Z6lP7h1xLE49v_Aa_1Jaxp0SmMoPrwPo06oKNmKMAAQECAgCHAAECBQYICYYAAQUHChBEETN3qlgwg4YH_yyNyyoHQO8Twsh0GO-1dVkkMjKmna8eKU3Qkq-DOtTfHpngA0xze5MpFvN4Fw"
}
}
이 절은 비규범적입니다.
이 명세에 관한 작업은 Christopher Allen, Shannon Appelcline, Kiara Robles, Brian Weller, Betty Dhamers, Kaliya Young, Manu Sporny, Drummond Reed, Joe Andrieu, Heather Vescent, Kim Hamilton Duffy, Samantha Chase, Andrew Hughes, Erica Connell, Shigeya Suzuki 및 Zaïda Rivai가 지원한 Rebooting the Web of Trust 커뮤니티의 도움을 받았습니다. Phil Windley, Kaliya Young, Doc Searls 및 Heidi Nobantu Saul이 지원한 Internet Identity Workshop의 참가자들도 이 명세에 관해 교육하고 토론하며 개선하기 위해 마련된 수많은 작업 세션을 통해 이 작업의 개선을 지원했습니다.
워킹 그룹은 또한 의장 Brent Zundel, 전 의장 Kristina Yasuda 및 W3C 직원 담당자인 Ivan Herman에게 W3C 표준화 과정 전반에서 그룹을 전문적으로 관리하고 꾸준히 지도해 주신 데 대해 감사드립니다.
이 명세에 관한 작업의 일부는 미국 국토안보부 과학기술국의 계약 70RSAT20T00000003, 70RSAT20T00000029, 70RSAT20T00000033, 70RSAT21T00000016, 70RSAT23T00000005, 70RSAT20T00000010/P00001, 70RSAT20T00000029, 70RSAT21T00000016/P00001, 70RSAT23T00000005, 70RSAT23C00000030, 70RSAT23R00000006, 70RSAT24T00000011 및 미국 국립과학재단의 NSF 22-572를 통해 자금을 지원받았습니다. 이 명세의 내용이 반드시 미국 정부의 입장이나 정책을 반영하는 것은 아니며, 어떠한 공식적인 승인도 추론해서는 안 됩니다.
워킹 그룹은 이 명세를 검토하고 피드백을 제공해 주신 다음 분들께도 감사드립니다(알파벳순):
Will Abramson, Mahmoud Alkhraishi, Christopher Allen, Joe Andrieu, Bohdan Andriyiv, Anthony, George Aristy, Hadley Beeman, Greg Bernstein, Bob420, Sarven Capadisli, Melvin Carvalho, David Chadwick, Matt Collier, Gabe Cohen, Sebastian Crane, Kyle Den Hartog, Veikko Eeva, Eric Elliott, Raphael Flechtner, Julien Fraichot, Benjamin Goering, Kim Hamilton Duffy, Joseph Heenan, Helge, Ivan Herman, Michael Herman, Anil John, Andrew Jones, Michael B. Jones, Rieks Joosten, Gregory K, Gregg Kellogg, Filip Kolarik, David I. Lehn, Charles E. Lehner, Christine Lemmer-Webber, Eric Lim, Dave Longley, Tobias Looker, Jer Miller, nightpool, Luis Osta, Nate Otto, George J. Padayatti, Addison Phillips, Mike Prorock, Brian Richter, Anders Rundgren, Eugeniu Rusu, Markus Sabadello, silverpill, Wesley Smith, Manu Sporny, Patrick St-Louis, Orie Steele, Henry Story, Oliver Terbu, Ted Thibodeau Jr, John Toohey, Bert Van Nuffelen, Mike Varley, Snorre Lothar von Gohren Edwin, Jeffrey Yasskin, Kristina Yasuda, Benjamin Young, Dmitri Zagidulin, 그리고 Brent Zundel.