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

Proteja el contenido de su suscripción mediante el cifrado del lado del cliente

Si tiene una publicación en línea, probablemente dependa de los suscriptores para obtener ingresos. Puede bloquear el contenido premium detrás de un muro de pago en el cliente mediante la ofuscación de CSS (visualización: ninguna).

Premium content is hidden until users are authenticated.

Desafortunadamente, los expertos en tecnología pueden solucionar esto.

En su lugar, es posible que a los usuarios se les muestre un documento que carece por completo de contenido premium. Y se les entregue una página completamente nueva una vez que su backend valide al usuario. Aunque es más seguro, este método cuesta tiempo, recursos y la satisfacción del usuario.

Resuelva los problemas implementando la validación de suscriptores premium y el desencriptando el contenido en el lado del cliente. Con esta solución, los usuarios con acceso premium podrán desencriptar contenido sin la necesidad de cargar una nueva página o esperar a que responda un backend

Descripción general de la configuración

Para implementar la desencriptación en el lado del cliente, se combinará la criptografía de clave simétrica y de clave pública de la siguiente manera:

  1. Cree una clave simétrica aleatoria para cada documento, permitiendo que cada documento tenga una clave única.
  2. Cifre el contenido premium con la clave simétrica de su documento.
    La clave es simétrica para permitir que la misma clave cifre y descifre el contenido.
  3. Cifre la clave del documento con una clave pública, utilizando un protocolo de cifrado híbrido para cifrar las claves simétricas.
  4. Con los componentes <amp-subscriptions> y/o <amp-subscriptions-google> almacene la clave del documento cifrado dentro del documento de AMP, junto con el contenido premium cifrado.

El documento de AMP almacena la clave cifrada dentro de sí mismo. Esto evita el disociación del documento cifrado con la clave que lo desencripta.

¿Cómo funciona?

  1. AMP analiza la clave del contenido cifrado en el documento destino del usuario.
  2. Mientras entrega el contenido premium, AMP envía la clave simétrica cifrada del documento al autorizador como parte de la recuperación de derechos del usuario.
  3. El autorizador decide si el usuario cuenta con los permisos correctos. En caso afirmativo, el autorizador desencripta la clave simétrica del documento con la clave privada del autorizador de su par de claves públicas o privadas. Después, el autorizador devuelve la clave del documento a la lógica del componente amp-subscriptions.
  4. ¡AMP desencripta el contenido premium con la clave del documento y se lo muestre al usuario!

Pasos de la implementación

Siga siguientes los pasos para integrar la administración del cifrado de AMP con su servidor de derechos interno.

Paso 1: crear un par de claves públicas o privadas

Para cifrar la clave simétrica del documento, debe tener su propio par de claves públicas o privadas. El cifrado de claves públicas es un protocolo de cifrado híbrido, específicamente es un método de cifrado asimétrico ECIES de curva elíptica P-256 con un método de cifrado simétrico AES-GCM (128-bits).

Además, es necesario que la administración de claves públicas se realice con Tink utilizando este tipo de clave asimétrica. Para crear su par de claves públicas y privadas, utilice cualquiera de los siguientes:

Ambos son compatibles con la rotación de claves. La implementación de la rotación de claves limita la vulnerabilidad a una clave privada riesgosa.

Para ayudarlo a comenzar a crear claves asimétricas, creamos este script:

  1. Cree un nuevo ECIES con clave AEAD.
  2. Envíe la clave pública en texto sin formato a un archivo de salida.
  3. Envíe la clave privada a otro archivo de salida.
  4. Cifre la clave privada generada mediante una clave alojada en Google Cloud (GCP) antes de escribir en el archivo de salida (comúnmente conocido como Envoltura de cifrado).

Es necesario almacenar o publicar su conjunto de claves Tink públicas en formato JSON. Esto permite que otras herramientas proporcionadas por AMP funcionen de forma eficiente. Nuestro script ya genera la clave pública en este formato.

Paso 2: Cifrar los artículos

Decida si hará el cifrado manual del contenido premium o hará el cifrado automático del contenido premium.

Cifrado manual

Es necesario el método simétrico AES-GCM 128 que utiliza Tink para cifrar contenido premium. La clave simétrica del documento que se utiliza para cifrar el contenido premium debe ser única para cada documento. Agregue la clave del documento a un objeto JSON que incluya la clave en texto sin formato codificado en base64, así como los SKU necesarios para acceder al contenido cifrado del documento.

En el siguiente objeto JSON se incluye un ejemplo de la clave en texto sin formato codificado en base64 y el SKU.

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

Cifre el objeto JSON anterior utilizando la clave pública generada en Crear un par de claves públicas o privadas.

Agregue el resultado cifrado como valor a la clave "local". Coloque el par clave-valor dentro de un objeto JSON envuelto dentro de una etiqueta <script type="application/json" cryptokeys="">. Coloque la etiqueta en el encabezado del documento.

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

Debe cifrar la clave del documento con el entorno local y la clave pública de Google. Incluir la clave pública de Google permite que el caché AMP de Google entregue su documento. Debe crear una instancia de un Tink Keyset para aceptar la clave pública de Google desde su URL:

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

La clave pública de Google es un Tink Keyset en formato JSON. Consulte aquí un ejemplo de cómo trabajar con este conjunto de claves.

Lectura: Consulte un ejemplo de un documento AMP cifrado que funciona.

Cifrado automático

Cifre el documento mediante nuestro script. El script acepta un documento HTML y encripta todo el contenido dentro de las etiquetas <section subscriptions-section="content" encrypted>. Utilizando las claves públicas ubicadas en las URL que se le transfieren, el script cifra la clave del documento que crea el script. El uso de esta secuencia de comandos garantiza que todo el contenido esté codificado y formateado correctamente para su publicación. Aquí se encuentra la información para obtener más instrucciones sobre el uso de este script.

Paso 3: Integrar el autorizador

Debe actualizar su autorizador para descifrar las claves del documento cuando un usuario tiene los derechos correctos. El componente amp-subscriptions envía automáticamente la clave del documento cifrada al autorizador "local" a través de un parámetro URL “crypt=”, el cual realiza:

  1. Un análisis de la clave en el documento del campo con una clave JSON "local".
  2. Desencripta documentos.

Debe utilizar Tink para desencriptar las claves de los documentos en su autorizador. Para desencriptar con Tink, cree una instancia de un cliente HybridDecrypt utilizando las claves privadas generadas en la sección Crear un par de claves públicas o privadas. Haga esto al iniciar el servidor para obtener un rendimiento óptimo.

Su implementación de HybridDecrypt o del Autorizador debe coincidir aproximadamente con su programa de rotación de claves. Esto crea disponibilidad de todas las claves generadas para el cliente HybridDecrypt.

Tink cuenta con un amplio número de documentos y ejemplos en C ++, Java, Go y Javascript para ayudarlo a comenzar con la implementación del lado del servidor.

Administración de solicitudes

Cuando llega una solicitud a su autorizador:

  1. Analice la URL de pingback de derechos para el parámetro "crypt =".
  2. Desencripta el valor del parámetro "crypt =" con base64. El valor almacenado en el parámetro de URL es el objeto JSON cifrado codificado en base64.
  3. Una vez que la clave cifrada está en su forma de bytes sin procesar, utilice la función de desencriptado de HybridDecrypt para desencriptar la clave utilizando su clave privada.
  4. Si la desencriptación se realiza correctamente, analice el resultado en un objeto JSON.
  5. Verifique el acceso del usuario a uno de los derechos que se registran en el campo JSON AccessRequirements.
  6. Se devuelve la clave en el documento del campo "Clave" que se encuentra en el objeto JSON desencriptado en la respuesta de derechos. Agregue la clave del documento desencriptado en un nuevo campo titulado "DecryptedDocumentKey" que se encuentra en la respuesta de derechos. Esto le permite el acceso al Framework AMP.

El siguiente ejemplo es un fragmento de pseudocódigo en el que se describen los pasos anteriores:

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

Recursos relacionados

Consulte la documentación y los ejemplos que se encuentran en la página de Tink Github.

Todos los scripts auxiliares están disponibles en el repositorio subscriptions-project/encryption de Github.

Ayuda adicional

Si tiene alguna pregunta, comentario o inquietud, complete una Plantilla para solucionar problemas en GitHub.