署名を生成する

このガイドでは、署名の作成方法と、署名の必須フィールドとオプション フィールドについて説明します。

署名を作成するには、署名する文字列を作成します。このガイドでは、これを署名付き値と呼びます。署名された値には、保護するコンテンツ、署名された値の有効期限などを記述するパラメータが含まれます。

署名文字列を作成するときに、署名付き値を使用します。署名文字列を作成するには、署名のパラメータの非対称鍵の Ed25519 署名などを作成します。

メディア CDN は、最終作成の署名を使用してコンテンツを保護します。

サポートされている署名形式

Media CDN では、次の署名付きリクエスト形式がサポートされています。

フォーマット 動作
クエリ パラメータ(正確な URL)

特定の URL へのアクセスを許可するための正確な URL。

Exact:

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

クエリ パラメータ(URL 接頭辞) URLPrefix を指定すると、接頭辞に署名して、プレーヤーまたはマニフェスト生成内の複数の URL に同じクエリ パラメータを追加できます。

署名する内容:

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

PREFIX は、スキーム、ホスト、部分パスなどのアクセスを許可する接頭辞に置き換えます。

経路コンポーネント

接頭辞: "/edge-cache-token=[...]" コンポーネントより前の接頭辞を持つ任意の URL にアクセスできます。

これにより、相対マニフェスト URL は、サブリソースを取得するときに署名付き URL コンポーネントを自動的に継承できます。

https://media.example.com/video/edge-cache-token=Expires=EXPIRATION
&KeyName=KEY_NAME
&Signature=SIGNATURE/manifest_12382131.m3u8
署名付き Cookie 接頭辞: Cookie により、署名付き URLPrefix 値に指定された接頭辞を持つ URL にアクセスできます。

Edge-Cache-Cookie:

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

署名の作成

  1. 必須の署名フィールドと目的のオプションの署名フィールドを含む文字列を連結して、署名付き値を作成します。

    指定する場合は、URLPrefix を最初に配置し、ExpiresKeyName、続いて任意のパラメータを指定します。

    各フィールドと各パラメータは、次のように区切ります。

    • Cookie の場合はコロン : 文字を使用します。
    • クエリ パラメータとパス コンポーネントには、アンパサンド & 文字を使用します。
  2. Ed25519 署名を使用して署名付き値に署名します。

  3. フィールド区切り文字(: または &)の後に、Signature= と Ed25519 署名を文字列の最後に追加します。

署名付き URL を作成する

次の Python コードサンプルは、署名付き URL をプログラムで作成する方法を示しています。

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

必須の署名フィールド

すべての署名に次のフィールドが必要です。

  • Expires
  • KeyName
  • Signature

クエリ パラメータが存在する場合は、URL で最後のパラメータとしてグループ化する必要があります。特に指定しない限り、パラメータ名とその値は大文字と小文字が区別されます。

次の表で、各パラメータについて説明します。

フィールド名 署名パラメータ 署名付きの値
Expires Unix エポック(1970-01-01T00:00:00Z)から経過した整数秒数。 Expires=EXPIRATION_TIME。その後、署名は無効になります。
KeyName このリクエストへの署名に使用された EdgeCacheKeyset の名前。KeyName はキーセット全体を指します。キーセット自体の個々のキーではありません。 KeyName=EDGE_CACHE_KEYSET
Signature Base64 でエンコードされた署名。 該当なし

オプションの署名フィールド

クエリ パラメータが存在する場合は、URL で最後のパラメータとしてグループ化する必要があります。特に指定しない限り、パラメータ名とその値は大文字と小文字が区別されます。

次の表に、各パラメータの名前とオプションの署名パラメータの詳細を示します。

フィールド名 署名パラメータ 署名付きの値
HeaderName

リクエスト内に存在する名前付きリクエスト ヘッダー フィールド名。

ヘッダー フィールド名では大文字と小文字が区別されるため、署名時には小文字にする必要があります。メディア CDN は、署名を検証する前にヘッダーを小文字にします。

HeaderName=HEADER_NAME
HeaderValue リクエスト内に存在する必要がある、名前付きリクエスト ヘッダー フィールド値。通常、これはユーザー ID またはその他の不透明な識別子です。HeaderValue が指定されているが HeaderName がないリクエストは拒否されます。 HeaderValue=HEADER_VALUE
IPRanges

この URL がウェブセーフな Base64 形式で有効な、CIDR 形式の最大 5 つの IPv4 アドレスと IPv6 アドレスのリスト。たとえば、IP 範囲「192.6.13.13/32,193.5.64.135/32」を指定するには IPRanges=MTkyLjYuMTMuMTMvMzIsMTkzLjUuNjQuMTM1LzMy を指定します。

クライアントが WAN を移行するリスクがある場合や、アプリケーションのフロントエンドへのネットワーク パスが配信パスと異なる場合は、署名に IP 範囲を含めると便利です。 署名付きリクエストの一部ではない IP アドレスからクライアントが接続した場合、Media CDN は HTTP 403 コードでクライアントを拒否します。

HTTP 403 コードを含むクライアントで Media CDN が拒否される可能性があるのは、次のような場合です。

  • デュアルスタック(IPv4、IPv6)環境
  • 接続の移行(Wi-Fi からモバイル、モバイルから Wi-Fi)
  • キャリア ゲートウェイ NAT(CGNAT または CGN)を使用するモバイル ネットワーク
  • マルチパス TCP(MPTCP)

これらの要因は、再生セッション中に特定のクライアントに IP アドレスが変わる場合があります。アクセスの発行後にクライアント IP アドレスが変更され、クライアントが動画セグメントを再生バッファにダウンロードしようとすると、Media CDN から HTTP 403 が返されます。

IPRanges=BASE_64_IP_RANGES
URLPrefix アクセスを許可する base64(URL セーフ)URL 接頭辞。URLPrefix を指定すると、接頭辞に署名して、プレーヤーまたはマニフェストの生成内の複数の URL に同じクエリ パラメータを追加できます。 署名付き Cookie 形式を使用する場合は、URLPrefix が必要です。 URLPrefix=BASE_64_URL_PREFIX