Tanda pengenal digital dapat diterima dalam alur dalam aplikasi dan web. Untuk menerima kredensial dari Google Wallet, Anda harus:
- Lakukan integrasi menggunakan aplikasi atau web dengan mengikuti petunjuk yang diberikan.
- Gunakan ID pengujian untuk menguji alur Anda di sandbox Google Wallet.
- Saat Anda siap untuk mengaktifkan fitur ini, isi formulir ini untuk meminta dan menyetujui persyaratan layanan terkait penerimaan kredensial dari Google Wallet.
Prasyarat
Untuk menguji presentasi tanda pengenal secara digital, Anda harus mendaftar terlebih dahulu ke program beta publik menggunakan akun pengujian yang dimaksud (akun ini harus berupa akun Gmail). Selanjutnya, berikan detail berikut kepada kontak Google yang ditetapkan bagi Anda.
- Link Persyaratan Layanan
- Logo
- Situs
- ID paket aplikasi (untuk integrasi aplikasi Android)
- Termasuk build dev / debug
- Tanda tangan aplikasi
$ $ANDROID_SDK/build-tools/$BUILD_TOOLS_VERSION/apksigner verify --print-certs -v $APK
- ID Gmail yang digunakan untuk bergabung dengan versi beta publik
Format Kredensial yang Didukung
Ada beberapa standar yang diusulkan yang menentukan format data dokumen identitas digital, dengan dua di antaranya mendapatkan daya tarik industri yang signifikan:
- mdocs - ditentukan oleh ISO.
- w3c Verifiable Credentials - ditentukan oleh w3c.
Meskipun Pengelola Kredensial Android mendukung kedua format tersebut, Google Wallet saat ini hanya mendukung ID Digital berbasis mdoc.
Kredensial yang Didukung
Google Wallet mendukung 2 jenis kredensial:
- Surat Izin Mengemudi Digital (mDL)
- Tanda pengenal digital
Anda dapat meminta kredensial dalam alur dengan satu perubahan parameter.
Pengalaman pengguna
Bagian ini membahas alur presentasi online yang direkomendasikan. Alur ini menunjukkan penyajian usia ke aplikasi untuk pengiriman minuman beralkohol, tetapi UX-nya serupa untuk web dan jenis penyajian lainnya.
![]() |
![]() |
![]() |
![]() |
![]() |
Pengguna diminta untuk memverifikasi usia di aplikasi atau situs | Pengguna melihat kredensial yang memenuhi syarat dan tersedia | Pengguna melihat halaman konfirmasi di Google Wallet | Pengguna Melakukan Autentikasi untuk mengonfirmasi berbagi | Data yang dikirim ke aplikasi atau situs |
Catatan Penting
- Aplikasi atau situs memiliki fleksibilitas dalam cara membuat titik entri ke API. Seperti yang ditunjukkan di Langkah 1, sebaiknya tampilkan tombol umum seperti "Verifikasi dengan tanda pengenal digital" karena seiring waktu kami berharap opsi di luar Google Wallet akan tersedia melalui API.
- Layar pemilih pada langkah 2 dirender oleh Android. Kredensial yang memenuhi syarat ditentukan oleh kecocokan antara logika pendaftaran yang disediakan oleh setiap Wallet dan permintaan yang dikirim oleh pihak tepercaya
- Langkah 3 ditampilkan oleh Google Wallet. Google Wallet akan menampilkan nama, logo, dan kebijakan privasi yang diberikan developer di layar ini.
Menambahkan alur tanda pengenal digital
Jika pengguna tidak memiliki kredensial, sebaiknya berikan link di samping tombol "Verifikasi dengan tanda pengenal digital" yang akan melakukan deep link ke Google Wallet agar pengguna dapat menambahkan tanda pengenal digital.
![]() |
![]() |
Pengguna diminta untuk memverifikasi usia di aplikasi atau situs | Pengguna diarahkan ke Google Wallet untuk mendapatkan tanda pengenal digital |
Tidak ada tanda pengenal digital yang tersedia
Jika pengguna memilih opsi "Verifikasi dengan ID digital" tanpa memiliki ID digital, pesan error ini akan ditampilkan.
![]() |
![]() |
Pengguna diminta untuk memverifikasi usia di aplikasi atau situs | Pengguna akan melihat pesan error jika tidak memiliki tanda pengenal digital |
API ini tidak mendukung fitur untuk mempelajari secara diam-diam apakah pengguna memiliki ID digital yang tersedia untuk menjaga privasi pengguna. Oleh karena itu, sebaiknya sertakan opsi link aktivasi seperti yang ditunjukkan.
Format Permintaan untuk meminta kredensial ID dari dompet
Berikut adalah contoh permintaan mdoc requestJson
untuk mendapatkan kredensial Identitas
dari dompet mana pun di perangkat Android atau web.
{
"requests" : [
{
"protocol": "openid4vp",
"data": {<credential_request>} // This is an object, shouldn't be a string.
}
]
}
Meminta Enkripsi
client_metadata
berisi kunci publik enkripsi untuk setiap permintaan.
Anda harus menyimpan kunci pribadi untuk setiap permintaan dan menggunakannya untuk mengautentikasi
dan mengotorisasi token yang Anda terima dari aplikasi dompet.
Parameter credential_request
di requestJson
akan terdiri dari kolom berikut.
{
"response_type": "vp_token",
"response_mode": "dc_api.jwt",
"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"
]
},
{
"path": [
"org.iso.18013.5.1",
"given_name"
]
},
{
"path": [
"org.iso.18013.5.1",
"age_over_18"
]
}
]
}
]
},
"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",
"alg" : "ECDH-ES",
}
]
},
"authorization_encrypted_response_alg": "ECDH-ES",
"authorization_encrypted_response_enc": "A128GCM"
}
}
Anda dapat meminta sejumlah atribut yang didukung dari kredensial identitas apa pun yang disimpan di Google Wallet.
Dalam Aplikasi
Untuk meminta kredensial identitas dari aplikasi Android Anda, ikuti langkah-langkah berikut:
Memperbarui dependensi
Dalam build.gradle project, perbarui dependensi untuk menggunakan Pengelola Kredensial (beta):
dependencies {
implementation("androidx.credentials:credentials:1.5.0-beta01")
// optional - needed for credentials support from play services, for devices running Android 13 and below.
implementation("androidx.credentials:credentials-play-services-auth:1.5.0-beta01")
}
Mengonfigurasi Pengelola Kredensial
Untuk mengonfigurasi dan melakukan inisialisasi objek CredentialManager
, tambahkan logika yang mirip dengan berikut ini:
// Use your app or activity context to instantiate a client instance of CredentialManager.
val credentialManager = CredentialManager.create(context)
Meminta atribut Identitas
Daripada menentukan parameter satu per satu untuk permintaan identitas, aplikasi menyediakannya secara bersamaan sebagai string JSON dalam CredentialOption. Credential Manager meneruskan string JSON ini ke dompet digital yang tersedia tanpa memeriksa isinya. Setiap dompet kemudian bertanggung jawab untuk: - Mengurai string JSON untuk memahami permintaan identitas. - Menentukan kredensial tersimpan mana, jika ada, yang memenuhi permintaan.
Sebaiknya partner membuat permintaan mereka di server, bahkan untuk integrasi aplikasi Android.
Anda akan menggunakan requestJson
dari Format Permintaan
yang terdiri dari request
dalam panggilan fungsi 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)
}
}
Memverifikasi dan Memvalidasi respons
Setelah mendapatkan respons kembali dari wallet, Anda akan memverifikasi apakah respons berhasil dan berisi respons 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}")
}
}
Respons credentialJson
berisi identityToken (JWT) terenkripsi,
yang ditentukan oleh W3C. Aplikasi Wallet bertanggung jawab untuk membuat respons ini.
Contoh:
{
"protocol" : "openid4vp",
"data" : {
<encrpted_response>
}
}
Anda akan meneruskan respons ini kembali ke server untuk memvalidasi keasliannya. Anda dapat menemukan langkah-langkah untuk memvalidasi respons kredensial.
Web
Untuk meminta Kredensial Identitas menggunakan Digital Credentials API di Chrome, Anda harus mendaftar ke uji coba origin Digital Credentials API.
const credentialResponse = await navigator.credentials.get({
digital : {
requests : [
{
protocol: "openid4vp",
data: {<credential_request>} // This is an object, shouldn't be a string.
}
]
}
})
Kirimkan respons dari API ini kembali ke server Anda untuk memvalidasi respons kredensial
Langkah-langkah untuk Memvalidasi respons kredensial
Setelah menerima identityToken terenkripsi dari aplikasi atau situs Anda, ada beberapa validasi yang perlu Anda lakukan sebelum memercayai respons.
Mendekripsi respons menggunakan kunci pribadi
Langkah pertama adalah mendekripsi token menggunakan kunci pribadi yang disimpan dan mendapatkan JSON respons.
Contoh Python:
from jwcrypto import jwe, jwk # Retrieve the Private Key from Datastore reader_private_jwk = jwk.JWK.from_json(jwe_private_key_json_str) # 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
akan menghasilkan JSONvp_token
yang berisi kredensial{ "vp_token": { "cred1": "<credential_token>" } }
Membuat transkrip sesi
Langkah selanjutnya adalah membuat SessionTranscript dari ISO/IEC 18013-5:2021 dengan struktur Pengalihan khusus Android atau Web:
SessionTranscript = [ null, // DeviceEngagementBytes not available null, // EReaderKeyBytes not available [ "OpenID4VPDCAPIHandover", AndroidHandoverDataBytes // BrowserHandoverDataBytes for Web ] ]
Untuk penyerahan Android / web, Anda harus menggunakan nonce yang sama dengan yang Anda gunakan untuk membuat
credential_request
.Pengalihan Android
AndroidHandoverData = [ origin, // "android:apk-key-hash:<base64SHA256_ofAppSigningCert>", clientId, // "android-origin:<app_package_name>", nonce, // nonce that was used to generate credential request ] AndroidHandoverDataBytes = hashlib.sha256(cbor2.dumps(AndroidHandoverData)).digest()
Pengalihan Browser
BrowserHandoverData =[ origin, // Origin URL clientId, // "web-origin:<origin>" nonce, // nonce that was used to generate credential request ] BrowserHandoverDataBytes = hashlib.sha256(cbor2.dumps(BrowserHandoverData)).digest()
Menggunakan
SessionTranscript
, DeviceResponse harus divalidasi sesuai dengan klausul 9 ISO/IEC 18013-5:2021. Hal ini mencakup beberapa langkah, seperti:Periksa Sertifikat Penerbit Negara Bagian. Periksa sertifikat IACA penerbit yang didukung
Verifikasi tanda tangan MSO (18013-5 Bagian 9.1.2)
Menghitung dan memeriksa ValueDigest untuk Elemen Data (18013-5 Bagian 9.1.2)
Verifikasi tanda tangan
deviceSignature
(18013-5 Bagian 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
}
Menguji solusi Anda
Untuk menguji solusi Anda, bangun dan jalankan aplikasi Android penampung referensi open source kami. Berikut adalah langkah-langkah untuk membuat dan menjalankan aplikasi pemegang referensi:
- Meng-clone repositori aplikasi referensi
- Buka project di Android Studio
- Buat dan jalankan target
appholder
di perangkat atau emulator Android Anda.
Verifikasi berbasis Zero Knowledge Proof (ZKP)
Bukti Tanpa Pengetahuan (ZKP) adalah metode kriptografi yang memungkinkan seseorang (pembuktian) membuktikan kepada verifikator bahwa ia memiliki informasi identitas tertentu atau memenuhi kriteria tertentu (misalnya, berusia di atas 18 tahun, memegang kredensial yang valid) tanpa mengungkapkan data pokok yang sebenarnya. Pada dasarnya, ini adalah cara untuk mengonfirmasi kebenaran pernyataan tentang identitas seseorang sekaligus menjaga kerahasiaan detail sensitif.
Sistem identitas digital yang mengandalkan berbagi data identitas secara langsung sering kali mewajibkan pengguna untuk membagikan informasi pribadi yang berlebihan, sehingga meningkatkan risiko pelanggaran data dan pencurian identitas. ZKP menawarkan perubahan paradigma, yang memungkinkan verifikasi dengan pengungkapan minimal.
Konsep Utama ZKP dalam Identitas Digital:
- Pembuktian: Individu yang mencoba membuktikan aspek identitasnya.
- Verifier: Entitas yang meminta bukti atribut identitas.
- Bukti: Protokol kriptografi yang memungkinkan pembuktian meyakinkan verifikator tentang kebenaran klaimnya tanpa mengungkapkan informasi rahasia.
Properti Inti Bukti Tanpa Pengetahuan:
- Kelengkapan: Jika pernyataan benar dan prover serta verifier jujur, verifier akan yakin.
- Kredibilitas: Jika pernyataan salah, pembuktian yang tidak jujur tidak dapat (dengan probabilitas yang sangat tinggi) meyakinkan verifikator yang jujur bahwa pernyataan tersebut benar.
- Tanpa Pengetahuan: Verifikator tidak mempelajari apa pun selain fakta bahwa pernyataan tersebut benar. Tidak ada data sebenarnya dari identitas pembuktian yang diekspos.
Untuk mendapatkan bukti Zero Knowledge dari Google Wallet, Anda perlu mengubah
format permintaan menjadi mso_mdoc_zk
dan menambahkan zk_system_type
ke Permintaan Anda
...
"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": "2093f64f54c81fb2f7f96a46593951d04005784da3d479e4543e2190dcf205d6", //This will differ if you need more than 1 attribute.
"num_attributes": 1, // number of attributes (in claims) this has can support
"version": 2
},
{
"system": "longfellow-libzk-v1",
"circuit_hash": "2836f0df5b7c2c431be21411831f8b3d2b7694b025a9d56a25086276161f7a93", // This will differ if you need more than 1 attribute.
"num_attributes": 1, // number of attributes (in claims) this has can support
"version": 1
}
],
"verifier_message": "challenge"
},
"claims": [{
...