Do you build things with AMP? Fill out the AMP Developer Survey!
AMP

Melindungi konten langganan Anda dengan enkripsi pihak klien

Jika Anda melakukan publikasi online, Anda mungkin mengandalkan pelanggan untuk memperoleh pendapatan. Anda dapat memblokir konten premium di belakang paywall pada klien dengan menggunakan pengaburan CSS obfuscation (display: none).

Premium content is hidden until users are authenticated.

Sayangnya, orang yang pintar teknologi dapat mengakali hal ini.

Sebaliknya, Anda dapat memperlihatkan dokumen yang benar-benar kekurangan konten premium kepada pengguna! Menyajikan halaman yang sepenuhnya baru setelah backend Anda mengesahkan pengguna. Meskipun lebih aman, metode ini mengorbankan waktu, sumber daya, dan kebahagiaan pengguna.

Selesaikan kedua masalah ini dengan menerapkan validasi pelanggan premium dan dekripsi konten pada pihak atau sisi klien. Dengan solusi ini, pengguna dengan akses premium akan dapat mendekripsi konten tanpa perlu memuat halaman baru atau menunggu backend untuk menanggapi!

Gambaran umum penyiapan

Untuk menerapkan dekripsi pihak klien, Anda akan menggabungkan kriptografi kunci publik dan kunci simetris dengan cara berikut ini:

  1. Buat kunci simetris acak untuk setiap dokumen, dan berikan setiap dokumen kunci yang unik.
  2. Enkripsi konten premium dengan kunci simetris dokumennya.
    Kunci ini simetris untuk memungkinkan kunci yang sama mengenkripsi dan mendekripsi konten.
  3. Enkripsi kunci dokumen dengan kunci publik, dengan menggunakan protokol enkripsi hibrida untuk mengenkripsi kunci simetris.
  4. Dengan menggunakan komponen <amp-subscriptions> dan/atau <amp-subscriptions-google>, simpan kunci dokumen yang dienkripsi di dalam dokumen AMP, bersama konten premium yang dienkripsi.

Dokumen AMP menyimpan kunci yang dienkripsi di dalam dokumen AMP sendiri. Ini mencegah penguraian dokumen yang dienkripsi dengan kunci yang mendekodenya.

Bagaimana cara kerjanya?

  1. AMP menguraikan kunci dari konten yang dienkripsi pada dokumen tempat pengguna tiba.
  2. Sambil menyajikan konten premium, AMP mengirimkan kunci simetris yang dienkripsi dari dokumen ke pengesah (authorizer) sebagai bagian dari pengambilan hak pengguna.
  3. Pengesah memutuskan apakah pengguna mempunyai izin yang benar. Jika benar, pengesah mendekripsi kunci simetris dokumen dengan kunci pribadi pengesah dari pasangan kunci publik/pribadi mereka. Lalu, pengesah mengembalikan kunci dokumen ke logika komponen amp-subscriptions.
  4. AMP mendekripsi konten premium dengan kunci dokumen dan memperlihatkannya kepada pengguna!

Langkah-langkah penerapan

Ikuti langkah-langkah di bawah ini untuk mengintegrasikan penanganan enkripsi AMP dengan server hak internal Anda.

Langkah ke-1: Membuat pasangan kunci publik/pribadi

Untuk mengenkripsi kunci simetris dokumen, Anda perlu mempunyai pasangan kunci publik/pribadi sendiri. Enkripsi kunci publik adalah protokol enkripsi hibrida, terutama metode enkripsi asimetris ECIES Kurva Eliptis P-256 dengan metode enkripsi simetris AES-GCM (128 bit).

Penanganan kunci publik harus dilakukan dengan Tink menggunakan menggunakan jenis kunci asimetris ini. Untuk membuat pasangan kunci pribadi-publik Anda, gunakan salah satu dari yang berikut ini:

Keduanya mendukung rotasi kunci. Menerapkan rotasi kunci membatasi kerawanan kunci pribadi yang telah rusak.

Untuk membantu Anda memulai pembuatan kunci asimetris, kami telah membuat skrip ini. Skrip ini:

  1. Membuat ECIES baru dengan kunci AEAD.
  2. Mengeluarkan output kunci publik dalam teks polos ke berkas output
  3. Mengeluarkan output kunci pribadi ke berkas output lain.
  4. Mengenkripsi kunci pribadi yang dihasilkan dengan menggunakan kunci yang dikelola di Google Cloud (GCP) sebelum menulis ke berkas output, (biasa dirujuk sebagai Enkripsi Amplop).

Kami mewajibkan penyimpanan/publikasi Keyset Tink publik Anda dalam format JSON. Ini memungkinkan alat lain yang disediakan AMP berfungsi dengan lancar. Skrip kami sudah membuat output kunci publik di dalam format ini.

Langkah ke-2: Mengenkripsi artikel

Putuskan apakah Anda ingin mengenkripsi konten premium secara manual, atau mengenkripsi konten premium secara otomatis.

Mengenkripsi secara manual

Kita membutuhkan metode simetris AES-GCM 128 dengan menggunakan Tink untuk mengenkripsi konten premium. Kunci dokumen simetris yang digunakan untuk mengenkripsi konten premium harus unik untuk setiap dokumen. Tambahkan kunci dokumen ke objek JSON yang berisi kunci dalam teks polos yang dikodekan dengan base64, serta SKU yang diperlukan untuk mengakses konten dokumen yang dienkripsi.

Objek JSON di bawah ini berisi contoh kunci dalam teks polos yang dikodekan dengan base64 dan SKU.

{
  AccessRequirements: ['thenewsynews.com:premium'],
  Key: 'aBcDef781-2-4/sjfdi',
}

Enkripsi objek JSON di atas dengan menggunakan kunci publik yang dibuat di Membuat Pasangan Kunci Publik/Pribadi.

Tambahkan hasil yang dienkripsi sebagai nilai pada kunci "local". Tempatkan pasangan kunci-nilai di dalam objek JSON yang dibungkus di dalam tag <script type="application/json" cryptokeys="">. Tempatkan tag di bagian atas (head) dokumen.

<head>
...
<script type="application/json" cryptokeys="">
{
  "local": ['y0^r$t^ff'], // This is for your environment
  "google.com": ['g00g|e$t^ff'], // This is for Google's environment
}
</script></head>

Anda harus mengenkripsi kunci dokumen dengan lingkungan lokal dan kunci publik Google. Menyertakan kunci publik Google memungkinkan cache AMP Google untuk menyajikan dokumen Anda. Anda harus memberikan contoh kepada Keyset Tink untuk menerima kunci publik Google dari URL-nya:

https://news.google.com/swg/encryption/keys/prod/tink/public\_key

Kunci publik Google adalah Keyset Tink dalam format JSON. Lihat di sini untuk mengetahui contoh menggunakan keyset atau rangkaian kunci ini.

Bacalah: Melihat contoh dokumen AMP yang dienkripsi yang berhasil.

Enkripsi Otomatis

Enkripsi dokumen dengan menggunakan skrip kami. Skrip ini menerima dokumen HTML dan mengenkripsi semua konten di dalam tag <section subscriptions-section="content" encrypted>. Dengan menggunakan kunci publik yang berlokasi di URL yang diteruskan kepadanya, skrip ini mengenkripsi kunci dokumen yang dibuat oleh skrip. Menggunakan skrip ini memastikan bahwa semua konten dikodekan dan diformat dengan benar untuk penyajian. Lihat di sini untuk mengetahui instruksi lebih lanjut dalam menggunakan skrip ini.

Langkah ke-3: Mengintegrasikan pengesah

Anda perlu memperbarui pengesah Anda untuk mendekripsi kunci dokumen saat seorang pengguna mempunyai hak yang benar. Komponen amp-subscriptions secara otomatis mengirimkan kunci dokumen yang dienkripsi ke pengesah "local" melalui sebuah parameter URL “crypt=”. Parameter ini melakukan:

  1. Penguraian kunci dokumen dari bidang kunci JSON "local".
  2. Dekripsi dokumen.

Anda harus menggunakan Tink untuk mendekripsi kunci dokumen di pengesah Anda. Untuk mendekripsi dengan Tink, berikan contoh kepada klien HybridDecrypt dengan menggunakan kunci pribadi yang dihasilkan di bagian Membuat Pasangan Kunci Publik/Pribadi. Lakukan ini saat server dinyalakan untuk menghasilkan kinerja optimum.

Penggunaan HybridDecrypt/Pengesah Anda harus cocok dengan jadwal rotasi kunci Anda. Ini menciptakan ketersediaan semua kunci yang dihasilkan untuk klien HybridDecrypt.

Tink mempunyai dokumentasi yang ekstensif dan contoh-contoh dalam C++, Java, Go, dan JavaScript untuk membantu Anda memulai penerapan di sisi server Anda.

Manajemen permintaan

Saat sebuah permintaan sampai di pengesah Anda:

  1. Uraikan URL pingback hak untuk parameter “crypt=”.
  2. Dekode nilai parameter "crypt=” dengan base64. Nilai yang disimpan di parameter URL adalah berdasarkan objek JSON yang dienkripsi yang dikodekan dengan base64.
  3. Setelah kunci yang dienkripsi berada dalam bentuk byte mentah, gunakan fungsi dekripsi HybridDecrypt untuk mendekripsi kunci tersebut dengan menggunakan kunci pribadi Anda.
  4. Jika dekripsi berhasil, uraikan hasilnya ke dalam objek JSON.
  5. Verifikasi akses pengguna ke salah satu dari hak yang tercantum pada bidang JSON AccessRequirements.
  6. Hasilkan kunci dokumen dari bidang “Kunci” objek JSON yang didekripsi di dalam tanggapan hak. Tambahkan kunci dokumen yang didekripsi di dalam bidang baru berjudul “decryptedDocumentKey” di dalam tanggapan hak. Ini memberikan akses ke kerangka kerja AMP.

Sampel di bawah ini adalah snippet kode semu yang menguraikan langkah-langkah deskripsi di atas:

string decryptDocumentKey(string encryptedKey, List < string > usersEntitlements,
    HybridDecrypt hybridDecrypter) {
    // 1. Base64 decode the input encrypted key.
    bytes encryptedKeyBytes = base64.decode(encryptedKey);
    // 2. Try to decrypt the encrypted key.
    bytes decryptedKeyBytes;
    try {
        decryptedKeyBytes = hybridDecrypter.decrypt(
            encryptedKeyBytes, null /* contextInfo */ );
    } catch (error e) {
        // Decryption error occurred. Handle it how you want.
        LOG("Error occurred decrypting: ", e);
        return "";
    }
    // 3. Parse the decrypted text into a JSON object.
    string decryptedKey = new string(decryptedKeyBytes, UTF_8);
    json::object decryptedParsedJson = JsonParser.parse(decryptedKey);
    // 4. Check to see if the requesting user has the entitlements specified in
    //    the AccessRequirements section of the JSON object.
    for (entitlement in usersEntitlements) {
        if (decryptedParsedJson["AccessRequirements"]
            .contains(entitlement)) {
            // 5. Return the document key if the user has entitlements.
            return decryptedParsedJson["Key"];
        }
    }
    // User doesn't have correct requirements, return empty string.
    return "";
}

JsonResponse getEntitlements(string requestUri) {
    // Do normal handling of entitlements here…
    List < string > usersEntitlements = getUsersEntitlementInfo();

    // Check if request URI has "crypt" parameter.
    String documentCrypt = requestUri.getQueryParameters().getFirst("crypt");

    // If URI has "crypt" param, try to decrypt it.
    string documentKey;
    if (documentCrypt != null) {
        documentKey = decryptDocumentKey(
            documentCrypt,
            usersEntitlements,
            this.hybridDecrypter_);
    }

    // Construct JSON response.
    JsonResponse response = JsonResponse {
        signedEntitlements: getSignedEntitlements(),
        isReadyToPay: getIsReadyToPay(),
    };
    if (!documentKey.empty()) {
        response.decryptedDocumentKey = documentKey;
    }
    return response;
}

Sumber daya terkait

Kunjungi dokumentasi dan contoh-contoh yang ditemukan di Halaman Tink Github.

Semua skrip pembantu ada di subscriptions-project/encryption Github repo.

Dukungan lebih lanjut

Jika ada pertanyaan, komentar, atau masalah apa pun silakan ajukan Masalah Github.