Générer des signatures

Ce guide explique comment créer une signature et présente les champs obligatoires et facultatifs pour les signatures.

Pour créer une signature, vous devez composer une chaîne à signer, que nous appellerons une valeur signée dans le présent guide. La valeur signée inclut des paramètres qui décrivent le contenu que vous protégez, le délai d'expiration de la valeur signée, etc.

Vous utilisez la valeur signée lors de la création d'une chaîne de signature. Vous créez une chaîne de signature en composant les paramètres de la signature, par exemple une signature Ed25519 de clé asymétrique associée à la valeur signée.

Media CDN utilise la signature composée finale pour protéger votre contenu.

Formats de signature acceptés

Media CDN est compatible avec les formats de requête signée suivants :

Format Comportement Exemple
Paramètres de requête (URL exacte)

URL exacte, pour accorder l'accès à une URL spécifique.

Exact :

https://media.example.com/content/manifest.m3u8?
Expires=EXPIRATION
&KeyName=KEY_NAME
&Signature=SIGNATURE

Paramètres de requête (préfixe d'URL) Spécifier un URLPrefix vous permet de signer un préfixe et d'ajouter les mêmes paramètres de requête à plusieurs URL dans votre génération de lecteur ou de fichier manifeste.

Quels éléments signer :

URLPrefix=PREFIX
&Expires=EXPIRATION
&KeyName=KEY_NAME
&Signature=SIGNATURE

Remplacez PREFIX par le préfixe auquel vous souhaitez accorder l'accès, en incluant le schéma, l'hôte et le chemin d'accès partiel.

Composant de chemin

Préfixe : permet d'accéder à n'importe quelle URL avec un préfixe placé avant le composant "/edge-cache-token=[...]".

Cela permet aux URL de fichier manifeste relatif d'hériter automatiquement du composant d'URL signé lors de la récupération des sous-ressources.

https://media.example.com/video/edge-cache-token=Expires=EXPIRATION
&KeyName=KEY_NAME
&Signature=SIGNATURE/manifest_12382131.m3u8
Cookie signé Préfixe : le cookie permet d'accéder à n'importe quelle URL comportant le préfixe spécifié dans la valeur URLPrefix signée.

Edge-Cache-Cookie :

URLPrefix=PREFIX:
Expires=EXPIRATION:
KeyName=KEY_NAME:
Signature=SIGNATURE

Créer une signature

  1. Créez une valeur signée en concaténant une chaîne contenant les champs de signature requis et les champs de signature facultatifs souhaités.

    Le cas échéant, URLPrefix doit apparaître en premier, suivi de Expires, KeyName, puis de tout paramètre facultatif.

    Séparez chaque champ et tous les paramètres avec les éléments suivants :

    • Pour les cookies, utilisez le caractère deux-points :.
    • Pour les paramètres de requête et les composants de chemin d'accès, utilisez une esperluette &.
  2. Signez la valeur signée avec une signature Ed25519.

  3. Ajoutez un séparateur de champ (: ou &) suivi de Signature= et de la signature Ed25519 à la fin de la chaîne.

Créer des URL signées

L'exemple de code Python suivant montre comment créer des URL signées par programmation :

import base64
import datetime

import cryptography.hazmat.primitives.asymmetric.ed25519 as ed25519

from six.moves import urllib

def sign_url(url: str, key_name: str, base64_key: str, expiration_time: datetime.datetime) -> str:
    """Gets the Signed URL string for the specified URL and configuration.

    Args:
        url: URL to sign as a string.
        key_name: name of the signing key as a string.
        base64_key: signing key as a base64 encoded byte string.
        expiration_time: expiration time as a UTC datetime object.

    Returns:
        Returns the Signed URL appended with the query parameters based on the
        specified configuration.
    """
    stripped_url = url.strip()
    parsed_url = urllib.parse.urlsplit(stripped_url)
    query_params = urllib.parse.parse_qs(
        parsed_url.query, keep_blank_values=True)
    epoch = datetime.datetime.utcfromtimestamp(0)
    expiration_timestamp = int((expiration_time - epoch).total_seconds())
    decoded_key = base64.urlsafe_b64decode(base64_key)

    url_pattern = u'{url}{separator}Expires={expires}&KeyName={key_name}'

    url_to_sign = url_pattern.format(
            url=stripped_url,
            separator='&' if query_params else '?',
            expires=expiration_timestamp,
            key_name=key_name)

    digest = ed25519.Ed25519PrivateKey.from_private_bytes(
        decoded_key).sign(url_to_sign.encode('utf-8'))
    signature = base64.urlsafe_b64encode(digest).decode('utf-8')
    signed_url = u'{url}&Signature={signature}'.format(
            url=url_to_sign, signature=signature)

    return signed_url

def sign_url_prefix(url: str, url_prefix, key_name: str, base64_key: str, expiration_time: datetime.datetime) -> str:
    """Gets the Signed URL string for the specified URL prefix and configuration.

    Args:
        url: URL of request.
        url_prefix: URL prefix to sign as a string.
        key_name: name of the signing key as a string.
        base64_key: signing key as a base64 encoded string.
        expiration_time: expiration time as a UTC datetime object.

    Returns:
        Returns the Signed URL appended with the query parameters based on the
        specified URL prefix and configuration.
    """
    stripped_url = url.strip()
    parsed_url = urllib.parse.urlsplit(stripped_url)
    query_params = urllib.parse.parse_qs(
        parsed_url.query, keep_blank_values=True)
    encoded_url_prefix = base64.urlsafe_b64encode(
            url_prefix.strip().encode('utf-8')).decode('utf-8')
    epoch = datetime.datetime.utcfromtimestamp(0)
    expiration_timestamp = int((expiration_time - epoch).total_seconds())
    decoded_key = base64.urlsafe_b64decode(base64_key)

    policy_pattern = u'URLPrefix={encoded_url_prefix}&Expires={expires}&KeyName={key_name}'
    policy = policy_pattern.format(
            encoded_url_prefix=encoded_url_prefix,
            expires=expiration_timestamp,
            key_name=key_name)

    digest = ed25519.Ed25519PrivateKey.from_private_bytes(
        decoded_key).sign(policy.encode('utf-8'))
    signature = base64.urlsafe_b64encode(digest).decode('utf-8')
    signed_url = u'{url}{separator}{policy}&Signature={signature}'.format(
            url=stripped_url,
            separator='&' if query_params else '?',
            policy=policy,
            signature=signature)
    return signed_url

Champs de signature obligatoires

Les champs suivants sont obligatoires pour chaque signature :

  • Expires
  • KeyName
  • Signature

Si des paramètres de requête sont présents, ils doivent être regroupés en tant que derniers paramètres dans l'URL. Sauf indication contraire, les noms de paramètres et leurs valeurs sont sensibles à la casse.

Le tableau suivant explique chaque paramètre :

Nom du champ Paramètres de signature Valeur signée
Expires Nombre entier de secondes écoulées depuis l'époque Unix (1970-01-01T00:00:00Z) Expires=EXPIRATION_TIME, après lequel la signature n'est plus valide.
KeyName Nom de l'objet EdgeCacheKeyset utilisé pour signer cette requête. KeyName fait référence à l'ensemble de la collection de clés, et non aux clés individuelles de la collection. KeyName=EDGE_CACHE_KEYSET
Signature Version de la signature encodée en base64. Non applicable

Champs de signature facultatifs

Si des paramètres de requête sont présents, ils doivent être regroupés en tant que derniers paramètres dans l'URL. Sauf indication contraire, les noms de paramètres et leurs valeurs sont sensibles à la casse.

Le tableau suivant décrit le nom et les détails de chaque paramètre de signature facultatif :

Nom du champ Paramètres de signature Valeur signée
HeaderName

Nom du champ d'en-tête de requête nommé qui doit être présent dans la requête.

Doit être en minuscules lorsqu'il est signé, car les noms de champs d'en-tête sont sensibles à la casse. Media CDN convertit l'en-tête en minuscules avant de valider la signature.

HeaderName=HEADER_NAME
HeaderValue Une valeur de champ d'en-tête de requête nommé qui doit être présente dans la requête. Il s'agit généralement d'un identifiant utilisateur ou d'un autre identifiant opaque. Les requêtes avec HeaderValue mais sans HeaderName sont rejetées. HeaderValue=HEADER_VALUE
IPRanges

Liste incluant jusqu'à cinq adresses IPv4 et IPv6 au format CIDR pour lesquelles cette URL est valide au format base64 web-safe. Par exemple, pour spécifier les plages d'adresses IP "192.6.13.13/32,193.5.64.135/32", spécifiez IPRanges=MTkyLjYuMTMuMTMvMzIsMTkzLjUuNjQuMTM1LzMy.

Les plages d'adresses IP peuvent ne pas être utiles à inclure dans les signatures lorsque les clients sont susceptibles d'effectuer des migrations WAN ou dans les cas où le chemin d'accès réseau à l'interface de l'application est différent du chemin de distribution. Media CDN rejette les clients disposant d'un code HTTP 403 lorsqu'ils se connectent avec une adresse IP ne faisant pas partie de la requête signée.

Les cas suivants peuvent entraîner le rejet des clients avec le code HTTP 403 dans Media CDN :

  • Environnements double pile (IPv4, IPv6)
  • Migration de connexion (Wi-Fi vers mobile et mobile vers Wi-Fi)
  • Réseaux mobiles utilisant la passerelle NAT (CGNAT ou CGN)
  • TCP multi-chemin (MPTCP)

Tous ces facteurs peuvent contribuer à ce qu'un client donné ait une adresse IP non déterministe pendant une session de lecture vidéo. Si l'adresse IP du client change après avoir accordé l'accès et que le client tente de télécharger un segment vidéo dans son tampon de lecture, il reçoit une erreur HTTP 403 de Media CDN.

IPRanges=BASE_64_IP_RANGES
URLPrefix Préfixe d'URL en base64 (URL-safe) auquel accorder l'accès. Spécifier un URLPrefix vous permet de signer un préfixe et d'ajouter les mêmes paramètres de requête à plusieurs URL dans votre génération de lecteur ou de fichier manifeste. L'élément URLPrefix est requis lors de l'utilisation du format de cookie signé. URLPrefix=BASE_64_URL_PREFIX