인증 대리인 등록처 온보딩 가이드

개요

이 섹션에서는 인증 기관 등록 대행자가 Google 월렛 ID 서비스에 온보딩하는 단계별 절차를 설명합니다.

인증 대리인 등록기관 (예: 다른 법인을 대신하여 인증하는 IDV 회사)은 자체 인증 기관 (CA) 역할을 하여 관리하는 다운스트림 최종 신뢰 당사자 (RP)의 신원 요청에 서명합니다.

온보딩 프로세스

1단계: 인테이크 양식, 루트 인증서 제출 및 서비스 약관 수락

인증 기관 등록처 온보딩 등록 양식을 작성하여 제출합니다. 이 양식에서는 샌드박스 및 프로덕션 루트 인증서를 모두 제공합니다. 이 온보딩 인테이크 양식을 제출하면 Google 월렛 인증 기관 등록처 서비스 약관에도 정식으로 동의하는 것으로 간주됩니다.

2단계: 샌드박스 신뢰 및 테스트

온보딩 양식을 제출하면 Google에서 샌드박스 루트 인증서를 Google 월렛 샌드박스 트러스트 저장소에 추가하고 사용자에게 알림을 보냅니다. 그런 다음 샌드박스 루트에서 서명한 인증서를 사용하여 샌드박스에서 통합 테스트를 시작할 수 있습니다.

3단계: E2E 동영상 데모 녹화

샌드박스 테스트가 완료되면 초기 (1차) 신뢰 당사자의 인증 흐름에 대한 엔드 투 엔드 동영상 데모를 녹화하여 Google에 제출합니다.

  • 동영상 요구사항:
    • 해당하는 경우 인증 기관 호스팅 (자체 호스팅)판매자 호스팅 (RP 호스팅) 흐름 모두에 대한 데모를 기록합니다.
    • 동영상에 실제 판매자 표시 확장 소재 (이름, 로고, 서비스 약관 URL)와 애그리게이터 표시 확장 소재를 사용합니다.
    • 인증 흐름을 시작하는 사용자 인터페이스와 화면을 명확하게 보여줍니다.

4단계: 승인 및 프로덕션 루트 신뢰

엔드 투 엔드 동영상 데모를 받으면 Google은 동영상 검토 및 승인 절차를 트리거하는 동시에 프로덕션 루트 인증서 신뢰 프로세스를 시작합니다. 두 프로세스가 모두 완료되고 승인되면 다운스트림 최종 RP를 위한 서비스를 시작할 수 있습니다.

5단계: 지속적인 최종 RP 온보딩

서명하는 각 최종 RP에 대해 다음을 충족해야 합니다.

  • Google에 알림: 인증 기관 등록처 클라이언트 온보딩 양식을 사용하여 새 RP와 의도된 사용 사례를 Google에 알립니다.
  • 메타데이터 구성: RP의 표시 정보 (이름, 로고, 개인정보처리방침 URL)를 입력하고 인증서에 전역적으로 고유한 식별 이름 (주체)을 설정합니다.

기술 사양

A. 인증서 프로필

요청은 P-256 / ECDSA를 사용하여 생성되고 맞춤 Google 확장 프로그램을 포함하는 표준 X.509 v3 인증서로 서명되어야 합니다.

  • 맞춤 확장 프로그램 OID: 1.3.6.1.4.1.11129.10.1
  • 중요도: 중요하지 않음
  • 콘텐츠: ASN.1 OCTET STRING로 인코딩된 RelyingPartyMetadataBytes의 SHA256 해시입니다.

B. 메타데이터 스키마 (CBOR)

메타데이터는 CBOR 형식으로 인코딩해야 합니다.

; in CDDL for CBOR encoding
; schemaVersion = "v1"

RelyingPartyMetadataBytes = #6.24(bstr .cbor RelyingPartyMetadata)


RelyingPartyMetadata = {
  "schema_version": tstr,
  "display": DisplayInfo,
  "aggregator_info": DisplayInfo  ; Optional: include to show your branding alongside the RP
}

DisplayInfo = {
  "display_name": tstr,
  "logo_uri": tstr,             ; See brand guidelines link in following paragraph
  "privacy_policy_uri": tstr
}

logo_uriGoogle 월렛 브랜드 가이드라인을 따라야 합니다.

C. OpenID4VP 통합

서명된 OpenID4VP 사용자 인증 정보 요청을 포맷할 때는 다음 섹션의 샘플 요청 코드에 표시된 대로 client_metadata 객체 내의 gw_rp_metadata_bytes 필드에 base64url로 인코딩된 메타데이터를 포함합니다.

규정 준수 및 취소

  • 악용 모니터링: Google은 악의적인 RP 활동을 모니터링하고 감지된 악용 사례를 알려줍니다.
  • 즉시 해지: 악용 RP의 인증서를 즉시 해지하고 업데이트된 인증서 해지 목록 (CRL)을 게시해야 합니다.
  • 감사: Google은 RP 요청이 등록된 사용 사례와 일치하는지 확인하기 위해 익명처리된 로그를 유지합니다.

다음 단계

인증 기관 등록 기관으로 온보딩을 시작하려면 인증 기관 등록 기관 온보딩 접수 양식을 작성하여 제출하세요. 후속 다운스트림 클라이언트를 온보딩하려면 인증 기관 등록자 클라이언트 온보딩 양식을 사용하세요.

온보딩 및 통합에 관한 자주 묻는 질문은 디지털 ID 및 사용자 인증 정보 FAQ를 참고하세요.

인증 기관 등록처 통합 세부정보

다음 섹션에서는 디지털 사용자 인증 정보 API와 통합하는 인증 기관 등록처의 기술 통합 세부정보 (요청 형식 지정, 요청 암호화, API 트리거, 응답 검증, 제로 지식 증명 구현 포함)를 다룹니다.

지원되는 형식 및 기능

Google 월렛은 ISO mdoc 기반 디지털 신분증을 지원합니다.

요청 형식 지정

지갑에서 사용자 인증 정보를 요청하려면 OpenID4VP를 사용하여 요청의 형식을 지정해야 합니다. 단일 dcql_query 객체에서 특정 사용자 인증 정보 또는 여러 사용자 인증 정보를 요청할 수 있습니다.

JSON 요청 예

다음은 Android 기기 또는 웹의 지갑에서 ID 사용자 인증 정보를 가져오는 mdoc requestJson 요청의 샘플입니다.

{
      "requests" : [
        {
          "protocol": "openid4vp-v1-signed",
          "data": {<signed_credential_request>} // This is an object, shouldn't be a string.
        }
      ]
}

암호화 요청

client_metadata에는 각 요청의 암호화 공개 키가 포함됩니다. 각 요청의 비공개 키를 저장하고 이를 사용하여 지갑 앱에서 수신한 토큰을 인증하고 승인해야 합니다.

통합 OpenID4VP 메타데이터

사용자 인증 정보 요청을 포맷할 때는 client_metadata 객체 내에 gw_rp_metadata_bytes 필드를 포함해야 합니다 (아래 샘플 요청 코드 참고). 이 필드에는 Google 월렛에서 신원을 확인하고 사용자에게 브랜딩을 표시하는 데 필요한 Base64URL로 인코딩된 신뢰 당사자 메타데이터가 포함되어 있습니다.

requestJsoncredential_request 매개변수에는 다음 필드가 포함됩니다.

특정 사용자 인증 정보

{
  "response_type": "vp_token",
  "response_mode": "dc_api.jwt", // change this to dc_api if you want to demo with a non encrypted response.
  "nonce": "1234",
  "dcql_query": {
    "credentials": [
      {
        "id": "cred1",
        "format": "mso_mdoc",
        "meta": {
          "doctype_value": "org.iso.18013.5.1.mDL"  // this is for mDL. Use com.google.wallet.idcard.1 for ID pass
        },
        "claims": [
          {
            "path": [
              "org.iso.18013.5.1",
              "family_name"
            ],
            "intent_to_retain": false // set this to true if you are saving the value of the field
          },
          {
            "path": [
              "org.iso.18013.5.1",
              "given_name"
            ],
            "intent_to_retain": false
          },
          {
            "path": [
              "org.iso.18013.5.1",
              "age_over_18"
            ],
            "intent_to_retain": false
          }
        ]
      }
    ]
  },
  "client_metadata": {
    "jwks": {
      "keys": [ // sample request encryption key
        {
          "kty": "EC",
          "crv": "P-256",
          "x": "pDe667JupOe9pXc8xQyf_H03jsQu24r5qXI25x_n1Zs",
          "y": "w-g0OrRBN7WFLX3zsngfCWD3zfor5-NLHxJPmzsSvqQ",
          "use": "enc",
          "kid" : "1",  // This is required
          "alg" : "ECDH-ES",  // This is required
        }
      ]
    },
    "vp_formats_supported": {
      "mso_mdoc": {
        "deviceauth_alg_values": [
          -7
        ],
        "issuerauth_alg_values": [
          -7
        ]
      }
    },
    "gw_rp_metadata_bytes": "<base64url encoded metadata string>"
  }
}

사용 가능한 모든 사용자 인증 정보

다음은 mDL과 신분증 패스 모두에 대한 요청의 예입니다. 사용자는 둘 중 하나를 선택하여 계속 진행할 수 있습니다.

{
  "response_type": "vp_token",
  "response_mode": "dc_api.jwt", // change this to dc_api if you want to demo with a non encrypted response.
  "nonce": "1234",
  "dcql_query": {
    "credentials": [
      {
        "id": "mdl-request",
        "format": "mso_mdoc",
        "meta": {
          "doctype_value": "org.iso.18013.5.1.mDL"
        },
        "claims": [
          {
            "path": [
              "org.iso.18013.5.1",
              "family_name"
            ],
            "intent_to_retain": false // set this to true if you are saving the value of the field
          },
          {
            "path": [
              "org.iso.18013.5.1",
              "given_name"
            ],
            "intent_to_retain": false
          },
          {
            "path": [
              "org.iso.18013.5.1",
              "age_over_18"
            ],
            "intent_to_retain": false
          }
        ]
      },
      {  // Credential type 2
        "id": "id_pass-request",
        "format": "mso_mdoc",
        "meta": {
          "doctype_value": "com.google.wallet.idcard.1"
        },
        "claims": [
          {
            "path": [
              "org.iso.18013.5.1",
              "family_name"
            ],
            "intent_to_retain": false // set this to true if you are saving the value of the field
          },
          {
            "path": [
              "org.iso.18013.5.1",
              "given_name"
            ],
            "intent_to_retain": false
          },
          {
            "path": [
              "org.iso.18013.5.1",
              "age_over_18"
            ],
            "intent_to_retain": false
          }
        ]
      }
    ]
    credential_sets : [
      {
        "options": [
          [ "mdl-request" ],
          [ "id_pass-request" ]
        ]
      }
    ]
  },
  "client_metadata": {
    "jwks": {
      "keys": [ // sample request encryption key
        {
          "kty": "EC",
          "crv": "P-256",
          "x": "pDe667JupOe9pXc8xQyf_H03jsQu24r5qXI25x_n1Zs",
          "y": "w-g0OrRBN7WFLX3zsngfCWD3zfor5-NLHxJPmzsSvqQ",
          "use": "enc",
          "kid" : "1",  // This is required
          "alg" : "ECDH-ES",  // This is required
        }
      ]
    },
    "vp_formats_supported": {
      "mso_mdoc": {
        "deviceauth_alg_values": [
          -7
        ],
        "issuerauth_alg_values": [
          -7
        ]
      }
    },
    "gw_rp_metadata_bytes": "<base64url encoded metadata string>"
  }
}

Google 월렛에 저장된 모든 ID 인증 정보에서 원하는 수의 지원되는 속성을 요청할 수 있습니다.

서명된 요청

서명된 요청(JWT 보안 승인 요청)은 PKI 인프라를 사용하여 암호화 서명된 JSON 웹 토큰(JWT) 내에 확인 가능한 프레젠테이션 요청을 캡슐화하여 요청 무결성을 보장하고 Google 월렛에 신원을 증명합니다.

기본 요건

서명된 요청에 대한 코드 변경사항을 구현하기 전에 다음 사항을 확인하세요.

  • 비공개 키: 서버에서 관리되는 요청에 서명하려면 비공개 키 (예: 타원 곡선 ES256)가 필요합니다.
  • 인증서: 키 쌍에서 파생된 표준 X.509 인증서가 필요합니다.
  • 등록: 공개 인증서가 Google 월렛에 등록되어 있는지 확인합니다.

요청 구성 로직

요청을 구성하려면 비공개 키를 사용하고 페이로드를 JWS로 래핑해야 합니다.

def construct_openid4vp_request(
    doctypes: list[str],
    requested_fields: list[dict],
    nonce_base64: str,
    jwe_encryption_public_jwk: jwk.JWK,
    is_zkp_request: bool,
    is_signed_request: bool,
    state: dict,
    origin: str
) -> dict:

    # ... [Existing logic to build 'presentation_definition' and basic 'request_payload'] ...

    # ------------------------------------------------------------------
    # SIGNED REQUEST IMPLEMENTATION (JAR)
    # ------------------------------------------------------------------
    if is_signed_request:
        try:
            # 1. Load the Verifier's Certificate
            # We must load the PEM string into a cryptography x509 object
            verifier_cert_obj = x509.load_pem_x509_certificate(
                CERTIFICATE.encode('utf-8'),
                backend=default_backend()
            )

            # 2. Calculate Client ID (x509_hash)
            # We calculate the SHA-256 hash of the DER-encoded certificate.
            cert_der = verifier_cert_obj.public_bytes(serialization.Encoding.DER)
            verifier_fingerprint_bytes = hashlib.sha256(cert_der).digest()

            # Create a URL-safe Base64 hash (removing padding '=')
            verifier_fingerprint_b64 = base64.urlsafe_b64encode(verifier_fingerprint_bytes).decode('utf-8').rstrip("=")

            # Format the client_id as required by the spec
            client_id = f'x509_hash:{verifier_fingerprint_b64}'

            # 3. Update Request Payload with JAR specific fields
            request_payload["client_id"] = client_id

            # Explicitly set expected origins to prevent relay attacks
            # Format for android origin: origin = android:apk-key-hash:<base64SHA256_ofAppSigningCert>
            # Format for web origin: origin = <origin_url>
            if origin:
                request_payload["expected_origins"] = [origin]

            # 4. Create Signed JWT (JWS)
            # Load the signing private key
            signing_key = jwk.JWK.from_pem(PRIVATE_KEY.encode('utf-8'))

            # Initialize JWS with the JSON payload
            jws_token = jws.JWS(json.dumps(request_payload).encode('utf-8'))

            # Construct the JOSE Header
            # 'x5c' (X.509 Certificate Chain) is critical: it allows the wallet
            # to validate your key against the one registered in the console.
            x5c_value = base64.b64encode(cert_der).decode('utf-8')

            protected_header = {
                "alg": "ES256",                 # Algorithm (e.g., ES256 or RS256)
                "typ": "oauth-authz-req+jwt",   # Standard type for JAR
                "kid": "1",                     # Key ID
                "x5c": [x5c_value]              # Embed the certificate
            }

            # Sign the token
            jws_token.add_signature(
                key=signing_key,
                alg=None,
                protected=json_encode(protected_header)
            )

            # 5. Return the Request Object
            # Instead of returning the raw JSON, we return the signed JWT string
            # under the 'request' key.
            return {"request": jws_token.serialize(compact=True)}

        except Exception as e:
            print(f"Error signing OpenID4VP request: {e}")
            return None

    # ... [Fallback for unsigned requests] ...
    return request_payload

API 트리거

전체 API 요청은 서버 측에서 생성해야 합니다. 플랫폼에 따라 생성된 JSON을 플랫폼 API에 전달합니다.

인앱 (Android)

Android 앱에서 ID 사용자 인증 정보를 요청하려면 다음 단계를 따르세요.

종속 항목 업데이트

프로젝트의 build.gradle에서 인증 관리자 (베타)를 사용하도록 종속 항목을 업데이트합니다.

dependencies {
    implementation("androidx.credentials:credentials:1.5.0-beta01")
    implementation("androidx.credentials:credentials-play-services-auth:1.5.0-beta01")
}

인증 관리자 구성

CredentialManager 객체를 구성하고 초기화하려면 다음과 유사한 로직을 추가하세요.

// Use your app or activity context to instantiate a client instance of CredentialManager.
val credentialManager = CredentialManager.create(context)

요청 ID 속성

ID 요청에 개별 매개변수를 지정하는 대신 앱은 CredentialOption 내에서 모든 매개변수를 JSON 문자열로 함께 제공합니다. 인증 관리자는 콘텐츠를 검사하지 않고 이 JSON 문자열을 사용 가능한 디지털 지갑에 전달합니다. 그러면 각 지갑은 다음을 담당합니다. - JSON 문자열을 파싱하여 ID 요청을 이해합니다. - 저장된 사용자 인증 정보 중 요청을 충족하는 사용자 인증 정보가 있는지 확인합니다.

파트너는 Android 앱 통합의 경우에도 서버에서 요청을 생성하는 것이 좋습니다.

요청 형식requestJsonGetDigitalCredentialOption() 함수 호출에서 request로 사용합니다.

// The request in the JSON format to conform with
// the JSON-ified Digital Credentials API request definition.
val requestJson = generateRequestFromServer()
val digitalCredentialOption =
    GetDigitalCredentialOption(requestJson = requestJson)

// Use the option from the previous step to build the `GetCredentialRequest`.
val getCredRequest = GetCredentialRequest(
    listOf(digitalCredentialOption)
)

coroutineScope.launch {
    try {
        val result = credentialManager.getCredential(
            context = activityContext,
            request = getCredRequest
        )
        verifyResult(result)
    } catch (e : GetCredentialException) {
        handleFailure(e)
    }
}

사용자 인증 정보 응답 처리

지갑에서 응답을 받으면 응답이 성공적이고 credentialJson 응답이 포함되어 있는지 확인합니다.

// Handle the successfully returned credential.
fun verifyResult(result: GetCredentialResponse) {
    val credential = result.credential
    when (credential) {
        is DigitalCredential -> {
            val responseJson = credential.credentialJson
            validateResponseOnServer(responseJson) // make a server call to validate the response
        }
        else -> {
            // Catch any unrecognized credential type here.
            Log.e(TAG, "Unexpected type of credential ${credential.type}")
        }
    }
}

// Handle failure.
fun handleFailure(e: GetCredentialException) {
  when (e) {
        is GetCredentialCancellationException -> {
            // The user intentionally canceled the operation and chose not
            // to share the credential.
        }
        is GetCredentialInterruptedException -> {
            // Retry-able error. Consider retrying the call.
        }
        is NoCredentialException -> {
            // No credential was available.
        }
        else -> Log.w(TAG, "Unexpected exception type ${e::class.java}")
    }
}

credentialJson 응답에는 W3C에서 정의한 암호화된 identityToken (JWT)이 포함됩니다. 이 응답을 작성하는 것은 Wallet 앱의 책임입니다.

예:

{
  "protocol" : "openid4vp-v1-signed",
  "data" : {
    <encrpted_response>
  }
}

이 응답을 서버로 다시 전달하여 진위 여부를 확인합니다. 사용자 인증 정보 응답의 유효성을 검사하는 단계

Chrome 또는 기타 지원되는 브라우저에서 디지털 사용자 인증 정보 API를 사용하여 ID 사용자 인증 정보를 요청하려면 다음 요청을 실행하세요.

const credentialResponse = await navigator.credentials.get({
          digital : {
          requests : [
            {
              protocol: "openid4vp-v1-signed",
              data: {<credential_request>} // This is an object, shouldn't be a string.
            }
          ]
        }
      })

이 API의 응답을 서버로 다시 보내 사용자 인증 정보 응답을 검증합니다.

응답 유효성 검사

지갑에서 암호화된 identityToken (JWT)를 반환하면 데이터를 신뢰하기 전에 엄격한 서버 측 검증을 실행해야 합니다.

대답 복호화

요청의 client_metadata에 전송된 공개 키에 해당하는 비공개 키를 사용하여 JWE를 복호화합니다. 그러면 vp_token가 생성됩니다.

Python 예:

  from jwcrypto import jwe, jwk

  # Retrieve the Private Key from Datastore
  reader_private_jwk = jwk.JWK.from_json(jwe_private_key_json_str)
  # Save public key thumbprint for session transcript
  encryption_public_jwk_thumbprint = reader_private_jwk.thumbprint()


  # Decrypt the JWE encrypted response from Google Wallet
  jwe_object = jwe.JWE()
  jwe_object.deserialize(encrypted_jwe_response_from_wallet)
  jwe_object.decrypt(reader_private_jwk)
  decrypted_payload_bytes = jwe_object.payload
  decrypted_data = json.loads(decrypted_payload_bytes)

decrypted_data은 사용자 인증 정보가 포함된 vp_token JSON을 생성합니다.

  {
    "vp_token":
    {
      "cred1": ["<base64UrlNoPadding_encoded_credential>"] // This applies to OpenID4VP 1.0 spec.
    }
  }
  1. 세션 스크립트 만들기

    다음 단계는 Android 또는 웹 전용 핸드오버 구조를 사용하여 ISO/IEC 18013-5:2021에서 SessionTranscript를 만드는 것입니다.

    SessionTranscript = [
      null,                // DeviceEngagementBytes not available
      null,                // EReaderKeyBytes not available
      [
        "OpenID4VPDCAPIHandover",
        AndroidHandoverDataBytes   // BrowserHandoverDataBytes for Web
      ]
    ]
    

    Android 및 웹 핸드오버 모두 credential_request를 생성하는 데 사용한 것과 동일한 nonce를 사용해야 합니다.

    Android 핸드오버

        AndroidHandoverData = [
          origin,             // "android:apk-key-hash:<base64SHA256_ofAppSigningCert>",
          nonce,           // nonce that was used to generate credential request,
          encryption_public_jwk_thumbprint,  // Encryption public key (JWK) Thumbprint
        ]
    
        AndroidHandoverDataBytes = hashlib.sha256(cbor2.dumps(AndroidHandoverData)).digest()
        

    브라우저 핸드오버

        BrowserHandoverData =[
          origin,               // Origin URL
          nonce,               //  nonce that was used to generate credential request
          encryption_public_jwk_thumbprint,  // Encryption public key (JWK) Thumbprint
        ]
    
        BrowserHandoverDataBytes = hashlib.sha256(cbor2.dumps(BrowserHandoverData)).digest()
        

    SessionTranscript를 사용하여 기기 응답은 ISO/IEC 18013-5:2021 조항 9에 따라 검증해야 합니다.

    이 검증에는 다음과 같은 여러 단계가 포함됩니다.

  2. 발급자 인증서 확인: issuerAuth에서 발급자의 서명 인증서 체인을 추출하고 신뢰할 수 있는 IACA 루트 인증서에 대해 검증합니다. 지원되는 발급기관의 IACA 인증서를 참고하세요.

  3. MSO 서명 확인 (18013-5 섹션 9.1.2)

  4. 데이터 요소의 ValueDigests 계산 및 확인 (18013-5 섹션 9.1.2)

  5. deviceSignature 서명 확인 (18013-5 섹션 9.1.3)

{
  "version": "1.0",
  "documents": [
    {
      "docType": "org.iso.18013.5.1.mDL",
      "issuerSigned": {
        "nameSpaces": {...}, // contains data elements
        "issuerAuth": [...]  // COSE_Sign1 w/ issuer PK, mso + sig
      },
      "deviceSigned": {
        "nameSpaces": 24(<< {} >>), // empty
        "deviceAuth": {
          "deviceSignature": [...] // COSE_Sign1 w/ device signature
        }
      }
    }
  ],
  "status": 0
}

개인 정보 보호 연령 확인 (ZKP)

영지식 증명을 지원하려면 (예: 정확한 생년월일을 확인하지 않고 사용자가 18세 이상인지 확인) 요청 형식을 mso_mdoc_zk로 변경하고 필요한 zk_system_type 구성을 제공하세요.

ZKP의 정의와 기능에 관한 개요는 FAQ를 참고하세요.

  ...
  "dcql_query": {
    "credentials": [{
      "id": "cred1",
      "format": "mso_mdoc_zk",
      "meta": {
        "doctype_value": "org.iso.18013.5.1.mDL"
        "zk_system_type": [
        {
          "system": "longfellow-libzk-v1",
          "circuit_hash": "f88a39e561ec0be02bb3dfe38fb609ad154e98decbbe632887d850fc612fea6f", // This will differ if you need more than 1 attribute.
          "num_attributes": 1, // number of attributes (in claims) this has can support
          "version": 5,
          "block_enc_hash": 4096,
          "block_enc_sig": 2945,
        }
        {
          "system": "longfellow-libzk-v1",
          "circuit_hash": "137e5a75ce72735a37c8a72da1a8a0a5df8d13365c2ae3d2c2bd6a0e7197c7c6", // This will differ if you need more than 1 attribute.
          "num_attributes": 1, // number of attributes (in claims) this has can support
          "version": 6,
          "block_enc_hash": 4096,
          "block_enc_sig": 2945,
        }
       ],
       "verifier_message": "challenge"
      },
     "claims": [{
         ...
      "client_metadata": {
        "jwks": {
          "keys": [ // sample request encryption key
            {
              ...

지갑에서 암호화된 영지식 증명을 다시 받게 됩니다. Google의 longfellow-zk 라이브러리를 사용하여 발급자 IACA 인증서에 대해 이 증명을 검증할 수 있습니다.

verifier-service에는 특정 발급기관 IACA 인증서에 대해 응답을 검증할 수 있는 배포 준비가 완료된 Docker 기반 서버가 포함되어 있습니다.

신뢰할 IACA 발급자 인증서를 관리하도록 certs.pem을 수정할 수 있습니다.

리소스 및 지원