예제 #1
0
        protected override Recipient DeserializeEntity(XmlElement element, XmlNamespaceManager namespaces)
        {
            // First, just extract the X.509 certificate. It must exist or we will consider the delivery data invalid.
            var certificateNode = element.SelectSingleNode("cpix:DeliveryKey/ds:X509Data/ds:X509Certificate", namespaces);

            if (certificateNode == null)
            {
                throw new InvalidCpixDataException("Found a delivery data element with no X.509 certificate embedded. This is not supported.");
            }

            var certificate = new X509Certificate2(Convert.FromBase64String(certificateNode.InnerText));

            // If we do not already have the document secrets available, try to load them.
            if (Document.DocumentKey == null)
            {
                var matchingRecipientCertificate = Document.RecipientCertificates.FirstOrDefault(c => c.Thumbprint == certificate.Thumbprint);

                if (matchingRecipientCertificate != null)
                {
                    // Yes, we have a delivery key! Use this delivery key to load the delivery data.
                    var deliveryData = XmlHelpers.Deserialize <DeliveryDataElement>(element);
                    deliveryData.LoadTimeValidate();

                    var rsa         = matchingRecipientCertificate.GetRSAPrivateKey();
                    var macKey      = rsa.Decrypt(deliveryData.MacMethod.Key.CipherData.CipherValue, RSAEncryptionPadding.OaepSHA1);
                    var documentKey = rsa.Decrypt(deliveryData.DocumentKey.Data.Secret.EncryptedValue.CipherData.CipherValue, RSAEncryptionPadding.OaepSHA1);

                    Document.ImportKeys(documentKey, macKey);
                }
            }

            return(new Recipient(certificate));
        }
예제 #2
0
        protected override ContentKey DeserializeEntity(XmlElement element, XmlNamespaceManager namespaces)
        {
            var contentKey = XmlHelpers.Deserialize <ContentKeyElement>(element);

            contentKey.LoadTimeValidate();

            if (contentKey.HasPlainValue && Document.Recipients.Any())
            {
                throw new InvalidCpixDataException("A content key was delivered in the clear but delivery data was defined. Malformed CPIX!?");
            }

            byte[] value = null;

            if (contentKey.HasEncryptedValue && Document.ContentKeysAreReadable)
            {
                var mac = new HMACSHA512(Document.MacKey);

                var calculatedMac = mac.ComputeHash(contentKey.Data.Secret.EncryptedValue.CipherData.CipherValue);

                if (!calculatedMac.SequenceEqual(contentKey.Data.Secret.ValueMAC))
                {
                    throw new SecurityException("MAC validation failed - a content key value has been tampered with!");
                }

                var iv           = contentKey.Data.Secret.EncryptedValue.CipherData.CipherValue.Take(128 / 8).ToArray();
                var encryptedKey = contentKey.Data.Secret.EncryptedValue.CipherData.CipherValue.Skip(128 / 8).ToArray();

                var aes = new AesManaged
                {
                    BlockSize = 128,
                    KeySize   = 256,
                    Key       = Document.DocumentKey,
                    Mode      = CipherMode.CBC,
                    Padding   = PaddingMode.PKCS7,
                    IV        = iv
                };

                using (var decryptor = aes.CreateDecryptor())
                {
                    value = decryptor.TransformFinalBlock(encryptedKey, 0, encryptedKey.Length);
                }
            }
            else if (contentKey.HasPlainValue)
            {
                value = contentKey.Data.Secret.PlainValue;
            }
            else
            {
                // Value is encrypted and we cannot read it. Nothing to do here.
            }

            return(new ContentKey
            {
                Id = contentKey.KeyId,
                ExplicitIv = contentKey.ExplicitIv,
                Value = value,
                IsLoadedEncryptedKey = contentKey.HasEncryptedValue
            });
        }
예제 #3
0
        protected override DrmSystem DeserializeEntity(XmlElement element, XmlNamespaceManager namespaces)
        {
            var drmSystemElement = XmlHelpers.Deserialize <DrmSystemElement>(element);

            drmSystemElement.LoadTimeValidate();

            var drmSystem = new DrmSystem
            {
                SystemId = drmSystemElement.SystemId,
                KeyId    = drmSystemElement.KeyId,
                Pssh     = drmSystemElement.Pssh,
                SmoothStreamingProtectionHeaderData = drmSystemElement.SmoothStreamingProtectionHeaderData
            };

            if (drmSystemElement.ContentProtectionData != null)
            {
                drmSystem.ContentProtectionData = Encoding.UTF8.GetString(Convert.FromBase64String(drmSystemElement.ContentProtectionData));
            }

            if (drmSystemElement.HdsSignalingData != null)
            {
                drmSystem.HdsSignalingData = Encoding.UTF8.GetString(Convert.FromBase64String(drmSystemElement.HdsSignalingData));
            }

            if (drmSystemElement.HlsSignalingData.Count > 0)
            {
                drmSystem.HlsSignalingData = new HlsSignalingData();

                var mediaPlaylistDataAsBase64 = drmSystemElement.HlsSignalingData
                                                .SingleOrDefault(d => d.Playlist == null || string.Equals(d.Playlist, HlsPlaylistType.Media, StringComparison.InvariantCulture))?.Value;

                var masterPlaylistDataAsBase64 = drmSystemElement.HlsSignalingData
                                                 .SingleOrDefault(d => string.Equals(d.Playlist, HlsPlaylistType.Master, StringComparison.InvariantCulture))?.Value;

                if (mediaPlaylistDataAsBase64 != null)
                {
                    drmSystem.HlsSignalingData.MediaPlaylistData = Encoding.UTF8.GetString(Convert.FromBase64String(mediaPlaylistDataAsBase64));
                }

                if (masterPlaylistDataAsBase64 != null)
                {
                    drmSystem.HlsSignalingData.MasterPlaylistData = Encoding.UTF8.GetString(Convert.FromBase64String(masterPlaylistDataAsBase64));
                }
            }

            return(drmSystem);
        }
예제 #4
0
        protected override UsageRule DeserializeEntity(XmlElement element, XmlNamespaceManager namespaces)
        {
            var raw = XmlHelpers.Deserialize <UsageRuleElement>(element);

            raw.LoadTimeValidate();

            var rule = new UsageRule
            {
                KeyId = raw.KeyId
            };

            // This disables all usage rule processing, basically, and treats this particular rule as read-only.
            // The unknown filters will be preserved unless the rule is removed, just no rules from this document can be used.
            if (raw.UnknownFilters?.Any() == true)
            {
                rule.ContainsUnsupportedFilters = true;
            }

            if (raw.VideoFilters?.Length > 0)
            {
                rule.VideoFilters = raw.VideoFilters
                                    .Select(f => new VideoFilter
                {
                    MinPixels          = f.MinPixels,
                    MaxPixels          = f.MaxPixels,
                    MinFramesPerSecond = f.MinFps,
                    MaxFramesPerSecond = f.MaxFps,
                    WideColorGamut     = f.Wcg,
                    HighDynamicRange   = f.Hdr
                })
                                    .ToList();
            }

            if (raw.AudioFilters?.Length > 0)
            {
                rule.AudioFilters = raw.AudioFilters
                                    .Select(f => new AudioFilter
                {
                    MinChannels = f.MinChannels,
                    MaxChannels = f.MaxChannels
                })
                                    .ToList();
            }

            if (raw.BitrateFilters?.Length > 0)
            {
                rule.BitrateFilters = raw.BitrateFilters
                                      .Select(f => new BitrateFilter
                {
                    MinBitrate = f.MinBitrate,
                    MaxBitrate = f.MaxBitrate
                })
                                      .ToList();
            }

            if (raw.LabelFilters?.Length > 0)
            {
                rule.LabelFilters = raw.LabelFilters
                                    .Select(f => new LabelFilter
                {
                    Label = f.Label
                })
                                    .ToList();
            }

            return(rule);
        }