AMP

Abonelik içeriğinizi istemci tarafı şifrelemesiyle koruma

Çevrimiçi bir yayındaysanız, muhtemelen geliriniz abonelere dayanıyordur. CSS gizleme (display: none) kullanarak istemcide bir ödeme duvarının arkasındaki premium içeriği engelliyor olabilirsiniz.

Premium content is hidden until users are authenticated.

Ne yazık ki, bu sorunu genelde teknoloji bilgisi yüksek insanlar çözebilir.

Bunun yerine, kullanıcılara premium içerikten tamamen yoksun bir belge gösteriyor olabilirsiniz! Arka ucunuz kullanıcıyı doğruladığı anda tamamen yeni bir sayfa sunuyorsunuzdur. Daha güvenli olsa da, bu yöntem zamana, kaynaklara ve kullanıcı mutluluğuna mal olur.

İstemci tarafında premium abone doğrulaması ve içerik şifre çözümlemesi uygulayarak her iki sorunu çözün. Bu çözümle, premium erişime sahip kullanıcılar, yeni bir sayfa yüklemeye veya bir arka ucun yanıt vermesini beklemeye gerek kalmadan içeriğin şifresini çözebilecek!

Kuruluma genel bakış

İstemci tarafında şifre çözmeyi uygulamak için hem simetrik anahtar hem de açık anahtar şifrelemesini aşağıdaki şekilde birleştireceksiniz:

  1. Her belgeye eşsiz bir anahtar vererek her belge için rastgele bir simetrik anahtar oluşturun.
  2. Premium içeriği, belgenin simetrik anahtarıyla şifreleyin.
    Anahtar, aynı anahtarın içeriği şifrelemesine ve şifresini çözmesine izin verecek şekilde simetriktir.
  3. Simetrik anahtarları şifrelemek için bir karma şifreleme protokolü kullanarak belge anahtarını bir genel anahtarla şifreleyin.
  4. <amp-subscriptions> ve/veya <amp-subscriptions-google> bileşenlerini kullanarak, şifreli belge anahtarını, şifrelenmiş premium içerik ile birlikte AMP belgesinin içinde saklayın.

AMP belgesi, şifrelenmiş anahtarı kendi içinde depolar. Bu, şifrelenmiş belgenin şifresini çözen anahtarla ayrılmasını önler.

Nasıl çalışır?

  1. AMP, anahtarı kullanıcının açtığı belgedeki şifrelenmiş içerikten ayrıştırır.
  2. Premium içeriği sunarken AMP, kullanıcının yetkilerini getirme işleminin bir parçası olarak belgeden şifrelenmiş simetrik anahtarı yetkilendiriciye gönderir.
  3. Yetkilendirici, kullanıcının doğru izinlere sahip olup olmadığına karar verir. Yanıt evet ise, yetkilendirici belgenin simetrik anahtarının şifresini yetkilendiricinin kendi genel/özel anahtar çiftinden aldığı özel anahtarla çözer. Ardından, yetkilendirici belge anahtarını amp-subscriptions bileşen mantığına döndürür.
  4. AMP, premium içeriğin şifresini belge anahtarıyla çözer ve kullanıcıya gösterir!

Uygulama adımları

AMP şifreleme işlemini dahili yetkilendirme sunucunuza entegre etmek için aşağıdaki adımları izleyin.

1. Adım: Genel/özel anahtar çifti oluşturun

Belgenin simetrik anahtarını şifrelemek için kendi genel/özel anahtar çiftinize sahip olmanız gerekir. Açık anahtar şifreleme, karma bir şifreleme protokolüdür, özellikle de bir AES-GCM (128-bit) simetrik şifreleme yöntemiyle bir P-256 Elliptic Curve ECIES asimetrik şifreleme yöntemidir.

Bu asimetrik anahtar türü kullanılarak Tink ile genel anahtar işlemeyi zorunlu kılıyoruz. Özel-genel anahtar çiftinizi oluşturmak için aşağıdakilerden birini kullanın:

Her ikisi de anahtar rotasyonunu destekler. Anahtar rotasyonunun uygulanması, güvenliği ihlal edilmiş bir özel anahtara yönelik güvenlik açığını sınırlar.

Asimetrik anahtarlar oluşturmaya başlamanıza yardımcı olmak için bu betiği oluşturduk. Şunları yapar:

  1. AEAD anahtarı ile yeni bir ECIES oluşturur.
  2. Açık anahtarı düz metin olarak bir çıktı dosyasına aktarır.
  3. Özel anahtarı başka bir çıktı dosyasına aktarır.
  4. Oluşturulan özel anahtarı çıktı dosyasına yazmadan önce Google Cloud'da (GCP) barındırılan bir anahtarı kullanarak şifreler (bu genellikle Zarf Şifreleme olarak adlandırılır).

Genel Tink Keyset anahtarınızı JSON biçiminde depolamanızı/yayınlamanızı zorunlu kılıyoruz. Bu, AMP tarafından sağlanan diğer araçların sorunsuz çalışmasına olanak tanır. Betiğimiz zaten genel anahtarı bu biçimde çıkarır.

2. Adım: Makaleleri şifreleme

Premium içeriği manuel olarak mı yoksa otomatik olarak mı şifreleyeceğinize karar verin.

Manuel Olarak Şifreleme

Premium içeriği şifrelemek için Tink kullanan AES-GCM 128 simetrik yöntemini gerekli kılıyoruz. Premium içeriği şifrelemek için kullanılan simetrik belge anahtarı, her belge için benzersiz olmalıdır. Belge anahtarını, base64 kodlu düz metinde anahtarın yanı sıra belgenin şifrelenmiş içeriğine erişmek için gereken SKU'ları içeren bir JSON nesnesine ekleyin.

Aşağıdaki JSON nesnesi, base64 kodlu düz metin ve SKU'daki anahtarın bir örneğini içerir.

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

Genel/Özel Anahtar Çifti Oluşturma bölümünde yaratılan genel anahtarı kullanarak yukarıdaki JSON nesnesini şifreleyin.

Şifrelenmiş sonucu, değer olarak "local" anahtarına ekleyin. Anahtar/değer çiftini bir <script type="application/json" cryptokeys=""> etiketi içine sarılmış bir JSON nesnesinin içine yerleştirin. Etiketi belgenin başına yerleştirin.

<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>

Belge anahtarını yerel ortamla ve Google'ın genel anahtarıyla şifrelemeniz gerekir. Google'ın genel anahtarının dahil edilmesi, Google AMP önbelleğinin belgenizi sunmasına izin verir. Google genel anahtarını URL'sinden kabul etmek için bir Tink Keyset oluşturmalısınız:

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

Google'ın genel anahtarı, JSON biçiminde bir Tink Keyset şeklindedir. Bu anahtar setiyle çalışma örneği için buraya bakın.

Okumaya devam edin: Çalışan bir şifrelenmiş AMP belgesi örneğine bakın.

Otomatik Şifreleme

Betiğimizi kullanarak belgeyi şifreleyin. Betik bir HTML belgesini kabul eder ve <section subscriptions-section="content" encrypted> etiketlerinin içindeki tüm içeriği şifreler. Komut, kendisine iletilen URL'lerde bulunan ortak anahtarları kullanarak, betik tarafından oluşturulan belge anahtarını şifreler. Bu betiği kullanmak, tüm içeriğin sunum için doğru şekilde kodlanmasını ve biçimlendirilmesini sağlar. Bu betiği kullanmaya dair daha fazla talimat için buraya bakın.

3. Adım: Yetkilendiriciyi entegre etme

Bir kullanıcı doğru yetkilere sahip olduğunda belge anahtarlarının şifresini çözmek için yetkilendiricinizi güncellemeniz gerekir. Amp-subscriptions bileşeni, şifrelenmiş belge anahtarını otomatik olarak bir "crypt =" URL parametresi aracılığıyla "local" yetkilendiriciye gönderir. Şunları yapar:

  1. Belge anahtarını "local" JSON anahtarı alanından ayrıştırır.
  2. Belge şifresini çözer.

Yetkilendiricinizdeki belge anahtarlarının şifresini çözmek için Tink'i kullanmanız gerekir. Tink ile şifresini çözmek için, Bir Genel/Özel Anahtar Çifti Oluşturma bölümünde yaratılan özel anahtarları kullanarak bir HybridDecrypt istemcisinin örneğini oluşturun. En iyi performans için bunu sunucu başlatılırken yapın.

HybridDecrypt/Authorizer dağıtımınız kabaca anahtar rotasyon programınızla eşleşmelidir. Bu, yaratılan tüm anahtarların HybridDecrypt istemcisi için kullanılabilir olmasını sağlar.

Tink, sunucu tarafı uygulamanıza başlamanıza yardımcı olacak C++, Java, Go ve Javascript'te kapsamlı belgelere ve örneklere sahiptir.

İstek yönetimi

Yetkilendiricinize bir istek geldiğinde:

  1. “crypt=” parametresi için yetki geri pingi URL'sini ayrıştırın.
  2. "crypt=" parametre değerinin kodunu base64 ile çözün. URL parametresinde saklanan değer, base64 kodlu şifreli JSON nesnesidir.
  3. Şifrelenmiş anahtar ham bayt biçiminde olduğunda, özel anahtarınızı kullanarak anahtarın şifresini çözmek için HybridDecrypt'in şifre çözme işlevini kullanın.
  4. Şifre çözme başarılı olursa, sonucu bir JSON nesnesine ayrıştırın.
  5. Kullanıcının AccessRequirements JSON alanında listelenen yetkilerden birine erişimini doğrulayın.
  6. Yetki yanıtında şifresi çözülmüş JSON nesnesinin "Anahtar" alanından belge anahtarını döndürün. Yetkilendirmeler yanıtında "decryptedDocumentKey" adlı yeni bir alana şifresi çözülmüş belge anahtarını ekleyin. Bu, AMP çerçevesine erişim sağlar.

Aşağıdaki örnek, yukarıdaki açıklama adımlarını özetleyen sözde bir kod parçacığıdır:

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;
}

İlgili kaynaklar

Tink Github sayfasında bulunan belgelere ve örneklere göz atın.

Tüm yardımcı betikler abonelikler-proje / şifreleme Github bilgi havuzundadır.

Daha fazla destek

Herhangi bir sorunuz, yorumunuz veya kuşkunuz için lütfen bir Github Konusu açın.