private IContentKey[] GetContentKeys(ContentProtection contentProtection) { List <IContentKey> contentKeys = new List <IContentKey>(); if (contentProtection.AES) { ContentKeyType keyType = ContentKeyType.EnvelopeEncryption; string keyName = Constants.Media.ContentProtection.ContentKeyNameAes; IContentKey contentKey = GetContentKey(keyType, keyName, contentProtection); contentKeys.Add(contentKey); } if (contentProtection.DRMPlayReady && contentProtection.DRMWidevine) { ContentKeyType keyType = ContentKeyType.CommonEncryption; string keyName = Constants.Media.ContentProtection.ContentKeyNameDrmPlayReadyWidevine; IContentKey contentKey = GetContentKey(keyType, keyName, contentProtection); contentKeys.Add(contentKey); } else if (contentProtection.DRMPlayReady) { ContentKeyType keyType = ContentKeyType.CommonEncryption; string keyName = Constants.Media.ContentProtection.ContentKeyNameDrmPlayReady; IContentKey contentKey = GetContentKey(keyType, keyName, contentProtection); contentKeys.Add(contentKey); } else if (contentProtection.DRMWidevine) { ContentKeyType keyType = ContentKeyType.CommonEncryption; string keyName = Constants.Media.ContentProtection.ContentKeyNameDrmWidevine; IContentKey contentKey = GetContentKey(keyType, keyName, contentProtection); contentKeys.Add(contentKey); } return(contentKeys.ToArray()); }
public SelectAutPolicy(CloudMediaContext context, ContentKeyType keyType) { InitializeComponent(); this.Icon = Bitmaps.Azure_Explorer_ico; _context = context; _keyType = keyType; }
public static IContentKey CreateTestKey(CloudMediaContext mediaContext, ContentKeyType contentKeyType, out byte[] key, string name = "") { key = ContentKeyTests.GetRandomBuffer(16); IContentKey contentKey = mediaContext.ContentKeys.Create(Guid.NewGuid(), key, name, contentKeyType); return(contentKey); }
public static IContentKey CreateTestKey(CloudMediaContext mediaContext, ContentKeyType contentKeyType, out byte[] key, string name = "") { key = ContentKeyTests.GetRandomBuffer(16); IContentKey contentKey = mediaContext.ContentKeys.Create(Guid.NewGuid(), key, name, contentKeyType); return contentKey; }
public CreateTestToken(IAsset _asset, CloudMediaContext _context, ContentKeyType? keytype = null, string optionid = null) { InitializeComponent(); this.Icon = Bitmaps.Azure_Explorer_ico; MyAsset = _asset; mycontext = _context; var query = from key in MyAsset.ContentKeys join autpol in _context.ContentKeyAuthorizationPolicies on key.AuthorizationPolicyId equals autpol.Id select new { keyname = key.Name, keytype = key.ContentKeyType, keyid = key.Id, aupolid = autpol.Id }; listViewAutOptions.BeginUpdate(); listViewAutOptions.Items.Clear(); foreach (var key in query) { var queryoptions = _context.ContentKeyAuthorizationPolicies.Where(a => a.Id == key.aupolid).FirstOrDefault().Options; foreach (var option in queryoptions) { if (option.Restrictions.FirstOrDefault().KeyRestrictionType == (int)ContentKeyRestrictionType.TokenRestricted) { ListViewItem item = new ListViewItem(key.keytype.ToString()); IContentKey keyj = MyAsset.ContentKeys.Where(k => k.Id == key.keyid).FirstOrDefault(); ContentKeyDisplayed.Add(keyj); item.SubItems.Add(option.Name); item.SubItems.Add(option.Id); string tokenTemplateString = option.Restrictions.FirstOrDefault().Requirements; if (!string.IsNullOrEmpty(tokenTemplateString)) { TokenRestrictionTemplate tokenTemplate = TokenRestrictionTemplateSerializer.Deserialize(tokenTemplateString); item.SubItems.Add(tokenTemplate.TokenType == TokenType.JWT ? "JWT" : "SWT"); if (tokenTemplate.PrimaryVerificationKey != null) { item.SubItems.Add(tokenTemplate.PrimaryVerificationKey.GetType() == typeof(SymmetricVerificationKey) ? "Symmetric" : "Asymmetric X509"); } else if (tokenTemplate.OpenIdConnectDiscoveryDocument != null) { item.SubItems.Add("OpenID"); } } listViewAutOptions.Items.Add(item); if (optionid == option.Id) listViewAutOptions.Items[listViewAutOptions.Items.IndexOf(item)].Selected = true; } } } if (listViewAutOptions.Items.Count > 0 && listViewAutOptions.SelectedItems.Count == 0) // no selection, in that case, first line selected { listViewAutOptions.Items[0].Selected = true; } listViewAutOptions.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize); listViewAutOptions.EndUpdate(); }
private IContentKey GetContentKey(ContentKeyType keyType, string keyName, ContentProtection contentProtection) { IContentKey contentKey = GetEntityByName(MediaEntity.ContentKey, keyName, true) as IContentKey; if (contentKey == null) { Guid keyId = Guid.NewGuid(); byte[] encryptionKey = CreateEncryptionKey(); contentKey = _media.ContentKeys.Create(keyId, encryptionKey, keyName, keyType); SetContentKeyAuthPolicy(contentKey, contentProtection); } return(contentKey); }
/// <summary> /// Create and associate a key /// </summary> /// <param name="asset"></param> /// <returns></returns> private static IContentKey CreateContentKey(IAsset asset, ContentKeyType contentKeyType) { // Create envelope encryption content key Guid keyId = Guid.NewGuid(); var contentKey = DRMHelper.GetRandomBuffer(16); IContentKey key = _context.ContentKeys.Create(keyId, contentKey, $"ContentKey {contentKeyType.ToString()}", contentKeyType); // Associate the key with the asset. asset.ContentKeys.Add(key); return(key); }
private static IContentKey CreateKeyWithPolicy(IAsset asset) { IContentKey key = asset.ContentKeys.Where(k => k.ContentKeyType == ContentKeyType.CommonEncryption).SingleOrDefault(); if (key != null) { CleanupKey(key); key.Delete(); } var keyId = Guid.NewGuid(); byte[] contentKey = Guid.NewGuid().ToByteArray(); ContentKeyType contentKeyType = ContentKeyType.CommonEncryption; IContentKeyAuthorizationPolicyOption policyOption; var restrictions = new List <ContentKeyAuthorizationPolicyRestriction> { new ContentKeyAuthorizationPolicyRestriction { Name = "Open", KeyRestrictionType = (int)ContentKeyRestrictionType.Open, Requirements = null } }; string configuration = "{}"; //string configuration = "{\"allowed_track_types\":\"SD_HD\",\"content_key_specs\":[{\"track_type\":\"SD\",\"security_level\":1,\"required_output_protection\":{\"hdcp\":\"HDCP_NONE\"}}],\"policy_overrides\":{\"can_play\":true,\"can_persist\":true,\"can_renew\":false}}"; policyOption = _mediaContext.ContentKeyAuthorizationPolicyOptions.Create( "widevinetest", ContentKeyDeliveryType.Widevine, restrictions, configuration); key = _mediaContext.ContentKeys.Create(keyId, contentKey, "TestWidevineKey", contentKeyType); var contentKeyAuthorizationPolicy = _mediaContext.ContentKeyAuthorizationPolicies.CreateAsync("test").Result; contentKeyAuthorizationPolicy.Options.Add(policyOption); key.AuthorizationPolicyId = contentKeyAuthorizationPolicy.Id; key = key.UpdateAsync().Result; asset.ContentKeys.Add(key); return(key); }
/// <summary> /// Creates a content key with the specified key identifier and value. /// </summary> /// <param name="keyId">The key identifier.</param> /// <param name="contentKey">The value of the content key.</param> /// <param name="name">A friendly name for the content key.</param> /// <param name="contentKeyType">Type of content key to create.</param> /// <returns>A <see cref="IContentKey"/> that can be associated with an <see cref="IAsset"/>.</returns> public override IContentKey Create(Guid keyId, byte[] contentKey, string name, ContentKeyType contentKeyType) { try { Task<IContentKey> task = this.CreateAsync(keyId, contentKey, name, contentKeyType); task.Wait(); return task.Result; } catch (AggregateException exception) { throw exception.InnerException; } }
public static IContentKey CreateTestKeyWithSpecified(string keyIdentifier, CloudMediaContext mediaContext, ContentKeyType contentKeyType, string name = "") { var keyId = EncryptionUtils.GetKeyIdAsGuid(keyIdentifier); SymmetricAlgorithm symmetricAlgorithm = new AesCryptoServiceProvider(); if ((contentKeyType == ContentKeyType.CommonEncryption) || (contentKeyType == ContentKeyType.EnvelopeEncryption)) { symmetricAlgorithm.KeySize = EncryptionUtils.KeySizeInBitsForAes128; } else { symmetricAlgorithm.KeySize = EncryptionUtils.KeySizeInBitsForAes256; } IContentKey contentKey = mediaContext.ContentKeys.Create(keyId, symmetricAlgorithm.Key, name, contentKeyType); return contentKey; }
private static IContentKey CreateKeyWithPolicy(IAsset asset) { IContentKey key = asset.ContentKeys.Where(k => k.ContentKeyType == ContentKeyType.CommonEncryptionCbcs).SingleOrDefault(); if (key != null) { CleanupKey(key); } var keyId = Guid.NewGuid(); byte[] contentKey = Guid.NewGuid().ToByteArray(); ContentKeyType contentKeyType = ContentKeyType.CommonEncryptionCbcs; IContentKeyAuthorizationPolicyOption policyOption; var restrictions = new List <ContentKeyAuthorizationPolicyRestriction> { new ContentKeyAuthorizationPolicyRestriction { Name = "Open", KeyRestrictionType = (int)ContentKeyRestrictionType.Open, Requirements = null } }; byte[] iv = Guid.NewGuid().ToByteArray(); policyOption = CreateFairPlayPolicyOption(iv); key = _mediaContext.ContentKeys.Create(keyId, contentKey, "TestFairPlayKey", contentKeyType); var contentKeyAuthorizationPolicy = _mediaContext.ContentKeyAuthorizationPolicies.CreateAsync("test").Result; contentKeyAuthorizationPolicy.Options.Add(policyOption); key.AuthorizationPolicyId = contentKeyAuthorizationPolicy.Id; key = key.UpdateAsync().Result; asset.ContentKeys.Add(key); return(key); }
public static IContentKey MakeContentKey(CloudMediaContext context, ContentKeyType contentKeyType, string contentKeyId = null, string contentKeySecret = null) { string contentKeyName; switch (contentKeyType) { case ContentKeyType.CommonEncryption: contentKeyName = "Common Encryption ContentKey"; return(MediaServicesHelper.CreateContentKey(context, contentKeyName, ContentKeyType.CommonEncryption, contentKeyId, contentKeySecret)); case ContentKeyType.CommonEncryptionCbcs: contentKeyName = "Common Encryption CBCS ContentKey"; return(MediaServicesHelper.CreateContentKey(context, contentKeyName, ContentKeyType.CommonEncryptionCbcs, contentKeyId, contentKeySecret)); case ContentKeyType.EnvelopeEncryption: contentKeyName = "Envelope Encryption ContentKey"; return(MediaServicesHelper.CreateContentKey(context, contentKeyName, ContentKeyType.EnvelopeEncryption, contentKeyId, contentKeySecret)); } throw new NotImplementedException(contentKeyType.ToString() + " is not supported"); }
/// <summary> /// Gets the protection key id for content key. /// </summary> /// <param name="dataContext">The data context.</param> /// <param name="contentKeyType">Type of the content key.</param> /// <returns>The content key.</returns> internal static string GetProtectionKeyIdForContentKey(MediaContextBase mediaContext, ContentKeyType contentKeyType) { // First query Nimbus to find out what certificate to encrypt the content key with. string uriString = String.Format(CultureInfo.InvariantCulture, "/GetProtectionKeyId?contentKeyType={0}", Convert.ToInt32(contentKeyType, CultureInfo.InvariantCulture)); Uri uriGetProtectionKeyId = new Uri(uriString, UriKind.Relative); IMediaDataServiceContext dataContext = mediaContext.MediaServicesClassFactory.CreateDataServiceContext(); MediaRetryPolicy retryPolicy = mediaContext.MediaServicesClassFactory.GetQueryRetryPolicy(dataContext as IRetryPolicyAdapter); IEnumerable <string> results = retryPolicy.ExecuteAction <IEnumerable <string> >(() => dataContext.Execute <string>(uriGetProtectionKeyId)); return(results.Single()); }
/// <summary> /// Gets the certificate to encrypt content key. /// </summary> /// <param name="mediaContext">The media context.</param> /// <param name="contentKeyType">Type of the content key.</param> /// <returns>The content key.</returns> internal static X509Certificate2 GetCertificateToEncryptContentKey(MediaContextBase mediaContext, ContentKeyType contentKeyType) { string thumbprint = GetProtectionKeyIdForContentKey(mediaContext, contentKeyType); return(GetCertificateForProtectionKeyId(mediaContext, thumbprint)); }
public void AcquireLicenseAsync(Guid keyId, ContentKeyType keyType, Guid serviceId) { Console.WriteLine("System.Windows.Media.LicenseAcquirer.AcquireLicenseAsync: NIEX"); throw new NotImplementedException(); }
private static void VerifyEncryptionSettingsMatch(IAssetFile file, IAsset assetFromServer, ContentKeyType expectedKeyType) { bool fileFound = false; foreach (IAssetFile fileFromServer in assetFromServer.AssetFiles) { if (fileFromServer.Id == file.Id) { fileFound = true; Assert.IsTrue(file.IsEncrypted == fileFromServer.IsEncrypted, "IsEncrypted doesn't match"); Assert.IsTrue(file.InitializationVector == fileFromServer.InitializationVector, "InitializationVector doesn't match"); Assert.IsTrue(file.EncryptionKeyId == fileFromServer.EncryptionKeyId, "EncryptionKeyId doesn't match"); Assert.IsTrue(file.EncryptionScheme == fileFromServer.EncryptionScheme, "EncryptionScheme doesn't match"); Assert.IsTrue(file.EncryptionVersion == fileFromServer.EncryptionVersion, "EncryptionVersion doesn't match"); if (!string.IsNullOrEmpty(fileFromServer.EncryptionKeyId)) { VerifyContentKeyExists(file, assetFromServer, expectedKeyType); } break; } } Assert.IsTrue(fileFound, "The expected file identifier was not found in the IAsset.Files collection queried from the server."); }
/// <summary> /// Gets the certificate to encrypt content key. /// </summary> /// <param name="dataContext">The data context.</param> /// <param name="contentKeyType">Type of the content key.</param> /// <returns>The content key.</returns> internal static X509Certificate2 GetCertificateToEncryptContentKey(DataServiceContext dataContext, ContentKeyType contentKeyType) { string thumbprint = GetProtectionKeyIdForContentKey(dataContext, contentKeyType); return(GetCertificateForProtectionKeyId(dataContext, thumbprint)); }
private static IContentKey CreateDummyContentKey(ContentKeyType keyType) { return(MediaServicesHelper.CreateContentKey(_context, "Dummy ContentKey", keyType)); }
public void AcquireLicenseAsync (Guid keyId, ContentKeyType keyType, Guid serviceId) { Console.WriteLine ("System.Windows.Media.LicenseAcquirer.AcquireLicenseAsync: NIEX"); throw new NotImplementedException (); }
public static async Task <object> Run([HttpTrigger(WebHookType = "genericJson")] HttpRequestMessage req, TraceWriter log) { log.Info($"AMS v2 Function - CreateContentKeyAuthorizationPolicy was triggered!"); string jsonContent = await req.Content.ReadAsStringAsync(); dynamic data = JsonConvert.DeserializeObject(jsonContent); // Validate input objects if (data.assetId == null) { return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Please pass assetId in the input object" })); } if (data.contentKeyAuthorizationPolicyId == null) { return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Please pass contentKeyAuthorizationPolicyId in the input object" })); } if (data.assetDeliveryPolicyId == null) { return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Please pass assetDeliveryPolicyId in the input object" })); } if (data.contentKeyType == null) { return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Please pass contentKeyType in the input object" })); } string assetId = data.assetId; string contentKeyAuthorizationPolicyId = data.contentKeyAuthorizationPolicyId; string assetDeliveryPolicyId = data.assetDeliveryPolicyId; string contentKeyTypeName = data.contentKeyType; if (!MediaServicesHelper.AMSContentKeyType.ContainsKey(contentKeyTypeName)) { return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Please pass a valid contentKeyType in the input object" })); } ContentKeyType contentKeyType = MediaServicesHelper.AMSContentKeyType[contentKeyTypeName]; if (contentKeyType != ContentKeyType.CommonEncryption && contentKeyType != ContentKeyType.CommonEncryptionCbcs && contentKeyType != ContentKeyType.EnvelopeEncryption) { return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Please pass a valid contentKeyType in the input object" })); } string contentKeyName = null; if (data.contentKeyName != null) { contentKeyName = data.contentKeyName; } MediaServicesCredentials amsCredentials = new MediaServicesCredentials(); IAsset asset = null; IContentKeyAuthorizationPolicy ckaPolicy = null; IAssetDeliveryPolicy adPolicy = null; IContentKey contentKey = null; try { // Load AMS account context log.Info($"Using AMS v2 REST API Endpoint : {amsCredentials.AmsRestApiEndpoint.ToString()}"); AzureAdTokenCredentials tokenCredentials = new AzureAdTokenCredentials(amsCredentials.AmsAadTenantDomain, new AzureAdClientSymmetricKey(amsCredentials.AmsClientId, amsCredentials.AmsClientSecret), AzureEnvironments.AzureCloudEnvironment); AzureAdTokenProvider tokenProvider = new AzureAdTokenProvider(tokenCredentials); _context = new CloudMediaContext(amsCredentials.AmsRestApiEndpoint, tokenProvider); // Get the Asset, ContentKeyAuthorizationPolicy, AssetDeliveryPolicy asset = _context.Assets.Where(a => a.Id == assetId).FirstOrDefault(); if (asset == null) { return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Asset not found" })); } ckaPolicy = _context.ContentKeyAuthorizationPolicies.Where(p => p.Id == contentKeyAuthorizationPolicyId).Single(); if (ckaPolicy == null) { return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "ContentKeyAuthorizationPolicy not found" })); } adPolicy = _context.AssetDeliveryPolicies.Where(p => p.Id == assetDeliveryPolicyId).Single(); if (adPolicy == null) { return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "AssetDeliveryPolicy not found" })); } switch (contentKeyType) { case ContentKeyType.CommonEncryption: if (contentKeyName == null) { contentKeyName = "Common Encryption ContentKey"; } contentKey = MediaServicesHelper.CreateContentKey(_context, contentKeyName, ContentKeyType.CommonEncryption); break; case ContentKeyType.CommonEncryptionCbcs: if (contentKeyName == null) { contentKeyName = "Common Encryption CBCS ContentKey"; } contentKey = MediaServicesHelper.CreateContentKey(_context, contentKeyName, ContentKeyType.CommonEncryptionCbcs); break; case ContentKeyType.EnvelopeEncryption: if (contentKeyName == null) { contentKeyName = "Envelope Encryption ContentKey"; } contentKey = MediaServicesHelper.CreateContentKey(_context, contentKeyName, ContentKeyType.EnvelopeEncryption); break; } asset.ContentKeys.Add(contentKey); contentKey.AuthorizationPolicyId = ckaPolicy.Id; contentKey = contentKey.UpdateAsync().Result; asset.DeliveryPolicies.Add(adPolicy); } catch (Exception e) { log.Info($"ERROR: Exception {e}"); return(req.CreateResponse(HttpStatusCode.BadRequest)); } return(req.CreateResponse(HttpStatusCode.OK, new { contentKeyId = contentKey.Id })); }
public static IContentKey CreateTestKey(CloudMediaContext mediaContext, ContentKeyType contentKeyType, string name = "") { byte[] key; return CreateTestKey(mediaContext, contentKeyType, out key); }
public static IContentKey CreateContentKey(CloudMediaContext context, string contentKeyName, ContentKeyType keyType) { Guid keyId = Guid.NewGuid(); byte[] contentKey = GenericHelper.GetRandomBuffer(16); IContentKey key = context.ContentKeys.Create(keyId, contentKey, contentKeyName, keyType); return(key); }
/// <summary> /// Asynchronously creates a content key with the specifies key identifier and value. /// </summary> /// <param name="keyId">The key identifier.</param> /// <param name="contentKey">The value of the content key.</param> /// <param name="name">A friendly name for the content key.</param> /// <param name="contentKeyType">Type of content key to create.</param> /// <returns> /// A function delegate that returns the future result to be available through the Task<IContentKey>. /// </returns> public override Task <IContentKey> CreateAsync(Guid keyId, byte[] contentKey, string name, ContentKeyType contentKeyType) { var allowedKeyTypes = new[] { ContentKeyType.CommonEncryption, ContentKeyType.CommonEncryptionCbcs, ContentKeyType.EnvelopeEncryption, ContentKeyType.FairPlayASk, ContentKeyType.FairPlayPfxPassword, }; if (!allowedKeyTypes.Contains(contentKeyType)) { throw new ArgumentException(StringTable.ErrorUnsupportedContentKeyType, "contentKey"); } if (keyId == Guid.Empty) { throw new ArgumentException(StringTable.ErrorCreateKey_EmptyGuidNotAllowed, "keyId"); } if (contentKey == null) { throw new ArgumentNullException("contentKey"); } if (contentKeyType != ContentKeyType.FairPlayPfxPassword && contentKey.Length != EncryptionUtils.KeySizeInBytesForAes128) { throw new ArgumentException(StringTable.ErrorCommonEncryptionKeySize, "contentKey"); } IMediaDataServiceContext dataContext = this.MediaContext.MediaServicesClassFactory.CreateDataServiceContext(); X509Certificate2 certToUse = GetCertificateToEncryptContentKey(MediaContext, ContentKeyType.CommonEncryption); ContentKeyData contentKeyData = null; if (contentKeyType == ContentKeyType.CommonEncryption) { contentKeyData = InitializeCommonContentKey(keyId, contentKey, name, certToUse); } else if (contentKeyType == ContentKeyType.CommonEncryptionCbcs) { contentKeyData = InitializeCommonContentKey(keyId, contentKey, name, certToUse); contentKeyData.ContentKeyType = (int)ContentKeyType.CommonEncryptionCbcs; } else if (contentKeyType == ContentKeyType.EnvelopeEncryption) { contentKeyData = InitializeEnvelopeContentKey(keyId, contentKey, name, certToUse); } else if (contentKeyType == ContentKeyType.FairPlayPfxPassword) { contentKeyData = InitializeFairPlayPfxPassword(keyId, contentKey, name, certToUse); } else if (contentKeyType == ContentKeyType.FairPlayASk) { contentKeyData = InitializeFairPlayASk(keyId, contentKey, name, certToUse); } dataContext.AddObject(ContentKeySet, contentKeyData); MediaRetryPolicy retryPolicy = this.MediaContext.MediaServicesClassFactory.GetSaveChangesRetryPolicy(dataContext as IRetryPolicyAdapter); return(retryPolicy.ExecuteAsync <IMediaDataServiceResponse>(() => dataContext.SaveChangesAsync(contentKeyData)) .ContinueWith <IContentKey>( t => { t.ThrowIfFaulted(); return (ContentKeyData)t.Result.AsyncState; }, TaskContinuationOptions.ExecuteSynchronously)); }
/// <summary> /// Creates a content key with the specified key identifier and value. /// </summary> /// <param name="keyId">The key identifier.</param> /// <param name="contentKey">The value of the content key.</param> /// <param name="name">A friendly name for the content key.</param> /// <param name="contentKeyType">Type of content key to create.</param> /// <returns>A <see cref="IContentKey"/> that can be associated with an <see cref="IAsset"/>.</returns> public override IContentKey Create(Guid keyId, byte[] contentKey, string name, ContentKeyType contentKeyType) { try { Task <IContentKey> task = this.CreateAsync(keyId, contentKey, name, contentKeyType); task.Wait(); return(task.Result); } catch (AggregateException exception) { throw exception.InnerException; } }
private static void VerifyContentKeyExists(IAssetFile file, IAsset assetFromServer, ContentKeyType expectedKeyType) { bool keyFound = false; foreach (IContentKey contentKeyFromServer in assetFromServer.ContentKeys) { if (file.EncryptionKeyId == contentKeyFromServer.Id) { keyFound = true; Assert.IsNotNull(contentKeyFromServer.ProtectionKeyType, "ProtectionKeyType should not be null."); Assert.IsNotNull(contentKeyFromServer.ProtectionKeyId, "ProtectionKeyId should not be null."); Assert.IsNotNull(contentKeyFromServer.EncryptedContentKey, "EncryptedContentKey should not be null."); Assert.IsTrue(contentKeyFromServer.ContentKeyType == expectedKeyType, "ContentKeyType does not match expected value"); break; } } Assert.IsTrue(keyFound, "The expected key identifier was not found in the IAsset.ContentKeys collection queried from the server."); }
/// <summary> /// Asynchronously creates a content key with the specifies key identifier and value. /// </summary> /// <param name="keyId">The key identifier.</param> /// <param name="contentKey">The value of the content key.</param> /// <param name="name">A friendly name for the content key.</param> /// <param name="contentKeyType">Type of content key to create.</param> /// <returns> /// A function delegate that returns the future result to be available through the Task<IContentKey>. /// </returns> public abstract Task <IContentKey> CreateAsync(Guid keyId, byte[] contentKey, string name, ContentKeyType contentKeyType);
/// <summary> /// Creates a content key with the specifies key identifier and value. /// </summary> /// <param name="keyId">The key identifier.</param> /// <param name="contentKey">The value of the content key.</param> /// <param name="name">A friendly name for the content key.</param> /// <param name="contentKeyType">Type of content key to create.</param> /// <returns>A <see cref="IContentKey"/> that can be associated with an <see cref="IAsset"/>.</returns> public abstract IContentKey Create(Guid keyId, byte[] contentKey, string name, ContentKeyType contentKeyType);
/// <summary> /// Gets the protection key id for content key. /// </summary> /// <param name="dataContext">The data context.</param> /// <param name="contentKeyType">Type of the content key.</param> /// <returns>The content key.</returns> internal static string GetProtectionKeyIdForContentKey(DataServiceContext dataContext, ContentKeyType contentKeyType) { // First query Nimbus to find out what certificate to encrypt the content key with. string uriString = string.Format(CultureInfo.InvariantCulture, "/GetProtectionKeyId?contentKeyType={0}", Convert.ToInt32(contentKeyType, CultureInfo.InvariantCulture)); Uri uriGetProtectionKeyId = new Uri(uriString, UriKind.Relative); IEnumerable <string> results = dataContext.Execute <string>(uriGetProtectionKeyId); return(results.Single()); }
private IAssetDeliveryPolicy[] GetDeliveryPolicies(ContentProtection contentProtection) { List <IAssetDeliveryPolicy> deliveryPolicies = new List <IAssetDeliveryPolicy>(); AssetDeliveryPolicyType policyType = AssetDeliveryPolicyType.NoDynamicEncryption; Dictionary <AssetDeliveryPolicyConfigurationKey, string> policyConfig = null; string policyName = Constants.Media.DeliveryPolicy.DecryptionStorage; if (contentProtection.AES) { policyType = AssetDeliveryPolicyType.DynamicEnvelopeEncryption; policyName = Constants.Media.DeliveryPolicy.EncryptionAes; ContentKeyType keyType = ContentKeyType.EnvelopeEncryption; string keyName = Constants.Media.ContentProtection.ContentKeyNameAes; IContentKey contentKey = GetContentKey(keyType, keyName, contentProtection); Uri keyDeliveryUrl = contentKey.GetKeyDeliveryUrl(ContentKeyDeliveryType.BaselineHttp); byte[] encryptionIV = CreateEncryptionKey(); policyConfig = new Dictionary <AssetDeliveryPolicyConfigurationKey, string>(); policyConfig.Add(AssetDeliveryPolicyConfigurationKey.EnvelopeKeyAcquisitionUrl, keyDeliveryUrl.ToString()); policyConfig.Add(AssetDeliveryPolicyConfigurationKey.EnvelopeEncryptionIVAsBase64, Convert.ToBase64String(encryptionIV)); IAssetDeliveryPolicy deliveryPolicy = GetDeliveryPolicy(policyType, policyConfig, policyName, ContentKeyDeliveryType.BaselineHttp); deliveryPolicies.Add(deliveryPolicy); } if (contentProtection.DRMPlayReady && contentProtection.DRMWidevine) { policyType = AssetDeliveryPolicyType.DynamicCommonEncryption; policyName = Constants.Media.DeliveryPolicy.EncryptionDrmPlayReadyWidevine; ContentKeyType keyType = ContentKeyType.CommonEncryption; string keyName = Constants.Media.ContentProtection.ContentKeyNameDrmPlayReadyWidevine; IContentKey contentKey = GetContentKey(keyType, keyName, contentProtection); policyConfig = new Dictionary <AssetDeliveryPolicyConfigurationKey, string>(); Uri keyDeliveryUrl = contentKey.GetKeyDeliveryUrl(ContentKeyDeliveryType.PlayReadyLicense); policyConfig.Add(AssetDeliveryPolicyConfigurationKey.PlayReadyLicenseAcquisitionUrl, keyDeliveryUrl.ToString()); keyDeliveryUrl = contentKey.GetKeyDeliveryUrl(ContentKeyDeliveryType.Widevine); policyConfig.Add(AssetDeliveryPolicyConfigurationKey.WidevineLicenseAcquisitionUrl, keyDeliveryUrl.ToString()); IAssetDeliveryPolicy deliveryPolicy = GetDeliveryPolicy(policyType, policyConfig, policyName, ContentKeyDeliveryType.PlayReadyLicense); deliveryPolicies.Add(deliveryPolicy); deliveryPolicy = GetDeliveryPolicy(policyType, policyConfig, policyName, ContentKeyDeliveryType.Widevine); deliveryPolicies.Add(deliveryPolicy); } else if (contentProtection.DRMPlayReady) { policyType = AssetDeliveryPolicyType.DynamicCommonEncryption; policyName = Constants.Media.DeliveryPolicy.EncryptionDrmPlayReady; ContentKeyType keyType = ContentKeyType.CommonEncryption; string keyName = Constants.Media.ContentProtection.ContentKeyNameDrmPlayReady; IContentKey contentKey = GetContentKey(keyType, keyName, contentProtection); Uri keyDeliveryUrl = contentKey.GetKeyDeliveryUrl(ContentKeyDeliveryType.PlayReadyLicense); policyConfig = new Dictionary <AssetDeliveryPolicyConfigurationKey, string>(); policyConfig.Add(AssetDeliveryPolicyConfigurationKey.PlayReadyLicenseAcquisitionUrl, keyDeliveryUrl.ToString()); IAssetDeliveryPolicy deliveryPolicy = GetDeliveryPolicy(policyType, policyConfig, policyName, ContentKeyDeliveryType.PlayReadyLicense); deliveryPolicies.Add(deliveryPolicy); } else if (contentProtection.DRMWidevine) { policyType = AssetDeliveryPolicyType.DynamicCommonEncryption; policyName = Constants.Media.DeliveryPolicy.EncryptionDrmWidevine; ContentKeyType keyType = ContentKeyType.CommonEncryption; string keyName = Constants.Media.ContentProtection.ContentKeyNameDrmWidevine; IContentKey contentKey = GetContentKey(keyType, keyName, contentProtection); Uri keyDeliveryUrl = contentKey.GetKeyDeliveryUrl(ContentKeyDeliveryType.Widevine); policyConfig = new Dictionary <AssetDeliveryPolicyConfigurationKey, string>(); policyConfig.Add(AssetDeliveryPolicyConfigurationKey.WidevineLicenseAcquisitionUrl, keyDeliveryUrl.ToString()); IAssetDeliveryPolicy deliveryPolicy = GetDeliveryPolicy(policyType, policyConfig, policyName, ContentKeyDeliveryType.Widevine); deliveryPolicies.Add(deliveryPolicy); } return(deliveryPolicies.ToArray()); }
public static async Task <object> Run([HttpTrigger(WebHookType = "genericJson")] HttpRequestMessage req, TraceWriter log) { log.Info($"AMS v2 Function - Add Dynamic Encryption was triggered!"); string jsonContent = await req.Content.ReadAsStringAsync(); dynamic data = JsonConvert.DeserializeObject(jsonContent); // Validate input objects if (data.assetId == null && data.programId == null && data.channelName == null && data.programName == null) { return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Please pass assetId or programID or channelName/programName in the input object" })); } if (data.contentKeyAuthorizationPolicyId == null) { return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Please pass contentKeyAuthorizationPolicyId in the input object" })); } if (data.assetDeliveryPolicyId == null) { return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Please pass assetDeliveryPolicyId in the input object" })); } if (data.contentKeyType == null) { return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Please pass contentKeyType in the input object" })); } string assetId = data.assetId; string programId = data.programId; string channelName = data.channelName; string programName = data.programName; string contentKeyAuthorizationPolicyId = data.contentKeyAuthorizationPolicyId; string assetDeliveryPolicyId = data.assetDeliveryPolicyId; string contentKeyTypeName = data.contentKeyType; string contentKeyId = data.keyId; string contentKeySecret = data.contentKey; if (!MediaServicesHelper.AMSContentKeyType.ContainsKey(contentKeyTypeName)) { return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Please pass a valid contentKeyType in the input object" })); } ContentKeyType contentKeyType = MediaServicesHelper.AMSContentKeyType[contentKeyTypeName]; if (contentKeyType != ContentKeyType.CommonEncryption && contentKeyType != ContentKeyType.CommonEncryptionCbcs && contentKeyType != ContentKeyType.EnvelopeEncryption) { return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Please pass a valid contentKeyType in the input object" })); } string contentKeyName = null; if (data.contentKeyName != null) { contentKeyName = data.contentKeyName; } MediaServicesCredentials amsCredentials = new MediaServicesCredentials(); IAsset asset = null; IContentKeyAuthorizationPolicy ckaPolicy = null; IAssetDeliveryPolicy adPolicy = null; IContentKey contentKey = null; try { // Load AMS account context log.Info($"Using AMS v2 REST API Endpoint : {amsCredentials.AmsRestApiEndpoint.ToString()}"); AzureAdTokenCredentials tokenCredentials = new AzureAdTokenCredentials(amsCredentials.AmsAadTenantDomain, new AzureAdClientSymmetricKey(amsCredentials.AmsClientId, amsCredentials.AmsClientSecret), AzureEnvironments.AzureCloudEnvironment); AzureAdTokenProvider tokenProvider = new AzureAdTokenProvider(tokenCredentials); _context = new CloudMediaContext(amsCredentials.AmsRestApiEndpoint, tokenProvider); // Let's get the asset if (assetId != null) { // Get the Asset, ContentKeyAuthorizationPolicy, AssetDeliveryPolicy asset = _context.Assets.Where(a => a.Id == assetId).FirstOrDefault(); if (asset == null) { return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Asset not found" })); } } else if (programId != null) { var program = _context.Programs.Where(p => p.Id == programId).FirstOrDefault(); if (program == null) { log.Info("Program not found"); return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Program not found" })); } asset = program.Asset; } else // with channelName and programName { // find the Channel, Program and Asset var channel = _context.Channels.Where(c => c.Name == channelName).FirstOrDefault(); if (channel == null) { log.Info("Channel not found"); return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Channel not found" })); } var program = channel.Programs.Where(p => p.Name == programName).FirstOrDefault(); if (program == null) { log.Info("Program not found"); return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Program not found" })); } asset = program.Asset; } log.Info($"Using asset Id : {asset.Id}"); ckaPolicy = _context.ContentKeyAuthorizationPolicies.Where(p => p.Id == contentKeyAuthorizationPolicyId).Single(); if (ckaPolicy == null) { return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "ContentKeyAuthorizationPolicy not found" })); } adPolicy = _context.AssetDeliveryPolicies.Where(p => p.Id == assetDeliveryPolicyId).Single(); if (adPolicy == null) { return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "AssetDeliveryPolicy not found" })); } if (contentKeyId != null) { string keyiddwitprefix = ""; if (contentKeyId.StartsWith("nb:kid:UUID:")) { keyiddwitprefix = contentKeyId; contentKeyId = contentKeyId.Substring(12); } else { keyiddwitprefix = "nb:kid:UUID:" + contentKeyId; } // let's retrieve the key if it exists already contentKey = _context.ContentKeys.Where(k => k.Id == keyiddwitprefix).FirstOrDefault(); } if (contentKey == null) // let's create it as it was not found or delivered to the function { switch (contentKeyType) { case ContentKeyType.CommonEncryption: if (contentKeyName == null) { contentKeyName = "Common Encryption ContentKey"; } contentKey = MediaServicesHelper.CreateContentKey(_context, contentKeyName, ContentKeyType.CommonEncryption, contentKeyId, contentKeySecret); break; case ContentKeyType.CommonEncryptionCbcs: if (contentKeyName == null) { contentKeyName = "Common Encryption CBCS ContentKey"; } contentKey = MediaServicesHelper.CreateContentKey(_context, contentKeyName, ContentKeyType.CommonEncryptionCbcs, contentKeyId, contentKeySecret); break; case ContentKeyType.EnvelopeEncryption: if (contentKeyName == null) { contentKeyName = "Envelope Encryption ContentKey"; } contentKey = MediaServicesHelper.CreateContentKey(_context, contentKeyName, ContentKeyType.EnvelopeEncryption, contentKeyId, contentKeySecret); break; } } asset.ContentKeys.Add(contentKey); contentKey.AuthorizationPolicyId = ckaPolicy.Id; contentKey = contentKey.UpdateAsync().Result; asset.DeliveryPolicies.Add(adPolicy); } catch (Exception ex) { string message = ex.Message + ((ex.InnerException != null) ? Environment.NewLine + MediaServicesHelper.GetErrorMessage(ex) : ""); log.Info($"ERROR: Exception {message}"); return(req.CreateResponse(HttpStatusCode.InternalServerError, new { error = message })); } return(req.CreateResponse(HttpStatusCode.OK, new { contentKeyId = contentKey.Id, assetId = asset.Id })); }
public static IContentKey CreateContentKey(CloudMediaContext context, string contentKeyName, ContentKeyType keyType, string keyId = null, string contentKeyb64 = null) { byte[] contentKey; var keyidguid = (keyId == null) ? Guid.NewGuid() : Guid.Parse(keyId); if (contentKeyb64 == null) { contentKey = GetRandomBuffer(16); } else { contentKey = Convert.FromBase64String(contentKeyb64); } IContentKey key = context.ContentKeys.Create(keyidguid, contentKey, contentKeyName, keyType); return(key); }
public static IContentKey CreateTestKey(CloudMediaContext mediaContext, ContentKeyType contentKeyType, string name = "") { byte[] key; return(CreateTestKey(mediaContext, contentKeyType, out key)); }
public static TokenResult GetTestToken(IAsset MyAsset, CloudMediaContext _context, ContentKeyType? keytype = null, SigningCredentials signingcredentials = null, string optionid = null, bool displayUI = false) { TokenResult MyResult = new TokenResult(); /// WITH UI if (displayUI) { CreateTestToken form = new CreateTestToken(MyAsset, _context, keytype, optionid) { StartDate = DateTime.Now.AddMinutes(-5), EndDate = DateTime.Now.AddMinutes(Properties.Settings.Default.DefaultTokenDuration) }; if (form.ShowDialog() == DialogResult.OK) { if (form.GetOption != null) { string tokenTemplateString = form.GetOption.Restrictions.FirstOrDefault().Requirements; if (!string.IsNullOrEmpty(tokenTemplateString)) { Guid rawkey = EncryptionUtils.GetKeyIdAsGuid(form.GetContentKeyFromSelectedOption.Id); TokenRestrictionTemplate tokenTemplate = TokenRestrictionTemplateSerializer.Deserialize(tokenTemplateString); if (tokenTemplate.OpenIdConnectDiscoveryDocument == null) { MyResult.TokenType = tokenTemplate.TokenType; MyResult.IsTokenKeySymmetric = (tokenTemplate.PrimaryVerificationKey.GetType() == typeof(SymmetricVerificationKey)); MyResult.ContentKeyType = form.GetContentKeyFromSelectedOption.ContentKeyType; if (tokenTemplate.TokenType == TokenType.SWT) //SWT { MyResult.TokenString = TokenRestrictionTemplateSerializer.GenerateTestToken(tokenTemplate, null, rawkey, form.EndDate); } else // JWT { IList<Claim> myclaims = null; myclaims = form.GetTokenRequiredClaims; if (form.PutContentKeyIdentifier) myclaims.Add(new Claim(TokenClaim.ContentKeyIdentifierClaimType, rawkey.ToString())); if (tokenTemplate.PrimaryVerificationKey.GetType() == typeof(SymmetricVerificationKey)) { InMemorySymmetricSecurityKey tokenSigningKey = new InMemorySymmetricSecurityKey((tokenTemplate.PrimaryVerificationKey as SymmetricVerificationKey).KeyValue); signingcredentials = new SigningCredentials(tokenSigningKey, SecurityAlgorithms.HmacSha256Signature, SecurityAlgorithms.Sha256Digest); } else if (tokenTemplate.PrimaryVerificationKey.GetType() == typeof(X509CertTokenVerificationKey)) { X509Certificate2 cert = form.GetX509Certificate; if (cert != null) signingcredentials = new X509SigningCredentials(cert); } JwtSecurityToken token = new JwtSecurityToken(issuer: form.GetIssuerUri, audience: form.GetAudienceUri, notBefore: form.StartDate, expires: form.EndDate, signingCredentials: signingcredentials, claims: myclaims); JwtSecurityTokenHandler handler = new JwtSecurityTokenHandler(); MyResult.TokenString = handler.WriteToken(token); } } } } } } /////////////////////////////// NO UI else if (keytype != null) { IContentKey key = MyAsset.ContentKeys.Where(k => k.ContentKeyType == keytype).FirstOrDefault(); if (key != null && key.AuthorizationPolicyId != null) { IContentKeyAuthorizationPolicy policy = _context.ContentKeyAuthorizationPolicies.Where(p => p.Id == key.AuthorizationPolicyId).FirstOrDefault(); if (policy != null) { IContentKeyAuthorizationPolicyOption option = null; if (optionid == null) // user does not want a specific option { option = policy.Options.Where(o => (ContentKeyRestrictionType)o.Restrictions.FirstOrDefault().KeyRestrictionType == ContentKeyRestrictionType.TokenRestricted).FirstOrDefault(); } else { option = policy.Options.Where(o => o.Id == optionid).FirstOrDefault(); // user wants a token for a specific option } if (option != null) // && option.Restrictions.FirstOrDefault() != null && option.Restrictions.FirstOrDefault().KeyRestrictionType == (int)ContentKeyRestrictionType.TokenRestricted) { string tokenTemplateString = option.Restrictions.FirstOrDefault().Requirements; if (!string.IsNullOrEmpty(tokenTemplateString)) { Guid rawkey = EncryptionUtils.GetKeyIdAsGuid(key.Id); TokenRestrictionTemplate tokenTemplate = TokenRestrictionTemplateSerializer.Deserialize(tokenTemplateString); if (tokenTemplate.OpenIdConnectDiscoveryDocument == null) { MyResult.TokenType = tokenTemplate.TokenType; MyResult.IsTokenKeySymmetric = (tokenTemplate.PrimaryVerificationKey.GetType() == typeof(SymmetricVerificationKey)); MyResult.ContentKeyType = (ContentKeyType)keytype; if (tokenTemplate.TokenType == TokenType.SWT) //SWT { MyResult.TokenString = TokenRestrictionTemplateSerializer.GenerateTestToken(tokenTemplate, null, rawkey, DateTime.Now.AddMinutes(Properties.Settings.Default.DefaultTokenDuration)); } else // JWT { List<Claim> myclaims = null; myclaims = new List<Claim>(); myclaims.Add(new Claim(TokenClaim.ContentKeyIdentifierClaimType, rawkey.ToString())); if (tokenTemplate.PrimaryVerificationKey.GetType() == typeof(SymmetricVerificationKey)) { InMemorySymmetricSecurityKey tokenSigningKey = new InMemorySymmetricSecurityKey((tokenTemplate.PrimaryVerificationKey as SymmetricVerificationKey).KeyValue); signingcredentials = new SigningCredentials(tokenSigningKey, SecurityAlgorithms.HmacSha256Signature, SecurityAlgorithms.Sha256Digest); } else if (tokenTemplate.PrimaryVerificationKey.GetType() == typeof(X509CertTokenVerificationKey)) { if (signingcredentials == null) { X509Certificate2 cert = DynamicEncryption.GetCertificateFromFile(true); if (cert != null) signingcredentials = new X509SigningCredentials(cert); } } JwtSecurityToken token = new JwtSecurityToken(issuer: tokenTemplate.Issuer, audience: tokenTemplate.Audience, notBefore: DateTime.Now.AddMinutes(-5), expires: DateTime.Now.AddMinutes(Properties.Settings.Default.DefaultTokenDuration), signingCredentials: signingcredentials, claims: myclaims); JwtSecurityTokenHandler handler = new JwtSecurityTokenHandler(); MyResult.TokenString = handler.WriteToken(token); } } } } } } } return MyResult; }
public static IContentKey CreateTestKeyWithSpecified(string keyIdentifier, CloudMediaContext mediaContext, ContentKeyType contentKeyType, string name = "") { var keyId = EncryptionUtils.GetKeyIdAsGuid(keyIdentifier); SymmetricAlgorithm symmetricAlgorithm = new AesCryptoServiceProvider(); if ((contentKeyType == ContentKeyType.CommonEncryption) || (contentKeyType == ContentKeyType.EnvelopeEncryption)) { symmetricAlgorithm.KeySize = EncryptionUtils.KeySizeInBitsForAes128; } else { symmetricAlgorithm.KeySize = EncryptionUtils.KeySizeInBitsForAes256; } IContentKey contentKey = mediaContext.ContentKeys.Create(keyId, symmetricAlgorithm.Key, name, contentKeyType); return(contentKey); }
/// <summary> /// Asynchronously creates a content key with the specifies key identifier and value. /// </summary> /// <param name="keyId">The key identifier.</param> /// <param name="contentKey">The value of the content key.</param> /// <param name="name">A friendly name for the content key.</param> /// <param name="contentKeyType">Type of content key to create.</param> /// <returns> /// A function delegate that returns the future result to be available through the Task<IContentKey>. /// </returns> public override Task<IContentKey> CreateAsync(Guid keyId, byte[] contentKey, string name, ContentKeyType contentKeyType) { if ((contentKeyType != ContentKeyType.CommonEncryption) && (contentKeyType != ContentKeyType.EnvelopeEncryption)) { throw new ArgumentException(StringTable.ErrorUnsupportedContentKeyType, "contentKey"); } if (keyId == Guid.Empty) { throw new ArgumentException(StringTable.ErrorCreateKey_EmptyGuidNotAllowed, "keyId"); } if (contentKey == null) { throw new ArgumentNullException("contentKey"); } if (contentKey.Length != EncryptionUtils.KeySizeInBytesForAes128) { throw new ArgumentException(StringTable.ErrorCommonEncryptionKeySize, "contentKey"); } IMediaDataServiceContext dataContext = this.MediaContext.MediaServicesClassFactory.CreateDataServiceContext(); X509Certificate2 certToUse = ContentKeyBaseCollection.GetCertificateToEncryptContentKey(MediaContext, ContentKeyType.CommonEncryption); ContentKeyData contentKeyData = null; if (contentKeyType == ContentKeyType.CommonEncryption) { contentKeyData = InitializeCommonContentKey(keyId, contentKey, name, certToUse); } else if (contentKeyType == ContentKeyType.EnvelopeEncryption) { contentKeyData = InitializeEnvelopeContentKey(keyId, contentKey, name, certToUse); } dataContext.AddObject(ContentKeySet, contentKeyData); MediaRetryPolicy retryPolicy = this.MediaContext.MediaServicesClassFactory.GetSaveChangesRetryPolicy(dataContext as IRetryPolicyAdapter); return retryPolicy.ExecuteAsync<IMediaDataServiceResponse>(() => dataContext.SaveChangesAsync(contentKeyData)) .ContinueWith<IContentKey>( t => { t.ThrowIfFaulted(); return (ContentKeyData)t.Result.AsyncState; }, TaskContinuationOptions.ExecuteSynchronously); }