Uso della crittografia dinamica AES-128 e del servizio di distribuzione delle chiaviUsing AES-128 dynamic encryption and key delivery service

PanoramicaOverview

Nota

Vedere questo post di blog per crittografare i contenuti tramite AES per il recapito a Safari su macOS.See this blog post for encrypting content with AES for delivery to Safari on macOS. Vedere questo video per una panoramica di come proteggere il contenuto multimediale con la crittografia AES.See this video for an overview of how to protect your Media Content with AES encryption.

Servizi multimediali di Microsoft Azure consente di distribuire Http-Live-Streaming (HLS) e Smooth Streams crittografati con AES (Advanced Encryption Standard) mediante chiavi di crittografia a 128 bit.Microsoft Azure Media Services enables you to deliver Http-Live-Streaming (HLS) and Smooth Streams encrypted with Advanced Encryption Standard (AES) (using 128-bit encryption keys). Servizi multimediali fornisce anche il servizio di distribuzione chiavi che distribuisce chiavi di crittografia agli utenti autorizzati.Media Services also provides the Key Delivery service that delivers encryption keys to authorized users. Per consentire a Servizi multimediali di crittografare un asset, è necessario associare una chiave di crittografia all'asset e configurare anche i criteri di autorizzazione per la chiave.If you want for Media Services to encrypt an asset, you need to associate an encryption key with the asset and also configure authorization policies for the key. Quando un flusso viene richiesto da un lettore, Servizi multimediali usa la chiave specificata per crittografare dinamicamente i contenuti mediante AES.When a stream is requested by a player, Media Services uses the specified key to dynamically encrypt your content using AES encryption. Per decrittografare il flusso, il lettore richiede la chiave dal servizio di distribuzione delle chiavi.To decrypt the stream, the player requests the key from the key delivery service. Per decidere se l'utente è autorizzato a ottenere la chiave, il servizio valuta i criteri di autorizzazione specificati.To decide whether or not the user is authorized to get the key, the service evaluates the authorization policies that you specified for the key.

Servizi multimediali supporta più modalità di autenticazione degli utenti che eseguono richieste di chiavi.Media Services supports multiple ways of authenticating users who make key requests. I criteri di autorizzazione delle chiavi simmetriche possono avere una o più restrizioni di tipo Open o Token.The content key authorization policy could have one or more authorization restrictions: open or token restriction. I criteri con restrizione Token devono essere accompagnati da un token rilasciato da un servizio STS (Secure Token Service, servizio token di sicurezza).The token restricted policy must be accompanied by a token issued by a Secure Token Service (STS). Servizi multimediali supporta i token nei formati Simple Web Tokens (SWT) e JSON Web Token (JWT).Media Services supports tokens in the Simple Web Tokens (SWT) format and JSON Web Token (JWT) format. Per altre informazioni, vedere l'argomento Configurare i criteri di autorizzazione della chiave simmetrica.For more information, see Configure the content key’s authorization policy.

Per sfruttare la crittografia dinamica, è necessario disporre di un asset che contenga un set di file MP4 con velocità in bit multipla o di file di origine Smooth Streaming con velocità in bit multipla.To take advantage of dynamic encryption, you need to have an asset that contains a set of multi-bitrate MP4 files or multi-bitrate Smooth Streaming source files. È inoltre necessario configurare i criteri di distribuzione dell'asset (descritti più avanti in questo articolo).You also need to configure the delivery policy for the asset (described later in this article). Quindi, in base al formato specificato nell'URL di streaming, il server di streaming on demand garantisce che il flusso sia distribuito nel protocollo scelto.Then, based on the format specified in the streaming URL, the On-Demand Streaming server ensures that the stream is delivered in the protocol you have chosen. Di conseguenza, si archiviano e si pagano solo i file in un singolo formato di archiviazione e il servizio Servizi multimediali crea e fornisce la risposta appropriata in base alle richieste di un client.As a result, you only need to store and pay for the files in single storage format and Media Services service builds and serves the appropriate response based on requests from a client.

Questo articolo potrebbe essere utile per gli sviluppatori che usano applicazioni che forniscono contenuti protetti.This article would be useful to developers that work on applications that deliver protected media. L'articolo illustra come configurare il servizio di distribuzione delle chiavi con criteri di autorizzazione, in modo che solo i client autorizzati possano ricevere le chiavi di crittografia.The article shows you how to configure the key delivery service with authorization policies so that only authorized clients could receive the encryption keys. Viene inoltre illustrato come utilizzare la crittografia dinamica.It also shows how to use dynamic encryption.

Flusso di lavoro della crittografia dinamica AES-128 e servizio di distribuzione delle chiaviAES-128 Dynamic Encryption and Key Delivery Service Workflow

Di seguito sono indicati i passaggi generali da eseguire quando si esegue la crittografia degli asset con AES, tramite il servizio di distribuzione delle chiavi di Servizi multimediali e tramite la crittografia dinamica.The following are general steps that you would need to perform when encrypting your assets with AES, using the Media Services key delivery service, and also using dynamic encryption.

  1. Creare un asset e caricare file nell'asset.Create an asset and upload files into the asset.
  2. Codificare l'asset contenente il file per il set di file MP4 con velocità in bit adattiva.Encode the asset containing 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. In Servizi multimediali, la chiave simmetrica contiene la chiave di crittografia dell'asset.In Media Services, the content key contains the asset’s encryption key.
  4. Configurare i criteri di autorizzazione della chiave simmetrica.Configure the content key’s authorization policy. I criteri di autorizzazione della chiave simmetrica devono essere configurati dall'utente e soddisfatti dal client affinché la chiave simmetrica possa essere distribuita al client.The content key authorization policy must be configured by you and met by the client in order for the content key to be delivered to the client.
  5. Configurare i criteri di distribuzione di un asset.Configure the delivery policy for an asset. La configurazione dei criteri di distribuzione include: l'URL di acquisizione della chiave e il vettore di inizializzazione, AES 128 richiede che venga fornito lo stesso vettore di inizializzazione per la crittografia e la decrittografia; il protocollo di recapito, ad esempio MPEG-DASH, HLS, Smooth Streaming o tutti; il tipo di crittografia dinamica, ad esempio envelope o nessuna crittografia dinamica.The delivery policy configuration includes: key acquisition URL and Initialization Vector (IV) (AES 128 requires the same IV to be supplied when encrypting and decrypting), delivery protocol (for example, MPEG DASH, HLS, Smooth Streaming or all), the type of dynamic encryption (for example, envelope or no dynamic encryption).

    È possibile applicare criteri diversi per ogni protocollo allo stesso asset.You could apply different policy to each protocol on the same asset. Ad esempio, è possibile applicare la crittografia PlayReady a Smooth/DASH e AES Envelope ad HLS.For example, you could apply PlayReady encryption to Smooth/DASH and AES Envelope to HLS. Gli eventuali protocolli non definiti nei criteri di distribuzione (ad esempio quando si aggiunge un singolo criterio che specifica soltanto HLS come protocollo) verranno esclusi dallo streaming.Any protocols that are not defined in a delivery policy (for example, you add a single policy that only specifies HLS as the protocol) will be blocked from streaming. Questo comportamento non si verifica quando non è presente alcun criterio di distribuzione degli asset.The exception to this is if you have no asset delivery policy defined at all. In tal caso, sono consentiti tutti i protocolli in chiaro.Then, all protocols are allowed in the clear.

  6. Creare un localizzatore OnDemand per ottenere un URL di streaming.Create an OnDemand locator in order to get a streaming URL.

L'articolo inoltre indica come un'applicazione client può richiedere una chiave dal servizio di distribuzione delle chiavi.The article also shows how a client application can request a key from the key delivery service.

Notare un esempio .NET completo alla fine dell'articolo.You find a complete .NET example at the end of the article.

Nell'immagine seguente viene illustrato il flusso di lavoro descritto in precedenza.The following image demonstrates the workflow described above. Di seguito viene utilizzato il token per l'autenticazione.Here the token is used for authentication.

Proteggere con AES-128

Nella parte rimanente di questo articolo vengono fornite spiegazioni dettagliate, esempi di codice e collegamenti ad argomenti che illustrano come eseguire le attività descritte in precedenza.The rest of this article provides detailed explanations, code examples, and links to topics that show you how to achieve the tasks described above.

Limitazioni correntiCurrent limitations

Se si aggiungono o si aggiornano i criteri di distribuzione dell'asset, è necessario eliminare l'eventuale localizzatore esistente e creare un nuovo localizzatore.If you add or update your asset’s delivery policy, you must delete an existing locator (if any) and create a new locator.

Creare un asset e caricare file nell'assetCreate an asset and upload files into the asset

Per gestire, codificare e trasmettere i video, è innanzitutto necessario caricare il contenuto in Servizi multimediali di Microsoft Azure.In order to manage, encode, and stream your videos, you must first upload your content into Microsoft Azure Media Services. Dopo aver caricato i file, i contenuti vengono archiviati in modo sicuro nel cloud per altre operazioni di elaborazione e streaming.Once uploaded, your content is stored securely in the cloud for further processing and streaming.

Per informazioni dettagliate, vedere Carica file in un account di servizi multimediali.For detailed information, see Upload Files into a Media Services account.

Codificare l'asset contenente il file per il set di file MP4 con velocità in bit adattivaEncode the asset containing the file to the adaptive bitrate MP4 set

Con la crittografia dinamica è necessario solamente creare un asset che contenga un set di file MP4 con velocità in bit multipla o di file di origine Smooth Streaming con velocità in bit multipla.With dynamic encryption all, you need is to create an asset that contains a set of multi-bitrate MP4 files or multi-bitrate Smooth Streaming source files. In base al formato specificato nella richiesta del manifesto o del frammento, il server di streaming on demand garantisce che il flusso sia ricevuto nel protocollo scelto.Then, based on the specified format in the manifest or fragment request, the On-Demand Streaming server ensures that you receive the stream in the protocol you have chosen. Di conseguenza, si archiviano e si pagano solo i file in un singolo formato di archiviazione e il servizio Servizi multimediali crea e fornisce la risposta appropriata in base alle richieste di un client.As a result, you only need to store and pay for the files in single storage format and Media Services service will build and serve the appropriate response based on requests from a client. Per altre informazioni, vedere l'articolo Creazione dinamica dei pacchetti.For more information, see the Dynamic Packaging Overview article.

Nota

Quando l'account AMS viene creato, un endpoint di streaming predefinito viene aggiunto all'account con stato Arrestato.When your AMS account is created a default streaming endpoint is added to your account in the Stopped state. Per avviare lo streaming del contenuto e sfruttare i vantaggi della creazione dinamica dei pacchetti e della crittografia dinamica, l'endpoint di streaming da cui si vuole trasmettere il contenuto deve essere nello stato In esecuzione.To start streaming your content and take advantage of dynamic packaging and dynamic encryption, the streaming endpoint from which you want to stream content has to be in the Running state.

Per usare la creazione dinamica dei pacchetti e la crittografia dinamica, l'asset deve contenere un set di file MP4 o Smooth Streaming a velocità in bit adattiva.Also, to be able to use dynamic packaging and dynamic encryption your asset must contain a set of adaptive bitrate MP4s or adaptive bitrate Smooth Streaming files.

Per istruzioni su come eseguire la codifica, vedere Come codificare un asset mediante Media Encoder Standard.For instructions on how to encode, see How to encode an asset using Media Encoder Standard.

Creare una chiave simmetrica e associarla all'asset codificatoCreate a content key and associate it with the encoded asset

In Servizi multimediali, la chiave simmetrica contiene la chiave con cui si desidera crittografare un asset.In Media Services, the content key contains the key that you want to encrypt an asset with.

Per informazioni dettagliate, vedere Creare una chiave simmetrica.For detailed information, see Create content key.

Configurare i criteri di autorizzazione della chiave simmetrica.Configure the content key’s authorization policy

Servizi multimediali supporta più modalità di autenticazione degli utenti che eseguono richieste di chiavi.Media Services supports multiple ways of authenticating users who make key requests. I criteri di autorizzazione della chiave simmetrica devono essere configurati dall'utente e soddisfatti dal client (lettore) affinché la chiave possa essere distribuita al client.The content key authorization policy must be configured by you and met by the client (player) in order for the key to be delivered to the client. I criteri di autorizzazione delle chiavi simmetriche possono avere una o più restrizioni di tipo Open, Token o IP.The content key authorization policy could have one or more authorization restrictions: open, token restriction, or IP restriction.

Per informazioni dettagliate, vedere l'argomento Configurare i criteri di autorizzazione della chiave simmetrica.For detailed information, see Configure Content Key Authorization Policy.

Configurare i criteri di distribuzione dell'assetConfigure asset delivery policy

Configurare i criteri di distribuzione dell'asset.Configure the delivery policy for your asset. Alcuni aspetti inclusi nella configurazione dei criteri di distribuzione dell’asset:Some things that the asset delivery policy configuration includes:

  • URL di acquisizione della chiave.The Key acquisition URL.
  • Vettore di inizializzazione (IV) da utilizzare per la crittografia envelope.The Initialization Vector (IV) to use for the envelope encryption. AES 128 richiede che venga fornito lo stesso IV per la crittografia e la decrittografia.AES 128 requires the same IV to be supplied when encrypting and decrypting.
  • Il protocollo di recapito dell'asset (ad esempio, MPEG DASH, HLS, Smooth Streaming o tutti).The asset delivery protocol (for example, MPEG DASH, HLS, Smooth Streaming or all).
  • Il tipo di crittografia dinamica (ad esempio, envelope AES) o nessuna crittografia dinamica.The type of dynamic encryption (for example, AES envelope) or no dynamic encryption.

Per informazioni dettagliate, vedere Configurare i criteri di distribuzione degli asset .For detailed information, see Configure asset delivery policy.

Creare un localizzatore di streaming on demand per ottenere un URL di streamingCreate an OnDemand streaming locator in order to get a streaming URL

È necessario fornire all'utente l'URL di streaming per Smooth, DASH o HLS.You need to provide your user with the streaming URL for Smooth, DASH, or HLS.

Nota

Se si aggiungono o si aggiornano i criteri di distribuzione dell'asset, è necessario eliminare l'eventuale localizzatore esistente e creare un nuovo localizzatore.If you add or update your asset’s delivery policy, you must delete an existing locator (if any) and create a new locator.

Per istruzioni su come pubblicare un asset e creare un URL di streaming, vedere la sezione Creare URL di streaming.For instructions on how to publish an asset and build a streaming URL, see Build a streaming URL.

Ottenere un token di testGet a test token

Ottenere un token di test basato sulla restrizione Token usata per i criteri di autorizzazione della chiave.Get a test token based on the token restriction that was used for the key authorization policy.

// 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 data in the given TokenRestrictionTemplate.
//The GenerateTestToken method returns the token without the word “Bearer” in front
//so you have to add it in front of the token string. 
string testToken = TokenRestrictionTemplateSerializer.GenerateTestToken(tokenTemplate);
Console.WriteLine("The authorization token is:\nBearer {0}", testToken);

È possibile utilizzare il lettore AMS per testare il flusso.You can use the AMS Player to test your stream.

In che modo il client può richiedere una chiave dal servizio di distribuzione delle chiavi?How can your client request a key from the key delivery service?

Nel passaggio precedente, è stato realizzato l'URL che punta a un file manifesto.In the previous step, you constructed the URL that points to a manifest file. Il client deve estrarre le informazioni necessarie dai file manifesto del flusso per effettuare una richiesta al servizio di distribuzione delle chiavi.Your client needs to extract the necessary information from the streaming manifest files in order to make a request to the key delivery service.

File manifestoManifest files

Il client deve estrarre il valore URL (che contiene anche l'ID della chiave simmetrica kid) dal file manifesto.The client needs to extract the URL (that also contains content key ID (kid)) value from the manifest file. Il client tenterà quindi di ottenere la chiave di crittografia dal servizio di distribuzione delle chiavi.The client will then try to get the encryption key from the key delivery service. Inoltre, il client deve estrarre il valore IV e usarlo per decrittografare il flusso.The client also needs to extract the IV value and use it do decrypt the stream. Il frammento di codice seguente illustra l'elemento del manifesto Smooth Streaming.The following snippet shows the element of the Smooth Streaming manifest.

<Protection>
  <ProtectionHeader SystemID="B47B251A-2409-4B42-958E-08DBAE7B4EE9">
    <ContentProtection xmlns:sea="urn:mpeg:dash:schema:sea:2012" schemeIdUri="urn:mpeg:dash:sea:2012">
      <sea:SegmentEncryption schemeIdUri="urn:mpeg:dash:sea:aes128-cbc:2013"/>
      <sea:KeySystem keySystemUri="urn:mpeg:dash:sea:keysys:http:2013"/>
      <sea:CryptoPeriod IV="0xD7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7" 
                        keyUriTemplate="https://wamsbayclus001kd-hs.cloudapp.net/HlsHandler.ashx?
                                        kid=da3813af-55e6-48e7-aa9f-a4d6031f7b4d"/>
    </ContentProtection>
  </ProtectionHeader>
</Protection>

Nel caso di HLS, il manifesto radice viene suddiviso in file di segmento.In the case of HLS, the root manifest is broken into segment files.

Ad esempio, il manifesto radice è: http://test001.origin.mediaservices.windows.net/8bfe7d6f-34e3-4d1a-b289-3e48a8762490/BigBuckBunny.ism/manifest(format=m3u8-aapl) e contiene un elenco di nomi di file di segmento.For example, the root manifest is: http://test001.origin.mediaservices.windows.net/8bfe7d6f-34e3-4d1a-b289-3e48a8762490/BigBuckBunny.ism/manifest(format=m3u8-aapl) and it contains a list of segment file names.

. . . 
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=630133,RESOLUTION=424x240,CODECS="avc1.4d4015,mp4a.40.2",AUDIO="audio"
QualityLevels(514369)/Manifest(video,format=m3u8-aapl)
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=965441,RESOLUTION=636x356,CODECS="avc1.4d401e,mp4a.40.2",AUDIO="audio"
QualityLevels(842459)/Manifest(video,format=m3u8-aapl)
…

Se si apre uno dei file del segmento nell'editor di testo (ad esempio, http://test001.origin.mediaservices.windows.net/8bfe7d6f-34e3-4d1a-b289-3e48a8762490/BigBuckBunny.ism/QualityLevels(514369)/Manifest(video,format=m3u8-aapl), deve essere presente #EXT-X-KEY che indica che il file è crittografato.If you open one of the segment files in text editor (for example, http://test001.origin.mediaservices.windows.net/8bfe7d6f-34e3-4d1a-b289-3e48a8762490/BigBuckBunny.ism/QualityLevels(514369)/Manifest(video,format=m3u8-aapl), it should contain #EXT-X-KEY that indicates that the file is encrypted.

#EXTM3U
#EXT-X-VERSION:4
#EXT-X-ALLOW-CACHE:NO
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-TARGETDURATION:9
#EXT-X-KEY:METHOD=AES-128,
URI="https://wamsbayclus001kd-hs.cloudapp.net/HlsHandler.ashx?
     kid=da3813af-55e6-48e7-aa9f-a4d6031f7b4d",
        IV=0XD7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7
#EXT-X-PROGRAM-DATE-TIME:1970-01-01T00:00:00.000+00:00
#EXTINF:8.425708,no-desc
Fragments(video=0,format=m3u8-aapl)
#EXT-X-ENDLIST

Nota

Se si prevede di eseguire un flusso HLS crittografato con AES in Safari, vedere questo blog.If you are planning to play an AES encrypted HLS in Safari, see this blog.

Richiedere la chiave dal servizio di distribuzione delle chiaviRequest the key from the key delivery service

Il codice seguente indica come inviare una richiesta al servizio di distribuzione delle chiavi di Servizi multimediali usando un Uri di distribuzione della chiave (che è stato estratto dal manifesto) e un token (in questo articolo non viene discusso come ottenere token Web semplici da un servizio Secure Token).The following code shows how to send a request to the Media Services key delivery service using a key delivery Uri (that was extracted from the manifest) and a token (this article does not talk about how to get Simple Web Tokens from a Secure Token Service).

private byte[] GetDeliveryKey(Uri keyDeliveryUri, string token)
{
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(keyDeliveryUri);

    request.Method = "POST";
    request.ContentType = "text/xml";
    if (!string.IsNullOrEmpty(token))
    {
        request.Headers[AuthorizationHeader] = token;
    }
    request.ContentLength = 0;

    var response = request.GetResponse();

    var stream = response.GetResponseStream();
    if (stream == null)
    {
        throw new NullReferenceException("Response stream is null");
    }

    var buffer = new byte[256];
    var length = 0;
    while (stream.CanRead && length <= buffer.Length)
    {
        var nexByte = stream.ReadByte();
        if (nexByte == -1)
        {
            break;
        }
        buffer[length] = (byte)nexByte;
        length++;
    }
    response.Close();

    // AES keys must be exactly 16 bytes (128 bits).
    var key = new byte[length];
    Array.Copy(buffer, key, length);
    return key;
}

Proteggere i contenuti con AES-128 tramite .NETProtect your content with AES-128 using .NET

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 i seguenti elementi 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

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.Security.Cryptography;
using Microsoft.WindowsAzure.MediaServices.Client;
using System.Threading;
using Microsoft.WindowsAzure.MediaServices.Client.ContentKeyAuthorization;
using Microsoft.WindowsAzure.MediaServices.Client.DynamicEncryption;

namespace DynamicEncryptionWithAES
{
    class Program
    {
        // Read values from the App.config file.
        static string _AADTenantDomain =
            ConfigurationManager.AppSettings["AMSAADTenantDomain"];
        static string _RESTAPIEndpoint =
            ConfigurationManager.AppSettings["AMSRESTAPIEndpoint"];
        static string _AMSClientId =
            ConfigurationManager.AppSettings["AMSClientId"];
        static string _AMSClientSecret =
            ConfigurationManager.AppSettings["AMSClientSecret"];

        // A Uri describing the issuer of the token.  
        // Must match the value in the token for the token to be considered valid.
        private static readonly Uri _sampleIssuer =
            new Uri(ConfigurationManager.AppSettings["Issuer"]);
        // The Audience or Scope of the token.  
        // Must match the value in the token for the token to be considered valid.
        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)
        {
            AzureAdTokenCredentials tokenCredentials =
                new AzureAdTokenCredentials(_AADTenantDomain,
                    new AzureAdClientSymmetricKey(_AMSClientId, _AMSClientSecret),
                    AzureEnvironments.AzureCloudEnvironment);

            var tokenProvider = new AzureAdTokenProvider(tokenCredentials);

            _context = new CloudMediaContext(new Uri(_RESTAPIEndpoint), tokenProvider);
            
            bool tokenRestriction = true;
            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 = CreateEnvelopeTypeContentKey(encodedAsset);
            Console.WriteLine("Created key {0} for the asset {1} ", key.Id, encodedAsset.Id);
            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 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);

                //The GenerateTestToken method returns the token without the word “Bearer” in front
                //so you have to add it in front of the token string. 
                string testToken = TokenRestrictionTemplateSerializer.GenerateTestToken(tokenTemplate, null, rawkey, DateTime.UtcNow.AddDays(365));

                Console.WriteLine("The authorization token is:\nBearer {0}", testToken);
                Console.WriteLine();
            }

            // You can use the bit.ly/aesplayer Flash player to test the URL 
            // (with open authorization policy). 
            // Paste the URL and click the Update button to play the video. 
            //
            string URL = GetStreamingOriginLocator(encodedAsset);
            Console.WriteLine("Smooth Streaming Url: {0}/manifest", URL);
            Console.WriteLine();
            Console.WriteLine("HLS Url: {0}/manifest(format=m3u8-aapl)", URL);
            Console.WriteLine();

            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.StorageEncrypted);

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

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

            var policy = _context.AccessPolicies.Create(
                                    assetName,
                                    TimeSpan.FromDays(30),
                                    AccessPermissions.Write | AccessPermissions.List);

            var locator = _context.Locators.CreateLocator(LocatorType.Sas, inputAsset, policy);

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

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

            locator.Delete();
            policy.Delete();

            return inputAsset;
        }

        static public IAsset EncodeToAdaptiveBitrateMP4Set(IAsset asset)
        {
            // Declare a new job.
            IJob job = _context.Jobs.Create("Media Encoder Standard Job");
            // Get a media processor reference, and pass to it the name of the 
            // processor to use for the specific task.
            IMediaProcessor processor = GetLatestMediaProcessorByName("Media Encoder Standard");

            // Create a task with the encoding details, using a string preset.
            // In this case "H264 Multiple Bitrate 720p" preset is used.
            ITask task = job.Tasks.AddNew("My encoding task",
                processor,
                "H264 Multiple Bitrate 720p",
                TaskOptions.None);

            // Specify the input asset to be encoded.
            task.InputAssets.Add(asset);
            // Add an output asset to contain the results of the job. 
            // This output is specified as AssetCreationOptions.None, which 
            // means the output asset is not encrypted. 
            task.OutputAssets.AddNew("Output asset",
                AssetCreationOptions.None);

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

            return job.OutputMediaAssets[0];
        }

        private static IMediaProcessor GetLatestMediaProcessorByName(string mediaProcessorName)
        {
            var processor = _context.MediaProcessors.Where(p => p.Name == mediaProcessorName).
            ToList().OrderBy(p => new Version(p.Version)).LastOrDefault();

            if (processor == null)
                throw new ArgumentException(string.Format("Unknown media processor", mediaProcessorName));

            return processor;
        }

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

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

            // 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             
            IContentKeyAuthorizationPolicy policy = _context.
                                    ContentKeyAuthorizationPolicies.
                                    CreateAsync("Open Authorization Policy").Result;

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

            ContentKeyAuthorizationPolicyRestriction restriction =
                new ContentKeyAuthorizationPolicyRestriction
                {
                    Name = "HLS Open Authorization Policy",
                    KeyRestrictionType = (int)ContentKeyRestrictionType.Open,
                    Requirements = null // no requirements needed for HLS
                };

            restrictions.Add(restriction);

            IContentKeyAuthorizationPolicyOption policyOption =
                _context.ContentKeyAuthorizationPolicyOptions.Create(
                "policy",
                ContentKeyDeliveryType.BaselineHttp,
                restrictions,
                "");

            policy.Options.Add(policyOption);

            // Add ContentKeyAutorizationPolicy to ContentKey
            contentKey.AuthorizationPolicyId = policy.Id;
            IContentKey updatedKey = contentKey.UpdateAsync().Result;
            Console.WriteLine("Adding Key to Asset: Key ID is " + updatedKey.Id);
        }

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

            IContentKeyAuthorizationPolicy policy = _context.
                                    ContentKeyAuthorizationPolicies.
                                    CreateAsync("HLS token restricted authorization policy").Result;

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

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

            restrictions.Add(restriction);

            //You could have multiple options 
            IContentKeyAuthorizationPolicyOption policyOption =
                _context.ContentKeyAuthorizationPolicyOptions.Create(
                    "Token option for HLS",
                    ContentKeyDeliveryType.BaselineHttp,
                    restrictions,
                    null  // no key delivery data is needed for HLS
                    );

            policy.Options.Add(policyOption);

            // Add ContentKeyAutorizationPolicy to ContentKey
            contentKey.AuthorizationPolicyId = policy.Id;
            IContentKey updatedKey = contentKey.UpdateAsync().Result;
            Console.WriteLine("Adding Key to Asset: Key ID is " + updatedKey.Id);

            return tokenTemplateString;
        }

        static public void CreateAssetDeliveryPolicy(IAsset asset, IContentKey key)
        {
            Uri keyAcquisitionUri = key.GetKeyDeliveryUrl(ContentKeyDeliveryType.BaselineHttp);

            string envelopeEncryptionIV = Convert.ToBase64String(GetRandomBuffer(16));

            // The following policy configuration specifies: 
            //   key url that will have KID=<Guid> appended to the envelope and
            //   the Initialization Vector (IV) to use for the envelope encryption.
            Dictionary<AssetDeliveryPolicyConfigurationKey, string> assetDeliveryPolicyConfiguration =
                new Dictionary<AssetDeliveryPolicyConfigurationKey, string>
            {
                        {AssetDeliveryPolicyConfigurationKey.EnvelopeKeyAcquisitionUrl, keyAcquisitionUri.ToString()}
            };

            IAssetDeliveryPolicy assetDeliveryPolicy =
                _context.AssetDeliveryPolicies.Create(
                            "AssetDeliveryPolicy",
                            AssetDeliveryPolicyType.DynamicEnvelopeEncryption,
                            AssetDeliveryProtocol.SmoothStreaming | AssetDeliveryProtocol.HLS | AssetDeliveryProtocol.Dash,
                            assetDeliveryPolicyConfiguration);

            // Add AssetDelivery Policy to the asset
            asset.DeliveryPolicies.Add(assetDeliveryPolicy);
            Console.WriteLine();
            Console.WriteLine("Adding Asset Delivery Policy: " +
                assetDeliveryPolicy.AssetDeliveryPolicyType);
        }

        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. 
            // You cannot create a streaming locator using an AccessPolicy that includes write or delete permissions.            
            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 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 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 size)
        {
            byte[] randomBytes = new byte[size];
            using (RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider())
            {
                rng.GetBytes(randomBytes);
            }

            return randomBytes;
        }
    }
}

Percorsi di apprendimento di Servizi multimedialiMedia 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: