Google berkomitmen untuk mendorong terwujudnya keadilan ras bagi komunitas Kulit Hitam. Lihat caranya.

SafetyNet Attestation API

SafetyNet Attestation API adalah API anti-penyalahgunaan yang memungkinkan developer aplikasi mengevaluasi perangkat Android yang menjalankan aplikasi mereka. API ini harus digunakan sebagai bagian dari sistem deteksi penyalahgunaan untuk membantu menentukan apakah server Anda berinteraksi dengan aplikasi asli yang berjalan di perangkat Android asli.

SafetyNet Attestation API memberikan pengesahan yang ditandatangani secara kriptografis, sehingga akan mengevaluasi integritas perangkat. Untuk membuat pengesahan ini, API memeriksa lingkungan software dan hardware perangkat, yang dilakukan untuk mencari masalah integritas, dan membandingkannya dengan data referensi untuk perangkat Android yang disetujui. Pengesahan yang dihasilkan terikat dengan nonce yang disediakan aplikasi pemanggil. Pengesahan ini juga memuat stempel waktu pembuatan dan metadata tentang aplikasi yang meminta.

API ini tidak dirancang untuk memenuhi kasus penggunaan berikut:

  • Bertindak sebagai mekanisme anti-penyalahgunaan atau keamanan aplikasi yang berdiri sendiri. Gunakan API ini sebagai kombinasi dengan praktik terbaik untuk keamanan aplikasi dan berbagai sinyal anti-penyalahgunaan khusus untuk produk Anda.
  • Berfungsi saat perangkat tidak tersambung ke internet. Dalam skenario tersebut, API akan menampilkan error.
  • Meminta responsnya ditafsirkan langsung di aplikasi yang memanggil. Pindahkan semua logika keputusan anti-penyalahgunaan ke server yang berada di bawah kendali Anda.
  • Menyediakan sinyal terperinci tentang modifikasi sistem. API ini menawarkan nilai boolean yang mengekspresikan berbagai tingkat integritas sistem.
  • Berisi sinyal kasus penggunaan untuk aplikasi tertentu, seperti ID perangkat, status emulasi GPS, dan status penguncian layar.
  • Mengganti atau menerapkan pemeriksaan DRM yang kuat.
  • Murni memeriksa apakah perangkat di-root, karena API ini dirancang untuk memeriksa integritas perangkat secara keseluruhan.

Ringkasan

SafetyNet Attestation API menggunakan alur kerja berikut:

  1. SafetyNet Attestation API menerima panggilan dari aplikasi Anda. Panggilan ini dapat menyertakan nonce.
  2. Layanan SafetyNet Attestation mengevaluasi lingkungan runtime dan meminta pengesahan bertanda tangan atas hasil evaluasi tersebut dari server Google.
  3. Server Google mengirimkan pengesahan bertanda tangan ke layanan SafetyNet Attestation di perangkat.
  4. Layanan SafetyNet Attestation mengembalikan pengesahan bertanda tangan ini ke aplikasi Anda.
  5. Aplikasi Anda meneruskan pengesahan bertanda tangan ke server Anda.
  6. Server memvalidasi respons dan menggunakannya untuk keputusan anti-penyalahgunaan. Server menyampaikan temuannya ke aplikasi Anda.

Gambaran grafis proses ini ditampilkan pada Gambar 1:

Gambar 1. Protokol SafetyNet Attestation API

Catatan: Dokumentasi dan checklist tambahan

Selama inisialisasi, konfigurasi, dan aktivasi SafetyNet Attestation API, dan selain dokumentasi utama ini, perhatikan dan patuhi saran berikut:

Mendapatkan kunci API

Untuk memanggil metode SafetyNet Attestation API, Anda harus menggunakan kunci API. Untuk membuat dan menyematkan kunci ini, selesaikan langkah-langkah berikut:

  1. Buka halaman Library di Google API Console.
  2. Telusuri, lalu pilih, Android Device Verification API. Layar dasbor Android Device Verification API akan ditampilkan.
  3. Jika API belum diaktifkan, klik Aktifkan.
  4. Jika tombol Buat kredensial ditampilkan, klik tombol tersebut untuk membuat kunci API. Jika tidak, klik menu drop-down Semua kredensial API, lalu pilih kunci API yang terkait dengan project Anda yang telah mengaktifkan Android Device Verification API.
  5. Di sidebar sebelah kiri, klik Kredensial. Salin kunci API yang ditampilkan.
  6. Gunakan kunci API ini saat Anda memanggil metode attest() class SafetyNetClient.

Setelah membuat kunci API ini, ikuti milis klien SafetyNet API.

Kuota dan pemantauan API

Penting: Alokasi kuota default (per project) untuk memanggil Safety Attestation API adalah 10.000 permintaan per hari.

Jika aplikasi Anda memerlukan kuota yang lebih tinggi, ajukan permintaan sebelum men-deploy aplikasi ke pengguna. Untuk melakukannya, ikuti langkah berikut:

  1. Baca seluruh dokumentasi yang disediakan untuk API ini. Permintaan yang tidak sesuai dengan praktik terbaik yang direkomendasikan dapat ditolak.
  2. Isi formulir permintaan kuota.
  3. Tunggu email konfirmasi yang menunjukkan kapan permintaan Anda diproses. Biasanya permintaan akan ditangani dalam 2-3 hari kerja.

Catatan: Terlepas dari kuota yang disediakan untuk project Anda, instance aplikasi individual dibatasi ke maksimum 5 permintaan per menit. Jika batas ini terlampaui, semua permintaan yang tersisa selama menit tersebut akan menampilkan error.

Perhatikan perilaku ini saat menerapkan mekanisme coba ulang aplikasi Anda.

Terlepas dari kuota API aplikasi Anda, sebaiknya siapkan pemantauan dan pemberitahuan kuota.

Memeriksa versi layanan Google Play

Sebelum menggunakan SafetyNet Attestation API, Anda harus memastikan bahwa layanan Google Play dengan versi yang benar telah diinstal di perangkat pengguna. Jika versi yang diinstal salah, aplikasi Anda dapat berhenti merespons setelah memanggil API. Jika aplikasi mendeteksi bahwa versi yang diinstal salah, Anda harus meminta pengguna mengupdate aplikasi layanan Google Play di perangkat mereka.

Untuk memeriksa kompatibilitas versi layanan Google Play yang terinstal dengan versi Android SDK yang Anda gunakan, panggil metode isGooglePlayServicesAvailable(), seperti yang ditampilkan dalam cuplikan kode berikut:

if (GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context)
            == ConnectionResult.SUCCESS) {
      // The SafetyNet Attestation API is available.
    } else {
      // Prompt user to update Google Play services.
    }
    

Pada perangkat yang menjalankan Layanan Google Play v13.0 dan yang lebih baru, SafetyNet Attestation API juga mendukung kunci API yang dibatasi aplikasi. Fitur ini mengurangi risiko penggunaan yang tidak disengaja atau tidak sah dari kunci API yang memiliki batasan kuota. Untuk menggunakan fitur opsional ini, pastikan versi minimum Layanan Google Play di perangkat tersebut setidaknya v13.0, seperti yang ditampilkan dalam cuplikan kode berikut:

if (GoogleApiAvailability.getInstance()
        .isGooglePlayServicesAvailable(context, 13000000) ==
        ConnectionResult.SUCCESS) {
      // The SafetyNet Attestation API is available.
    } else {
      // Prompt user to update Google Play Services.
    }
    

Meminta pengesahan SafetyNet

Setelah Anda mendapatkan kunci API yang valid untuk Android Device Verification API di Konsol API Google, aplikasi Anda dapat menggunakan layanan SafetyNet Attestation. Caranya, ikuti langkah-langkah berikut:

  1. Dapatkan nonce.
  2. Minta pengesahan SafetyNet.
  3. Transfer responsnya ke server Anda.
  4. Gunakan respons tersebut di server Anda, bersama dengan sinyal anti-penyalahgunaan lainnya, untuk mengontrol perilaku aplikasi Anda.

Agar aplikasi Anda tetap responsif, jalankan langkah-langkah ini di luar thread eksekusi utama aplikasi Anda. Untuk mempelajari lebih lanjut cara membuat thread eksekusi terpisah, lihat Mengirimkan operasi ke beberapa thread.

Anda harus melakukan pemeriksaan ini untuk melindungi semua tindakan penting—termasuk login, pembelian, dan pemerolehan produk dalam aplikasi yang baru—di aplikasi Anda. Panggilan ke SafetyNet Attestation API menyebabkan peningkatan latensi, penggunaan data seluler, dan penggunaan baterai, sehingga temukan keseimbangan antara keamanan dan kegunaan. Sebagai contoh, Anda dapat memilih untuk meminta pengesahan SafetyNet setelah login dan menjalankan pemeriksaan ulang paling banyak sekali setiap 30 menit. Anda juga dapat mengizinkan server memutuskan kapan aplikasi Anda meminta pengesahan, untuk mempersulit pihak-pihak tidak bertanggung jawab yang ingin memprediksi waktu pemeriksaan Anda.

Mendapatkan nonce

Saat memanggil SafetyNet Attestation API, Anda harus meneruskan nonce. Pengesahan yang dihasilkan akan memuat nonce ini, yang memungkinkan Anda menentukan bahwa pengesahan itu adalah milik panggilan API Anda dan belum diputar ulang oleh penyerang.

Nonce yang digunakan dengan permintaan SafetyNet harus memiliki panjang minimal 16 byte. Anda harus memasukkan variabilitas ke dalam nonce, untuk memastikan bahwa nonce yang sama tidak digunakan dua kali. Sebagai praktik terbaik, ambil bagian nonce dari data yang dikirim ke server Anda. Misalnya, gabungkan hash nama pengguna dengan stempel waktu permintaan untuk membentuk nonce.

Penting: Sertakan sebanyak mungkin data dalam nonce. Dengan demikian, Anda mempersulit penyerang untuk melakukan serangan putar ulang. Misalnya, mengambil nonce dari nama pengguna akan membatasi serangan putar ulang pada akun yang sama. Namun, mengambil nonce dari semua detail sebuah peristiwa pembelian akan membatasi penggunaan pesan respons API pada peristiwa pembelian itu saja.

Setelah menerima respons bertanda tangan dari API, selalu bandingkan nonce dalam respons bertanda tangan dengan nonce yang Anda buat dari pesan lainnya yang dikirim ke server Anda. Pemeriksaan ini memastikan bahwa penyerang tidak dapat menggunakan kembali pengesahan bertanda tangan yang diambil dari perangkat yang baik untuk membuat permintaan lain yang berbahaya.

Untuk informasi tambahan tentang penggunaan fungsi kriptografi, lihat panduan cara menggunakan kriptografi.

Meminta pengesahan

Setelah Anda tersambung ke layanan Google Play dan telah membuat nonce, Anda siap membuat permintaan pengesahan SafetyNet. Respons atas permintaan Anda mungkin tidak segera, jadi sebaiknya siapkan pemroses callback untuk menangani respons dari layanan. Contoh pemroses muncul dalam cuplikan kode berikut:

Kotlin

    SafetyNet.getClient(this).attest(nonce, API_KEY)
        .addOnSuccessListener(this) {
            // Indicates communication with the service was successful.
            // Use response.getJwsResult() to get the result data.
        }
        .addOnFailureListener(this) { e ->
            // An error occurred while communicating with the service.
            if (e is ApiException) {
                // An error with the Google Play services API contains some
                // additional details.
                val apiException = e as ApiException

                // You can retrieve the status code using the
                // apiException.statusCode property.
            } else {
                // A different, unknown type of error occurred.
                Log.d(FragmentActivity.TAG, "Error: " + e.message)
            }
        }
    

Java

    // The nonce should be at least 16 bytes in length.
    // You must generate the value of API_KEY in the Google APIs dashboard.
    SafetyNet.getClient(this).attest(nonce, API_KEY)
        .addOnSuccessListener(this,
            new OnSuccessListener<SafetyNetApi.AttestationResponse>() {
                @Override
                public void onSuccess(SafetyNetApi.AttestationResponse response) {
                    // Indicates communication with the service was successful.
                    // Use response.getJwsResult() to get the result data.
                }
            })
        .addOnFailureListener(this, new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {
                // An error occurred while communicating with the service.
                if (e instanceof ApiException) {
                    // An error with the Google Play services API contains some
                    // additional details.
                    ApiException apiException = (ApiException) e;
                    // You can retrieve the status code using the
                    // apiException.getStatusCode() method.
                } else {
                    // A different, unknown type of error occurred.
                    Log.d(TAG, "Error: " + e.getMessage());
                }
            }
        });
    

Metode onSuccess() menunjukkan bahwa komunikasi dengan layanan berhasil, tetapi tidak menunjukkan apakah perangkat lulus pengesahan SafetyNet atau tidak. Bagian selanjutnya dalam artikel ini membahas cara membaca hasil pengesahan dan memverifikasi integritasnya.

Mentransfer respons pengesahan SafetyNet ke server Anda

Saat aplikasi Anda berkomunikasi dengan SafetyNet, layanan memberikan respons yang berisi hasil pengesahan SafetyNet, dan menyertakan informasi tambahan untuk membantu Anda memverifikasi integritas pesan tersebut. Hasilnya disediakan sebagai objek SafetyNetApi.AttestationResponse. Gunakan metode getJwsResult() objek ini untuk mendapatkan data permintaan. Respons diformat sebagai Tanda tangan Web JSON (JWS).

Kirimkan objek JWS kembali ke server Anda untuk divalidasi dan digunakan.

Menggunakan respons pengesahan SafetyNet di server

Nukilan JWS berikut menunjukkan format dan contoh konten data payload:

{
      "timestampMs": 9860437986543,
      "nonce": "R2Rra24fVm5xa2Mg",
      "apkPackageName": "com.package.name.of.requesting.app",
      "apkCertificateDigestSha256": ["base64 encoded, SHA-256 hash of the
                                      certificate used to sign requesting app"],
      "ctsProfileMatch": true,
      "basicIntegrity": true,
    }
    

Payload pengesahan bertanda tangan biasanya berisi kolom-kolom berikut:

Stempel waktu respons

  • timestampMs: Milidetik setelah epoch UNIX saat pesan respons JWS dihasilkan oleh server Google.

Data yang diberikan oleh aplikasi pemanggil

  • nonce: Token sekali pakai yang diteruskan aplikasi pemanggil ke API.

Data tentang aplikasi pemanggil

  • apkPackageName: Nama paket aplikasi pemanggil.
  • apkCertificateDigestSha256: Representasi berenkode Base-64 dari hash SHA-256 untuk sertifikat penandatanganan aplikasi pemanggil.

Verdict integritas

  • ctsProfileMatch: Verdict integritas perangkat yang lebih ketat. Jika ctsProfileMatch bernilai true, maka profil perangkat yang menjalankan aplikasi Anda cocok dengan profil perangkat yang telah lulus uji kompatibilitas Android.
  • basicIntegrity: Verdict integritas perangkat yang lebih longgar. Jika hanya basicIntegrity yang bernilai true, maka perangkat yang menjalankan aplikasi Anda kemungkinan tidak dimodifikasi. Tetapi, perangkat tersebut belum tentu lulus uji kompatibilitas Android.

    Untuk informasi selengkapnya tentang pengujian kompatibilitas Android, lihat Mendesain Perangkat Android serta Kompatibilitas Android dan Paket Pengujian Kompatibilitas (CTS).

Kolom opsional

  • error: Informasi error berenkode yang relevan dengan permintaan API saat ini.
  • advice: Saran tentang cara mengembalikan perangkat ke kondisi yang baik.

Verdict integritas yang berpotensi

Pesan JWS berisi dua parameter yang menunjukkan hasil pemeriksaan kompatibilitas perangkat: ctsProfileMatch dan basicIntegrity. Status perangkat yang menjalankan aplikasi Anda dapat memengaruhi nilai setiap parameter, seperti ditunjukkan pada Tabel 1:

Tabel 1. Contoh pengaruh status perangkat terhadap nilai basicIntegrity dan ctsProfileMatch

Status Perangkat Nilai ctsProfileMatch Nilai basicIntegrity
Perangkat tersertifikasi, asli, dan lolos CTS true true
Perangkat tersertifikasi dengan bootloader tidak terkunci false true
Perangkat asli tetapi tidak tersertifikasi, misalnya produsen tidak mengajukan sertifikasi false true
Perangkat dengan ROM kustom (tidak di-root) false true
Emulator false false
Tidak ada perangkat (seperti skrip pengemulasi protokol) false false
Tanda-tanda penyusupan integritas sistem, salah satunya mungkin dengan metode rooting false false
Tanda-tanda serangan aktif lainnya, seperti hooking API false false

Kasus error

Pesan JWS juga dapat menampilkan beberapa jenis kondisi error:

  • Hasil null menunjukkan bahwa panggilan ke layanan tidak selesai dengan baik.
  • Parameter error di JWS menunjukkan bahwa masalah telah terjadi, seperti error jaringan atau error yang dipalsukan penyerang. Sebagian besar error bersifat sementara dan akan menghilang jika Anda melakukan panggilan lain ke layanan. Sebaiknya Anda mencoba lagi beberapa kali dengan menambah lamanya penundaan antara setiap percobaan ulang.
  • Jika perangkat dimodifikasi — artinya, jika basicIntegrity dalam respons ditetapkan ke salah — verdict mungkin tidak memuat data tentang aplikasi pemanggil, seperti apkPackageName dan apkCertificateDigestSha256. Hal ini terjadi saat sistem kami tidak dapat menentukan dengan pasti aplikasi pemanggil tersebut.

Apa yang harus dilakukan jika pengesahan bertanda tangan melaporkan error?

  • Coba lagi. Error pada perangkat yang sah bersifat sementara dan akan menghilang jika Anda melakukan panggilan lain ke layanan.
  • Pastikan aplikasi Anda tidak memanggil API lebih dari 5 kali per detik di perangkat yang terpengaruh dan kuota API project Anda belum habis.
  • Asumsikan bahwa mungkin penyerang sengaja memicu kasus error untuk menyamarkan aktivitasnya.

Saran agar lulus pemeriksaan mendatang

Jika tersedia, advice menyediakan informasi untuk membantu menjelaskan mengapa SafetyNet Attestation API menetapkan ctsProfileMatch atau basicIntegrity ke salah dalam hasil tertentu. Nilai parameter ini berisi daftar string, seperti dalam contoh berikut:

{"advice": "LOCK_BOOTLOADER,RESTORE_TO_FACTORY_ROM"}
    

Di aplikasi, Anda dapat menerjemahkan nilai dalam parameter saran menjadi pesan yang mudah digunakan untuk membantu pengguna lulus dalam pengesahan SafetyNet selanjutnya, seperti ditunjukkan dalam daftar berikut:

LOCK_BOOTLOADER
Pengguna harus mengunci bootloader perangkatnya.
RESTORE_TO_FACTORY_ROM
Pengguna harus memulihkan perangkat ke ROM asli pabrik.

Memverifikasi respons pengesahan SafetyNet

Anda harus memastikan bahwa respons pengesahan SafetyNet benar-benar berasal dari layanan SafetyNet dan menyertakan data yang cocok dengan permintaan Anda.

Untuk memverifikasi asal pesan JWS, selesaikan langkah-langkah berikut:

  1. Ekstrak rantai sertifikat SSL dari pesan JWS.
  2. Validasi rantai sertifikat SSL tersebut dan gunakan pencocokan hostname SSL untuk memverifikasi bahwa sertifikat leaf itu diterbitkan untuk hostname attest.android.com.
  3. Gunakan sertifikat tersebut untuk memverifikasi tanda tangan pesan JWS.
  4. Periksa data pesan JWS untuk memastikan kecocokannya dengan data dalam permintaan awal Anda. Secara khusus, pastikan stempel waktu telah divalidasi dan bahwa nonce, nama paket, dan hash sertifikat penandatanganan aplikasi sesuai dengan nilai yang diharapkan.

Anda perlu memverifikasi pernyataan JWS menggunakan solusi kriptografis standar, seperti yang tercantum dalam contoh penggunaan API android-play-safetynet, yang tersedia di GitHub.

Selama pengujian awal dan pengembangan (tetapi tidak selama produksi), Anda dapat memanggil API online untuk memverifikasi tanda tangan pernyataan JWS. Proses ini juga telah ditampilkan dalam contoh penggunaan API android-play-safetynet di GitHub. Perhatikan bahwa API verifikasi online ditujukan semata-mata untuk pengujian tahap awal, dan Anda memiliki kuota tetap sebesar 10.000 permintaan per hari.

Penting: Penggunaan API verifikasi online hanya memvalidasi bahwa pesan JWS ditandatangani oleh server SafetyNet Attestation API. API online ini tidak dapat memverifikasi apakah kolom-kolom dalam payload cocok dengan nilai yang diharapkan oleh layanan Anda.

Membuat rencana untuk menangani kasus tidak terduga

Sebaiknya rencanakan penggunaan Anda dengan memperhitungkan perubahan dan gangguan.

Perubahan API
Kolom-kolom baru (eksperimental) dapat muncul dalam verdict kapan saja. Pastikan kolom tambahan ini tidak merusak parser atau logika penggunaan Anda. Secara khusus, jangan mengandalkan kolom eksperimental sebelum diumumkan di milis klien SafetyNet API.
SafetyNet Attestation API tidak aktif

Jika SafetyNet Attestation API tidak tersedia, pengguna sangat dianjurkan untuk membuat kapabilitas di sistem server yang secara dinamis mampu mengontrol ketergantungan pada ketersediaan serta kualitas API ini beserta responsnya.

Strategi standar harus menyertakan kemampuan untuk secara dinamis memerintahkan aplikasi agar berhenti memanggil API ini, serta daftar akses yang diizinkan baik berdasarkan aplikasi maupun perangkat untuk mengabaikan hasil SafetyNet Attestation API bagi class perangkat dan pengguna tertentu.

Contoh Kode

Untuk panduan tambahan tentang menggunakan SafetyNet API, lihat contoh kode yang tersedia di GitHub.

Daftar Pengumuman

Sebaiknya Anda mengikuti milis klien SafetyNet API untuk menerima info terbaru tentang SafetyNet Attestation API.

Masukan

Pertimbangkan untuk memberikan masukan Anda terkait API ini. Kami menggunakan masukan Anda untuk memprioritaskan fitur dan kemampuan baru untuk API ini.

Selengkapnya

Untuk mempelajari lebih lanjut praktik terbaik penggunaan SafetyNet Attestation API, lihat link berikut:

Persyaratan layanan tambahan

Dengan mengakses atau menggunakan SafetyNet API, Anda menyetujui Persyaratan Layanan Google API, dan Persyaratan Tambahan berikut. Harap baca dan pahami semua persyaratan dan kebijakan yang berlaku sebelum mengakses API.

Persyaratan Layanan SafetyNet

Seperti halnya data yang dikumpulkan dalam jumlah besar dari pengamatan di lapangan, ada kemungkinan munculnya positif palsu (PP) dan negatif palsu (NP). Kami menyajikan data sebaik-baiknya sesuai dengan pemahaman kami. Kami menguji mekanisme pendeteksian kami secara ekstensif untuk memastikan akurasinya, dan kami berkomitmen untuk menyempurnakan metode tersebut dari waktu ke waktu untuk memastikan metode tersebut tetap akurat.

Anda setuju untuk mematuhi semua hukum, peraturan, dan hak pihak ketiga yang berlaku (termasuk, tanpa batasan, undang-undang yang mengatur impor atau ekspor data atau software, privasi, dan hukum setempat). Anda tidak boleh menggunakan API untuk mendorong atau mempromosikan kegiatan ilegal atau pelanggaran terhadap hak-hak pihak ketiga. Anda tidak boleh melanggar persyaratan layanan lainnya dengan Google (atau afiliasinya).

Anda menerima dan memahami bahwa SafetyNet API bekerja dengan mengumpulkan informasi hardware dan software, seperti data perangkat dan aplikasi, serta hasil pengesahan SafetyNet, dan mengirimkan data tersebut ke Google untuk dianalisis. Berdasarkan Pasal 3(d) Persyaratan Layanan Google API, Anda setuju bahwa jika Anda menggunakan API, Anda bertanggung jawab untuk memberikan pemberitahuan atau persetujuan apa pun yang diperlukan terkait pengumpulan dan pembagian data ini dengan Google.