Proteggere il contenuto HLS con Apple FairPlay o Microsoft PlayReadyProtect your HLS content with Apple FairPlay or Microsoft PlayReady

Servizi multimediali di Azure consente di crittografare dinamicamente il contenuto di HTTP Live Streaming (HLS) usando i formati seguenti:Azure Media Services enables you to dynamically encrypt your HTTP Live Streaming (HLS) content by using the following formats:

  • Chiave envelope non crittografata AES-128AES-128 envelope clear key

    L'intero blocco viene crittografato usando la modalità AES-128 CBC.The entire chunk is encrypted by using the AES-128 CBC mode. La decrittografia del flusso è supportata dai lettori iOS e OSX in modo nativo.The decryption of the stream is supported by iOS and OS X player natively. Per altre informazioni, vedere Uso della crittografia dinamica AES-128 e del servizio di distribuzione delle chiavi.For more information, see Using AES-128 dynamic encryption and key delivery service.

  • Apple FairPlayApple FairPlay

    I singoli campioni audio e video vengono crittografati con la modalità AES-128 CBC.The individual video and audio samples are encrypted by using the AES-128 CBC mode. FairPlay Streaming (FPS) è integrato nei sistemi operativi dei dispositivi, con supporto nativo per iOS e Apple TV.FairPlay Streaming (FPS) is integrated into the device operating systems, with native support on iOS and Apple TV. Safari su OS X abilita FPS con il supporto dell'interfaccia EME (Encrypted Media Extensions).Safari on OS X enables FPS by using the Encrypted Media Extensions (EME) interface support.

  • Microsoft PlayReadyMicrosoft PlayReady

L'immagine seguente illustra il flusso di lavoro della crittografia dinamica HLS + FairPlay o PlayReady.The following image shows the HLS + FairPlay or PlayReady dynamic encryption workflow.

Diagramma del flusso di lavoro della crittografia dinamica

Questo articolo illustra come usare Servizi multimediali per crittografare dinamicamente il contenuto HLS con Apple FairPlay.This article demonstrates how to use Media Services to dynamically encrypt your HLS content with Apple FairPlay. Viene anche illustrato come usare il servizio di distribuzione delle licenze di Servizi multimediali per distribuire le licenze FairPlay ai client.It also shows how to use the Media Services license delivery service to deliver FairPlay licenses to clients.

Nota

Se si vuole crittografare anche il contenuto HLS con PlayReady, è necessario creare una chiave di contenuto comune e associarla all'asset.If you also want to encrypt your HLS content with PlayReady, you need to create a common content key and associate it with your asset. È anche necessario configurare i criteri di autorizzazione della chiave simmetrica, come descritto in Uso della crittografia comune dinamica PlayReady.You also need to configure the content key’s authorization policy, as described in Using PlayReady dynamic common encryption.

Problemi e considerazioniRequirements and considerations

Se si usa Servizi multimediali per distribuire contenuto HLS crittografato con FairPlay e per distribuire licenze FairPlay, è necessario:The following are required when using Media Services to deliver HLS encrypted with FairPlay, and to deliver FairPlay licenses:

È necessario impostare quanto segue in aggiunta alla distribuzione delle chiavi di Servizi multimediali:The following things must be set on Media Services key delivery side:

  • App Cert (AC): file con estensione pfx contenente la chiave privata.App Cert (AC): This is a .pfx file that contains the private key. Creare il file e crittografarlo con una password.You create this file and encrypt it with a password.

    Quando si configurano i criteri di distribuzione delle chiavi, è necessario specificare la password e il file pfx in formato Base64.When you configure a key delivery policy, you must provide that password and the .pfx file in Base64 format.

    La procedura seguente descrive come generare un file di certificato pfx per FairPlay:The following steps describe how to generate a .pfx certificate file for FairPlay:

    1. Installare OpenSSL da https://slproweb.com/products/Win32OpenSSL.html.Install OpenSSL from https://slproweb.com/products/Win32OpenSSL.html.

      Passare alla cartella contenente il certificato FairPlay e altri file forniti da Apple.Go to the folder where the FairPlay certificate and other files delivered by Apple are.

    2. Eseguire il comando seguente dalla riga di comando.Run the following command from the command line. Il comando converte il file con estensione cer in un file con estensione pem.This converts the .cer file to a .pem file.

      "C:\OpenSSL-Win32\bin\openssl.exe" x509 -inform der -in FairPlay.cer -out FairPlay-out.pem"C:\OpenSSL-Win32\bin\openssl.exe" x509 -inform der -in FairPlay.cer -out FairPlay-out.pem

    3. Eseguire il comando seguente dalla riga di comando.Run the following command from the command line. Questo comando converte il file con estensione pem in un file con estensione pfx con la chiave privata.This converts the .pem file to a .pfx file with the private key. La password per il file con estensione pfx viene quindi richiesta da OpenSSL.The password for the .pfx file is then asked by OpenSSL.

      "C:\OpenSSL-Win32\bin\openssl.exe" pkcs12 -export -out FairPlay-out.pfx -inkey privatekey.pem -in FairPlay-out.pem -passin file:privatekey-pem-pass.txt"C:\OpenSSL-Win32\bin\openssl.exe" pkcs12 -export -out FairPlay-out.pfx -inkey privatekey.pem -in FairPlay-out.pem -passin file:privatekey-pem-pass.txt

  • App Cert password: password del cliente per creare il file con estensione pfx.App Cert password: The password for creating the .pfx file.
  • App Cert password ID: è necessario caricare la password con una procedura simile a quella usata per caricare le altre chiavi di Servizi multimediali.App Cert password ID: You must upload the password, similar to how they upload other Media Services keys. Usare il valore di enumerazione ContentKeyType.FairPlayPfxPassword per ottenere l'ID di Servizi multimediali.Use the ContentKeyType.FairPlayPfxPassword enum value to get the Media Services ID. Questo valore è necessario nell'opzione dei criteri di distribuzione delle chiavi.This is what they need to use inside the key delivery policy option.
  • iv: valore casuale di 16 byteiv: This is a random value of 16 bytes. che deve corrispondere al valore iv nei criteri di distribuzione dell'asset.It must match the iv in the asset delivery policy. Si genera l'iv e lo inserisce sia nei criteri di distribuzione dell'asset che nell'opzione dei criteri di distribuzione delle chiavi.You generate the iv, and put it in both places: the asset delivery policy and the key delivery policy option.
  • ASK: chiave ricevuta quando si genera la certificazione usando il portale Apple Developer.ASK: This key is received when you generate the certification by using the Apple Developer portal. Ogni team di sviluppo riceve una chiave ASK univoca.Each development team receives a unique ASK. Salvare una copia della chiave ASK e archiviarla in un luogo sicuro.Save a copy of the ASK, and store it in a safe place. Successivamente è necessario configurare la chiave ASK come FairPlayAsk in Servizi multimediali.You need to configure ASK as FairPlayAsk to Media Services later.
  • ID ASK: ID ottenuto quando si carica la chiave privata dell'applicazione in Servizi multimediali.ASK ID: This ID is obtained when you upload ASK into Media Services. È necessario caricare la chiave privata dell'applicazione usando il valore di enumerazione ContentKeyType.FairPlayASk.You must upload ASK by using the ContentKeyType.FairPlayAsk enum value. Verrà restituito l'ID di Servizi multimediali che dovrà essere usato per impostare l'opzione dei criteri di distribuzione delle chiavi.As the result, the Media Services ID is returned, and this is what should be used when setting the key delivery policy option.

Sul lato client FPS è necessario impostare quanto segue:The following things must be set by the FPS client side:

  • App Cert (AC): file con estensione cer/der contenente la chiave pubblica usata dal sistema operativo per crittografare alcuni payload.App Cert (AC): This is a .cer/.der file that contains the public key, which the operating system uses to encrypt some payload. È necessario che Servizi multimediali lo riconosca perché è richiesto dal lettore.Media Services needs to know about it because it is required by the player. Il servizio di distribuzione delle chiavi lo decrittografa usando la chiave privata corrispondente.The key delivery service decrypts it using the corresponding private key.

Per riprodurre un flusso crittografato FairPlay, ottenere prima una chiave privata dell'applicazione reale, quindi generare un certificato reale.To play back a FairPlay encrypted stream, get a real ASK first, and then generate a real certificate. Questo processo crea tutte le 3 parti:That process creates all three parts:

  • file con estensione der.der file
  • file con estensione pfx.pfx file
  • password per il file pfxpassword for the .pfx

I client seguenti supportano il formato HLS con la crittografia AES-128 CBC: Safari in OS X, Apple TV e iOS.The following clients support HLS with AES-128 CBC encryption: Safari on OS X, Apple TV, iOS.

Configurare la crittografia dinamica FairPlay e i servizi di distribuzione delle licenzeConfigure FairPlay dynamic encryption and license delivery services

Di seguito sono indicati i passaggi generali per la protezione degli asset con FairPlay usando il servizio di distribuzione delle licenze di Servizi multimediali e la crittografia dinamica.The following are general steps for protecting your assets with FairPlay by using the Media Services license delivery service, and also by using dynamic encryption.

  1. Creare un asset e caricare file al suo interno.Create an asset, and upload files into the asset.
  2. Codificare l'asset contenente il file nel set MP4 con velocità in bit adattiva.Encode the asset that contains the file to the adaptive bitrate MP4 set.
  3. Creare una chiave simmetrica e associarla all'asset codificato.Create a content key, and associate it with the encoded asset.
  4. Configurare i criteri di autorizzazione della chiave simmetrica.Configure the content key’s authorization policy. Specificare quanto segue:Specify the following:

    • metodo di distribuzione, in questo caso FairPlay,The delivery method (in this case, FairPlay).
    • configurazione delle opzioni dei criteri FairPlay.FairPlay policy options configuration. Per informazioni dettagliate sulla configurazione di FairPlay, vedere il metodo ConfigureFairPlayPolicyOptions() nell'esempio seguente.For details on how to configure FairPlay, see the ConfigureFairPlayPolicyOptions() method in the sample below.

      Nota

      In genere è opportuno configurare le opzioni dei criteri FairPlay una sola volta, dato che sarà presente un solo set di certificazione e chiave privata dell'applicazione.Usually, you would want to configure FairPlay policy options only once, because you will only have one set of a certification and an ASK.

    • Restrizioni aperte o token.Restrictions (open or token).
    • Informazioni specifiche per il tipo di distribuzione delle chiavi che definiscono la modalità di distribuzione della chiave al client.Information specific to the key delivery type that defines how the key is delivered to the client.
  5. Configurare i criteri di distribuzione dell'asset.Configure the asset delivery policy. La configurazione dei criteri di distribuzione include:The delivery policy configuration includes:

    • Il protocollo di recapito (HLS).The delivery protocol (HLS).
    • Il tipo di crittografia dinamica (crittografia CBC comune).The type of dynamic encryption (common CBC encryption).
    • L'URL di acquisizione delle licenze.The license acquisition URL.

      Nota

      Per distribuire un flusso crittografato con FairPlay e un altro sistema Digital Rights Management (DRM), è necessario configurare criteri di distribuzione separati:If you want to deliver a stream that is encrypted with FairPlay and another Digital Rights Management (DRM) system, you have to configure separate delivery policies:

      • Una norma IAssetDeliveryPolicy per configurare Dynamic Adaptive Streaming over HTTP (DASH) con Common Encryption (CENC) (PlayReady e Widevine) e Smooth con PlayReadyOne IAssetDeliveryPolicy to configure Dynamic Adaptive Streaming over HTTP (DASH) with Common Encryption (CENC) (PlayReady + Widevine), and Smooth with PlayReady
      • Un altro criterio IAssetDeliveryPolicy per configurare FairPlay per HLSAnother IAssetDeliveryPolicy to configure FairPlay for HLS
  6. Creare un localizzatore OnDemand per ottenere un URL di streaming.Create an OnDemand locator to get a streaming URL.

Usare la distribuzione delle chiavi FairPlay con applicazioni lettoreUse FairPlay key delivery by player apps

È possibile sviluppare applicazioni lettore usando l'SDK per iOS.You can develop player apps by using the iOS SDK. Per riprodurre contenuto FairPlay, è necessario implementare il protocollo di scambio delle licenze.To be able to play FairPlay content, you have to implement the license exchange protocol. Questo protocollo non è specificato da Apple.This protocol is not specified by Apple. Spetta a ogni app scegliere come inviare le richieste di distribuzione delle chiavi.It is up to each app how to send key delivery requests. Il servizio di distribuzione delle chiavi FairPlay di Servizi multimediali prevede che SPC venga indicato in un messaggio codificato come www-form-url nel formato seguente:The Media Services FairPlay key delivery service expects the SPC to come as a www-form-url encoded post message, in the following form:

spc=<Base64 encoded SPC>

Nota

Azure Media Player supporta la riproduzione FairPlay.Azure Media Player supports FairPlay playback. Vedere la documentazione di Azure Media Player per altre informazioni.See Azure Media Player documentation for further information.

URL di streamingStreaming URLs

Se l'asset è stato crittografato con più soluzioni DRM, è necessario usare un tag di crittografia nell'URL di streaming (format='m3u8-aapl', encryption='xxx').If your asset was encrypted with more than one DRM, you should use an encryption tag in the streaming URL: (format='m3u8-aapl', encryption='xxx').

Si applicano le considerazioni seguenti:The following considerations apply:

  • Può essere specificato solo un tipo di crittografia oppure nessuno.Only zero or one encryption type can be specified.
  • Il tipo di crittografia non deve essere specificato nell'URL se all'asset è stata applicata una sola crittografia.The encryption type doesn't have to be specified in the URL if only one encryption was applied to the asset.
  • Il tipo di crittografia non fa distinzione tra maiuscole e minuscole.The encryption type is case insensitive.
  • Possono essere specificati i seguenti tipi di crittografia:The following encryption types can be specified:
    • cenc: crittografia comune (PlayReady o Widevine)cenc: Common encryption (PlayReady or Widevine)
    • cbcs-aapl: FairPlaycbcs-aapl: FairPlay
    • cbc: crittografia busta AEScbc: AES envelope encryption

Creare e configurare un progetto di Visual StudioCreate and configure a Visual Studio project

  1. Configurare l'ambiente di sviluppo e popolare il file app.config con le informazioni di connessione, come descritto in Sviluppo di applicazioni di Servizi multimediali con .NET.Set up your development environment and populate the app.config file with connection information, as described in Media Services development with .NET.
  2. Aggiungere gli elementi seguenti alla sezione appSettings definita nel file app.config:Add the following elements to appSettings defined in your app.config file:

     <add key="Issuer" value="http://testacs.com"/>
     <add key="Audience" value="urn:test"/>
    

EsempioExample

L'esempio seguente illustra la funzionalità che consente di usare Servizi multimediali per distribuire contenuto crittografato con FairPlay.The following sample demonstrates the ability to use Media Services to deliver your content encrypted with FairPlay. Questa funzionalità è stata introdotta in Azure Media Services SDK for .NET, versione 3.6.0.This functionality was introduced in the Azure Media Services SDK for .NET version 3.6.0.

Sovrascrivere il codice nel file Program.cs con il codice riportato in questa sezione.Overwrite the code in your Program.cs file with the code shown in this section.

Nota

È previsto un limite di 1.000.000 di criteri per i diversi criteri AMS (ad esempio per i criteri Locator o ContentKeyAuthorizationPolicy).There is a limit of 1,000,000 policies for different AMS policies (for example, for Locator policy or ContentKeyAuthorizationPolicy). Usare lo stesso ID criterio se si usano sempre gli stessi giorni/autorizzazioni di accesso, come nel cado di criteri per i localizzatori che devono rimanere attivi per molto tempo (criteri di non caricamento).You should use the same policy ID if you are always using the same days / access permissions, for example, policies for locators that are intended to remain in place for a long time (non-upload policies). Per altre informazioni, vedere questo articolo.For more information, see this article.

Assicurarsi di aggiornare le variabili in modo da puntare alle cartelle in cui si trovano i file di input.Make sure to update variables to point to folders where your input files are located.

using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Threading;
using Microsoft.WindowsAzure.MediaServices.Client;
using Microsoft.WindowsAzure.MediaServices.Client.ContentKeyAuthorization;
using Microsoft.WindowsAzure.MediaServices.Client.DynamicEncryption;
using Microsoft.WindowsAzure.MediaServices.Client.FairPlay;
using Newtonsoft.Json;
using System.Security.Cryptography.X509Certificates;

namespace DynamicEncryptionWithFairPlay
{
    class Program
    {
    // Read values from the App.config file.
    private static readonly string _AADTenantDomain =
    ConfigurationManager.AppSettings["AADTenantDomain"];
    private static readonly string _RESTAPIEndpoint =
    ConfigurationManager.AppSettings["MediaServiceRESTAPIEndpoint"];

    private static readonly Uri _sampleIssuer =
        new Uri(ConfigurationManager.AppSettings["Issuer"]);
    private static readonly Uri _sampleAudience =
        new Uri(ConfigurationManager.AppSettings["Audience"]);

    // Field for service context.
    private static CloudMediaContext _context = null;

    private static readonly string _mediaFiles =
        Path.GetFullPath(@"../..\Media");

    private static readonly string _singleMP4File =
        Path.Combine(_mediaFiles, @"BigBuckBunny.mp4");

    static void Main(string[] args)
    {
        var tokenCredentials = new AzureAdTokenCredentials(_AADTenantDomain, AzureEnvironments.AzureCloudEnvironment);
        var tokenProvider = new AzureAdTokenProvider(tokenCredentials);

        _context = new CloudMediaContext(new Uri(_RESTAPIEndpoint), tokenProvider);

        bool tokenRestriction = false;
        string tokenTemplateString = null;

        IAsset asset = UploadFileAndCreateAsset(_singleMP4File);
        Console.WriteLine("Uploaded asset: {0}", asset.Id);

        IAsset encodedAsset = EncodeToAdaptiveBitrateMP4Set(asset);
        Console.WriteLine("Encoded asset: {0}", encodedAsset.Id);

        IContentKey key = CreateCommonCBCTypeContentKey(encodedAsset);
        Console.WriteLine("Created key {0} for the asset {1} ", key.Id, encodedAsset.Id);
        Console.WriteLine("FairPlay License Key delivery URL: {0}", key.GetKeyDeliveryUrl(ContentKeyDeliveryType.FairPlay));
        Console.WriteLine();

        if (tokenRestriction)
        tokenTemplateString = AddTokenRestrictedAuthorizationPolicy(key);
        else
        AddOpenAuthorizationPolicy(key);

        Console.WriteLine("Added authorization policy: {0}", key.AuthorizationPolicyId);
        Console.WriteLine();

        CreateAssetDeliveryPolicy(encodedAsset, key);
        Console.WriteLine("Created asset delivery policy. \n");
        Console.WriteLine();

        if (tokenRestriction && !String.IsNullOrEmpty(tokenTemplateString))
        {
        // Deserializes a string containing an Xml representation of a TokenRestrictionTemplate
        // back into a TokenRestrictionTemplate class instance.
        TokenRestrictionTemplate tokenTemplate =
            TokenRestrictionTemplateSerializer.Deserialize(tokenTemplateString);

        // Generate a test token based on the the data in the given TokenRestrictionTemplate.
        // Note, you need to pass the key id Guid because we specified
        // TokenClaim.ContentKeyIdentifierClaim in during the creation of TokenRestrictionTemplate.
        Guid rawkey = EncryptionUtils.GetKeyIdAsGuid(key.Id);
        string testToken = TokenRestrictionTemplateSerializer.GenerateTestToken(tokenTemplate, null, rawkey,
                                    DateTime.UtcNow.AddDays(365));
        Console.WriteLine("The authorization token is:\nBearer {0}", testToken);
        Console.WriteLine();
        }

        string url = GetStreamingOriginLocator(encodedAsset);
        Console.WriteLine("Encrypted HLS URL: {0}/manifest(format=m3u8-aapl)", url);

        Console.ReadLine();
    }

    static public IAsset UploadFileAndCreateAsset(string singleFilePath)
    {
        if (!File.Exists(singleFilePath))
        {
        Console.WriteLine("File does not exist.");
        return null;
        }

        var assetName = Path.GetFileNameWithoutExtension(singleFilePath);
        IAsset inputAsset = _context.Assets.Create(assetName, AssetCreationOptions.None);

        var assetFile = inputAsset.AssetFiles.Create(Path.GetFileName(singleFilePath));

        Console.WriteLine("Created assetFile {0}", assetFile.Name);

        Console.WriteLine("Upload {0}", assetFile.Name);

        assetFile.Upload(singleFilePath);
        Console.WriteLine("Done uploading {0}", assetFile.Name);

        return inputAsset;
    }

    static public IAsset EncodeToAdaptiveBitrateMP4Set(IAsset inputAsset)
    {
        var encodingPreset = "Adaptive Streaming";

        IJob job = _context.Jobs.Create(String.Format("Encoding {0}", inputAsset.Name));

        var mediaProcessors =
        _context.MediaProcessors.Where(p => p.Name.Contains("Media Encoder Standard")).ToList();

        var latestMediaProcessor =
        mediaProcessors.OrderBy(mp => new Version(mp.Version)).LastOrDefault();

        ITask encodeTask = job.Tasks.AddNew("Encoding", latestMediaProcessor, encodingPreset, TaskOptions.None);
        encodeTask.InputAssets.Add(inputAsset);
        encodeTask.OutputAssets.AddNew(String.Format("{0} as {1}", inputAsset.Name, encodingPreset), AssetCreationOptions.StorageEncrypted);

        job.StateChanged += new EventHandler<JobStateChangedEventArgs>(JobStateChanged);
        job.Submit();
        job.GetExecutionProgressTask(CancellationToken.None).Wait();

        return job.OutputMediaAssets[0];
    }

    static public IContentKey CreateCommonCBCTypeContentKey(IAsset asset)
    {
        // Create HLS SAMPLE AES encryption content key
        Guid keyId = Guid.NewGuid();
        byte[] contentKey = GetRandomBuffer(16);

        IContentKey key = _context.ContentKeys.Create(
                    keyId,
                    contentKey,
                    "ContentKey",
                    ContentKeyType.CommonEncryptionCbcs);

        // Associate the key with the asset.
        asset.ContentKeys.Add(key);

        return key;
    }


    static public void AddOpenAuthorizationPolicy(IContentKey contentKey)
    {
        // Create ContentKeyAuthorizationPolicy with Open restrictions
        // and create authorization policy          

        List<ContentKeyAuthorizationPolicyRestriction> restrictions = new List<ContentKeyAuthorizationPolicyRestriction>
                {
                new ContentKeyAuthorizationPolicyRestriction
                {
                    Name = "Open",
                    KeyRestrictionType = (int)ContentKeyRestrictionType.Open,
                    Requirements = null
                }
                };


        // Configure FairPlay policy option.
        string FairPlayConfiguration = ConfigureFairPlayPolicyOptions();

        IContentKeyAuthorizationPolicyOption FairPlayPolicy =
        _context.ContentKeyAuthorizationPolicyOptions.Create("",
        ContentKeyDeliveryType.FairPlay,
        restrictions,
        FairPlayConfiguration);


        IContentKeyAuthorizationPolicy contentKeyAuthorizationPolicy = _context.
            ContentKeyAuthorizationPolicies.
            CreateAsync("Deliver Common CBC Content Key with no restrictions").
            Result;

        contentKeyAuthorizationPolicy.Options.Add(FairPlayPolicy);

        // Associate the content key authorization policy with the content key.
        contentKey.AuthorizationPolicyId = contentKeyAuthorizationPolicy.Id;
        contentKey = contentKey.UpdateAsync().Result;
    }

    public static string AddTokenRestrictedAuthorizationPolicy(IContentKey contentKey)
    {
        string tokenTemplateString = GenerateTokenRequirements();

        List<ContentKeyAuthorizationPolicyRestriction> restrictions = new List<ContentKeyAuthorizationPolicyRestriction>
                {
                new ContentKeyAuthorizationPolicyRestriction
                {
                    Name = "Token Authorization Policy",
                    KeyRestrictionType = (int)ContentKeyRestrictionType.TokenRestricted,
                    Requirements = tokenTemplateString,
                }
                };

        // Configure FairPlay policy option.
        string FairPlayConfiguration = ConfigureFairPlayPolicyOptions();


        IContentKeyAuthorizationPolicyOption FairPlayPolicy =
        _context.ContentKeyAuthorizationPolicyOptions.Create("Token option",
               ContentKeyDeliveryType.FairPlay,
               restrictions,
               FairPlayConfiguration);

        IContentKeyAuthorizationPolicy contentKeyAuthorizationPolicy = _context.
            ContentKeyAuthorizationPolicies.
            CreateAsync("Deliver Common CBC Content Key with token restrictions").
            Result;

        contentKeyAuthorizationPolicy.Options.Add(FairPlayPolicy);

        // Associate the content key authorization policy with the content key
        contentKey.AuthorizationPolicyId = contentKeyAuthorizationPolicy.Id;
        contentKey = contentKey.UpdateAsync().Result;

        return tokenTemplateString;
    }

    private static string ConfigureFairPlayPolicyOptions()
    {
        // For testing you can provide all zeroes for ASK bytes together with the cert from Apple FPS SDK.
        // However, for production you must use a real ASK from Apple bound to a real prod certificate.
        byte[] askBytes = Guid.NewGuid().ToByteArray();
        var askId = Guid.NewGuid();
        // Key delivery retrieves askKey by askId and uses this key to generate the response.
        IContentKey askKey = _context.ContentKeys.Create(
                    askId,
                    askBytes,
                    "askKey",
                    ContentKeyType.FairPlayASk);

        //Customer password for creating the .pfx file.
        string pfxPassword = "<customer password for creating the .pfx file>";
        // Key delivery retrieves pfxPasswordKey by pfxPasswordId and uses this key to generate the response.
        var pfxPasswordId = Guid.NewGuid();
        byte[] pfxPasswordBytes = System.Text.Encoding.UTF8.GetBytes(pfxPassword);
        IContentKey pfxPasswordKey = _context.ContentKeys.Create(
                    pfxPasswordId,
                    pfxPasswordBytes,
                    "pfxPasswordKey",
                    ContentKeyType.FairPlayPfxPassword);

        // iv - 16 bytes random value, must match the iv in the asset delivery policy.
        byte[] iv = Guid.NewGuid().ToByteArray();

        //Specify the .pfx file created by the customer.
        var appCert = new X509Certificate2("path to the .pfx file created by the customer", pfxPassword, X509KeyStorageFlags.Exportable);

        string FairPlayConfiguration =
        Microsoft.WindowsAzure.MediaServices.Client.FairPlay.FairPlayConfiguration.CreateSerializedFairPlayOptionConfiguration(
            appCert,
            pfxPassword,
            pfxPasswordId,
            askId,
            iv);

        return FairPlayConfiguration;
    }

    static private string GenerateTokenRequirements()
    {
        TokenRestrictionTemplate template = new TokenRestrictionTemplate(TokenType.SWT);

        template.PrimaryVerificationKey = new SymmetricVerificationKey();
        template.AlternateVerificationKeys.Add(new SymmetricVerificationKey());
        template.Audience = _sampleAudience.ToString();
        template.Issuer = _sampleIssuer.ToString();
        template.RequiredClaims.Add(TokenClaim.ContentKeyIdentifierClaim);

        return TokenRestrictionTemplateSerializer.Serialize(template);
    }

    static public void CreateAssetDeliveryPolicy(IAsset asset, IContentKey key)
    {
        var kdPolicy = _context.ContentKeyAuthorizationPolicies.Where(p => p.Id == key.AuthorizationPolicyId).Single();

        var kdOption = kdPolicy.Options.Single(o => o.KeyDeliveryType == ContentKeyDeliveryType.FairPlay);

        FairPlayConfiguration configFP = JsonConvert.DeserializeObject<FairPlayConfiguration>(kdOption.KeyDeliveryConfiguration);

        // Get the FairPlay license service URL.
        Uri acquisitionUrl = key.GetKeyDeliveryUrl(ContentKeyDeliveryType.FairPlay);

        // The reason the below code replaces "https://" with "skd://" is because
        // in the IOS player sample code which you obtained in Apple developer account,
        // the player only recognizes a Key URL that starts with skd://.
        // However, if you are using a customized player,
        // you can choose whatever protocol you want.
        // For example, "https".

        Dictionary<AssetDeliveryPolicyConfigurationKey, string> assetDeliveryPolicyConfiguration =
        new Dictionary<AssetDeliveryPolicyConfigurationKey, string>
        {
                {AssetDeliveryPolicyConfigurationKey.FairPlayLicenseAcquisitionUrl, acquisitionUrl.ToString().Replace("https://", "skd://")},
                {AssetDeliveryPolicyConfigurationKey.CommonEncryptionIVForCbcs, configFP.ContentEncryptionIV}
        };

        var assetDeliveryPolicy = _context.AssetDeliveryPolicies.Create(
            "AssetDeliveryPolicy",
        AssetDeliveryPolicyType.DynamicCommonEncryptionCbcs,
        AssetDeliveryProtocol.HLS,
        assetDeliveryPolicyConfiguration);

        // Add AssetDelivery Policy to the asset
        asset.DeliveryPolicies.Add(assetDeliveryPolicy);

    }


    /// <summary>
    /// Gets the streaming origin locator.
    /// </summary>
    /// <param name="assets"></param>
    /// <returns></returns>
    static public string GetStreamingOriginLocator(IAsset asset)
    {

        // Get a reference to the streaming manifest file from the  
        // collection of files in the asset.

        var assetFile = asset.AssetFiles.Where(f => f.Name.ToLower().
                     EndsWith(".ism")).
                     FirstOrDefault();

        // Create a 30-day readonly access policy.
        IAccessPolicy policy = _context.AccessPolicies.Create("Streaming policy",
        TimeSpan.FromDays(30),
        AccessPermissions.Read);

        // Create a locator to the streaming content on an origin.
        ILocator originLocator = _context.Locators.CreateLocator(LocatorType.OnDemandOrigin, asset,
        policy,
        DateTime.UtcNow.AddMinutes(-5));

        // Create a URL to the manifest file.
        return originLocator.Path + assetFile.Name;
    }

    static private void JobStateChanged(object sender, JobStateChangedEventArgs e)
    {
        Console.WriteLine(string.Format("{0}\n  State: {1}\n  Time: {2}\n\n",
        ((IJob)sender).Name,
        e.CurrentState,
        DateTime.UtcNow.ToString(@"yyyy_M_d__hh_mm_ss")));
    }

    static private byte[] GetRandomBuffer(int length)
    {
        var returnValue = new byte[length];

        using (var rng =
        new System.Security.Cryptography.RNGCryptoServiceProvider())
        {
        rng.GetBytes(returnValue);
        }

        return returnValue;
    }
    }
}

Passaggi successivi: Percorsi di apprendimento di Servizi multimedialiNext steps: Media Services learning paths

Altre informazioni sui percorsi di apprendimento di Servizi multimediali di Azure:Read about the Azure Media Services learning paths:

Fornire commenti e suggerimentiProvide feedback

Usare il forum di suggerimenti degli utenti per fornire commenti e suggerimenti su come migliorare Servizi multimediali di Azure.Use the User Voice forum to provide feedback and make suggestions on how to improve Azure Media Services. È anche possibile passare direttamente a una delle categorie seguenti:You also can go directly to one of the following categories: