/// <summary>
        /// Creates an envelope encryption content key.
        /// </summary>
        /// <param name="keyId">The key id.</param>
        /// <param name="contentKey">The content key data.</param>
        /// <param name="name">The name.</param>
        /// <param name="cert">The cert.</param>
        /// <returns>The content key.</returns>
        internal static ContentKeyData InitializeEnvelopeContentKey(Guid keyId, byte[] contentKey, string name, X509Certificate2 cert)
        {
            if (cert == null)
            {
                throw new ArgumentNullException("cert");
            }

            if (contentKey == null)
            {
                throw new ArgumentNullException("contentKey");
            }

            if (contentKey.Length != EncryptionUtils.KeySizeInBytesForAes128)
            {
                throw new ArgumentOutOfRangeException("contentKey", "Envelope Encryption content keys are 128-bits (16 bytes) in length.");
            }

            byte[] encryptedContentKey = EncryptionUtils.EncryptSymmetricKeyData(cert, contentKey);

            ContentKeyData contentKeyData = new ContentKeyData
            {
                Id = EncryptionUtils.GetKeyIdentifierAsString(keyId),
                EncryptedContentKey = Convert.ToBase64String(encryptedContentKey),
                ContentKeyType      = (int)ContentKeyType.EnvelopeEncryption,
                ProtectionKeyId     = cert.Thumbprint,
                ProtectionKeyType   = (int)ProtectionKeyType.X509CertificateThumbprint,
                Name     = name,
                Checksum = EncryptionUtils.CalculateChecksum(contentKey, keyId)
            };

            return(contentKeyData);
        }
        /// <summary>
        /// Create a notification endpoint object in asynchronous mode.
        /// </summary>
        /// <param name="name">Name of notification endpoint</param>
        /// <param name="endPointType">Notification endpoint type</param>
        /// <param name="endPointAddress">Notification endpoint address</param>
        /// <param name="credential"></param>
        /// <returns>Task of creating notification endpoint.</returns>
        public Task <INotificationEndPoint> CreateAsync(string name, NotificationEndPointType endPointType,
                                                        string endPointAddress, byte[] credential)
        {
            if (credential == null || credential.Length == 0)
            {
                throw new ArgumentNullException("credential");
            }

            if (endPointType != NotificationEndPointType.WebHook)
            {
                throw new NotSupportedException(string.Format(CultureInfo.InvariantCulture, StringTable.SupportWebHookWithCredentialOnly, "endPointType"));
            }

            IMediaDataServiceContext dataContext =
                this.MediaContext.MediaServicesClassFactory.CreateDataServiceContext();

            string protectionKeyId = ContentKeyBaseCollection.GetProtectionKeyIdForContentKey(MediaContext,
                                                                                              ContentKeyType.ConfigurationEncryption);
            X509Certificate2 certToUse = ContentKeyBaseCollection.GetCertificateForProtectionKeyId(MediaContext, protectionKeyId);

            byte[] encryptedContentKey = EncryptionUtils.EncryptSymmetricKeyData(certToUse, credential);

            NotificationEndPoint notificationEndPoint = new NotificationEndPoint
            {
                Name                        = name,
                EndPointType                = (int)endPointType,
                EndPointAddress             = endPointAddress,
                CredentialType              = (int)NotificationEndPointCredentialType.SigningKey,
                EncryptedEndPointCredential = Convert.ToBase64String(encryptedContentKey),
                ProtectionKeyType           = (int)ProtectionKeyType.X509CertificateThumbprint,
                ProtectionKeyId             = protectionKeyId
            };

            notificationEndPoint.SetMediaContext(MediaContext);
            dataContext.AddObject(NotificationEndPoints, notificationEndPoint);

            MediaRetryPolicy retryPolicy =
                this.MediaContext.MediaServicesClassFactory.GetSaveChangesRetryPolicy(dataContext as IRetryPolicyAdapter);

            return(retryPolicy.ExecuteAsync <IMediaDataServiceResponse>(
                       () => dataContext.SaveChangesAsync(notificationEndPoint))
                   .ContinueWith <INotificationEndPoint>(
                       t =>
            {
                t.ThrowIfFaulted();

                return (NotificationEndPoint)t.Result.AsyncState;
            },
                       TaskContinuationOptions.ExecuteSynchronously));
        }