すべてのプロダクト
Search
ドキュメントセンター

ApsaraVideo Media Processing:HLS 暗号化

最終更新日:Jun 04, 2026

HLS 暗号化は、動画コンテンツへの不正アクセスを防ぐために使用され、オンライン教育や金融などの分野で広く利用されています。Alibaba Cloud は、Alibaba Cloud 専用の暗号化 (推奨) と HLS 暗号化の 2 種類の暗号化方式をサポートしています。このトピックでは、ApsaraVideo Media Processing (MPS) における HLS 暗号化の仕組みと実装方法について説明します。

仕組み

基本概念

MPS では、エンベロープ暗号化を使用します。サービスが Key Management Service (KMS) を呼び出して、データキー (DK) とエンベロープ化されたデータキー (EDK) を生成します。DK で動画を暗号化します。暗号化されたファイルと EDK は一緒に保存されます。プレーヤーは、復号サービスから DK を取得し、動画を復号して再生します。

説明

HLS 暗号化では、データキー (DK) を保護する必要があります。

概念

説明

データキー (DK)

動画の暗号化に使用されるプレーンテキストキーです。

エンベロープ化されたデータキー (EDK)

DK をエンベロープ暗号化で暗号化して生成された暗号文キーです。復号時にプレーンテキストの DK を復元するために使用されます。

Resource Access Management (RAM)

ユーザー ID とリソースアクセス権限を管理します。詳細については、「RAM とは」をご参照ください。

Key Management Service (KMS)

キー管理、データ暗号化、認証情報のセキュリティを提供します。詳細については、「Key Management Service とは」をご参照ください。

Object Storage Service (OSS)

MPS で処理されたメディアリソースを保存します。詳細については、「OSS とは」をご参照ください。

コンテンツデリバリーネットワーク (CDN)

コンテンツを配信し、HLS 再生時に M3U8 ファイル内の復号 URI を動的に変更します。詳細については、「Alibaba Cloud CDN とは」をご参照ください。

暗号化フロー

暗号化フローは次のように動作します。

mts_wf_hls_encrypt

  1. MPS、OSS、RAM、KMS、CDN がまだアクティベートされていない場合は、アクティベートします。

  2. MPS に KMS へのアクセスを許可します。

    説明

    MPS は、暗号化時に KMS の GenerateDataKey API を呼び出して、DK と EDK を生成します。

  3. 出力 OSS バケットドメインを CDN アクセラレーションドメインとして設定します。CNAME レコードとオリジンホストを設定します。

  4. 暗号化ワークフローを作成します。出力 OSS バケットとキー URI を指定します。

    キー URI は、復号サービスのエンドポイントです。MPS は、暗号化後に M3U8 ファイルにこれを書き込みます。

  5. 動画をアップロードし、アップロード時に暗号化ワークフローを指定します。

  6. アップロード後、MPS は自動的に暗号化とトランスコーディングをトリガーします。

    MPS は GenerateDataKey を呼び出して DK と EDK を生成し、DK で動画を暗号化してから、キー URI と EDK を M3U8 ファイルに書き込みます。

  7. MPS は、M3U8 ファイルと TS ファイルを出力 OSS バケットに保存します。

復号フロー

復号と再生フローは次のように動作します。

mts_hls_decrypt

  1. MtsHlsUriToken を発行するトークンサービスを構築します。

    重要

    トークンサービスは MtsHlsUriToken を発行します。

  2. KMS の Decrypt API を呼び出して DK を取得し、プレーヤーに返す復号サービスを構築します。

    重要

    KMS は Base64 でエンコードされたデータキーを返します。サービスは、それをプレーヤーに返す前に Base64 デコードする必要があります。

  3. QueryMediaList を呼び出して M3U8 ファイルの URL を取得し、MtsHlsUriToken を付加して URL をプレーヤーに返します。

  4. プレーヤーは、MtsHlsUriToken を含むリクエストを CDN に送信し、M3U8 ファイルを取得します。CDN は、キー URI と EDK を含むようにファイルを書き換えて返します。プレーヤーは復号キーをリクエストし、動画を再生します。

実装の概要

HLS 暗号化と再生の完全なフローを実装するには、次のコンポーネントを構築する必要があります。

  1. 暗号化ワークフローを作成します。

    説明

    コンソールでワークフローを作成することもできますが、サーバーサイド SDK を統合することで、より完全で効率的な暗号化サービスを提供できます。

  2. MtsHlsUriToken のトークン発行と検証サービスを構築します。各トークンは 1 回のみ使用する必要があります。

  3. KMS の Decrypt API を呼び出す復号サービスを構築します。プレーンテキストキーを Base64 デコードし、プレーヤーに返します。

前提条件

HLS 暗号化を使用する前に、次の前提条件を満たす必要があります。

  1. 必要な Alibaba Cloud サービスをアクティベートします。

    MPS、OSS、KMS、RAM、CDN がまだアクティベートされていない場合は、アクティベートします。

    1. MPS をアクティベートします。詳細については、「MPS のアクティベート」をご参照ください。

    2. OSS をアクティベートします。詳細については、「OSS のアクティベート」をご参照ください。

    3. KMS をアクティベートします。詳細については、「KMS のアクティベート」をご参照ください。

    4. CDN をアクティベートします。詳細については、「CDN のアクティベート」をご参照ください。

  2. MPS に KMS へのアクセスを許可します。

    1. RAM コンソールにログインします。

    2. 承認する をクリックして、新規権限 ページに移動します。

    3. [プリンシパル] 検索ボックスで、AliyunMtsDefaultRole を検索し、MPS のためにシステムが作成したロールを選択します。

    4. [権限] の検索ボックスで KMS を検索し、AliyunKMSFullAccess を選択して [OK] をクリックします。

    権限付与後、MPS は KMS API を呼び出して、動画暗号化用のデータキーを取得できるようになります。

  3. 出力 OSS バケットの CNAME レコードとオリジンホストを設定します。詳細については、「アクセラレーションドメイン名の設定」をご参照ください。すでに設定済みの場合は、この手順をスキップしてください。

    説明

    exampleBucket****.oss-cn-hangzhou.aliyuncs.com などの Alibaba Cloud OSS バケットのパブリックエンドポイントを手動で入力するか、同一アカウント内で高速化する OSS バケットを選択できます。同一リージョン内の内部アクセス用のエンドポイントはサポートされていません。

動画の暗号化

動画を暗号化するには、次の手順を実行します。

  1. 暗号化ワークフローを作成します。

    MPS の依存関係を含む Alibaba Cloud SDK を統合します。コードサンプルのプログラミング言語を選択してください。

    重要

    暗号化ワークフローを作成するときは、キー URI を指定します。MPS は、暗号化中にこの URI を M3U8 ファイルに書き込み、OSS に保存します。例: example.aliyundoc.com

    言語

    SDK の統合

    暗号化ワークフローのコードサンプル

    Java

    Java SDK のインストール

    HLS 暗号化ワークフローの作成

    Python

    Python SDK のインストール

    HLS 暗号化ワークフローの作成

    PHP

    PHP SDK のインストール

    HLS 暗号化ワークフローの作成

  2. 動画をアップロードして、暗号化とトランスコーディングをトリガーします。MPS コンソールまたは OSS コンソールからアップロードします。

    説明

    アップロード時に暗号化ワークフローを指定すると、自動的に暗号化とトランスコーディングがトリガーされます。

    暗号化後、OSS コンソールで出力バケット内の M3U8 ファイルを確認します。サンプルファイル:

    #EXTM3U
    #EXT-X-VERSION:3
    #EXT-X-TARGETDURATION:5
    #EXT-X-MEDIA-SEQUENCE:0
    #EXT-X-KEY:METHOD=AES-128,URI="https://example.aliyundoc.com?Ciphertext=aabbccddeeff&MediaId=fbbf98691ea44b7c82dd75c5bc8b****"
    #EXTINF:4.127544,
    15029611683170-00001.ts
    #EXT-X-ENDLIST

    URI には、設定したキー URI と、KMS から取得した EDK が含まれています。

HLS 暗号化動画の再生

動画を復号して再生するには、次の手順を実行します。

  1. トークンサービスを構築します。

    説明

    暗号化ロジックに基づいてトークンサービスを構築し、動画のセキュリティを強化することを推奨します。

  2. 復号サービスを構築します。

    動画を復号し、復号キーを返すローカル HTTP サービスを構築します。MPS では、Java と Python のコードサンプルを提供しています。

    • Java コードサンプル

      Java SDK には次の依存関係が必要です。

      復号サービスのサンプル (固定キー):

      サンプルコードを表示するにはクリックしてください

      import com.sun.net.httpserver.*;
      import com.sun.net.httpserver.spi.HttpServerProvider;
      
      import java.io.IOException;
      import java.io.OutputStream;
      import java.net.HttpURLConnection;
      import java.net.InetSocketAddress;
      
      /**
       * *****   注意事項   ******
       * このデモでは、単純な復号サービスのコードサンプルを提供します。
       * デモのポート番号は 8888 です。KeyUri 復号サービスのポートと同じであることを確認してください。
       * 追加のトークン検証が必要な場合は、KMS ベースの復号サービスの実装ロジックをご参照ください。
       *
       * *****   ロジックの概要   ******
       * 1. 復号リクエストを受信します。
       * 2. ハードコードされたキーを返します。
       */
      public class Base64DecryptServer {
      
          public static void main(String[] args) throws IOException {
              Base64DecryptServer server = new Base64DecryptServer();
              server.startService();
          }
      
          public class Base64DecryptHandler implements HttpHandler {
              /**
               * 復号リクエストを処理します。
               * @param httpExchange
               * @throws IOException
               */
              public void handle(HttpExchange httpExchange) throws IOException {
                  String requestMethod = httpExchange.getRequestMethod();
                  if ("GET".equalsIgnoreCase(requestMethod)) {
                      // ここでの復号キーは、暗号化キーと同じである必要があります。
                      byte[] key = "encryptionkey128".getBytes();
                      // ヘッダーを設定します。
                      setHeader(httpExchange, key);
                      // キーを返します。
                      OutputStream responseBody = httpExchange.getResponseBody();
                      System.out.println(new String(key));
                      responseBody.write(key);
                      responseBody.close();
                  }
              }
              private void setHeader(HttpExchange httpExchange, byte[] key) throws IOException {
                  Headers responseHeaders = httpExchange.getResponseHeaders();
                  responseHeaders.set("Access-Control-Allow-Origin", "*");
                  httpExchange.sendResponseHeaders(HttpURLConnection.HTTP_OK, key.length);
              }
          }
          /**
           * サービスを開始します。
           * @throws IOException
           */
          private void startService() throws IOException {
              HttpServerProvider provider = HttpServerProvider.provider();
              // ポート 8888 でリッスンし、30 の同時リクエストを受け入れます。
              HttpServer httpserver = provider.createHttpServer(new InetSocketAddress(8888), 30);
              httpserver.createContext("/", new Base64DecryptHandler());
              httpserver.start();
              System.out.println("base64 hls decrypt server started");
          }
      
      }

      KMS 復号サンプル:

      サンプルコードを表示するにはクリックしてください

      import com.aliyun.mps.sdk.utils.InitClient;
      import com.aliyuncs.DefaultAcsClient;
      import com.aliyuncs.exceptions.ClientException;
      import com.aliyuncs.http.ProtocolType;
      import com.aliyuncs.kms.model.v20160120.DecryptRequest;
      import com.aliyuncs.kms.model.v20160120.DecryptResponse;
      import com.sun.net.httpserver.*;
      import com.sun.net.httpserver.spi.HttpServerProvider;
      import org.apache.commons.codec.binary.Base64;
      
      import java.io.IOException;
      import java.io.OutputStream;
      import java.net.HttpURLConnection;
      import java.net.InetSocketAddress;
      import java.net.URI;
      import java.util.regex.Matcher;
      import java.util.regex.Pattern;
      
      /**
       * *****   注意事項   ******
       * このデモでは、標準暗号化の書き換えが無効になっている場合の KMS ベースの復号サービスのコードサンプルを提供します。MtsHlsUriToken 検証のロジックは含まれていません。
       * デモのポート番号は 8888 です。KeyUri 復号サービスのポートと同じであることを確認してください。
       *
       * *****   ロジックの概要   ******
       * 1. 復号リクエストを受信し、暗号文キーを取得します。
       * 2. KMS の Decrypt API を呼び出して、暗号文からプレーンテキストキーを取得します。
       * 3. プレーンテキストキーを Base64 デコードして返します。
       */
      public class HlsDecryptServerNoToken {
      
          private static DefaultAcsClient client;
          static {
              try{
                  client = InitClient.initMpsClient();
              }catch (Exception e){
                  e.printStackTrace();
              }
          }
      
          public static void main(String[] args) throws IOException {
              HlsDecryptServerNoToken server = new HlsDecryptServerNoToken();
              server.startService();
          }
      
          public class HlsDecryptHandler implements HttpHandler {
              public void handle(HttpExchange httpExchange) throws IOException {
                  String requestMethod = httpExchange.getRequestMethod();
                  if(requestMethod.equalsIgnoreCase("GET")){
                      // URL から暗号文キーを取得します。
                      String ciphertext = getCiphertext(httpExchange);
                      System.out.println(ciphertext);
                      if (null == ciphertext)
                          return;
                      // KMS で復号し、Base64 デコードします。
                      byte[] key = decrypt(ciphertext);
                      // ヘッダーを設定します。
                      setHeader(httpExchange, key);
                      // キーを返します。
                      OutputStream responseBody = httpExchange.getResponseBody();
                      responseBody.write(key);
                      responseBody.close();
                  }
              }
      
              private void setHeader(HttpExchange httpExchange, byte[] key) throws IOException {
                  Headers responseHeaders = httpExchange.getResponseHeaders();
                  responseHeaders.set("Access-Control-Allow-Origin", "*");
                  httpExchange.sendResponseHeaders(HttpURLConnection.HTTP_OK, key.length);
              }
      
              private byte[] decrypt(String ciphertext) {
                  DecryptRequest request = new DecryptRequest();
                  request.setCiphertextBlob(ciphertext);
                  request.setProtocol(ProtocolType.HTTPS);
                  try {
                      DecryptResponse response = client.getAcsResponse(request);
                      String plaintext = response.getPlaintext();
                      // 注意: キーは Base64 デコードする必要があります。
                      return Base64.decodeBase64(plaintext);
                  } catch (ClientException e) {
                      e.printStackTrace();
                      return null;
                  }
              }
              private String getCiphertext(HttpExchange httpExchange) {
                  URI uri = httpExchange.getRequestURI();
                  String queryString = uri.getQuery();
                  String pattern = "Ciphertext=(\\w*)";
                  Pattern r = Pattern.compile(pattern);
                  Matcher m = r.matcher(queryString);
                  if (m.find())
                      return m.group(1);
                  else {
                      System.out.println("Not Found Ciphertext");
                      return null;
                  }
              }
          }
      
          /**
           * サービスを開始します。
           *
           * @throws IOException
           */
          private void startService() throws IOException {
              HttpServerProvider provider = HttpServerProvider.provider();
              // ポート 8888 でリッスンし、30 の同時リクエストを受け入れます。必要に応じてポート番号を変更できます。
              HttpServer httpserver = provider.createHttpServer(new InetSocketAddress(8888), 30);
              httpserver.createContext("/", new HlsDecryptHandler());
              httpserver.start();
              System.out.println("no token hls decrypt server started");
          }
      
      }
    • Python コードサンプル

      Python SDK には次の依存関係が必要です。

      • pip install aliyun-python-sdk-core

      • pip install aliyun-python-sdk-kms

      • pip install aliyun-python-sdk-mts

      次は Python コードサンプルです。

      サンプルコードを表示するにはクリックしてください

      # -*- coding: UTF-8 -*-
      from http.server import BaseHTTPRequestHandler, HTTPServer
      from urllib.parse import urlparse, parse_qs
      from aliyunsdkcore.client import AcsClient
      from aliyunsdkcore.request import CommonRequest
      import cgi
      import json
      import base64
      import logging
      from urllib.parse import urlparse
      
      logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
      # お使いの AccessKey ID、AccessKey Secret、およびリージョン ID に置き換えてください。
      client = AcsClient("<お使いの AccessKey ID>", "<お使いの AccessKey Secret>", "<お使いのリージョン ID>")
      
      class AuthorizationHandler(BaseHTTPRequestHandler):
        def do_GET(self):
          #self.check()
          self.set_header()
          cipertext = self.get_cihpertext()
          #print(cipertext)
          plaintext = self.decrypt_cihpertext(cipertext)
          #print(plaintext)
          key = base64.b64decode(plaintext)
          #print(key)
          self.wfile.write(key)
      
        def do_POST(self):
          pass
        
        def check(self):
      # MtsHlsUriToken などをチェックします。
          pass
        
        def set_header(self):
          self.send_response(200)
      # CORS
          self.send_header('Access-Control-Allow-Origin', '*')
          self.end_headers()
      
        def get_cihpertext(self):
          path = urlparse(self.path)
          query = parse_qs(path.query) 
          return query.get('Ciphertext')[0]
          
        def decrypt_cihpertext(self, cipertext):
          request = CommonRequest()
          # KMS エンドポイントを設定します。your-region-id の部分をお使いのリージョン ID に変更してください。
          # 例: 'kms.cn-hangzhou.aliyuncs.com'
          request.set_domain('kms.your-region-id.aliyuncs.com')
          request.set_version('2016-01-20')
          request.set_action_name('Decrypt')
          # パラメーター名は 'CiphertextBlob' です。
          request.add_query_param('CiphertextBlob', cipertext)
      
          response = client.do_action_with_exception(request)
          # print("####################################")
          # print(response)
          jsonResp = json.loads(response)
          return jsonResp["PlainText"]
        
      if __name__ == '__main__':
      # シンプルなサーバーを起動し、ループし続けます。
        print("Starting server, use <Ctrl+C> to stop")
        # 必要に応じてポート番号を変更してください。
        server = HTTPServer(('127.0.0.1', 8099), AuthorizationHandler)
        server.serve_forever()
  3. QueryMediaList API を呼び出して、再生 URL を取得します。

    API Explorer でこの操作を呼び出すか、サービスに統合してください。

  4. 暗号化された動画を再生します。

    独自のプレーヤーまたは ApsaraVideo Player を使用して、暗号化された動画を再生します。

    • 別のプレーヤーを使用する場合は、再生ロジックをご自身で実装してください。

    • ApsaraVideo Player を使用する場合は、トークンと認証情報を取得してから再生を開始してください。詳細については、「動画の再生」をご参照ください。

    オンラインプレーヤーで再生をテストできます。

    たとえば、ApsaraVideo Player 診断ツールを使用します。再生 URL を貼り付けて、[動画を再生] をクリックします。

    説明

    ブラウザでのデバッグ中、プレーヤーは自動的に認証サーバーに復号キーをリクエストし、動画を復号して再生します。

    ApsaraVideo Player での再生プロセスは次のように動作します。

    • プレーヤーは、OSS ドメインを CDN ドメインに置き換え、MtsHlsUriToken を追加して、CDN に M3U8 ファイルをリクエストします。リクエストの例: https://example.aliyundoc.com/test_01.m3u8?MediaId=fbbf98691ea44b7c82dd75c5bc8b****&MtsHlsUriToken=<サービスによって発行されたトークン>

      重要

      ApsaraVideo Player は自動的に MtsHlsUriToken を追加します。別のプレーヤーを使用する場合は、手動でトークンを追加する必要があります。

    • CDN は、M3U8 ファイル内の復号 URI を動的に変更します。 たとえば、https://example.aliyundoc.com?Ciphertext=aabbccddeeff&MediaId=fbbf98691ea44b7c82dd75c5bc8b****https://example.aliyundoc.com?Ciphertext=aabbccddeeff&MediaId=fbbf98691ea44b7c82dd75c5bc8b****&MtsHlsUriToken=<お使いのサービスによって発行されたトークン> になります。

    • プレーヤーは、EXT-X-KEY タグ内の URI にアクセスして復号キーを取得します。サービスは Decrypt を呼び出し、平文キーを Base64 デコードして、プレーヤーに返します。プレーヤーは DK を使用して、再生用に TS ファイルを復号します。

参考情報

Alibaba Cloud 専用の暗号化