מדריך למשתמשים חדשים של רשם מאמתים

סקירה כללית

בקטע הזה מפורט תהליך ההצטרפות של רשמי מאמתים לשירות הזהויות של Google Wallet.

אם אתם רשומים כמאמתים (לדוגמה, חברה לאימות זהויות שמאמתת זהויות בשם ישויות אחרות), אתם פועלים כרשות אישורים (CA) משלכם, וחותמים על בקשות אימות זהות עבור הצדדים המסתמכים (RP) שאתם מנהלים.

תהליך ההצטרפות

שלב 1: שליחת טופס ההצטרפות, אישורי הבסיס ואישור התנאים וההגבלות

ממלאים את טופס ההצטרפות של רשם מאמתים ושולחים אותו. בטופס הזה תצטרכו לספק את אישורי הבסיס של סביבת ארגז החול וסביבת הייצור. שליחת טופס ההצטרפות הזה מבטאת גם את ההסכמה הרשמית שלך לתנאים ולהגבלות של רשם מאמתים של Google Wallet.

שלב 2: בדיקות ומהימנות של ארגז חול

אחרי ששולחים את טופס ההצטרפות, Google מוסיפה את אישור הבסיס של ארגז החול למאגר האישורים של ארגז החול של Google Wallet ושולחת לכם הודעה. אחר כך תוכלו להתחיל לבדוק את השילוב בארגז החול באמצעות אישורים שחתומים על ידי שורש ארגז החול שלכם.

שלב 3: הקלטת הדגמה של תהליך מקצה לקצה

בסיום הבדיקה בסביבת ארגז החול, צריך להקליט הדגמות וידאו של תהליך האימות עבור הצד הראשון (הראשוני) שנסמך על הזהות, ולשלוח אותן ל-Google.

  • דרישות לגבי סרטונים:
    • צריך להקליט הדגמות של תהליכי האימות גם באימות באתר של המאמת (אירוח עצמי) וגם באימות באתר של המוכר (אירוח על ידי RP), בהתאם לצורך.
    • שימוש בנכסי תצוגה של מוֹכרים בפועל (שם, לוגו, כתובת URL של התנאים וההגבלות) ובנכסי תצוגה של צוברים בסרטונים.
    • הדגמה ברורה של ממשק המשתמש והמסכים שמובילים לתהליך האימות.

שלב 4: אישור והפקת שורש מהימן

אחרי ש-Google מקבלת את ההדגמות שלכם באמצעות סרטונים מקצה לקצה, היא מפעילה את תהליך הבדיקה והאישור של הסרטונים, ובמקביל מתחילה את תהליך ההסתמכות על אישור השורש של הייצור. אחרי ששני התהליכים יושלמו ויאושרו, תוכלו להתחיל להשיק את השירות עבור ספקי ה-RP במורד הזרם.

שלב 5: הצטרפות מתמשכת של משתמשי קצה ל-RP

לכל הסכם End RP שחותמים עליו, צריך:

  • לעדכן את Google: צריך להשתמש בטופס ההצטרפות של לקוח רשם מאמת כדי להודיע ל-Google על ה-RP החדש ועל תרחיש השימוש המיועד שלו.
  • הגדרת מטא-נתונים: מאכלסים את פרטי התצוגה של ספק הזהויות (שם, לוגו, כתובת URL של מדיניות הפרטיות) ומגדירים שם ייחודי גלובלי (נושא) באישור שלו.

מפרטים טכניים

א. פרופיל האישור

הבקשות צריכות להיות חתומות על ידי אישורי X.509 v3 סטנדרטיים שנוצרו באמצעות P-256 / ECDSA ומכילים תוסף מותאם אישית של Google:

  • מזהה OID של תוסף מותאם אישית: 1.3.6.1.4.1.11129.10.1
  • רמת החומרה: לא קריטית.
  • תוכן: גיבוב SHA256 של RelyingPartyMetadataBytes, עם קידוד ב-ASN.1 OCTET STRING.

ב. סכימת מטא-נתונים (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_uri צריך לעמוד בדרישות הנחיות המיתוג של Google Wallet.

ג. שילוב של OpenID4VP

כשמגדירים את הפורמט של בקשת אישורים חתומה של OpenID4VP, צריך לכלול את המטא-נתונים בקידוד Base64URL בשדה gw_rp_metadata_bytes באובייקט client_metadata (כפי שמוצג בקוד של בקשת הדוגמה בקטע הבא).

תאימות וביטול

  • מעקב אחר מקרים של שימוש לרעה: Google עוקבת אחרי פעילות זדונית של RP ותודיע לכם על כל מקרה של שימוש לרעה שתזהה.
  • ביטול מהיר: עליכם לבטל במהירות אישורים של ספקי זהויות שמתנהלים בצורה פוגעת ולפרסם רשימה מעודכנת של אישורים שבוטלו (CRL).
  • ביקורת: Google שומרת יומנים שעברו אנונימיזציה כדי לוודא שבקשות RP תואמות לתרחישי השימוש הרשומים שלהן.

השלבים הבאים

כדי להתחיל את תהליך ההצטרפות כרשם מאמת, צריך למלא ולשלוח את טופס ההצטרפות של רשם מאמת. כדי לצרף לקוחות נוספים בהמשך, משתמשים בטופס הצירוף של לקוח מאמת רשם.

שאלות נפוצות על צירוף ואינטגרציה מופיעות במאמר בנושא שאלות נפוצות על זהויות דיגיטליות ואישורים.

פרטי השילוב של מאמת עם רשם

בקטע הבא מפורטים פרטים טכניים על שילוב של רשמי אימות עם Digital Credentials API (כולל פורמט הבקשה, הצפנת הבקשה, הפעלת ה-API, אימות התגובות והטמעה של הוכחות אפס ידע).

פורמטים ויכולות נתמכים

‫Google Wallet תומך בתעודות מזהות דיגיטליות שמבוססות על ISO mdoc.

בחירת הפורמט של הבקשה

כדי לבקש פרטי כניסה מכל ארנק, צריך לעצב את הבקשה באמצעות OpenID4VP. אפשר לבקש פרטי כניסה ספציפיים או כמה פרטי כניסה באובייקט dcql_query אחד.

דוגמה לבקשת JSON

הנה דוגמה לבקשת mdoc requestJson לקבלת פרטי זהות מכל ארנק במכשיר Android או באינטרנט.

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

בקשת הצפנה

התג client_metadata מכיל את המפתח הציבורי להצפנה של כל בקשה. תצטרכו לאחסן מפתחות פרטיים לכל בקשה ולהשתמש בהם כדי לאמת ולאשר את הטוקן שאתם מקבלים מאפליקציית Wallet.

מטא-נתונים משולבים של OpenID4VP

כשמגדירים את הבקשה לאישור פרטי הכניסה, צריך לכלול את השדה gw_rp_metadata_bytes בתוך האובייקט client_metadata (כפי שמוצג בקוד הבקשה לדוגמה שלמטה). השדה הזה מכיל את המטא-נתונים של הצד המסתמך בקידוד Base64URL, שנדרשים ל-Google Wallet כדי לאמת את הזהות שלכם ולהציג למשתמש את המיתוג שלכם.

הפרמטר credential_request ב-requestJson מכיל את השדות הבאים.

פרטי כניסה ספציפיים

{
  "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 Wallet.

בקשות חתומות

בקשות חתומות (בקשות הרשאה מאובטחות באמצעות JWT) כוללות את בקשת ההצגה הניתנת לאימות בתוך אסימון אינטרנט מסוג JSON‏ (JWT) שחתום קריפטוגרפית באמצעות תשתית ה-PKI שלכם. כך מובטחת שלמות הבקשה ומוכח הזיהוי שלכם ב-Google Wallet.

דרישות מוקדמות

לפני שמטמיעים את שינויי הקוד לבקשה חתומה, צריך לוודא שיש לכם:

  • מפתח פרטי: צריך מפתח פרטי (למשל, Elliptic Curve ES256) כדי לחתום על הבקשה שמנוהלת בשרת.
  • אישור: נדרש אישור X.509 רגיל שנגזר מזוג המפתחות שלכם.
  • הרשמה: מוודאים שהאישור הציבורי שלכם רשום ב-Google Wallet.

לוגיקה של יצירת בקשות

כדי ליצור בקשה, צריך להשתמש במפתח הפרטי ולעטוף את מטען הייעודי (payload) ב-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, פועלים לפי השלבים הבאים:

עדכון יחסי תלות

בקובץ build.gradle של הפרויקט, מעדכנים את יחסי התלות כדי להשתמש ב-Credential Manager (בטא):

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

הגדרת Credential Manager

כדי להגדיר ולאתחל אובייקט CredentialManager, מוסיפים לוגיקה דומה ללוגיקה הבאה:

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

מאפייני זהות בבקשה

במקום לציין פרמטרים נפרדים לבקשות לזיהוי, האפליקציה מספקת את כולם יחד כמחרוזת JSON בתוך CredentialOption. Credential Manager מעביר את מחרוזת ה-JSON הזו לארנקים הדיגיטליים הזמינים בלי לבדוק את התוכן שלה. כל ארנק אחראי לפעולות הבאות: – ניתוח מחרוזת ה-JSON כדי להבין את בקשת הזהות. – קביעה אילו מהפרטים המאוחסנים שלה, אם יש כאלה, עומדים בדרישות הבקשה.

אנחנו ממליצים לשותפים ליצור את הבקשות שלהם בשרת, גם בשילובים של אפליקציות ל-Android.

משתמשים ב-requestJson מתוך Request Format בתור request בקריאה לפונקציה GetDigitalCredentialOption().

// 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 מכילה identityToken (JWT) מוצפן, כפי שמוגדר על ידי W3C. אפליקציית Google Wallet אחראית ליצירת התגובה הזו.

דוגמה:

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

תעבירו את התגובה הזו בחזרה לשרת כדי לאמת את האותנטיות שלה. כאן אפשר למצוא את השלבים לאימות תשובה של פרטי כניסה

פיתוח אתרים

כדי לבקש פרטי כניסה לזהות באמצעות Digital Credentials API ב-Chrome או בדפדפנים נתמכים אחרים, שולחים את הבקשה הבאה.

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 יניב קובץ JSON ‏vp_token שמכיל את פרטי הכניסה

  {
    "vp_token":
    {
      "cred1": ["<base64UrlNoPadding_encoded_credential>"] // This applies to OpenID4VP 1.0 spec.
    }
  }
  1. יצירת תמליל של הסשן

    השלב הבא הוא ליצור את SessionTranscript מתוך ISO/IEC 18013-5:2021 עם מבנה העברה ספציפי ל-Android או לאינטרנט:

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

    גם במעבר בין אפליקציות ל-Android וגם במעבר בין אפליקציות לאתרים, צריך להשתמש באותו מספר חד-פעמי שבו השתמשתם כדי ליצור את credential_request.

    העברה בין מכשירים ב-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, צריך לאמת את תגובת המכשיר בהתאם לסעיף 9 בתקן ISO/IEC 18013-5:2021.

    תהליך האימות הזה כולל כמה שלבים:

  2. בדיקת אישור המנפיק: מחלצים את שרשרת אישורי החתימה של המנפיק מ-issuerAuth ומאמתים אותה מול אישורי הבסיס המהימנים של IACA. כאן אפשר לראות את רשימת המנפיקים הנתמכים של אישורי IACA.

  3. אימות חתימה של MSO (18013-5 Section 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 והיכולות שלה מופיעה בשאלות הנפוצות.

  ...
  "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
            {
              ...

תקבלו מהארנק הוכחה מוצפנת של אפס ידע. אפשר לאמת את ההוכחה הזו מול אישורי IACA של מנפיקים באמצעות הספרייה longfellow-zk של Google.

ה-verifier-service מכיל שרת מבוסס-Docker שמוכן לפריסה, שמאפשר לכם לאמת את התגובה מול אישורים מסוימים של IACA שהונפקו על ידי הרשות המנפיקה.

אפשר לשנות את certs.pem כדי לנהל אישורי הנפקה של IACA שרוצים לתת בהם אמון.

מקורות מידע ותמיכה