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); } }
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); }
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); }
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"); } }
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); }
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)); }
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); }
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); }
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())); }
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); }
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())); }
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); }
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())); }
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); }
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); } }
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); } }
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()))); }
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); } }
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); }
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); }