示例#1
0
        public void Generate(Stream outputStream)
        {
            var document = new CpixDocument();

            document.ContentKeys.Add(new ContentKey
            {
                Id    = new Guid("bbe06060-1c26-4ed5-8ccd-ee03ddb2ffd9"),
                Value = Convert.FromBase64String("aTqer0SFxijnIoQLXGHYJg==")
            });

            document.Recipients.Add(new Recipient(TestHelpers.Certificate1WithPublicKey));
            document.SignedBy = TestHelpers.Certificate2WithPrivateKey;

            var buffer = new MemoryStream();

            document.Save(buffer);

            var xml = new XmlDocument();

            buffer.Position = 0;
            xml.Load(buffer);

            XmlHelpers.DeclareNamespace(xml.DocumentElement, "xxx", "http://example.com/this/makes/the/document/signature/invalid");

            using (var writer = XmlWriter.Create(outputStream, new XmlWriterSettings
            {
                Encoding = Encoding.UTF8,
                CloseOutput = false
            }))
            {
                xml.Save(writer);
            }
        }
示例#2
0
        public void Generate(Stream outputStream)
        {
            var document = new CpixDocument();

            document.ContentKeys.Add(new ContentKey
            {
                Id    = new Guid("bc365b99-0667-446f-b417-ff0398c9a4c4"),
                Value = Convert.FromBase64String("gMMdXMudvuGpYW5k3lzf/g==")
            });
            document.ContentKeys.Add(new ContentKey
            {
                Id    = new Guid("1e25f2a7-76a9-4570-bc1a-d8181800d529"),
                Value = Convert.FromBase64String("WUxnvQjGw28bA3cgW/1jfg==")
            });
            document.ContentKeys.Add(new ContentKey
            {
                Id    = new Guid("2e4e6c21-c0d7-4a1c-80af-bff3d7cc5270"),
                Value = Convert.FromBase64String("cCudMIPMQkak1l+oCVXT2A==")
            });
            document.ContentKeys.Add(new ContentKey
            {
                Id    = new Guid("8ad35bd4-53ab-437b-8f42-6e1ea8e2f0d8"),
                Value = Convert.FromBase64String("zqvOfAja51IUSRV385bvoA==")
            });

            document.Recipients.Add(new Recipient(TestHelpers.Certificate1WithPublicKey));
            document.Recipients.Add(new Recipient(TestHelpers.Certificate2WithPublicKey));
            document.Recipients.Add(new Recipient(TestHelpers.Certificate3WithPublicKey));
            document.Recipients.Add(new Recipient(TestHelpers.Certificate4WithPublicKey));

            document.Save(outputStream);
        }
示例#3
0
        public void Generate(Stream outputStream)
        {
            var document = new CpixDocument();

            document.ContentKeys.Add(new ContentKey
            {
                Id    = new Guid("40d02dd1-61a3-4787-a155-572325d47b80"),
                Value = Convert.FromBase64String("gPxt0PMwrHM4TdjwdQmhhQ==")
            });
            document.ContentKeys.Add(new ContentKey
            {
                Id    = new Guid("0a30ea4f-539d-4b02-94b2-2b3fba2576d3"),
                Value = Convert.FromBase64String("x/gaoS/fDi8BqGNIhkixwQ==")
            });
            document.ContentKeys.Add(new ContentKey
            {
                Id    = new Guid("9f7908fa-5d5c-4097-ba53-50edc2235fbc"),
                Value = Convert.FromBase64String("3iv9lYwafpe0uEmxDc6PSw==")
            });
            document.ContentKeys.Add(new ContentKey
            {
                Id    = new Guid("fac2cbf5-889c-412b-a385-04a29d409bdc"),
                Value = Convert.FromBase64String("1OZVZZoYFSU2X/7qT3sHwg==")
            });

            document.Save(outputStream);
        }
示例#4
0
        private static void WritingCpixExample()
        {
            var document = new CpixDocument();

            // Let's create a CPIX document with two content keys.

            document.ContentKeys.Add(new ContentKey
            {
                Id    = Guid.NewGuid(),
                Value = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6 }
            });
            document.ContentKeys.Add(new ContentKey
            {
                Id    = Guid.NewGuid(),
                Value = new byte[] { 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5 }
            });

            using (var myCertificateAndPrivateKey = new X509Certificate2("Cert1.pfx", "Cert1"))
                using (var recipientCertificate = new X509Certificate2("Cert2.cer"))
                {
                    // Optional: we sign the list added elements to and also the document as a whole.
                    document.ContentKeys.AddSignature(myCertificateAndPrivateKey);
                    document.SignedBy = myCertificateAndPrivateKey;

                    // Optional: the presence of recipients will automatically mark the content keys to be encrypted on save.
                    document.Recipients.Add(new Recipient(recipientCertificate));

                    document.Save("cpix.xml");
                }
        }
示例#5
0
        public void LoadDocument_WithXmlCommentsAddedAfterSigning_SuccessfullyValidatesSignature()
        {
            // The canonicalization we use excludes comments, so comments should have no effect on signature validity.

            var document = new CpixDocument();

            FillDocumentWithData(document);

            document.Recipients.AddSignature(TestHelpers.Certificate4WithPrivateKey);
            document.ContentKeys.AddSignature(TestHelpers.Certificate4WithPrivateKey);
            document.UsageRules.AddSignature(TestHelpers.Certificate4WithPrivateKey);
            document.SignedBy = TestHelpers.Certificate3WithPrivateKey;

            var buffer = new MemoryStream();

            document.Save(buffer);

            // Let's now sprinkle comments all over the place.
            var xmlDocument = new XmlDocument();

            buffer.Position = 0;
            xmlDocument.Load(buffer);

            var namespaces = XmlHelpers.CreateCpixNamespaceManager(xmlDocument);

            AddCommentAsChild(xmlDocument.DocumentElement);

            AddCommentAsChild((XmlElement)xmlDocument.SelectSingleNode("/cpix:CPIX/cpix:DeliveryDataList", namespaces));
            AddCommentAsChild((XmlElement)xmlDocument.SelectSingleNode("/cpix:CPIX/cpix:ContentKeyList", namespaces));
            AddCommentAsChild((XmlElement)xmlDocument.SelectSingleNode("/cpix:CPIX/cpix:ContentKeyUsageRuleList", namespaces));

            AddCommentAsChild((XmlElement)xmlDocument.SelectSingleNode("/cpix:CPIX/cpix:DeliveryDataList/cpix:DeliveryData", namespaces));
            AddCommentAsChild((XmlElement)xmlDocument.SelectSingleNode("/cpix:CPIX/cpix:ContentKeyList/cpix:ContentKey", namespaces));
            AddCommentAsChild((XmlElement)xmlDocument.SelectSingleNode("/cpix:CPIX/cpix:ContentKeyUsageRuleList/cpix:ContentKeyUsageRule", namespaces));

            buffer.SetLength(0);

            using (var writer = XmlWriter.Create(buffer, new XmlWriterSettings
            {
                Encoding = Encoding.UTF8,
                CloseOutput = false,
            }))
            {
                xmlDocument.Save(writer);
            }

            buffer.Position = 0;
            document        = CpixDocument.Load(buffer);

            Assert.NotNull(document.SignedBy);
            Assert.Single(document.Recipients.SignedBy);
            Assert.Single(document.ContentKeys.SignedBy);
            Assert.Single(document.UsageRules.SignedBy);

            // And, of course, the data should still be there.
            Assert.Equal(2, document.ContentKeys.Count);
            Assert.Equal(2, document.Recipients.Count);
            Assert.Equal(2, document.UsageRules.Count);
        }
示例#6
0
        public static CpixDocument Reload(CpixDocument document, IReadOnlyCollection <X509Certificate2> decryptionCertificates = null)
        {
            var buffer = new MemoryStream();

            document.Save(buffer);
            buffer.Position = 0;

            return(CpixDocument.Load(buffer, decryptionCertificates));
        }
示例#7
0
        public void Generate(Stream outputStream)
        {
            var document = new CpixDocument();

            document.Recipients.Add(new Recipient(TestHelpers.Certificate3WithPublicKey));
            document.Recipients.Add(new Recipient(TestHelpers.Certificate4WithPublicKey));

            document.Save(outputStream);
        }
示例#8
0
        public void LoadDocument_WithUtf16EncodedInput_Succeeds()
        {
            // We ensure that some non-ASCII text survives the encoding/decoding/signing process intact.
            const string canary = "滆 柦柋牬 趉軨鄇 鶊鵱, 緳廞徲 鋑鋡髬 溮煡煟 綡蒚";

            var document = new CpixDocument();

            FillDocumentWithData(document);

            document.UsageRules.First().LabelFilters = new[]
            {
                new LabelFilter
                {
                    Label = canary
                }
            };

            document.Recipients.AddSignature(TestHelpers.Certificate4WithPrivateKey);
            document.ContentKeys.AddSignature(TestHelpers.Certificate4WithPrivateKey);
            document.UsageRules.AddSignature(TestHelpers.Certificate4WithPrivateKey);
            document.SignedBy = TestHelpers.Certificate3WithPrivateKey;

            var buffer = new MemoryStream();

            document.Save(buffer);

            // Now we have a basic UTF-8 document in the buffer. Convert to UTF-16!
            // Using XmlDocument here to do it in a "smart" way with all the XML processing.
            var xmlDocument = new XmlDocument();

            buffer.Position = 0;
            xmlDocument.Load(buffer);

            buffer.SetLength(0);

            using (var writer = XmlWriter.Create(buffer, new XmlWriterSettings
            {
                Encoding = Encoding.Unicode,
                CloseOutput = false,
            }))
            {
                xmlDocument.Save(writer);
            }

            buffer.Position = 0;

            // Okay, does it load? It should!
            document = CpixDocument.Load(buffer);

            Assert.Equal(2, document.ContentKeys.Count);
            Assert.Equal(2, document.Recipients.Count);
            Assert.Equal(2, document.UsageRules.Count);

            Assert.Equal(canary, document.UsageRules.First().LabelFilters.Single().Label);
        }
示例#9
0
        public void Save_WithDrmSystemThatReferencesNonExistentContentKey_Fails()
        {
            var document = new CpixDocument();

            document.ContentKeys.Add(TestHelpers.GenerateContentKey());

            document.DrmSystems.Add(new DrmSystem
            {
                SystemId = Guid.NewGuid(),
                KeyId    = Guid.NewGuid()
            });

            Assert.Throws <InvalidCpixDataException>(() => document.Save(new MemoryStream()));
        }
示例#10
0
        static void GenerateCpix(string name, IReadOnlyDictionary <Guid, byte[]> keys)
        {
            var document = new CpixDocument();

            foreach (var pair in keys)
            {
                document.ContentKeys.Add(new ContentKey
                {
                    Id    = pair.Key,
                    Value = pair.Value
                });
            }

            document.Save(name);
        }
示例#11
0
        public void Save_WithSneakilyCorruptedContentKey_Fails()
        {
            var contentKey = TestHelpers.GenerateContentKey();

            var document = new CpixDocument();

            // It will be validated here.
            document.ContentKeys.Add(contentKey);

            // Corrupt it after validation!
            contentKey.Value = null;

            // The corruption should still be caught.
            Assert.Throws <InvalidCpixDataException>(() => document.Save(new MemoryStream()));
        }
示例#12
0
        private static MemoryStream GenerateNontrivialCpixStream()
        {
            var document = new CpixDocument();

            FillDocumentWithData(document);

            // It will be saved without whitespace or formatting. This is fine.
            var buffer = new MemoryStream();

            document.Save(buffer);

            buffer.Position = 0;

            return(buffer);
        }
示例#13
0
        public void Save_WithSneakilyCorruptedUsageRule_Fails()
        {
            var document = new CpixDocument();

            document.ContentKeys.Add(TestHelpers.GenerateContentKey());

            // It will be validated here.
            var rule = TestHelpers.AddUsageRule(document);

            // Corrupt it after validation!
            rule.KeyId = Guid.NewGuid();

            // The corruption should still be caught.
            Assert.ThrowsAny <Exception>(() => document.Save(new MemoryStream()));
        }
示例#14
0
        public void Generate(Stream outputStream)
        {
            var document = new CpixDocument();

            foreach (var pair in _contentKeys)
            {
                document.ContentKeys.Add(new ContentKey
                {
                    Id    = pair.Key,
                    Value = Convert.FromBase64String(pair.Value)
                });
            }

            document.Recipients.Add(new Recipient(TestHelpers.Certificate1WithPublicKey));

            document.Save(outputStream);
        }
示例#15
0
        public void Save_OneClearKey_DoesNotHorriblyFail()
        {
            var keyData = TestHelpers.GenerateKeyData();

            var document = new CpixDocument();

            document.ContentKeys.Add(new ContentKey
            {
                Id    = keyData.Item1,
                Value = keyData.Item2
            });

            using (var buffer = new MemoryStream())
            {
                document.Save(buffer);

                // Something got saved and there was no exception. Good enough!
                Assert.NotEqual(0, buffer.Length);
            }
        }
示例#16
0
        public void Generate(Stream outputStream)
        {
            var document = new CpixDocument();

            document.ContentKeys.Add(new ContentKey
            {
                Id    = new Guid("c003b21a-fe68-4162-a809-b0add9fe49c1"),
                Value = Convert.FromBase64String("fV2AfUA1WnvFaySrl6I7vg==")
            });
            document.ContentKeys.Add(new ContentKey
            {
                Id    = new Guid("a3813bc3-986a-462b-84d1-c5d17d3ac0f5"),
                Value = Convert.FromBase64String("fs1XSl6sqULnEjX0g6UyBg==")
            });

            document.ContentKeys.AddSignature(TestHelpers.Certificate4WithPrivateKey);

            var buffer = new MemoryStream();

            document.Save(buffer);

            var xml = new XmlDocument();

            buffer.Position = 0;
            xml.Load(buffer);

            var namespaces = XmlHelpers.CreateCpixNamespaceManager(xml);

            var firstContentKey = (XmlElement)xml.SelectSingleNode("/cpix:CPIX/cpix:ContentKeyList/cpix:ContentKey", namespaces);

            firstContentKey.ParentNode.RemoveChild(firstContentKey);

            using (var writer = XmlWriter.Create(outputStream, new XmlWriterSettings
            {
                Encoding = Encoding.UTF8,
                CloseOutput = false
            }))
            {
                xml.Save(writer);
            }
        }
示例#17
0
        public void Save_WithValidDrmSystem_Succeeds()
        {
            var document = new CpixDocument();

            document.ContentKeys.Add(TestHelpers.GenerateContentKey());

            document.DrmSystems.Add(new DrmSystem
            {
                SystemId = Guid.NewGuid(),
                KeyId    = document.ContentKeys.First().Id,
                ContentProtectionData = "<pssh>data</pssh>",
                HdsSignalingData      = "<drmAdditionalHeader>data</drmAdditionalHeader>",
                Pssh             = Convert.ToBase64String(new byte[] { 0x11, 0x22, 0x33 }),
                HlsSignalingData = new HlsSignalingData
                {
                    MasterPlaylistData = "hlsmasterdata1",
                    MediaPlaylistData  = "hlsmediadata2"
                },
                SmoothStreamingProtectionHeaderData = "smoothstreamingdata"
            });

            Assert.Null(Record.Exception(() => document.Save(new MemoryStream())));
        }
示例#18
0
        public void Generate(Stream outputStream)
        {
            var document = new CpixDocument();

            document.ContentKeys.Add(new ContentKey
            {
                Id    = new Guid("5ad2b739-4f46-48df-9a44-aab8c35abf71"),
                Value = Convert.FromBase64String("QsCLorCoPAmTd2IHz2pogg==")
            });

            document.Recipients.Add(new Recipient(TestHelpers.Certificate1WithPublicKey));

            var buffer = new MemoryStream();

            document.Save(buffer);

            var xml = new XmlDocument();

            buffer.Position = 0;
            xml.Load(buffer);

            var namespaces = XmlHelpers.CreateCpixNamespaceManager(xml);
            var mac        = xml.SelectSingleNode("/cpix:CPIX/cpix:ContentKeyList/cpix:ContentKey/cpix:Data/pskc:Secret/pskc:ValueMAC", namespaces);

            // No way this will be the right MAC!
            mac.InnerText = "YtijEC7siGSqLg/9WrZ5Z7/TCVE9BydVO9UOv28yZr5+QCdstz8uAQvC9mFFx8hag0LKw461/OKIe5Fr7Mvo2A==";

            using (var writer = XmlWriter.Create(outputStream, new XmlWriterSettings
            {
                Encoding = Encoding.UTF8,
                CloseOutput = false
            }))
            {
                xml.Save(writer);
            }
        }
示例#19
0
        public void Generate(Stream outputStream)
        {
            var document = new CpixDocument();

            const string complexLabel = "滆 柦柋牬 趉軨鄇 鶊鵱, 緳廞徲 鋑鋡髬 溮煡煟 綡蒚";

            document.SignedBy = TestHelpers.Certificate4WithPrivateKey;
            document.Recipients.AddSignature(TestHelpers.Certificate3WithPrivateKey);
            document.Recipients.AddSignature(TestHelpers.Certificate4WithPrivateKey);
            document.ContentKeys.AddSignature(TestHelpers.Certificate3WithPrivateKey);
            document.ContentKeys.AddSignature(TestHelpers.Certificate4WithPrivateKey);
            document.DrmSystems.AddSignature(TestHelpers.Certificate3WithPrivateKey);
            document.DrmSystems.AddSignature(TestHelpers.Certificate4WithPrivateKey);
            document.UsageRules.AddSignature(TestHelpers.Certificate3WithPrivateKey);
            document.UsageRules.AddSignature(TestHelpers.Certificate4WithPrivateKey);

            document.ContentKeys.Add(new ContentKey
            {
                Id         = new Guid("b4c3188b-eddd-453d-9bc2-1cbca7566239"),
                Value      = Convert.FromBase64String("b1pkxdNYqPxljV68gohWcw=="),
                ExplicitIv = Convert.FromBase64String("eMCi02KFz9fdUGd/6B+lgw==")
            });
            document.ContentKeys.Add(new ContentKey
            {
                Id         = new Guid("c6294999-5f48-445f-bcce-f7e5f736d7c6"),
                Value      = Convert.FromBase64String("moOVrJvuhUUQ4LpPusAd5g=="),
                ExplicitIv = Convert.FromBase64String("XiLNTv8ZHbMI+F2g2TkL6w==")
            });
            document.ContentKeys.Add(new ContentKey
            {
                Id         = new Guid("b181a4df-2c38-41a4-993f-90b2f21343f6"),
                Value      = Convert.FromBase64String("67gabJtKDWd2crHr+JQT1A=="),
                ExplicitIv = Convert.FromBase64String("E5XdJoK4ja+Rf/dcVvhRTA==")
            });
            document.ContentKeys.Add(new ContentKey
            {
                Id         = new Guid("a466cdfd-e556-4b1d-8098-c1a4aa78997a"),
                Value      = Convert.FromBase64String("rRuRUWAibaUtai0qQnb71g=="),
                ExplicitIv = Convert.FromBase64String("yIZGwf6xwXgRHyXBNV0jRA==")
            });

            DrmSignalingHelpers.AddDefaultSignalingForAllKeys(document);

            document.Recipients.Add(new Recipient(TestHelpers.Certificate1WithPublicKey));
            document.Recipients.Add(new Recipient(TestHelpers.Certificate2WithPublicKey));

            document.UsageRules.Add(new UsageRule
            {
                KeyId = document.ContentKeys.First().Id,

                AudioFilters = new[]
                {
                    new AudioFilter
                    {
                        MinChannels = 1,
                        MaxChannels = 2
                    },
                    new AudioFilter
                    {
                        MinChannels = 8,
                        MaxChannels = 10
                    }
                },
                BitrateFilters = new[]
                {
                    new BitrateFilter
                    {
                        MinBitrate = 1000,
                        MaxBitrate = 5 * 1000 * 1000
                    },
                    new BitrateFilter
                    {
                        MinBitrate = 10 * 1000 * 1000,
                        MaxBitrate = 32 * 1000 * 1000
                    }
                },
                LabelFilters = new[]
                {
                    new LabelFilter("EncryptedStream"),
                    new LabelFilter("CencStream"),
                    new LabelFilter(complexLabel),
                }
            });

            document.UsageRules.Add(new UsageRule
            {
                KeyId = document.ContentKeys.Last().Id,

                BitrateFilters = new[]
                {
                    new BitrateFilter
                    {
                        MinBitrate = 1000,
                        MaxBitrate = 5 * 1000 * 1000
                    },
                    new BitrateFilter
                    {
                        MinBitrate = 10 * 1000 * 1000,
                        MaxBitrate = 32 * 1000 * 1000
                    }
                },
                LabelFilters = new[]
                {
                    new LabelFilter("EncryptedStream"),
                    new LabelFilter("CencStream"),
                    new LabelFilter(complexLabel),
                },
                VideoFilters = new[]
                {
                    new VideoFilter
                    {
                        MinPixels          = 1000,
                        MaxPixels          = 1920 * 1080,
                        MinFramesPerSecond = 10,
                        MaxFramesPerSecond = 30,
                        WideColorGamut     = false,
                        HighDynamicRange   = true,
                    },
                    new VideoFilter
                    {
                        MinPixels          = 1000,
                        MaxPixels          = 4096 * 4096,
                        MinFramesPerSecond = 30,
                        MaxFramesPerSecond = 200,
                        WideColorGamut     = false,
                        HighDynamicRange   = false,
                    }
                }
            });

            document.Save(outputStream);
        }
示例#20
0
        public void Generate(Stream outputStream)
        {
            var document = new CpixDocument();

            document.ContentKeys.Add(new ContentKey
            {
                Id    = new Guid("ba6c62d6-4a49-4aa4-8869-ce4d2727a2b5"),
                Value = Convert.FromBase64String("sLVGDIuvogAUW+Ay0mE9ZA==")
            });
            document.ContentKeys.Add(new ContentKey
            {
                Id    = new Guid("37e3de05-9a3b-4c69-8970-63c17a95e0b7"),
                Value = Convert.FromBase64String("UvL2JdZiEX2exVMwn796Tg==")
            });
            document.ContentKeys.Add(new ContentKey
            {
                Id    = new Guid("53abdba2-f210-43cb-bc90-f18f9a890a02"),
                Value = Convert.FromBase64String("lOgzNKBnPZlGSns+WqO8zw==")
            });
            document.ContentKeys.Add(new ContentKey
            {
                Id    = new Guid("7ae8e96f-309e-42c3-a510-24023d923373"),
                Value = Convert.FromBase64String("K9uQ8+GgwrNx4keBHnI4Xw==")
            });

            document.UsageRules.Add(new UsageRule
            {
                KeyId = document.ContentKeys.ElementAt(0).Id,

                LabelFilters = new[]
                {
                    new LabelFilter("AllAudioStreams"),
                    new LabelFilter("Audio"),
                    new LabelFilter("PositionalAudio"),
                    new LabelFilter("Stereo"),
                }
            });

            // Intentionally add two rules for first key ID, to emphasize that there is no limit of one.
            document.UsageRules.Add(new UsageRule
            {
                KeyId = document.ContentKeys.ElementAt(0).Id,

                LabelFilters = new[]
                {
                    new LabelFilter("Commentary"),
                    new LabelFilter("Telephony"),
                    new LabelFilter("Speech"),
                }
            });

            document.UsageRules.Add(new UsageRule
            {
                KeyId = document.ContentKeys.ElementAt(1).Id,

                LabelFilters = new[]
                {
                    new LabelFilter("SD-Video"),
                }
            });

            document.UsageRules.Add(new UsageRule
            {
                KeyId = document.ContentKeys.ElementAt(2).Id,

                LabelFilters = new[]
                {
                    new LabelFilter("HD-Video"),
                }
            });

            document.UsageRules.Add(new UsageRule
            {
                KeyId = document.ContentKeys.ElementAt(3).Id,

                LabelFilters = new[]
                {
                    new LabelFilter("UHD-Video"),
                    new LabelFilter("3D-Video"),
                    new LabelFilter("WCG-Video"),
                    new LabelFilter("HDR-Video"),
                }
            });

            // Intentionally no rule for last key ID, to emphasize that not all keys need to have usage rules.

            document.Save(outputStream);
        }