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 プレーヤー
- ACS サービス ID で認証を受ける
- ACS から認証トークンを取得
- ACS トークンを使用して AMS キー配信サービスから暗号化解除キーを取得
- 暗号化解除とビデオの再生
下図で、このエンドツーエンド プロトタイプの設計を図解しています。
このエンドツーエンド プロトタイプは、Azure と Azure Media Services にホストされます。これに関連する情報は以下のとおりです。
- AES 動的暗号化を適用した Smooth Streaming アセットの URL
- キー配信用 URL
- SWT 認証トークンを発行する Azure ACS 名前空間の URL
- OSMF プレーヤーの URL (英語)
実行方法
- OSMF 用 Adaptive Streaming プラグインで構築した OSMF プレーヤー (英語) をブラウザーに表示します。必要な情報は既にプレーヤー
ページの UI に提示されています。 - 再生ボタンをクリックするたびに、ACS から新しい認証トークンが要求されます。この新しい認証トークンは、OSMFプラグインが再生用の暗号化解除キーを要求するために使用されます。ACS 2.0 名前空間から取得した認証トークンはプレーヤー ページに表示されます。以下はプレーヤーのスクリーンショットです。
実装
実装の概要は以下のとおりです。
- Azure Media Services の .NET API を使用して、Smooth Streaming アセットの AES-128 動的暗号化を構成します。
- コンテンツ キー ID およびコンテンツ キーを生成します。
- 暗号化解除キー配信サービスを構成します。
- アセット配信ポリシー経由で AES 動的暗号化を構成します。
- アセットを発行します。
- Azure ACS 2.0 名前空間をセットアップしてプレーヤー クライアントを認証し、認証トークンを発行します。
- 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 プレーヤーを使用するフローは以下のとおりです。
- テスト アセットのクライアント マニフェストに示すように、AES-128 によって暗号化されたコンテンツを表し、キー配信 URL を含む Smooth Streaming マニフェストをダウンロードします。
- 認証トークンを要求します。
- 認証トークンを使用して暗号化解除キーを要求します。
- 暗号化解除とビデオの再生を行います。
まず、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 暗号化ソリューションのエンドツーエンド プロトタイプをご紹介しました。このプロトタイプには、以下の主要なコンポーネントがすべて含まれます。
- コンテンツ キー ID およびコンテンツ
キーの生成 - Azure Media
Services のストリーミング ソース - Azure Media
Services の Content Protection を使用した AES 暗号化 - Azure Media Services の Content Protection を使用した AES キー配信
- Azure ACS 2.0 による STS (Secure Token Service) のプレーヤー クライアント認証と認証トークンの発行
- ACS 認証、ACS 承認、暗号化解除キーの取得、ビデオ再生を処理する、Azure IaaS VM でホストされたビデオ プレーヤー アプリケーション
謝辞: 今回の記事の執筆に協力してくれた Microsoft Azure Media Services チームの
Quintin Burns とMingfei Yan に深く感謝いたします。