この記事は翻訳者によって翻訳されたものです。 記事の文章にポインターを重ねると、原文のテキストが表示されます。
|
訳文
原文
|
デジタル著作権管理 (DRM)
|
---|
|
このトピックには次のセクションが含まれています。
- 1.DRM のシナリオ
- 2 Silverlight DRM のオンライン シナリオ
- 2.1 オンラインでの Silverlight DRM の概念の概要
- 2.2 PlayReady とWMDRM
- 2.3 Silverlight DRM の使用に関する制限
- 2.4 PlayReady 暗号化の使用の考慮事項とWMDRM 暗号化
- 2.5 Silverlight での WMDRM コンテンツの再生
- 2.6 Silverlight への DRM の統合
- 2.7 サーバー インフラストラクチャのセットアップ
- 2.8 Silverlight アプリケーションからの DRM コンテンツの参照
- 2.9 DRM 状態の検出
- 2.10 エラー処理
- 2.11 カスタム ロジックの追加
- 3 Silverlight DRM のオフライン シナリオ
- 3.1 基本的なオフラインでの DRM (1 回限りの購入)
- 3.2 ダウンロード前のライセンスの検証
- 3.3 コンテンツを再生できるコンピューター (ドメイン) の管理
- 3.4 レンタルとサブスクリプション
- 3.5 ルート ライセンス、リーフ ライセンス、およびライセンス チェーン
- 3.6 ライセンスの反復処理
- 4.1 出力保護の基本
- 4.2 Silverlight での出力保護のサポート
- 4.3 アプリケーション制限メディア
- 関連トピック
-
オンライン シナリオ: これらのシナリオでは、メディア コンテンツを再生している間、ユーザーがオンライン状態を維持する必要があります。 -
ライブ ストリーミング: ライブ ストリーミング (本来の意味でのストリーミング) では、コンテンツがコンピューターやデバイスに直接送信され、ファイルがハード ディスクに保存されることはありません。 ライブ ストリーミングは、ブロードキャストされている間だけ利用できます。 ライブ ストリーミングの例としては、インターネット テレビやラジオがあります。 -
プログレッシブ ダウンロード: プログレッシブ ダウンロードでは、ユーザーはメディアをダウンロードしながら再生できます。 ユーザーの視点から見たプログレッシブ ダウンロードとライブ ストリーミングの主な違いは、プログレッシブ ダウンロードでは少しずつダウンロードしたコンテンツが、一時的であれ、ユーザーのコンピューターまたはデバイスに保存されることです。
-
-
オフライン シナリオ: これらのシナリオでは、ユーザーはオフラインでもコンテンツを再生できます。 この場合は、ユーザーのコンピューターまたはデバイスにオフライン Silverlight ランタイムがインストールされている必要があります。また、コンテンツを初めてダウンロードしたり、サブスクリプションを更新したりするためには、ユーザーは断続的でもオンラインになる必要があります。 -
ダウンロード ファイル オフライン (1 回限りの購入): ユーザーはインターネットからコンテンツをダウンロードし、後でオフラインの Silverlight プレーヤーを使用して再生します。 たとえば、オンラインのビデオ店の場合、ユーザーは有料でビデオ ファイルをダウンロードし、そのファイルを好きなときにオフラインの Silverlight プレーヤーで再生できます。 DRM ソフトウェアでは、ビデオ ファイルの再配信を 1 つまたは複数のデバイスに制限できます (この後の「ドメイン」を参照してください)。 -
レンタル: DRM ライセンスの制限時間を指定して、コンテンツの再生を制限できます。 たとえば、オンラインのビデオ店でビデオのレンタルを行うとします。 レンタルを購入し、ライセンスをダウンロードすると、ライセンスの有効期限は、発行から 30 日後またはコンテンツを最初に再生してから 24 時間後のどちらか早い時点で切れます。 -
サブスクリプション: サブスクリプション モデルに基づいて、ユーザーがコンテンツを再生できるようにすることができます。 たとえば、オンラインのビデオ店で、ユーザーが月額料金を支払うことで、テレビ コンテンツを 100 時間までオンラインで視聴でき、最大で 20 タイトルをダウンロードできるとします。 サブスクリプション ライセンスは 45 日ごとに有効期限が切れるため、サブスクリプションを更新するには、月額料金を支払い、少なくとも月に 1 回はサービスに接続する必要があります。
-
|
---|
|
1.Silverlight クライアントによるコンテンツへのアクセス
2.ユーザーのコンピューターは個別化されているか
3.Silverlight によるライセンスの要求
4.クライアントはドメインに参加する必要があるか (オプション)
5.永続ライセンス ストアへのライセンスのコピー (オプション)
6.コンテンツの再生
|
---|
|
|
---|
|
|
---|
|
-
Silverlight では、PlayReady でサポートされるすべてのファイルの種類がサポートされるわけではありません。 Silverlight では、DRM で暗号化された VC1、WMA、WMA Pro、h.264、および AAC の各ストリームの再生のみがサポートされています。
-
コンテンツのストリーミングを行う場合、ライブ ソースからリアルタイムでエンコードとストリーミングを行うのか、またはあらかじめ暗号化したファイルをオンデマンドでストリーミングするのか。 -
コンテンツを再生するユーザーは Silverlight を使用しているのか、または Windows Media Player も使用しているのか。 -
WMDRM でパッケージ化されたコンテンツ (WMDRM SDK を使用してパッケージ化されたコンテンツ) の大量のライブラリがあり、これを Silverlight ユーザーに配信するのか、または PlayReady を使用してすべてのコンテンツをパッケージ化するのか。 -
PIFF 形式を使用する必要があるのか。 PIFF は、PlayReady を使用する場合にサポートされます。
-
ストリーミング コンテンツ: PlayReady を使用してストリーミング コンテンツをライブ ソースからリアルタイムでエンコードする必要がある場合は、サードパーティのソリューションを使用できます。 また、このシナリオでは WMDRM を使用することもできます。 WMDRM と Silverlight を統合するソリューションについては、後述する「Silverlight での WMDRM コンテンツの再生」を参照してください。 アダプティブ ストリーミングをサポートするために Silverlight で使用される MediaStreamSource を使用する場合は、PlayReady でパッケージ化されたコンテンツを使用する必要があります。 -
クライアント プレーヤー: ユーザーが Silverlight のみを使用して DRM を再生する場合は、すべてのコンテンツを PlayReady を使用してパッケージ化できます。ただし、Windows Media Player クライアントも対象にしているユーザーには、WMDRM 暗号化が必要です。 -
コンテンツ ライブラリ: コンテンツを Silverlight でのみ再生するかどうかに関係なく、コンテンツを PlayReady を使用してパッケージ化することを避けるには、WMDRM でパッケージ化されたコンテンツを考慮した DRM ソリューションを作成する必要があります。
|
---|
|
-
DRM で保護されたコンテンツを配信するために必要なサーバー インフラストラクチャをセットアップします。 -
MediaElement を使用して、Silverlight アプリケーションからこの保護されたコンテンツを参照します。 -
予想されるエラーを処理します (たとえば、ユーザーが DRM コンテンツを許可しないなど)。 -
必要に応じて、LicenseAcquirer クラスまたは DomainAcquirer クラスをサブクラス化してカスタム ビジネス ロジックを作成します。
|
---|
|
-
WMDRM 10 SDK -
PlayReady Server SDK
<MediaElement x:Name="myMediaElement" Source="myProtectedVideo.wmv" />
myMediaElement.LicenseAcquirer.LicenseServerUriOverride = new Uri("http://contoso.com/myLicenseServer.asmx", UriKind.Absolute);
if (myMediaElement.CurrentState == MediaElementState.Individualizing) { myStateTextBlock.text = "Downloading DRM Client"; } else if(myMediaElement.CurrentState == MediaElementState.AcquiringLicense) { myStateTextBlock.text = "Aquiring License"; }
DRM に関連するその他のエラー
|
|
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
---|
|
|
---|
|
<StackPanel x:Name="LayoutRoot" Background="Gray" Orientation="Vertical"> <MediaElement x:Name="myME" Height="100"/> </StackPanel>
public partial class Page : UserControl { public Page() { InitializeComponent(); this.Loaded += new RoutedEventHandler(Page_Loaded); } void Page_Loaded(object sender, RoutedEventArgs e) { // Test a full fledged manual acquirer // Set the LicenseAcquirer of the MediaElement to the custom License Acquirer // defined in this sample. myME.LicenseAcquirer = new ManualLicenseAcquirer(myME.Name); // Set the License URI to proper License Server address. myME.LicenseAcquirer.LicenseServerUriOverride = new Uri("http://contoso.com/myLicenseServer.asmx", UriKind.Absolute); myME.MediaFailed += new EventHandler<ExceptionRoutedEventArgs>(myME_MediaFailed); // Set the source of the MediaElement to the URL of the media encrypted with WMDRM. myME.Source = new Uri("http://contoso.com/wmdrm_url.wmv", UriKind.Absolute); } void myME_MediaFailed(object sender, ExceptionRoutedEventArgs e) { string errorMessage = ""; if (e.ErrorException.ToString().Contains(" 6001 ")) { errorMessage = "The individualization component software failed to" + " download to the user’s computer. This error would" + " come up when the MediaElement is in the Individualizing" + " MediaElementState. One possible reason for this error is" + " that the Silverlight client cannot connect the Microsoft" + " Individualization Server."; } else if (e.ErrorException.ToString().Contains(" 6004 ")) { errorMessage = " The installation of Silverlight on the client is" + " out of date and needs to be updated."; } else { errorMessage = "MediaFailed: " + e.ErrorException.Message + "."; } System.Windows.Browser.HtmlPage.Window.Alert(errorMessage); } // makes license request explicitly public class ManualLicenseAcquirer : LicenseAcquirer { private string challengeString; string _mediaElementName; public ManualLicenseAcquirer(string mediaElementName) { _mediaElementName = mediaElementName; } // The default implementation of OnAcquireLicense calls into the MediaElement to acquire a // license. It is called when the Media pipeline is building a topology and will be raised // before MediaOpened is raised. protected override void OnAcquireLicense(System.IO.Stream licenseChallenge, Uri licenseServerUri) { StreamReader sr = new StreamReader(licenseChallenge); challengeString = sr.ReadToEnd(); // Need to resolve the URI for the License Server -- make sure it is correct // and store that correct URI as resolvedLicenseServerUri. Uri resolvedLicenseServerUri; if (LicenseServerUriOverride == null) resolvedLicenseServerUri = licenseServerUri; else resolvedLicenseServerUri = LicenseServerUriOverride; // Make a HttpWebRequest to the License Server. HttpWebRequest request = WebRequest.Create(resolvedLicenseServerUri) as HttpWebRequest; request.Method = "POST"; // Set ContentType through property request.ContentType = "application/xml"; // ADD REQUIRED HEADERS. // The headers below are necessary so that error handling and redirects are handled // properly via the Silverlight client. request.Headers["msprdrm_server_redirect_compat"] = "false"; request.Headers["msprdrm_server_exception_compat"] = "false"; // Initiate getting request stream IAsyncResult asyncResult = request.BeginGetRequestStream(new AsyncCallback(RequestStreamCallback), request); } // This method is called when the asynchronous operation completes. void RequestStreamCallback(IAsyncResult ar) { HttpWebRequest request = ar.AsyncState as HttpWebRequest; // populate request stream request.ContentType = "text/xml"; Stream requestStream = request.EndGetRequestStream(ar); StreamWriter streamWriter = new StreamWriter(requestStream, System.Text.Encoding.UTF8); streamWriter.Write(challengeString); streamWriter.Close(); // Make async call for response request.BeginGetResponse(new AsyncCallback(ResponseCallback), request); } private void ResponseCallback(IAsyncResult ar) { HttpWebRequest request = ar.AsyncState as HttpWebRequest; WebResponse response = request.EndGetResponse(ar); SetLicenseResponse(response.GetResponseStream()); } } }
// Called when the user is online and wants to download some protected content. public void GetLicensePreDelivery(string customData, Guid keyId) { Uri licenseServerUrl = new Uri("http://contoso.com/myLicenseServer.asmx"); LicenseAcquirer acquirer = new LicenseAcquirer(); acquirer.ChallengeCustomData = customData; // Set the License URI to proper License Server address. acquirer.LicenseServerUriOverride = licenseServerUrl; acquirer.AcquireLicenseCompleted += new EventHandler<AcquireLicenseCompletedEventArgs>(acquirer_Completed); acquirer.AcquireLicenseAsync(keyId, ContentKeyType.Aes128Bit, Guid.Empty); }
public void acquirer_Completed(object sender, AcquireLicenseCompletedEventArgs e) { if (e.Error != null) { // take appropriate action. Might be retrying for instance. } else if (e.Cancelled) { // take appropriate action. Might be nothing. } else { // // We acquired the license successfully, go ahead and download // the content. Note the service decided to stash the content // url in the LicenseAcquirer response custom data. // string contentAcquisitionUrl = e.ResponseCustomData; DownloadContent(contentAcquisitionUrl); } }
Guid c_ServiceId = new Guid("{deb47f00-8a3b-416d-9b1e-5d55fd023044}"); Uri c_DomainServerUrl = new Uri("http://domainserver.contoso.com/rmsdk/rightsmanager.asmx"); Uri c_LicenseServerUrl = new Uri("http://licenseserver.contaso.com/rmsdk/rightsmanager.asmx"); public void acquirer_JoinDomainCompleted(object sender, DomainOperationCompletedEventArgs e) { if (e.Error != null) { // Standard error handling may include logging the error, // retrying, or reporting failure to the user // e.CustomData may have additional information depending on // the type of error is reported in e.Message } else if (e.Cancelled) { // Standard cancellation handling } else { // Update the ISO store that we are joined to the domain // The application may want to store e.AccountId } } public void JoinDomainOnFirstUse() { if (false == IsJoinedToDomain()) { string friendlyName = PromptUserForClientFriendlyName(); DomainAcquirer acquirer = new DomainAcquirer(); acquirer.JoinDomainCompleted +=new EventHandler<JoinDomainCompletedEventArgs>( acquirer_JoinDomainCompleted); acquirer.JoinDomainAsync(c_ServiceId, Guid.Empty, c_DomainServerUrl, friendlyName); } }
public void RemoveClientFromAccountButton_OnClick(object sender, RoutedEventArgs e) { // // The service may want to prompt the user with a "Are you sure?" // prompt before removing the client as it will disable media // playback of any domain bound content. // // The service will want to look up the currently logged in user’s // account identifier from the ISO store. The accountId parameter // is strictly required, and it is the responsibility of the // service to ensure that is is available at this point. // Guid m_AccountId = accountId; DomainAcquirer acquirer = new myDomainAcquirer(); acquirer.LeaveDomainCompleted += new EventHandler<LeaveDomainCompletedEventArgs>( acquirer_LeaveDomainCompleted); acquirer.LeaveDomainAsync(c_ServiceId, m_AccountId, c_DomainServerUrl); } public void acquirer_LeaveDomainCompleted(object sender, DomainOperationCompletedEventArgs e) { if (e.Error != null) { // Error handling may include logging the error, retrying, or // reporting failure to the user e.CustomData may have // additional information depending on the type of error is // reported in e.Message } else if (e.Cancelled) { // Handle cancel } else { // Update the ISO store that we left the domain. Likely means // cleaning up the domain object for the given AccountId. } }
メモ
public void RenewDomain() { LicenseAcquirer myLicenseAcquirer = new LicenseAcquirer(); myLicenseAcquirer.DomainAcquirer = new myDomainAcquirer(); mediaElement.LicenseAcquirer = myLicenseAcquirer; mediaElement.LicenseAcquirer.LicenseServerUriOverride = c_LicenseServerUrl; mediaElement.Source = new Uri("http://contoso.com/content.wmv"); // // If the license server decides that the client does not have a // domain membership, the domain membership is out of date, // then a DomainRequiredException or RenewDomainException respectively // will be thrown and the client will send back a response containing // the necessary information (url, serviceid, accountid, etc) to // send to the domain server. The license acquisition pipeline // would treat this somewhat like an Indiv message in that // it would do the join domain and then restart the license // acquisition. // // Note that a customized DomainAcquirer was provided so the // OnJoinDomain method will be called to allow // authentication information to be provided with the Join Domain // request. // mediaElement.Play(); }
-
シンプル ライセンス: PlayReady Server SDK を使用して作成されたアプリケーションから配信される、関連付けられているコンテンツのキーと共に権利と制限を含む PlayReady ライセンスです。 -
ルート ライセンス: 1 つ以上のリーフ ライセンスを制御するライセンスです。 リーフ ライセンスでは特定のコンテンツの再生を制御するのに対し、ルート ライセンスではすべてのリーフ ライセンスを制御します。 たとえば、サブスクリプション モデルでは、ルート ライセンスには有効期限がありますが、リーフ ライセンスにはありません。 ルート ライセンスの有効期限が切れると、新しいルート ライセンスを取得するまで、リーフ ライセンスは使用できません。 -
リーフ ライセンス: ルート ライセンスに依存するシンプル ライセンスです。
|
---|
|
private void CheckSubscriptionRootForRenewal(Guid parentKeyId, Uri licenseServerUrl) { DateTimeOffset renewalDate = DateTimeOffset.Now.AddDays(5); // Query the licensemanager to see if we have a usable root license IEnumerable<MediaLicense> myLicenses = LicenseManagement.SelectLicenses(parentKeyId); bool renewRoot = true; foreach (MediaLicense ML in myLicenses) { // If the license expires within the next 5 days, // renew the subscribtion by requesting a new root license. if ((ML.Usable) && (ML.ExpirationDate > renewalDate)) { renewRoot = false; break; } } if (renewRoot) { LicenseAcquirer acquirer = new LicenseAcquirer(); acquirer.LicenseServerUriOverride = licenseServerUrl; acquirer.AcquireLicenseCompleted += new EventHandler<AcquireLicenseCompletedEventArgs>(acquirer_Completed); acquirer.AcquireLicenseAsync(parentKeyId, ContentKeyType.Aes128Bit, Guid.Empty); }
ライセンス チェーン (リーフとルート) 単一のシンプル ライセンス 単一のリーフ ライセンス (ルートが存在しない) 単一のルート ライセンス (ルートを直接照会する)
public bool IsUsableLicenseAvailableForContent(System.IO.Stream contentFile) { bool returnValue = false; // SelectLicenses works only if the user is running the Silverlight application offline // *and* elevated trust. IEnumerable<MediaLicense> myLicenses = LicenseManagement.SelectLicenses(contentFile); foreach (MediaLicense ML in myLicenses) { if (ML.Usable) { returnValue = true; break; } } return returnValue; }
ポリシー データ
|
|
---|---|
|
|
|
|
|
|
|
|
ポリシー マネージャー
セキュリティで保護された準拠ドライバー
COPP
OPM
セキュリティで保護された、暗号化されたチャネル
|
|
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
セキュリティで保護された出力
Silverlight 5 での出力保護
|
|
|
|
|
---|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-
* 出力コネクタを決定できない場合は再生が許可されることがあります。 Silverlight は、この場合にすべての出力保護ポリシーを評価し、最も制限の厳しいポリシーを適用します。 -
** Silverlight は、この場合にすべての出力保護ポリシーを評価し、最も制限の厳しいポリシーを適用します。 -
*** コネクタを判断できない場合は、この出力保護レベル (出力保護レベル ポリシーからは独立) の存在により拒否になります
Silverlight 4 での出力保護
|
|
|
|
|
---|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-
1このケースでは、常に結果はブロック -
2 最小のアナログ ビデオの出力保護のレベル = 200 と設定するのと同じ -
3このケースでは、常に結果は再生
機能の混在
|
|
---|---|
|
|
|
|
|
|
|
|
キー ローテーション
COPP および OPM ドライバーの考慮事項
出力保護関連 API
|
|
|
|
|
Silverlight MediaFailed エラー メッセージ
|
|
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
---|
|
signtool sign /v /f certificateFile.pfx fileToSign