Freigeben über


ACS 認証および ACS トークン認証による AES 暗号化のエンドツーエンド プロトタイプ

 このポストは、11 月 26 日に投稿された An End-to-End Prototype of AES Encryption with ACS Authentication and ACS Token Authorization の翻訳です。

はじめに

この記事は、私が以前執筆したブログ記事「ACS 認証および ACS トークン認証による PlayReady 保護のエンドツーエンド プロトタイプ」の続編です。

環境によっては、DRM による完全な保護が必要でない場合や、経済的に見合わない場合があります。このような場合には、代わりに AES暗号化を利用することができます。ただし、AES 暗号化は DRM ではなく、まったくの別物であるという点に注意しなくてはなりません。以下の表に、DRM とAES 暗号化の相違点をまとめましたのでご覧ください。

比較事項

DRM (PlayReady など)

AES 暗号化 (AES-128 など)

コンテンツ保護か、ファイル保護か

コンテンツ

コンテンツ

承認されたユーザーは信頼されたユーザーか

☓  承認されたユーザーに許可されている保護されたコンテンツへの操作は、DRM ライセンスに含まれる制限と権利によって制限されます。

○  承認されたユーザーには、任意のディスプレイ デバイスへのコピー、保存、共有、エクスポートなど、コンテンツのあらゆる操作が許可されます。

保護されるコンテンツの性質

ビデオなど、共有を目的としたコンテンツ

ユーザーが共有しないことを前提とした、個人用のコンテンツ

クライアント デバイス上で暗号化解除したコンテンツの保護

×

日時によるコンテンツへのアクセス制限

×

アプリケーションのホワイトリストへの登録

×

ドメインのバインドと管理

×

暗号化キーのローテーション

×

ブラックアウト

×

出力保護

×

ライセンス チェーン

×

Azure Media Services の Content Protection (コンテンツ保護) では、AES 動的暗号化機能により、ワンクリックで AES 暗号化を実行できます。

このブログでは、トークン認証を使用した Smooth Streaming アセットの AES 暗号化のエンドツーエンド プロトタイプをご紹介します。この認証トークンは、PlayReady 保護のエンドツーエンドプロトタイプに使用したものと同じ ACS 2.0 名前空間によって発行されます。

 

エンドツーエンドのプロトタイプ

設計と機能

以下のことが可能なエンドツーエンドのプロトタイプを用意することが今回の目標です。

  • トークン制限を適用した AMS のアセットの AES-128 動的暗号化
  • Azure Media Services のキー配信サービスによる暗号化解除キーの配信
  • Azure ACS (英語) (Microsoft Azure Active Directory Access Control Service) を STS として利用した SWT 認証トークンの発行
  • OSMF プレーヤー
    1. ACS サービス ID で認証を受ける
    2. ACS から認証トークンを取得
    3. ACS トークンを使用して AMS キー配信サービスから暗号化解除キーを取得
    4. 暗号化解除とビデオの再生

下図で、このエンドツーエンド プロトタイプの設計を図解しています。

Blog_Secure_Delivery_AES

このエンドツーエンド プロトタイプは、Azure と Azure Media Services にホストされます。これに関連する情報は以下のとおりです。

 

実行方法

  1. OSMF 用 Adaptive Streaming プラグインで構築した OSMF プレーヤー (英語) をブラウザーに表示します。必要な情報は既にプレーヤー
    ページの UI に提示されています。
  2. 再生ボタンをクリックするたびに、ACS から新しい認証トークンが要求されます。この新しい認証トークンは、OSMFプラグインが再生用の暗号化解除キーを要求するために使用されます。ACS 2.0 名前空間から取得した認証トークンはプレーヤー ページに表示されます。以下はプレーヤーのスクリーンショットです。

OMFPlayer

 

実装

実装の概要は以下のとおりです。

  1. Azure Media Services の .NET API を使用して、Smooth Streaming アセットの AES-128 動的暗号化を構成します。
    • コンテンツ キー ID およびコンテンツ キーを生成します。
    • 暗号化解除キー配信サービスを構成します。
    • アセット配信ポリシー経由で AES 動的暗号化を構成します。
    • アセットを発行します。
  2. Azure ACS 2.0 名前空間をセットアップしてプレーヤー クライアントを認証し、認証トークンを発行します。
  3. ACS 認証、認証トークン要求、暗号化解除キー要求、ビデオ再生を実行する OSMF プレーヤーを開発します。

このプロトタイプで OSMF プレーヤーを選択したのは、OSMF 用 Microsoft Adaptive Streaming プラグインがオンデマンドおよびライブの Smooth Streaming コンテンツの AES 暗号化をサポートしているためです。

 

AES 動的暗号化の設定

まずは、エンベロープ タイプのコンテンツ キーを作成します。コードは以下のようになります。

 static public IContentKey CreateEnvelopeTypeContentKey(CloudMediaContext objCloudMediaContext)
{
// エンベロープ 暗号化 コンテンツ キーを作成する
    Guid keyId = Guid.NewGuid();
    byte[] contentKey = CryptoUtils.GenerateCryptographicallyStrongRandomBytes(16);

    IContentKey objIContentKey = objCloudMediaContext.ContentKeys.Create(keyId, contentKey, "myContentKey", ContentKeyType.EnvelopeEncryption);

    return objIContentKey;
}

 

次に、認証ポリシーを作成して、上記で作成したコンテンツ キーに追加します。この図 (英語) に示すように、各 IContentKey には単一の IContentKeyAuthorizationPolicy のインスタンスが関連付けられています。以下のコードでは、IContentKeyAuthorizationPolicyを作成して、IContentKey にアタッチします。

 public static IContentKey AddAuthorizationPolicyToContentKey(CloudMediaContext objCloudMediaContext, IContentKey objIContentKey)
{
// 制限を設定した ContentKeyAuthorizationPolicy を作成し、認証ポリシーを作成する             
    IContentKeyAuthorizationPolicy policy = objCloudMediaContext.ContentKeyAuthorizationPolicies.CreateAsync("Open Authorization Policy").Result;

    List<ContentKeyAuthorizationPolicyRestriction> restrictions = new List<ContentKeyAuthorizationPolicyRestriction>();

    ContentKeyAuthorizationPolicyRestriction restriction = new ContentKeyAuthorizationPolicyRestriction
    {
        Name = "Authorization Policy with Token Restriction",
        KeyRestrictionType = (int)ContentKeyRestrictionType.TokenRestricted,
        Requirements = ContentKeyAuthorizationHelper.CreateRestrictionRequirements()
    };

    restrictions.Add(restriction);

    IContentKeyAuthorizationPolicyOption policyOption = objCloudMediaContext.ContentKeyAuthorizationPolicyOptions.Create("myDynamicEncryptionPolicy", ContentKeyDeliveryType.BaselineHttp, restrictions, "");

    policy.Options.Add(policyOption);

// ContentKey に ContentKeyAutorizationPolicy を追加する
    objIContentKey.AuthorizationPolicyId = policy.Id;
    IContentKey IContentKeyUpdated = objIContentKey.UpdateAsync().Result;

    return IContentKeyUpdated;
}

 

上記のContentKeyAuthorizationHelper.CreateRestrictionRequirements() メソッドは、以下のように定義されます。

 public static string CreateRestrictionRequirements()
{
    string primarySymmetricKey   = System.Configuration.ConfigurationManager.AppSettings["PrimarySymmetricKey"];
    string secondarySymmetricKey = System.Configuration.ConfigurationManager.AppSettings["SecondarySymmetricKey"];
    string scope                 = System.Configuration.ConfigurationManager.AppSettings["AcsScope"];
    string issuer                = System.Configuration.ConfigurationManager.AppSettings["AcsIssuer"];

    TokenRestrictionTemplate objTokenRestrictionTemplate = new TokenRestrictionTemplate();

    objTokenRestrictionTemplate.PrimaryVerificationKey = new SymmetricVerificationKey(Convert.FromBase64String(primarySymmetricKey));
    objTokenRestrictionTemplate.AlternateVerificationKeys.Add(new SymmetricVerificationKey(Convert.FromBase64String(secondarySymmetricKey)));
    objTokenRestrictionTemplate.Audience               = new Uri(scope);
    objTokenRestrictionTemplate.Issuer                 = new Uri(issuer);

    return TokenRestrictionTemplateSerializer.Serialize(objTokenRestrictionTemplate);
}

: AES (動的) 暗号化の認証ポリシーを構成する際には、ACS 2.0 名前空間に使用したものと同じ (プライマリ) 対称ハッシュ キーを使用してください。

 

次に、アセットの配信に使用される IAssetDeliveryPolicy を作成します。

 public static IAssetDeliveryPolicy CreateAssetDeliveryPolicy(CloudMediaContext objCloudMediaContext, IContentKey objIContentKey)
{
    Uri keyAcquisitionUri = objIContentKey.GetKeyDeliveryUrl(ContentKeyDeliveryType.BaselineHttp);

    string envelopeEncryptionIV = Convert.ToBase64String(CryptoUtils.GenerateCryptographicallyStrongRandomBytes(16));

// 下記のポリシーの構成では、以下を指定 
//   エンベロープに KID=<Guid> を追加したキーの URL
//   エンベロープの暗号化に使用する初期化ベクトル (IV)
    Dictionary<AssetDeliveryPolicyConfigurationKey, string> assetDeliveryPolicyConfiguration = new Dictionary<AssetDeliveryPolicyConfigurationKey, string> 
            {
                {AssetDeliveryPolicyConfigurationKey.EnvelopeKeyAcquisitionUrl, keyAcquisitionUri.ToString()},
                {AssetDeliveryPolicyConfigurationKey.EnvelopeEncryptionIVAsBase64, envelopeEncryptionIV}
            };

    IAssetDeliveryPolicy objIAssetDeliveryPolicy = objCloudMediaContext.AssetDeliveryPolicies.Create(
                "SmoothHLSDynamicEncryptionAssetDeliveryPolicy",
                AssetDeliveryPolicyType.DynamicEnvelopeEncryption,
                AssetDeliveryProtocol.SmoothStreaming | AssetDeliveryProtocol.HLS,
                assetDeliveryPolicyConfiguration);

    Console.WriteLine();
    Console.WriteLine("Adding Asset Delivery Policy: " + objIAssetDeliveryPolicy.AssetDeliveryPolicyType);
    Console.WriteLine("Key Delivery URL = {0}", keyAcquisitionUri.ToString());

    return objIAssetDeliveryPolicy;
}

 

最後に、上記のすべてを組み合わせて、以下のようにアセットの AES 動的暗号化を追加する全体的なフローを作成します。

 public static void DynamicAesEncryptionFlow(CloudMediaContext objCloudMediaContext, IAsset objIAsset)
{
// IContentKey を作成する
    IContentKey objIContentKey = CreateEnvelopeTypeContentKey(objCloudMediaContext);

// IContentKey に AuthorizationPolicy を追加する
    objIContentKey = AddAuthorizationPolicyToContentKey(objCloudMediaContext, objIContentKey);

// アセット配信ポリシーを作成する
    IAssetDeliveryPolicy objIAssetDeliveryPolicy = CreateAssetDeliveryPolicy(objCloudMediaContext, objIContentKey);

// IContentKey と IAsset を関連付ける
    objIAsset.ContentKeys.Add(objIContentKey);

// アセットに AssetDelivery ポリシーを追加する
    objIAsset.DeliveryPolicies.Add(objIAssetDeliveryPolicy);

このコードを実行した後に、アセットを発行する必要があります。これは、API を使用してプログラムで実行するか、Azure管理ポータルを使用します。

 

ACS のセットアップ

ここでは、ブログ記事「ACS 認証および ACS トークン認証による PlayReady 保護のエンドツーエンド プロトタイプ」でセットアップした名前空間を使用できます。対称検証キー、サービスID、発行者、スコープなど、すべての設定をそのまま使用します。

 

プレーヤーのコード

OSMF 用 Microsoft Adaptive Streaming プラグインでは、AES-128 によって暗号化された Smooth Streaming のオンデマンド再生とライブ再生の両方をサポートしています。そのため、ここではOSMF プレーヤーを使用します。OSMF プレーヤーを使用するフローは以下のとおりです。

  1. テスト アセットのクライアント マニフェストに示すように、AES-128 によって暗号化されたコンテンツを表し、キー配信 URL を含む Smooth Streaming マニフェストをダウンロードします。
  2. 認証トークンを要求します。
  3. 認証トークンを使用して暗号化解除キーを要求します。
  4. 暗号化解除とビデオの再生を行います。

まず、ACS 名前空間から認証トークンを要求するコードは以下のようになります。

 public string GetAcsToken()
{
    string issuer   = System.Configuration.ConfigurationManager.AppSettings["AcsIssuer"];
    string scope    = System.Configuration.ConfigurationManager.AppSettings["AcsScope"];
    string username = System.Configuration.ConfigurationManager.AppSettings["Username"];
    string password = System.Configuration.ConfigurationManager.AppSettings["Password"];

    string tokenToReturn = null;

    using (WebClient client = new WebClient())
    {
// 認証要求を作成してトークンを取得する
        client.BaseAddress = (new Uri(issuer)).AbsoluteUri;

        var oauthRequestValues = new NameValueCollection
        {
            {"grant_type",    "client_credentials"},
            {"client_id",     username},
            {"client_secret", password},
            {"scope",         scope},
        };

        byte[] responseBytes = null;

        try
        {
            responseBytes = client.UploadValues("/v2/OAuth2-13", "POST", oauthRequestValues);
        }
        catch (WebException we)
        {
            Stream stream = we.Response.GetResponseStream();
            StreamReader reader = new StreamReader(stream);

            throw;
        }

        using (var responseStream = new MemoryStream(responseBytes))
        {
            OAuth2TokenResponse tokenResponse = (OAuth2TokenResponse)new DataContractJsonSerializer(typeof(OAuth2TokenResponse)).ReadObject(responseStream);
            tokenToReturn = tokenResponse.AccessToken;
        }
    }

    return tokenToReturn;

OAuth2TokenResponse 型は以下のように定義されます。

 [DataContract]
public class OAuth2TokenResponse
{
    [DataMember(Name = "access_token")]
    public string AccessToken { get; set; }

    [DataMember(Name = "expires_in")]
    public int ExpirationInSeconds { get; set; }
}

プレーヤーをホストする ASP.NET Web ページは以下のようになります。

 <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Aes128OSMFPlayer.aspx.cs" Inherits="SilverlightApplication.Web.OSMF.Aes128OSMFPlayer" %>

<!DOCTYPE html>

<html xmlns="https://www.w3.org/1999/xhtml">
<head runat="server">
    <title>AES Encryption | OSMF Player</title>
    <style type="text/css">
        .auto-style1 {
            height: 17px;
        }
    </style>
</head>
<body style="font-family:Verdana;font-size:11px">
    <form id="form1" runat="server">
        <div>
            <h3>End-to-End Prototype of AES Encryption with ACS Authorization Token for Smooth Streaming</h3>
            <table><tr><td>Source URL: </td><td>
                <asp:TextBox ID="txtSrcUrl" runat="server" Width="913px">https://willzhanmediaservice.origin.mediaservices.windows.net/474c4840-4753-48ec-b3aa-9d05daef612a/LyncSkypeSizzleVideo750k.ism/manifest</asp:TextBox>
            </td></tr>
            <tr><td>Key Delivery URL:</td><td><a href="https://willzhanmediaservice.keydelivery.mediaservices.windows.net/?KID=1814f449-0550-4977-abd5-fe3efeaf6086" target="_blank">https://willzhanmediaservice.keydelivery.mediaservices.windows.net/?KID=1814f449-0550-4977-abd5-fe3efeaf6086</a>
            </td></tr>
                <tr><td class="auto-style1">Authorization Token:</td><td class="auto-style1"><%=authorizationToken %></td></tr>
            <tr><td>Token Issuer: </td><td><a href="https://willzhanacs.accesscontrol.windows.net" target="_blank">https://willzhanacs.accesscontrol.windows.net</a></td></tr>
            <tr><td></td><td>
                <asp:Button ID="cmdPlay" runat="server" OnClick="cmdPlay_Click" Text="Play" />
            </td></tr>
            <tr><td></td><td>
                    <object width="920" height="640">
                        <param name="movie" value="StrobeMediaPlayback.2.0.swf"></param>
                        <param name="flashvars" value="src=<%=srcUrl %>&autoPlay=<%=autoPlay %>&plugin_AdaptiveStreamingPlugin=MSAdaptiveStreamingPlugin-v1.0.12-osmf2.0.swf&AdaptiveStreamingPlugin_retryLive=true&AdaptiveStreamingPlugin_retryInterval=10&AdaptiveStreamingPlugin_encryptionKeyToken=<%=authorizationToken %>"></param>
                        <param name="allowFullScreen" value="true"></param>
                        <param name="allowscriptaccess" value="always"></param>
                        <param name="wmode" value="direct"></param>
                        <embed src="StrobeMediaPlayback.2.0.swf"
                            type="application/x-shockwave-flash"
                            allowscriptaccess="always"
                            allowfullscreen="true"
                            wmode="direct"
                            width="920"
                            height="640"
                            flashvars="src=<%=srcUrl %>&autoPlay=<%=autoPlay %>&plugin_AdaptiveStreamingPlugin=MSAdaptiveStreamingPlugin-v1.0.12-osmf2.0.swf&AdaptiveStreamingPlugin_retryLive=true&AdaptiveStreamingPlugin_retryInterval=10&AdaptiveStreamingPlugin_encryptionKeyToken=<%=authorizationToken %>">
                        </embed>
                    </object>
                </td></tr>
                </table>
        </div>
    </form>
</body>
</html>

 

対応するバックグラウンドのコードは以下のようになります

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace SilverlightApplication.Web.OSMF
{
    public partial class Aes128OSMFPlayer : System.Web.UI.Page
    {
        protected string authorizationToken;
        protected string autoPlay;
        protected string srcUrl;
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!Page.IsPostBack)
            {
                this.Play();
            }
        }

        protected void cmdPlay_Click(object sender, EventArgs e)
        {
            this.Play();
        }

        protected void Play()
        {
// ACS 2.0 名前空間から認証トークンを要求する
            WCFService objWCFService = new WCFService();
            string token = objWCFService.GetAcsToken();
            token = string.Format("Bearer={0}", token);

// トークンを使用する前に URL エンコードを行う
            authorizationToken = System.Web.HttpUtility.UrlEncode(token);

            srcUrl = txtSrcUrl.Text;
            autoPlay = true.ToString();
        }
    }
}

 

まとめ

今回は、Azure Media Services AES 暗号化ソリューションのエンドツーエンド プロトタイプをご紹介しました。このプロトタイプには、以下の主要なコンポーネントがすべて含まれます。

  1. コンテンツ キー ID およびコンテンツ
    キーの生成
  2. Azure Media
    Services のストリーミング ソース
  3. Azure Media
    Services の Content Protection を使用した AES 暗号化
  4. Azure Media Services の Content Protection を使用した AES キー配信
  5. Azure ACS 2.0 による STS (Secure Token Service) のプレーヤー クライアント認証と認証トークンの発行
  6. ACS 認証、ACS 承認、暗号化解除キーの取得、ビデオ再生を処理する、Azure IaaS VM でホストされたビデオ プレーヤー アプリケーション

謝辞: 今回の記事の執筆に協力してくれた Microsoft Azure Media Services チームの
Quintin Burns とMingfei Yan に深く感謝いたします。