Gerar assinaturas

Neste guia, explicamos como criar uma assinatura e as etapas obrigatórias e para assinaturas.

Para criar uma assinatura, escreva uma string para assinar, chamada de assinado valor neste guia. O valor assinado inclui parâmetros que descrevem o conteúdo que você está protegendo, o prazo de validade do valor assinado; para a frente.

Você usa o valor com sinal ao criar uma string de assinatura. Você cria uma string de assinatura compondo os parâmetros para a assinatura, como uma assinatura de chave assimétrica Ed25519 do valor assinado.

O Media CDN usa a assinatura composta final para ajudar a proteger seus conteúdo.

Formatos de assinatura aceitos

O Media CDN oferece suporte aos seguintes formatos de solicitação assinada.

Formato Comportamento Exemplo
Parâmetros de consulta (URL exato)

URL exato, para conceder acesso a um URL específico.

Exata:

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

Parâmetros de consulta (prefixo de URL) Especificar um URLPrefix permite assinar um prefixo e anexar os mesmos parâmetros de consulta a vários URLs no player ou manifesto geração de imagens.

O que assinar:

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

Substitua PREFIX pelo prefixo a ser concedido. incluindo o esquema, o host e o caminho parcial.

Componente do caminho

Prefixo: permite acesso a qualquer URL com um prefixo antes do Componente "/edge-cache-token=[...]".

Isso permite que os URLs de manifesto relativos herdem automaticamente a componente de URL assinado ao buscar sub-recursos.

https://media.example.com/video/edge-cache-token=Expires=EXPIRATION
&KeyName=KEY_NAME
&Signature=SIGNATURE/manifest_12382131.m3u8
Cookie assinado Prefixo: o cookie permite acesso a qualquer URL com o prefixo especificado no valor URLPrefix com assinatura.

Edge-Cache-Cookie:

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

Criar uma assinatura

  1. Crie um valor assinado concatenando uma string que contém o campos de assinatura obrigatórios e campos de assinatura opcionais.

    Se especificado, URLPrefix precisa vir em primeiro lugar, seguido por Expires, KeyName e, em seguida, os parâmetros opcionais.

    Separe cada campo e qualquer parâmetro com o seguinte:

    • Para cookies, use dois-pontos :.
    • Para parâmetros de consulta e componentes de caminho, use um E comercial & caractere.
  2. Assine o valor assinado com uma assinatura Ed25519.

  3. Anexe um separador de campo (: ou &) seguido por Signature= e a assinatura Ed25519 ao final da string.

Criar um URL assinado

Os exemplos de código a seguir mostram como criar um URL assinado de forma programática.

Go

Para autenticar no Media CDN, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.

import (
	"crypto/ed25519"
	"encoding/base64"
	"fmt"
	"io"
	"strings"
	"time"
)

// signURL prints the signed URL string for the specified URL and configuration.
func signURL(w io.Writer, url, keyName string, privateKey []byte, expires time.Time) error {
	// url := "http://example.com"
	// keyName := "your_key_name"
	// privateKey := "[]byte{34, 31, ...}"
	// expires := time.Unix(1558131350, 0)

	sep := '?'
	if strings.ContainsRune(url, '?') {
		sep = '&'
	}
	toSign := fmt.Sprintf("%s%cExpires=%d&KeyName=%s", url, sep, expires.Unix(), keyName)
	sig := ed25519.Sign(privateKey, []byte(toSign))

	fmt.Fprintf(w, "%s&Signature=%s", toSign, base64.RawURLEncoding.EncodeToString(sig))

	return nil
}

Python

Para autenticar no Media CDN, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.

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 = "{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 = "{url}&Signature={signature}".format(
        url=url_to_sign, signature=signature
    )

    return signed_url

Criar um prefixo de URL assinado

Os exemplos de código a seguir mostram como criar programaticamente um prefixo de URL assinado.

Go

Para autenticar no Media CDN, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.

import (
	"crypto/ed25519"
	"encoding/base64"
	"fmt"
	"io"
	"strings"
	"time"
)

// signURLPrefix prints the signed URL string for the specified URL prefix and configuration.
func signURLPrefix(w io.Writer, urlPrefix, keyName string, privateKey []byte, expires time.Time) error {
	// urlPrefix := "https://examples.com"
	// keyName := "your_key_name"
	// privateKey := "[]byte{34, 31, ...}"
	// expires := time.Unix(1558131350, 0)

	sep := '?'
	if strings.ContainsRune(urlPrefix, '?') {
		sep = '&'
	}

	toSign := fmt.Sprintf(
		"URLPrefix=%s&Expires=%d&KeyName=%s",
		base64.RawURLEncoding.EncodeToString([]byte(urlPrefix)),
		expires.Unix(),
		keyName,
	)
	sig := ed25519.Sign(privateKey, []byte(toSign))

	fmt.Fprintf(
		w,
		"%s%c%s&Signature=%s",
		urlPrefix,
		sep,
		toSign,
		base64.RawURLEncoding.EncodeToString(sig),
	)

	return nil
}

Python

Para autenticar no Media CDN, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.

import base64
import datetime

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


from six.moves import urllib

def sign_url_prefix(
    url: str,
    url_prefix: str,
    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 = (
        "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 = "{url}{separator}{policy}&Signature={signature}".format(
        url=stripped_url,
        separator="&" if query_params else "?",
        policy=policy,
        signature=signature,
    )
    return signed_url

Os exemplos de código a seguir mostram como criar um URL assinado de forma programática cookie.

Criar um componente de caminho assinado

Os exemplos de código a seguir mostram como criar um caminho assinado de forma programática componente.

Python

Para autenticar no Media CDN, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.

import base64
import datetime
import hashlib
import hmac

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


def base64_encoder(value: bytes) -> str:
    """
    Returns a base64-encoded string compatible with Media CDN.

    Media CDN uses URL-safe base64 encoding and strips off the padding at the
    end.
    """
    encoded_bytes = base64.urlsafe_b64encode(value)
    encoded_str = encoded_bytes.decode("utf-8")
    return encoded_str.rstrip("=")


def sign_path_component(
    url_prefix: str,
    filename: str,
    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_prefix: URL Prefix to sign as a string.
        filename: The filename of the sample request
        key_name: The name of the signing key as a string.
        base64_key: The signing key as a base64 encoded string.
        expiration_time: Expiration time as a UTC datetime object with timezone.

    Returns:
        Returns the Signed URL appended with the query parameters based on the
        specified URL prefix and configuration.
    """

    expiration_duration = expiration_time.astimezone(
        tz=datetime.timezone.utc
    ) - datetime.datetime.fromtimestamp(0, tz=datetime.timezone.utc)
    decoded_key = base64.urlsafe_b64decode(base64_key)

    policy_pattern = "{url_prefix}edge-cache-token=Expires={expires}&KeyName={key_name}"
    policy = policy_pattern.format(
        url_prefix=url_prefix,
        expires=int(expiration_duration.total_seconds()),
        key_name=key_name,
    )

    digest = ed25519.Ed25519PrivateKey.from_private_bytes(decoded_key).sign(
        policy.encode("utf-8")
    )
    signature = base64_encoder(digest)

    signed_url = "{policy}&Signature={signature}/{filename}".format(
        policy=policy, signature=signature, filename=filename
    )

    return signed_url

Campos de assinatura obrigatórios

Os campos a seguir são obrigatórios para todas as assinaturas:

  • Expires
  • KeyName
  • Signature

Se houver parâmetros de consulta, eles precisarão ser agrupados como o último parâmetros no URL. A menos que especificado de outra forma, os nomes dos parâmetros e seus diferenciam maiúsculas de minúsculas.

A tabela a seguir explica cada parâmetro:

Nome do campo Parâmetros de assinatura Valor assinado
Expires Segundos inteiros decorridos desde a época Unix (1970-01-01T00:00:00Z) Expires=EXPIRATION_TIME. Depois disso, a assinatura não é mais válida.
KeyName O nome do EdgeCacheKeyset usado para assinar o documento solicitação. KeyName refere-se a todo o conjunto de chaves, não chaves individuais dentro do próprio conjunto de chaves. KeyName=EDGE_CACHE_KEYSET
Signature Uma versão da assinatura codificada em base64. Não relevante

Campos de assinatura opcionais

Se houver parâmetros de consulta, eles precisarão ser agrupados como o último parâmetros no URL. A menos que especificado de outra forma, os nomes dos parâmetros e seus diferenciam maiúsculas de minúsculas.

A tabela a seguir explica o nome e os detalhes de cada parâmetro de assinatura opcional:

Nome do campo Parâmetros de assinatura Valor assinado
HeaderName

Um nome de campo de cabeçalho de solicitação nomeado que precisa estar presente no solicitação.

Precisa ser em letras minúsculas quando assinado, porque os nomes de campos de cabeçalho diferenciam maiúsculas de minúsculas. O Media CDN coloca o cabeçalho em letras minúsculas antes de validar a assinatura.

HeaderName=HEADER_NAME
HeaderValue Um valor de campo de cabeçalho de solicitação nomeado que precisa estar presente na solicitação. Geralmente é um ID do usuário ou outro identificador opaco. Solicitações com HeaderValue, mas sem HeaderName são recusados. HeaderValue=HEADER_VALUE
IPRanges

Uma lista de até cinco endereços IPv4 e IPv6 no formato CIDR para em que o URL é válido no formato base64 seguro para a Web. Por exemplo: para especificar os intervalos de IP "192.6.13.13/32,193.5.64.135/32", especifique IPRanges=MTkyLjYuMTMuMTMvMzIsMTkzLjUuNjQuMTM1LzMy:

Pode não ser útil incluir IPRanges em assinaturas quando os clientes estão correndo risco de migrações de WAN ou casos em que o caminho de rede front-end do aplicativo é diferente do caminho de entrega. O Media CDN rejeita clientes com um HTTP 403 ao se conectarem a um endereço IP que não faz parte da solicitação assinada.

Confira a seguir casos que podem resultar no Media CDN Rejeite clientes com um código HTTP 403:

  • Ambientes de pilha dupla (IPv4, IPv6)
  • Migração da conexão (Wi-Fi para celular e celular para Wi-Fi)
  • Redes móveis que usam Carrier Gateway NAT (CGNAT ou CGN)
  • TCP de vários caminhos (MPTCP)

Todos esses fatores podem contribuir para que um determinado cliente endereço IP não determinista durante uma sessão de reprodução de vídeo. Se o o endereço IP do cliente for alterado depois que você conceder acesso, e o o cliente tenta baixar um trecho de vídeo nos vídeos reserva, eles recebem um HTTP 403 Media CDN do Google Cloud.

IPRanges=BASE_64_IP_RANGES
URLPrefix O prefixo de URL base64 (seguro para URL) ao qual conceder acesso. Especificar um URLPrefix permite assinar um prefixo e anexar a mesma consulta. parâmetros para vários URLs no player ou na geração de manifesto. O URLPrefix é necessário ao usar o cookie assinado . URLPrefix=BASE_64_URL_PREFIX