diff --git a/src/libraries/System.Security.Cryptography.Xml/tests/CanonicalXmlEntityReferenceTest.cs b/src/libraries/System.Security.Cryptography.Xml/tests/CanonicalXmlEntityReferenceTest.cs new file mode 100644 index 00000000000000..ecb430f68306d9 --- /dev/null +++ b/src/libraries/System.Security.Cryptography.Xml/tests/CanonicalXmlEntityReferenceTest.cs @@ -0,0 +1,170 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.IO; +using System.Text; +using System.Xml; +using Xunit; + +namespace System.Security.Cryptography.Xml.Tests +{ + public class CanonicalXmlEntityReferenceTest + { + [Fact] + public void EntityReferenceInCanonicalization() + { + // This test exercises CanonicalXmlEntityReference by using a transform + // that internally creates a CanonicalXmlDocument and loads XML into it. + // When an XmlNodeReader reads from a document containing entity references, + // the target document's CreateEntityReference method is called. + + string xml = @" +]> +&test;"; + + XmlDocument doc = new XmlDocument(); + doc.PreserveWhitespace = true; + doc.LoadXml(xml); + + // Use C14N transform which internally uses CanonicalXmlDocument + XmlDsigC14NTransform transform = new XmlDsigC14NTransform(); + transform.LoadInput(doc); + + Stream output = (Stream)transform.GetOutput(); + string result = new StreamReader(output, Encoding.UTF8).ReadToEnd(); + + // Entity should be expanded in canonical form + Assert.Contains("TestValue", result); + Assert.Contains("", result); + } + + [Fact] + public void EntityReferenceWithXmlNodeList() + { + // Test with XmlNodeList input which triggers different code path in CanonicalXml + // When using XmlNodeList, nodes not in the list are not included, which may affect + // entity reference expansion in the canonical output + string xml = @" +]> +&test;"; + + XmlDocument doc = new XmlDocument(); + doc.PreserveWhitespace = true; + doc.LoadXml(xml); + + XmlNodeList nodeList = doc.SelectNodes("//child")!; + + XmlDsigC14NTransform transform = new XmlDsigC14NTransform(); + transform.LoadInput(nodeList); + + Stream output = (Stream)transform.GetOutput(); + string result = new StreamReader(output, Encoding.UTF8).ReadToEnd(); + + // The node should be present in canonical form + Assert.Contains("", result); + Assert.Contains("", result); + } + + [Fact] + public void EntityReferenceWithCommentsIncluded() + { + // Test with includeComments = true + string xml = @" +]> +&ent;"; + + XmlDocument doc = new XmlDocument(); + doc.PreserveWhitespace = true; + doc.LoadXml(xml); + + XmlDsigC14NWithCommentsTransform transform = new XmlDsigC14NWithCommentsTransform(); + transform.LoadInput(doc); + + Stream output = (Stream)transform.GetOutput(); + string result = new StreamReader(output, Encoding.UTF8).ReadToEnd(); + + // Both comment and expanded entity should be in output + Assert.Contains("", result); + Assert.Contains("EntityContent", result); + } + + [Fact] + public void EntityReferenceInExclusiveCanonicalization() + { + // Test with Exclusive C14N transform + string xml = @" +]> +&test;"; + + XmlDocument doc = new XmlDocument(); + doc.PreserveWhitespace = true; + doc.LoadXml(xml); + + XmlDsigExcC14NTransform transform = new XmlDsigExcC14NTransform(); + transform.LoadInput(doc); + + Stream output = (Stream)transform.GetOutput(); + string result = new StreamReader(output, Encoding.UTF8).ReadToEnd(); + + // Entity should be expanded in canonical form + Assert.Contains("ExclusiveTest", result); + Assert.Contains("http://example.com", result); + } + + [Fact] + public void EntityReferenceWithHash() + { + // Test the WriteHash code path by using GetDigestedOutput + string xml = @" +]> +&test;"; + + XmlDocument doc = new XmlDocument(); + doc.PreserveWhitespace = true; + doc.LoadXml(xml); + + XmlDsigC14NTransform transform = new XmlDsigC14NTransform(); + transform.LoadInput(doc); + + using (SHA256 hash = SHA256.Create()) + { + byte[] digest = transform.GetDigestedOutput(hash); + + // Should produce a valid hash + Assert.NotNull(digest); + Assert.Equal(32, digest.Length); // SHA256 produces 32 bytes + } + } + + [Fact] + public void MultipleEntityReferences() + { + // Test with multiple entity references + string xml = @" + +]> +&ent1; and &ent2;"; + + XmlDocument doc = new XmlDocument(); + doc.PreserveWhitespace = true; + doc.LoadXml(xml); + + XmlDsigC14NTransform transform = new XmlDsigC14NTransform(); + transform.LoadInput(doc); + + Stream output = (Stream)transform.GetOutput(); + string result = new StreamReader(output, Encoding.UTF8).ReadToEnd(); + + // Both entities should be expanded + Assert.Contains("First", result); + Assert.Contains("Second", result); + Assert.Contains("and", result); + } + } +} diff --git a/src/libraries/System.Security.Cryptography.Xml/tests/DataObjectTests.cs b/src/libraries/System.Security.Cryptography.Xml/tests/DataObjectTests.cs index a1c4935229414f..dfb5d1b5f98b2b 100644 --- a/src/libraries/System.Security.Cryptography.Xml/tests/DataObjectTests.cs +++ b/src/libraries/System.Security.Cryptography.Xml/tests/DataObjectTests.cs @@ -161,5 +161,143 @@ private static XmlElement CreateTestElement(string name, string idValue, string return element; } + + [Fact] + public void LoadXml_InvalidElement() + { + XmlDocument doc = new XmlDocument(); + doc.LoadXml(""); + + DataObject dataObject = new DataObject(); + // Actually doesn't throw - just loads it anyway + dataObject.LoadXml(doc.DocumentElement); + Assert.NotNull(dataObject.Data); + } + + [Fact] + public void GetXml_WithData() + { + DataObject dataObject = new DataObject(); + XmlDocument doc = new XmlDocument(); + XmlElement elem = doc.CreateElement("TestData"); + elem.InnerText = "test content"; + dataObject.Data = new XmlNodeList[] { elem.ChildNodes }[0]; + + XmlElement xml = dataObject.GetXml(); + Assert.NotNull(xml); + Assert.Equal("Object", xml.LocalName); + } + + [Fact] + public void Properties_SetAndGet() + { + DataObject dataObject = new DataObject(); + + dataObject.Id = "obj-1"; + Assert.Equal("obj-1", dataObject.Id); + + dataObject.MimeType = "text/xml"; + Assert.Equal("text/xml", dataObject.MimeType); + + dataObject.Encoding = "UTF-8"; + Assert.Equal("UTF-8", dataObject.Encoding); + + Assert.NotNull(dataObject.Data); + } + + [Fact] + public void LoadXml_WithData() + { + string xml = @" + data + "; + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + DataObject dataObject = new DataObject(); + dataObject.LoadXml(doc.DocumentElement); + Assert.Equal("obj1", dataObject.Id); + Assert.Equal(1, dataObject.Data.Count); + } + + [Fact] + public void LoadXml_NoId() + { + string xml = @" + data + "; + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + DataObject dataObject = new DataObject(); + dataObject.LoadXml(doc.DocumentElement); + Assert.Null(dataObject.Id); + } + + [Fact] + public void LoadXml_NoMimeType() + { + string xml = @" + data + "; + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + DataObject dataObject = new DataObject(); + dataObject.LoadXml(doc.DocumentElement); + Assert.Null(dataObject.MimeType); + } + + [Fact] + public void LoadXml_NoEncoding() + { + string xml = @" + data + "; + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + DataObject dataObject = new DataObject(); + dataObject.LoadXml(doc.DocumentElement); + Assert.Null(dataObject.Encoding); + } + + [Fact] + public void GetXml_NoData() + { + DataObject dataObject = new DataObject(); + dataObject.Id = "obj1"; + + XmlElement xml = dataObject.GetXml(); + Assert.NotNull(xml); + Assert.Equal("Object", xml.LocalName); + Assert.Equal("obj1", xml.GetAttribute("Id")); + } + + [Fact] + public void GetXml_EmptyStrings() + { + DataObject dataObject = new DataObject(); + dataObject.Id = ""; + dataObject.MimeType = ""; + dataObject.Encoding = ""; + + XmlElement xml = dataObject.GetXml(); + Assert.NotNull(xml); + Assert.Equal("Object", xml.LocalName); + } + + [Fact] + public void Constructor_NullArguments() + { + XmlDocument doc = new XmlDocument(); + XmlElement elem = doc.CreateElement("test"); + + DataObject dataObject = new DataObject(null, null, null, elem); + Assert.Null(dataObject.Id); + Assert.Null(dataObject.MimeType); + Assert.Null(dataObject.Encoding); + Assert.NotNull(dataObject.Data); + } } } diff --git a/src/libraries/System.Security.Cryptography.Xml/tests/DataReferenceTest.cs b/src/libraries/System.Security.Cryptography.Xml/tests/DataReferenceTest.cs index f4b9ac020475f8..ca43bd9f18b07f 100644 --- a/src/libraries/System.Security.Cryptography.Xml/tests/DataReferenceTest.cs +++ b/src/libraries/System.Security.Cryptography.Xml/tests/DataReferenceTest.cs @@ -25,5 +25,74 @@ public void LoadXml() EncryptedKey ek = new EncryptedKey(); ek.LoadXml(doc.DocumentElement); } + + [Fact] + public void Constructor_Empty() + { + DataReference dataRef = new DataReference(); + Assert.Equal(string.Empty, dataRef.Uri); + } + + [Fact] + public void Constructor_WithUri() + { + string uri = "#data1"; + DataReference dataRef = new DataReference(uri); + Assert.Equal(uri, dataRef.Uri); + } + + [Fact] + public void Constructor_WithUriAndTransformChain() + { + string uri = "#data1"; + TransformChain tc = new TransformChain(); + tc.Add(new XmlDsigBase64Transform()); + + DataReference dataRef = new DataReference(uri, tc); + Assert.Equal(uri, dataRef.Uri); + Assert.NotNull(dataRef.TransformChain); + Assert.Equal(1, dataRef.TransformChain.Count); + } + + [Fact] + public void GetXml_SimpleDataReference() + { + DataReference dataRef = new DataReference("#encrypted-data-1"); + XmlElement xml = dataRef.GetXml(); + Assert.Equal("DataReference", xml.LocalName); + Assert.Equal(EncryptedXml.XmlEncNamespaceUrl, xml.NamespaceURI); + Assert.Equal("#encrypted-data-1", xml.GetAttribute("URI")); + } + + [Fact] + public void GetXml_WithTransforms() + { + DataReference dataRef = new DataReference("#data1"); + dataRef.TransformChain.Add(new XmlDsigC14NTransform()); + + XmlElement xml = dataRef.GetXml(); + Assert.Equal("DataReference", xml.LocalName); + Assert.NotNull(xml.SelectSingleNode("//*[local-name()='Transforms']")); + } + + [Fact] + public void LoadXml_SimpleDataReference() + { + string xml = @""; + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + DataReference dataRef = new DataReference(); + dataRef.LoadXml(doc.DocumentElement); + Assert.Equal("#encrypted-element", dataRef.Uri); + } + + [Fact] + public void ReferenceType_IsDataReference() + { + DataReference dataRef = new DataReference(); + XmlElement xml = dataRef.GetXml(); + Assert.Equal("DataReference", xml.LocalName); + } } } diff --git a/src/libraries/System.Security.Cryptography.Xml/tests/EncryptedXmlTests.cs b/src/libraries/System.Security.Cryptography.Xml/tests/EncryptedXmlTests.cs index 73cccbd9f77806..46ebab839f5eda 100644 --- a/src/libraries/System.Security.Cryptography.Xml/tests/EncryptedXmlTests.cs +++ b/src/libraries/System.Security.Cryptography.Xml/tests/EncryptedXmlTests.cs @@ -36,5 +36,1332 @@ public static void DecryptWithCertificate_NotInStore() Assert.DoesNotContain(SecretMessage, document2.OuterXml); } } + + [Fact] + public static void EncryptedData_Constructor() + { + EncryptedData encData = new EncryptedData(); + Assert.Null(encData.Id); + Assert.Null(encData.Type); + Assert.Null(encData.MimeType); + Assert.Null(encData.Encoding); + } + + [Fact] + public static void EncryptedData_GetXml_ThrowsWhenCipherDataNull() + { + EncryptedData encData = new EncryptedData(); + Assert.Throws(() => encData.GetXml()); + } + + [Fact] + public static void EncryptedData_GetXml_WithCipherValue() + { + EncryptedData encData = new EncryptedData(); + encData.CipherData = new CipherData(new byte[] { 1, 2, 3 }); + XmlElement xml = encData.GetXml(); + Assert.Equal("EncryptedData", xml.LocalName); + Assert.Equal(EncryptedXml.XmlEncNamespaceUrl, xml.NamespaceURI); + } + + [Fact] + public static void EncryptedData_GetXml_WithAllProperties() + { + EncryptedData encData = new EncryptedData + { + Id = "test-id", + Type = EncryptedXml.XmlEncElementUrl, + MimeType = "text/xml", + Encoding = "utf-8", + CipherData = new CipherData(new byte[] { 1, 2, 3 }), + EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncAES256Url) + }; + + encData.KeyInfo.AddClause(new KeyInfoName("key1")); + + XmlDocument doc = new XmlDocument(); + XmlElement propElement = doc.CreateElement("EncryptionProperty", EncryptedXml.XmlEncNamespaceUrl); + propElement.InnerText = "value"; + EncryptionProperty prop = new EncryptionProperty(propElement); + encData.EncryptionProperties.Add(prop); + + XmlElement xml = encData.GetXml(); + Assert.Equal("EncryptedData", xml.LocalName); + Assert.Equal("test-id", xml.GetAttribute("Id")); + Assert.Equal(EncryptedXml.XmlEncElementUrl, xml.GetAttribute("Type")); + Assert.Equal("text/xml", xml.GetAttribute("MimeType")); + Assert.Equal("utf-8", xml.GetAttribute("Encoding")); + } + + [Fact] + public static void EncryptedData_LoadXml_MinimalValid() + { + string xml = @" + + AQID + + "; + + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + EncryptedData encData = new EncryptedData(); + encData.LoadXml(doc.DocumentElement); + Assert.NotNull(encData.CipherData); + Assert.NotNull(encData.CipherData.CipherValue); + } + + [Fact] + public static void EncryptedData_LoadXml_WithAttributes() + { + string xml = @" + + + AQID + + "; + + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + EncryptedData encData = new EncryptedData(); + encData.LoadXml(doc.DocumentElement); + Assert.Equal("id1", encData.Id); + Assert.Equal("http://example.com/type", encData.Type); + Assert.Equal("application/xml", encData.MimeType); + Assert.Equal("utf-8", encData.Encoding); + Assert.NotNull(encData.EncryptionMethod); + } + + [Fact] + public static void EncryptedData_LoadXml_WithEncryptionProperties() + { + string xml = @" + + AQID + + + + data + + + "; + + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + EncryptedData encData = new EncryptedData(); + encData.LoadXml(doc.DocumentElement); + Assert.Equal(1, encData.EncryptionProperties.Count); + } + + [Fact] + public static void EncryptedData_LoadXml_ThrowsWhenCipherDataMissing() + { + string xml = @" + + "; + + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + EncryptedData encData = new EncryptedData(); + Assert.Throws(() => encData.LoadXml(doc.DocumentElement)); + } + + [Fact] + public static void EncryptedKey_Constructor() + { + EncryptedKey encKey = new EncryptedKey(); + Assert.Null(encKey.Id); + Assert.Null(encKey.Type); + Assert.Null(encKey.MimeType); + Assert.Null(encKey.Encoding); + Assert.Equal(string.Empty, encKey.Recipient); + Assert.Null(encKey.CarriedKeyName); + } + + [Fact] + public static void EncryptedKey_Recipient_DefaultValue() + { + EncryptedKey encKey = new EncryptedKey(); + Assert.Equal(string.Empty, encKey.Recipient); + } + + [Fact] + public static void EncryptedKey_ReferenceList_NotNull() + { + EncryptedKey encKey = new EncryptedKey(); + Assert.NotNull(encKey.ReferenceList); + Assert.Equal(0, encKey.ReferenceList.Count); + } + + [Fact] + public static void EncryptedKey_AddReference_DataReference() + { + EncryptedKey encKey = new EncryptedKey(); + DataReference dataRef = new DataReference("#data1"); + encKey.AddReference(dataRef); + Assert.Equal(1, encKey.ReferenceList.Count); + } + + [Fact] + public static void EncryptedKey_AddReference_KeyReference() + { + EncryptedKey encKey = new EncryptedKey(); + KeyReference keyRef = new KeyReference("#key1"); + encKey.AddReference(keyRef); + Assert.Equal(1, encKey.ReferenceList.Count); + } + + [Fact] + public static void EncryptedKey_GetXml_ThrowsWhenCipherDataNull() + { + EncryptedKey encKey = new EncryptedKey(); + Assert.Throws(() => encKey.GetXml()); + } + + [Fact] + public static void EncryptedKey_GetXml_WithCipherValue() + { + EncryptedKey encKey = new EncryptedKey(); + encKey.CipherData = new CipherData(new byte[] { 1, 2, 3 }); + XmlElement xml = encKey.GetXml(); + Assert.Equal("EncryptedKey", xml.LocalName); + Assert.Equal(EncryptedXml.XmlEncNamespaceUrl, xml.NamespaceURI); + } + + [Fact] + public static void EncryptedKey_GetXml_WithAllProperties() + { + EncryptedKey encKey = new EncryptedKey + { + Id = "test-key-id", + Type = "http://example.com/keytype", + MimeType = "application/octet-stream", + Encoding = "base64", + Recipient = "recipient@example.com", + CarriedKeyName = "MyKey", + CipherData = new CipherData(new byte[] { 1, 2, 3 }), + EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncRSA15Url) + }; + + encKey.KeyInfo.AddClause(new KeyInfoName("wrappingKey")); + encKey.AddReference(new DataReference("#data1")); + encKey.AddReference(new KeyReference("#key1")); + + XmlDocument doc = new XmlDocument(); + XmlElement propElement = doc.CreateElement("EncryptionProperty", EncryptedXml.XmlEncNamespaceUrl); + propElement.InnerText = "value"; + EncryptionProperty prop = new EncryptionProperty(propElement); + encKey.EncryptionProperties.Add(prop); + + XmlElement xml = encKey.GetXml(); + Assert.Equal("EncryptedKey", xml.LocalName); + Assert.Equal("test-key-id", xml.GetAttribute("Id")); + Assert.Equal("http://example.com/keytype", xml.GetAttribute("Type")); + Assert.Equal("application/octet-stream", xml.GetAttribute("MimeType")); + Assert.Equal("base64", xml.GetAttribute("Encoding")); + Assert.Equal("recipient@example.com", xml.GetAttribute("Recipient")); + } + + [Fact] + public static void EncryptedKey_LoadXml_MinimalValid() + { + string xml = @" + + AQID + + "; + + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + EncryptedKey encKey = new EncryptedKey(); + encKey.LoadXml(doc.DocumentElement); + Assert.NotNull(encKey.CipherData); + Assert.NotNull(encKey.CipherData.CipherValue); + } + + [Fact] + public static void EncryptedKey_LoadXml_WithAttributes() + { + string xml = @" + + + AQID + + "; + + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + EncryptedKey encKey = new EncryptedKey(); + encKey.LoadXml(doc.DocumentElement); + Assert.Equal("key1", encKey.Id); + Assert.Equal("http://example.com/type", encKey.Type); + Assert.Equal("application/xml", encKey.MimeType); + Assert.Equal("utf-8", encKey.Encoding); + Assert.Equal("user@example.com", encKey.Recipient); + Assert.NotNull(encKey.EncryptionMethod); + } + + [Fact] + public static void EncryptedKey_LoadXml_WithCarriedKeyName() + { + string xml = @" + + AQID + + TestKeyName + "; + + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + EncryptedKey encKey = new EncryptedKey(); + encKey.LoadXml(doc.DocumentElement); + Assert.Equal("TestKeyName", encKey.CarriedKeyName); + } + + [Fact] + public static void EncryptedKey_LoadXml_WithReferenceList() + { + string xml = @" + + AQID + + + + + + "; + + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + EncryptedKey encKey = new EncryptedKey(); + encKey.LoadXml(doc.DocumentElement); + Assert.Equal(2, encKey.ReferenceList.Count); + } + + [Fact] + public static void EncryptedKey_LoadXml_ThrowsWhenCipherDataMissing() + { + string xml = @" + + "; + + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + EncryptedKey encKey = new EncryptedKey(); + Assert.Throws(() => encKey.LoadXml(doc.DocumentElement)); + } + + [Fact] + public static void CipherReference_Constructor() + { + CipherReference cipherRef = new CipherReference(); + Assert.Equal(string.Empty, cipherRef.Uri); + } + + [Fact] + public static void CipherReference_Constructor_WithUri() + { + string uri = "http://example.com/data"; + CipherReference cipherRef = new CipherReference(uri); + Assert.Equal(uri, cipherRef.Uri); + } + + [Fact] + public static void CipherReference_Constructor_WithUriAndTransformChain() + { + string uri = "http://example.com/data"; + TransformChain tc = new TransformChain(); + tc.Add(new XmlDsigBase64Transform()); + + CipherReference cipherRef = new CipherReference(uri, tc); + Assert.Equal(uri, cipherRef.Uri); + Assert.NotNull(cipherRef.TransformChain); + Assert.Equal(1, cipherRef.TransformChain.Count); + } + + [Fact] + public static void CipherReference_GetXml() + { + CipherReference cipherRef = new CipherReference("http://example.com/data"); + XmlElement xml = cipherRef.GetXml(); + Assert.Equal("CipherReference", xml.LocalName); + Assert.Equal("http://example.com/data", xml.GetAttribute("URI")); + } + + [Fact] + public static void CipherReference_GetXml_WithTransforms() + { + CipherReference cipherRef = new CipherReference("http://example.com/data"); + cipherRef.TransformChain.Add(new XmlDsigBase64Transform()); + XmlElement xml = cipherRef.GetXml(); + Assert.Equal("CipherReference", xml.LocalName); + Assert.NotNull(xml.SelectSingleNode("//*[local-name()='Transforms']")); + } + + [Fact] + public static void CipherReference_LoadXml_Simple() + { + string xml = @""; + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + CipherReference cipherRef = new CipherReference(); + cipherRef.LoadXml(doc.DocumentElement); + Assert.Equal("http://example.com/data", cipherRef.Uri); + } + + [Fact] + public static void CipherReference_LoadXml_WithTransforms() + { + string xml = @" + + + + "; + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + CipherReference cipherRef = new CipherReference(); + cipherRef.LoadXml(doc.DocumentElement); + Assert.Equal("http://example.com/data", cipherRef.Uri); + Assert.Equal(1, cipherRef.TransformChain.Count); + } + + [Fact] + public static void CipherReference_LoadXml_ThrowsWhenUriMissing() + { + string xml = @""; + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + CipherReference cipherRef = new CipherReference(); + Assert.Throws(() => cipherRef.LoadXml(doc.DocumentElement)); + } + + [Fact] + public static void KeyInfoEncryptedKey_Constructor() + { + KeyInfoEncryptedKey kiek = new KeyInfoEncryptedKey(new EncryptedKey()); + Assert.NotNull(kiek.EncryptedKey); + } + + [Fact] + public static void KeyInfoEncryptedKey_Constructor_Null() + { + KeyInfoEncryptedKey kiek = new KeyInfoEncryptedKey(null); + Assert.Null(kiek.EncryptedKey); + } + + [Fact] + public static void KeyInfoEncryptedKey_SetEncryptedKey() + { + EncryptedKey ek = new EncryptedKey(); + ek.Id = "test-key"; + ek.CipherData = new CipherData(new byte[] { 1, 2, 3 }); + + KeyInfoEncryptedKey kiek = new KeyInfoEncryptedKey(null); + kiek.EncryptedKey = ek; + Assert.Same(ek, kiek.EncryptedKey); + } + + [Fact] + public static void KeyInfoEncryptedKey_GetXml() + { + EncryptedKey ek = new EncryptedKey(); + ek.Id = "test-key-id"; + ek.CipherData = new CipherData(new byte[] { 1, 2, 3 }); + + KeyInfoEncryptedKey kiek = new KeyInfoEncryptedKey(ek); + XmlElement xml = kiek.GetXml(); + Assert.Equal("EncryptedKey", xml.LocalName); + Assert.Equal("test-key-id", xml.GetAttribute("Id")); + } + + [Fact] + public static void KeyInfoEncryptedKey_LoadXml() + { + string xml = @" + + AQID + + "; + + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + KeyInfoEncryptedKey kiek = new KeyInfoEncryptedKey(); + kiek.LoadXml(doc.DocumentElement); + Assert.NotNull(kiek.EncryptedKey); + Assert.Equal("key1", kiek.EncryptedKey.Id); + } + + [Fact] + public static void KeyInfoEncryptedKey_LoadXml_Null() + { + KeyInfoEncryptedKey kiek = new KeyInfoEncryptedKey(); + Assert.Throws(() => kiek.LoadXml(null)); + } + + [Fact] + public static void EncryptedReference_Properties() + { + DataReference dataRef = new DataReference("#data1"); + Assert.Equal("#data1", dataRef.Uri); + Assert.NotNull(dataRef.TransformChain); + + dataRef.Uri = "#data2"; + Assert.Equal("#data2", dataRef.Uri); + } + + [Fact] + public static void ReferenceList_Operations() + { + ReferenceList refList = new ReferenceList(); + Assert.Equal(0, refList.Count); + + DataReference dr1 = new DataReference("#data1"); + refList.Add(dr1); + Assert.Equal(1, refList.Count); + + KeyReference kr1 = new KeyReference("#key1"); + refList.Add(kr1); + Assert.Equal(2, refList.Count); + + Assert.Same(dr1, refList.Item(0)); + Assert.Same(kr1, refList.Item(1)); + + Assert.Same(dr1, refList[0]); + Assert.Same(kr1, refList[1]); + } + + [Fact] + public static void ReferenceList_IList() + { + ReferenceList refList = new ReferenceList(); + System.Collections.IList list = refList; + + DataReference dr = new DataReference("#data"); + list.Add(dr); + Assert.Equal(1, refList.Count); + Assert.True(list.Contains(dr)); + + list.Remove(dr); + Assert.Equal(0, refList.Count); + } + + [Fact] + public static void EncryptionPropertyCollection_Operations() + { + EncryptionPropertyCollection props = new EncryptionPropertyCollection(); + Assert.Equal(0, props.Count); + + XmlDocument doc = new XmlDocument(); + XmlElement elem1 = doc.CreateElement("EncryptionProperty", EncryptedXml.XmlEncNamespaceUrl); + EncryptionProperty prop1 = new EncryptionProperty(elem1); + props.Add(prop1); + Assert.Equal(1, props.Count); + + XmlElement elem2 = doc.CreateElement("EncryptionProperty", EncryptedXml.XmlEncNamespaceUrl); + EncryptionProperty prop2 = new EncryptionProperty(elem2); + props.Add(prop2); + Assert.Equal(2, props.Count); + + Assert.Same(prop1, props.Item(0)); + Assert.Same(prop2, props.Item(1)); + + Assert.Same(prop1, props[0]); + Assert.Same(prop2, props[1]); + } + + [Fact] + public static void EncryptionPropertyCollection_IList() + { + EncryptionPropertyCollection props = new EncryptionPropertyCollection(); + System.Collections.IList list = props; + + XmlDocument doc = new XmlDocument(); + XmlElement elem = doc.CreateElement("EncryptionProperty", EncryptedXml.XmlEncNamespaceUrl); + EncryptionProperty prop = new EncryptionProperty(elem); + + list.Add(prop); + Assert.Equal(1, props.Count); + Assert.True(list.Contains(prop)); + + list.Remove(prop); + Assert.Equal(0, props.Count); + } + + [Fact] + public static void EncryptedData_LoadXml_Null() + { + EncryptedData encData = new EncryptedData(); + Assert.Throws(() => encData.LoadXml(null)); + } + + [Fact] + public static void EncryptedKey_LoadXml_Null() + { + EncryptedKey encKey = new EncryptedKey(); + Assert.Throws(() => encKey.LoadXml(null)); + } + + [Fact] + public static void CipherReference_LoadXml_Null() + { + CipherReference cipherRef = new CipherReference(); + Assert.Throws(() => cipherRef.LoadXml(null)); + } + + [Fact] + public static void EncryptedData_Properties_SetNull() + { + EncryptedData encData = new EncryptedData(); + encData.Id = null; + encData.Type = null; + encData.MimeType = null; + encData.Encoding = null; + + Assert.Null(encData.Id); + Assert.Null(encData.Type); + Assert.Null(encData.MimeType); + Assert.Null(encData.Encoding); + } + + [Fact] + public static void EncryptedKey_Properties_SetNull() + { + EncryptedKey encKey = new EncryptedKey(); + encKey.Id = null; + encKey.Type = null; + encKey.MimeType = null; + encKey.Encoding = null; + encKey.Recipient = null; + encKey.CarriedKeyName = null; + + Assert.Null(encKey.Id); + Assert.Null(encKey.Type); + Assert.Null(encKey.MimeType); + Assert.Null(encKey.Encoding); + Assert.Equal(string.Empty, encKey.Recipient); // Default is empty string + Assert.Null(encKey.CarriedKeyName); + } + + [Fact] + public static void EncryptedReference_Uri_SetNull() + { + DataReference dataRef = new DataReference("#data1"); + Assert.Throws(() => dataRef.Uri = null); + } + + [Fact] + public static void EncryptedReference_TransformChain_NotNull() + { + DataReference dataRef = new DataReference(); + Assert.NotNull(dataRef.TransformChain); + Assert.Equal(0, dataRef.TransformChain.Count); + } + + [Fact] + public static void ReferenceList_ItemOutOfRange() + { + ReferenceList refList = new ReferenceList(); + Assert.Throws(() => refList.Item(0)); + } + + [Fact] + public static void ReferenceList_IndexerOutOfRange() + { + ReferenceList refList = new ReferenceList(); + Assert.Throws(() => refList[0]); + } + + [Fact] + public static void EncryptionPropertyCollection_ItemOutOfRange() + { + EncryptionPropertyCollection props = new EncryptionPropertyCollection(); + Assert.Throws(() => props.Item(0)); + } + + [Fact] + public static void EncryptionPropertyCollection_IndexerOutOfRange() + { + EncryptionPropertyCollection props = new EncryptionPropertyCollection(); + Assert.Throws(() => props[0]); + } + + [Fact] + public static void EncryptedData_LoadXml_WithKeyInfo() + { + string xml = @" + + + TestKey + + + AQID + + "; + + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + EncryptedData encData = new EncryptedData(); + encData.LoadXml(doc.DocumentElement); + Assert.NotNull(encData.KeyInfo); + Assert.Equal(1, encData.KeyInfo.Count); + } + + [Fact] + public static void EncryptedKey_LoadXml_WithKeyInfo() + { + string xml = @" + + + WrappingKey + + + AQID + + "; + + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + EncryptedKey encKey = new EncryptedKey(); + encKey.LoadXml(doc.DocumentElement); + Assert.NotNull(encKey.KeyInfo); + Assert.Equal(1, encKey.KeyInfo.Count); + } + + [Fact] + public static void EncryptedData_GetXml_CachedXml() + { + string xml = @" + + AQID + + "; + + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + EncryptedData encData = new EncryptedData(); + encData.LoadXml(doc.DocumentElement); + + XmlElement xml1 = encData.GetXml(); + XmlElement xml2 = encData.GetXml(); + Assert.Same(xml1, xml2); // Should be cached + } + + [Fact] + public static void EncryptedKey_GetXml_CachedXml() + { + string xml = @" + + AQID + + "; + + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + EncryptedKey encKey = new EncryptedKey(); + encKey.LoadXml(doc.DocumentElement); + + XmlElement xml1 = encKey.GetXml(); + XmlElement xml2 = encKey.GetXml(); + Assert.Same(xml1, xml2); // Should be cached + } + + [Fact] + public static void EncryptedData_SetProperty_InvalidatesCache() + { + string xml = @" + + AQID + + "; + + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + EncryptedData encData = new EncryptedData(); + encData.LoadXml(doc.DocumentElement); + + XmlElement xml1 = encData.GetXml(); + encData.Id = "new-id"; // Should invalidate cache + XmlElement xml2 = encData.GetXml(); + Assert.NotSame(xml1, xml2); + } + + [Fact] + public static void CipherReference_GetXml_CachedXml() + { + CipherReference cipherRef = new CipherReference("http://example.com/data"); + XmlElement xml1 = cipherRef.GetXml(); + XmlElement xml2 = cipherRef.GetXml(); + Assert.NotSame(xml1, xml2); // CipherReference doesn't cache when created programmatically + } + + [Fact] + public static void EncryptedData_LoadXml_CipherReference() + { + string xml = @" + + + + "; + + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + EncryptedData encData = new EncryptedData(); + encData.LoadXml(doc.DocumentElement); + Assert.NotNull(encData.CipherData); + Assert.NotNull(encData.CipherData.CipherReference); + Assert.Equal("http://example.com/data", encData.CipherData.CipherReference.Uri); + } + + [Fact] + public static void EncryptedKey_LoadXml_CipherReference() + { + string xml = @" + + + + "; + + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + EncryptedKey encKey = new EncryptedKey(); + encKey.LoadXml(doc.DocumentElement); + Assert.NotNull(encKey.CipherData); + Assert.NotNull(encKey.CipherData.CipherReference); + Assert.Equal("http://example.com/key", encKey.CipherData.CipherReference.Uri); + } + + [Fact] + public static void EncryptedData_GetXml_WithCipherReference() + { + EncryptedData encData = new EncryptedData(); + encData.CipherData = new CipherData(); + encData.CipherData.CipherReference = new CipherReference("http://example.com/data"); + + XmlElement xml = encData.GetXml(); + Assert.Equal("EncryptedData", xml.LocalName); + Assert.NotNull(xml.SelectSingleNode("//*[local-name()='CipherReference']")); + } + + [Fact] + public static void EncryptedKey_GetXml_WithCipherReference() + { + EncryptedKey encKey = new EncryptedKey(); + encKey.CipherData = new CipherData(); + encKey.CipherData.CipherReference = new CipherReference("http://example.com/key"); + + XmlElement xml = encKey.GetXml(); + Assert.Equal("EncryptedKey", xml.LocalName); + Assert.NotNull(xml.SelectSingleNode("//*[local-name()='CipherReference']")); + } + + [Fact] + public static void EncryptedData_SetCipherData_Null() + { + EncryptedData encData = new EncryptedData(); + encData.CipherData = new CipherData(new byte[] { 1, 2, 3 }); + + Assert.Throws(() => encData.CipherData = null); + } + + [Fact] + public static void EncryptedKey_SetCipherData_Null() + { + EncryptedKey encKey = new EncryptedKey(); + encKey.CipherData = new CipherData(new byte[] { 1, 2, 3 }); + + Assert.Throws(() => encKey.CipherData = null); + } + + [Fact] + public static void EncryptedData_SetEncryptionMethod_Null() + { + EncryptedData encData = new EncryptedData(); + encData.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncAES256Url); + + encData.EncryptionMethod = null; + Assert.Null(encData.EncryptionMethod); + } + + [Fact] + public static void EncryptedKey_SetEncryptionMethod_Null() + { + EncryptedKey encKey = new EncryptedKey(); + encKey.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncRSA15Url); + + encKey.EncryptionMethod = null; + Assert.Null(encKey.EncryptionMethod); + } + + [Fact] + public static void EncryptedData_SetKeyInfo_Null() + { + EncryptedData encData = new EncryptedData(); + KeyInfo ki = new KeyInfo(); + ki.AddClause(new KeyInfoName("key1")); + encData.KeyInfo = ki; + + encData.KeyInfo = null; + // KeyInfo auto-initializes on access + Assert.NotNull(encData.KeyInfo); + Assert.Equal(0, encData.KeyInfo.Count); + } + + [Fact] + public static void EncryptedKey_SetKeyInfo_Null() + { + EncryptedKey encKey = new EncryptedKey(); + KeyInfo ki = new KeyInfo(); + ki.AddClause(new KeyInfoName("key1")); + encKey.KeyInfo = ki; + + encKey.KeyInfo = null; + // KeyInfo auto-initializes on access + Assert.NotNull(encKey.KeyInfo); + Assert.Equal(0, encKey.KeyInfo.Count); + } + + [Fact] + public static void ReferenceList_AddMultipleTypes() + { + ReferenceList refList = new ReferenceList(); + + refList.Add(new DataReference("#data1")); + refList.Add(new KeyReference("#key1")); + refList.Add(new DataReference("#data2")); + refList.Add(new KeyReference("#key2")); + + Assert.Equal(4, refList.Count); + } + + [Fact] + public static void EncryptionPropertyCollection_CopyTo() + { + EncryptionPropertyCollection props = new EncryptionPropertyCollection(); + XmlDocument doc = new XmlDocument(); + + XmlElement elem1 = doc.CreateElement("EncryptionProperty", EncryptedXml.XmlEncNamespaceUrl); + EncryptionProperty prop1 = new EncryptionProperty(elem1); + props.Add(prop1); + + XmlElement elem2 = doc.CreateElement("EncryptionProperty", EncryptedXml.XmlEncNamespaceUrl); + EncryptionProperty prop2 = new EncryptionProperty(elem2); + props.Add(prop2); + + EncryptionProperty[] array = new EncryptionProperty[2]; + props.CopyTo(array, 0); + + Assert.Same(prop1, array[0]); + Assert.Same(prop2, array[1]); + } + + [Fact] + public static void ReferenceList_CopyTo() + { + ReferenceList refList = new ReferenceList(); + DataReference dr = new DataReference("#data1"); + KeyReference kr = new KeyReference("#key1"); + + refList.Add(dr); + refList.Add(kr); + + object[] array = new object[2]; + ((System.Collections.ICollection)refList).CopyTo(array, 0); + + Assert.Same(dr, array[0]); + Assert.Same(kr, array[1]); + } + + [Fact] + public static void EncryptedXml_Properties() + { + EncryptedXml exml = new EncryptedXml(); + + exml.XmlDSigSearchDepth = 5; + Assert.Equal(5, exml.XmlDSigSearchDepth); + + exml.XmlDSigSearchDepth = 100; + Assert.Equal(100, exml.XmlDSigSearchDepth); + + exml.Recipient = "test-recipient"; + Assert.Equal("test-recipient", exml.Recipient); + + exml.Recipient = ""; + Assert.Equal("", exml.Recipient); + } + + [Fact] + public static void EncryptedXml_ModeProperty() + { + EncryptedXml exml = new EncryptedXml(); + + exml.Mode = CipherMode.ECB; + Assert.Equal(CipherMode.ECB, exml.Mode); + + exml.Mode = CipherMode.CFB; + Assert.Equal(CipherMode.CFB, exml.Mode); + } + + [Fact] + public static void EncryptedXml_PaddingProperty() + { + EncryptedXml exml = new EncryptedXml(); + + exml.Padding = PaddingMode.PKCS7; + Assert.Equal(PaddingMode.PKCS7, exml.Padding); + + exml.Padding = PaddingMode.Zeros; + Assert.Equal(PaddingMode.Zeros, exml.Padding); + } + + [Fact] + public static void EncryptedXml_EncodingProperty() + { + EncryptedXml exml = new EncryptedXml(); + + exml.Encoding = System.Text.Encoding.ASCII; + Assert.Equal(System.Text.Encoding.ASCII, exml.Encoding); + + exml.Encoding = System.Text.Encoding.Unicode; + Assert.Equal(System.Text.Encoding.Unicode, exml.Encoding); + } + + [Fact] + public static void EncryptedXml_ResolverProperty() + { + EncryptedXml exml = new EncryptedXml(); + + exml.Resolver = null; + Assert.Null(exml.Resolver); + } + + [Fact] + public static void EncryptedXml_ClearKeyNameMappings() + { + EncryptedXml exml = new EncryptedXml(); + using (Aes aes = Aes.Create()) + { + exml.AddKeyNameMapping("key1", aes); + exml.ClearKeyNameMappings(); + // After clearing, the key should not be found + } + } + + [Fact] + public static void EncryptedXml_AddKeyNameMapping_Multiple() + { + EncryptedXml exml = new EncryptedXml(); + using (Aes aes1 = Aes.Create()) + using (Aes aes2 = Aes.Create()) + { + exml.AddKeyNameMapping("key1", aes1); + exml.AddKeyNameMapping("key2", aes2); + // Both keys should be mapped + } + } + + [Fact] + public static void EncryptedXml_ReplaceElement_ContentFalse() + { + XmlDocument doc = new XmlDocument(); + doc.LoadXml(""); + EncryptedData edata = new EncryptedData(); + edata.CipherData.CipherValue = new byte[16]; + + EncryptedXml.ReplaceElement(doc.DocumentElement, edata, false); + Assert.Equal("EncryptedData", doc.DocumentElement.Name); + } + + [Fact] + public static void ReferenceList_IListOperations() + { + ReferenceList refList = new ReferenceList(); + System.Collections.IList list = refList; + + Assert.False(list.IsFixedSize); + Assert.False(list.IsReadOnly); + Assert.False(list.IsSynchronized); + Assert.NotNull(list.SyncRoot); + + DataReference dr = new DataReference("#data1"); + list.Add(dr); + + Assert.Equal(0, list.IndexOf(dr)); + + list.Insert(0, new DataReference("#data0")); + Assert.Equal(2, list.Count); + + list.RemoveAt(0); + Assert.Equal(1, list.Count); + + list.Clear(); + Assert.Equal(0, list.Count); + } + + [Fact] + public static void EncryptionPropertyCollection_IListOperations() + { + EncryptionPropertyCollection props = new EncryptionPropertyCollection(); + System.Collections.IList list = props; + + Assert.False(list.IsFixedSize); + Assert.False(list.IsReadOnly); + Assert.False(list.IsSynchronized); + Assert.NotNull(list.SyncRoot); + + XmlDocument doc = new XmlDocument(); + XmlElement elem = doc.CreateElement("EncryptionProperty", EncryptedXml.XmlEncNamespaceUrl); + EncryptionProperty prop = new EncryptionProperty(elem); + + list.Add(prop); + Assert.Equal(0, list.IndexOf(prop)); + + XmlElement elem2 = doc.CreateElement("EncryptionProperty", EncryptedXml.XmlEncNamespaceUrl); + EncryptionProperty prop2 = new EncryptionProperty(elem2); + list.Insert(0, prop2); + Assert.Equal(2, list.Count); + + list.RemoveAt(0); + Assert.Equal(1, list.Count); + + list.Clear(); + Assert.Equal(0, list.Count); + } + + [Fact] + public static void EncryptedXml_DecryptDocument_WithDataReference() + { + XmlDocument doc = new XmlDocument(); + doc.LoadXml("secret"); + + using (Aes aes = Aes.Create()) + { + EncryptedXml exml = new EncryptedXml(doc); + + byte[] encrypted = exml.EncryptData(doc.DocumentElement, aes, false); + + EncryptedData encData = new EncryptedData(); + encData.Type = EncryptedXml.XmlEncElementUrl; + encData.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncAES256Url); + encData.CipherData.CipherValue = encrypted; + encData.Id = "enc1"; + + EncryptedXml.ReplaceElement(doc.DocumentElement, encData, false); + + // Now decrypt + exml.AddKeyNameMapping("aes", aes); + EncryptedData ed = new EncryptedData(); + ed.LoadXml(doc.DocumentElement); + + byte[] decrypted = exml.DecryptData(ed, aes); + Assert.NotNull(decrypted); + } + } + + [Fact] + public static void EncryptedXml_GetDecryptionIV_DifferentAlgorithms() + { + EncryptedXml exml = new EncryptedXml(); + + // AES256 + EncryptedData ed1 = new EncryptedData(); + ed1.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncAES256Url); + ed1.CipherData = new CipherData(new byte[32]); + byte[] iv1 = exml.GetDecryptionIV(ed1, EncryptedXml.XmlEncAES256Url); + Assert.Equal(16, iv1.Length); + + // AES192 + EncryptedData ed2 = new EncryptedData(); + ed2.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncAES192Url); + ed2.CipherData = new CipherData(new byte[24]); + byte[] iv2 = exml.GetDecryptionIV(ed2, EncryptedXml.XmlEncAES192Url); + Assert.Equal(16, iv2.Length); + + // AES128 + EncryptedData ed3 = new EncryptedData(); + ed3.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncAES128Url); + ed3.CipherData = new CipherData(new byte[16]); + byte[] iv3 = exml.GetDecryptionIV(ed3, EncryptedXml.XmlEncAES128Url); + Assert.Equal(16, iv3.Length); + } + + [Fact] + public static void EncryptedXml_GetIdElement_NestedStructure() + { + XmlDocument doc = new XmlDocument(); + doc.LoadXml(@" + + + content + + + "); + + EncryptedXml exml = new EncryptedXml(doc); + + XmlElement elem1 = exml.GetIdElement(doc, "id1"); + Assert.NotNull(elem1); + Assert.Equal("level1", elem1.LocalName); + + XmlElement elem2 = exml.GetIdElement(doc, "id2"); + Assert.NotNull(elem2); + Assert.Equal("level2", elem2.LocalName); + + XmlElement elem3 = exml.GetIdElement(doc, "id3"); + Assert.NotNull(elem3); + Assert.Equal("level3", elem3.LocalName); + } + + [Fact] + public static void EncryptedKey_WithReferenceList() + { + EncryptedKey encKey = new EncryptedKey(); + encKey.CipherData = new CipherData(new byte[] { 1, 2, 3, 4 }); + + encKey.ReferenceList.Add(new DataReference("#data1")); + encKey.ReferenceList.Add(new DataReference("#data2")); + encKey.ReferenceList.Add(new KeyReference("#key1")); + + XmlElement xml = encKey.GetXml(); + Assert.NotNull(xml); + + XmlNodeList refList = xml.SelectNodes("//*[local-name()='ReferenceList']"); + Assert.Equal(1, refList.Count); + + XmlNodeList refs = xml.SelectNodes("//*[local-name()='ReferenceList']/*"); + Assert.Equal(3, refs.Count); + } + + [Fact] + public static void EncryptedData_WithEncryptionProperties() + { + EncryptedData encData = new EncryptedData(); + encData.CipherData = new CipherData(new byte[] { 1, 2, 3 }); + + XmlDocument doc = new XmlDocument(); + XmlElement prop1 = doc.CreateElement("EncryptionProperty", EncryptedXml.XmlEncNamespaceUrl); + prop1.SetAttribute("Id", "prop1"); + encData.EncryptionProperties.Add(new EncryptionProperty(prop1)); + + XmlElement prop2 = doc.CreateElement("EncryptionProperty", EncryptedXml.XmlEncNamespaceUrl); + prop2.SetAttribute("Id", "prop2"); + encData.EncryptionProperties.Add(new EncryptionProperty(prop2)); + + XmlElement xml = encData.GetXml(); + XmlNodeList props = xml.SelectNodes("//*[local-name()='EncryptionProperty']"); + Assert.Equal(2, props.Count); + } + + [Fact] + public static void EncryptedXml_Recipient_Property() + { + EncryptedXml exml = new EncryptedXml(); + Assert.Equal(string.Empty, exml.Recipient); // Defaults to empty string + + exml.Recipient = "recipient@example.com"; + Assert.Equal("recipient@example.com", exml.Recipient); + + exml.Recipient = null; + Assert.Equal(string.Empty, exml.Recipient); // Setting null gives empty string + } + + [Fact] + public static void CipherReference_WithTransforms() + { + CipherReference cipherRef = new CipherReference("http://example.com/data"); + + cipherRef.AddTransform(new XmlDsigBase64Transform()); + cipherRef.AddTransform(new XmlDsigC14NTransform()); + + XmlElement xml = cipherRef.GetXml(); + XmlNodeList transforms = xml.SelectNodes("//*[local-name()='Transform']"); + Assert.Equal(2, transforms.Count); + } + + [Fact] + public static void EncryptedData_LoadXml_WithAllElements() + { + string xml = @" + + + TestKey + + + AQIDBA== + + + + data + + + "; + + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + EncryptedData encData = new EncryptedData(); + encData.LoadXml(doc.DocumentElement); + + Assert.Equal("ed1", encData.Id); + Assert.Equal(EncryptedXml.XmlEncElementUrl, encData.Type); + Assert.Equal("text/xml", encData.MimeType); + Assert.Equal("UTF-8", encData.Encoding); + Assert.NotNull(encData.EncryptionMethod); + Assert.NotNull(encData.KeyInfo); + Assert.NotNull(encData.CipherData); + Assert.Equal(1, encData.EncryptionProperties.Count); + } + + [Fact] + public static void EncryptedKey_LoadXml_WithAllElements() + { + string xml = @" + + + WrapKey + + + AQIDBA== + + + + + SessionKey + "; + + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + EncryptedKey encKey = new EncryptedKey(); + encKey.LoadXml(doc.DocumentElement); + + Assert.Equal("ek1", encKey.Id); + Assert.Equal("user@example.com", encKey.Recipient); + Assert.Equal("SessionKey", encKey.CarriedKeyName); + Assert.NotNull(encKey.EncryptionMethod); + Assert.NotNull(encKey.KeyInfo); + Assert.NotNull(encKey.CipherData); + Assert.Equal(1, encKey.ReferenceList.Count); + } } } diff --git a/src/libraries/System.Security.Cryptography.Xml/tests/EncryptionPropertyTest.cs b/src/libraries/System.Security.Cryptography.Xml/tests/EncryptionPropertyTest.cs index 77328cb7b15cff..4c9e0fbdd58252 100644 --- a/src/libraries/System.Security.Cryptography.Xml/tests/EncryptionPropertyTest.cs +++ b/src/libraries/System.Security.Cryptography.Xml/tests/EncryptionPropertyTest.cs @@ -125,5 +125,100 @@ public void GetXml_Cached() XmlElement output = encryptionProperty.GetXml(); Assert.Equal(ValidXml, output.OuterXml); } + + [Fact] + public void GetXml_NoPropertyElement() + { + EncryptionProperty encryptionProperty = new EncryptionProperty(); + Assert.Throws(() => encryptionProperty.GetXml()); + } + + [Fact] + public void LoadXml_WithChildren() + { + string xml = @" + Some data + + "; + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + EncryptionProperty encryptionProperty = new EncryptionProperty(); + encryptionProperty.LoadXml(doc.DocumentElement); + Assert.Equal("prop1", encryptionProperty.Id); + Assert.Equal("#data1", encryptionProperty.Target); + Assert.NotNull(encryptionProperty.PropertyElement); + } + + [Fact] + public void Constructor_ReadProperties() + { + XmlDocument doc = new XmlDocument(); + doc.LoadXml(ValidXml); + + EncryptionProperty encryptionProperty = new EncryptionProperty(doc.DocumentElement); + // Properties are only populated via LoadXml, not constructor + Assert.NotNull(encryptionProperty.PropertyElement); + } + + [Fact] + public void Constructor_InvalidElement() + { + XmlDocument doc = new XmlDocument(); + doc.LoadXml(""); + + Assert.Throws(() => new EncryptionProperty(doc.DocumentElement)); + } + + [Fact] + public void Constructor_Null() + { + Assert.Throws(() => new EncryptionProperty(null)); + } + + [Fact] + public void LoadXml_NoIdOrTarget() + { + string xml = @" + content + "; + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + EncryptionProperty encryptionProperty = new EncryptionProperty(); + encryptionProperty.LoadXml(doc.DocumentElement); + Assert.Null(encryptionProperty.Id); + Assert.Null(encryptionProperty.Target); + } + + [Fact] + public void LoadXml_OnlyId() + { + string xml = @" + content + "; + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + EncryptionProperty encryptionProperty = new EncryptionProperty(); + encryptionProperty.LoadXml(doc.DocumentElement); + Assert.Equal("prop1", encryptionProperty.Id); + Assert.Null(encryptionProperty.Target); + } + + [Fact] + public void LoadXml_OnlyTarget() + { + string xml = @" + content + "; + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + EncryptionProperty encryptionProperty = new EncryptionProperty(); + encryptionProperty.LoadXml(doc.DocumentElement); + Assert.Null(encryptionProperty.Id); + Assert.Equal("#data1", encryptionProperty.Target); + } } } diff --git a/src/libraries/System.Security.Cryptography.Xml/tests/KeyInfoNameTest.cs b/src/libraries/System.Security.Cryptography.Xml/tests/KeyInfoNameTest.cs index 88a8694e568167..68ed2e0c97e91e 100644 --- a/src/libraries/System.Security.Cryptography.Xml/tests/KeyInfoNameTest.cs +++ b/src/libraries/System.Security.Cryptography.Xml/tests/KeyInfoNameTest.cs @@ -68,5 +68,45 @@ public void InvalidValue2() Assert.Equal("", name.Value); Assert.Equal("", (name.GetXml().OuterXml)); } + + [Fact] + public void Constructor() + { + KeyInfoName name = new KeyInfoName(); + Assert.Null(name.Value); + } + + [Fact] + public void Constructor_WithValue() + { + KeyInfoName name = new KeyInfoName("TestKeyName"); + Assert.Equal("TestKeyName", name.Value); + } + + [Fact] + public void Value_SetNull() + { + KeyInfoName name = new KeyInfoName("test"); + name.Value = null; + Assert.Null(name.Value); + } + + [Fact] + public void GetXml_NullValue() + { + KeyInfoName name = new KeyInfoName(); + XmlElement xml = name.GetXml(); + Assert.Equal("KeyName", xml.LocalName); + Assert.Equal(string.Empty, xml.InnerText); + } + + [Fact] + public void GetXml_EmptyValue() + { + KeyInfoName name = new KeyInfoName(""); + XmlElement xml = name.GetXml(); + Assert.Equal("KeyName", xml.LocalName); + Assert.Equal(string.Empty, xml.InnerText); + } } } diff --git a/src/libraries/System.Security.Cryptography.Xml/tests/KeyInfoNodeTest.cs b/src/libraries/System.Security.Cryptography.Xml/tests/KeyInfoNodeTest.cs index 741d0ad9b7a4d8..c258eb1c5c1bbd 100644 --- a/src/libraries/System.Security.Cryptography.Xml/tests/KeyInfoNodeTest.cs +++ b/src/libraries/System.Security.Cryptography.Xml/tests/KeyInfoNodeTest.cs @@ -62,5 +62,56 @@ public void InvalidKeyNode() node1.LoadXml(null); Assert.Null(node1.Value); } + + [Fact] + public void Constructor_Empty() + { + KeyInfoNode node = new KeyInfoNode(); + Assert.Null(node.Value); + } + + [Fact] + public void Constructor_WithElement() + { + XmlDocument doc = new XmlDocument(); + doc.LoadXml("data"); + + KeyInfoNode node = new KeyInfoNode(doc.DocumentElement); + Assert.NotNull(node.Value); + Assert.Equal("test", node.Value.LocalName); + } + + [Fact] + public void Value_SetNull() + { + KeyInfoNode node = new KeyInfoNode(); + XmlDocument doc = new XmlDocument(); + doc.LoadXml(""); + node.Value = doc.DocumentElement; + + node.Value = null; + Assert.Null(node.Value); + } + + [Fact] + public void GetXml_NullValue() + { + KeyInfoNode node = new KeyInfoNode(); + // Throws InvalidOperationException, not returns null + Assert.Throws(() => node.GetXml()); + } + + [Fact] + public void LoadXml_ValidElement() + { + string xml = "test"; + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + KeyInfoNode node = new KeyInfoNode(); + node.LoadXml(doc.DocumentElement); + Assert.NotNull(node.Value); + Assert.Equal("CustomElement", node.Value.LocalName); + } } } diff --git a/src/libraries/System.Security.Cryptography.Xml/tests/KeyInfoRetrievalMethodTest.cs b/src/libraries/System.Security.Cryptography.Xml/tests/KeyInfoRetrievalMethodTest.cs index a16525ecb4077b..66ca3dbbd03995 100644 --- a/src/libraries/System.Security.Cryptography.Xml/tests/KeyInfoRetrievalMethodTest.cs +++ b/src/libraries/System.Security.Cryptography.Xml/tests/KeyInfoRetrievalMethodTest.cs @@ -77,5 +77,57 @@ public void InvalidKeyNode2() uri1.LoadXml(doc.DocumentElement); AssertCrypto.AssertXmlEquals("invalid", "", (uri1.GetXml().OuterXml)); } + + [Fact] + public void Constructor_WithUri() + { + string uri = "#KeyInfo1"; + KeyInfoRetrievalMethod kirm = new KeyInfoRetrievalMethod(uri); + Assert.Equal(uri, kirm.Uri); + } + + [Fact] + public void Constructor_WithUriAndType() + { + string uri = "#KeyInfo1"; + string type = "http://www.w3.org/2000/09/xmldsig#KeyValue"; + KeyInfoRetrievalMethod kirm = new KeyInfoRetrievalMethod(uri, type); + Assert.Equal(uri, kirm.Uri); + Assert.Equal(type, kirm.Type); + } + + [Fact] + public void Properties() + { + KeyInfoRetrievalMethod kirm = new KeyInfoRetrievalMethod(); + + kirm.Uri = "#key"; + Assert.Equal("#key", kirm.Uri); + + kirm.Type = "http://www.w3.org/2000/09/xmldsig#KeyName"; + Assert.Equal("http://www.w3.org/2000/09/xmldsig#KeyName", kirm.Type); + } + + [Fact] + public void GetXml_WithType() + { + KeyInfoRetrievalMethod kirm = new KeyInfoRetrievalMethod("#key1", "http://www.w3.org/2000/09/xmldsig#KeyValue"); + XmlElement xml = kirm.GetXml(); + Assert.Contains("Type=", xml.OuterXml); + Assert.Contains("#key1", xml.OuterXml); + } + + [Fact] + public void LoadXml_WithType() + { + string xml = @""; + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + KeyInfoRetrievalMethod kirm = new KeyInfoRetrievalMethod(); + kirm.LoadXml(doc.DocumentElement); + Assert.Equal("#key1", kirm.Uri); + Assert.Equal("http://www.w3.org/2000/09/xmldsig#KeyValue", kirm.Type); + } } } diff --git a/src/libraries/System.Security.Cryptography.Xml/tests/KeyInfoTests.cs b/src/libraries/System.Security.Cryptography.Xml/tests/KeyInfoTests.cs index e390fcb21bc8d8..9f64ef3ba449d2 100644 --- a/src/libraries/System.Security.Cryptography.Xml/tests/KeyInfoTests.cs +++ b/src/libraries/System.Security.Cryptography.Xml/tests/KeyInfoTests.cs @@ -36,6 +36,82 @@ public void Constructor() public void AddClause() { KeyInfo keyInfo = new KeyInfo(); + Assert.Equal(0, keyInfo.Count); + + KeyInfoName name1 = new KeyInfoName("key1"); + keyInfo.AddClause(name1); + Assert.Equal(1, keyInfo.Count); + + KeyInfoName name2 = new KeyInfoName("key2"); + keyInfo.AddClause(name2); + Assert.Equal(2, keyInfo.Count); + } + + [Fact] + public void GetEnumerator() + { + KeyInfo keyInfo = new KeyInfo(); + keyInfo.AddClause(new KeyInfoName("key1")); + keyInfo.AddClause(new KeyInfoName("key2")); + + int count = 0; + IEnumerator enumerator = keyInfo.GetEnumerator(); + while (enumerator.MoveNext()) + { + Assert.NotNull(enumerator.Current); + count++; + } + Assert.Equal(2, count); + } + + [Fact] + public void GetXml_WithId() + { + KeyInfo keyInfo = new KeyInfo(); + keyInfo.Id = "KeyInfo-1"; + keyInfo.AddClause(new KeyInfoName("TestKey")); + + XmlElement xml = keyInfo.GetXml(); + Assert.Equal("KeyInfo-1", xml.GetAttribute("Id")); + } + + [Fact] + public void LoadXml() + { + string xml = @" + key1 + key2 + "; + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + KeyInfo keyInfo = new KeyInfo(); + keyInfo.LoadXml(doc.DocumentElement); + Assert.Equal("info1", keyInfo.Id); + Assert.Equal(2, keyInfo.Count); + } + + [Fact] + public void LoadXml_Null() + { + KeyInfo keyInfo = new KeyInfo(); + Assert.Throws(() => keyInfo.LoadXml(null)); + } + + [Fact] + public void GenericEnumerator() + { + KeyInfo keyInfo = new KeyInfo(); + keyInfo.AddClause(new KeyInfoName("key1")); + keyInfo.AddClause(new KeyInfoName("key2")); + + int count = 0; + foreach (KeyInfoClause clause in keyInfo) + { + Assert.NotNull(clause); + count++; + } + Assert.Equal(2, count); } } } diff --git a/src/libraries/System.Security.Cryptography.Xml/tests/KeyReferenceTest.cs b/src/libraries/System.Security.Cryptography.Xml/tests/KeyReferenceTest.cs new file mode 100644 index 00000000000000..a69d5867747f5d --- /dev/null +++ b/src/libraries/System.Security.Cryptography.Xml/tests/KeyReferenceTest.cs @@ -0,0 +1,85 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Xml; +using Xunit; + +namespace System.Security.Cryptography.Xml.Tests +{ + public class KeyReferenceTest + { + [Fact] + public void Constructor_Default() + { + KeyReference keyRef = new KeyReference(); + Assert.NotNull(keyRef); + } + + [Fact] + public void Constructor_WithUri() + { + string uri = "#EncryptedKey1"; + KeyReference keyRef = new KeyReference(uri); + Assert.Equal(uri, keyRef.Uri); + } + + [Fact] + public void Constructor_WithUriAndTransformChain() + { + string uri = "#EncryptedKey1"; + TransformChain tc = new TransformChain(); + tc.Add(new XmlDsigBase64Transform()); + + KeyReference keyRef = new KeyReference(uri, tc); + Assert.Equal(uri, keyRef.Uri); + Assert.NotNull(keyRef.TransformChain); + } + + [Fact] + public void GetXml_ReturnsValidXml() + { + KeyReference keyRef = new KeyReference("#key1"); + XmlElement element = keyRef.GetXml(); + Assert.NotNull(element); + Assert.Equal("KeyReference", element.LocalName); + } + + [Fact] + public void LoadXml_ValidXml() + { + string xml = @""; + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + KeyReference keyRef = new KeyReference(); + keyRef.LoadXml(doc.DocumentElement); + Assert.Equal("#key1", keyRef.Uri); + } + + [Fact] + public void LoadXml_WithTransforms() + { + string xml = @" + + + + "; + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + KeyReference keyRef = new KeyReference(); + keyRef.LoadXml(doc.DocumentElement); + Assert.Equal("#key1", keyRef.Uri); + Assert.NotNull(keyRef.TransformChain); + Assert.Equal(1, keyRef.TransformChain.Count); + } + + [Fact] + public void ReferenceType_IsKeyReference() + { + KeyReference keyRef = new KeyReference(); + XmlElement element = keyRef.GetXml(); + Assert.Equal("KeyReference", element.LocalName); + } + } +} diff --git a/src/libraries/System.Security.Cryptography.Xml/tests/ReferenceListTest.cs b/src/libraries/System.Security.Cryptography.Xml/tests/ReferenceListTest.cs new file mode 100644 index 00000000000000..f2b35cb4928435 --- /dev/null +++ b/src/libraries/System.Security.Cryptography.Xml/tests/ReferenceListTest.cs @@ -0,0 +1,70 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Xml; +using Xunit; + +namespace System.Security.Cryptography.Xml.Tests +{ + public class ReferenceListTests + { + [Fact] + public void Constructor_CreatesEmptyList() + { + ReferenceList refList = new ReferenceList(); + Assert.Equal(0, refList.Count); + } + + [Fact] + public void Add_DataReference() + { + ReferenceList refList = new ReferenceList(); + DataReference dataRef = new DataReference("#data1"); + refList.Add(dataRef); + Assert.Equal(1, refList.Count); + } + + [Fact] + public void Add_KeyReference() + { + ReferenceList refList = new ReferenceList(); + KeyReference keyRef = new KeyReference("#key1"); + refList.Add(keyRef); + Assert.Equal(1, refList.Count); + } + + [Fact] + public void GetEnumerator_ReturnsValidEnumerator() + { + ReferenceList refList = new ReferenceList(); + refList.Add(new DataReference("#data1")); + refList.Add(new KeyReference("#key1")); + + int count = 0; + foreach (var item in refList) + { + count++; + } + Assert.Equal(2, count); + } + + [Fact] + public void Item_ByIndex() + { + ReferenceList refList = new ReferenceList(); + DataReference dataRef = new DataReference("#data1"); + refList.Add(dataRef); + + object item = refList.Item(0); + Assert.NotNull(item); + } + + [Fact] + public void Item_InvalidIndex_ThrowsArgumentOutOfRangeException() + { + ReferenceList refList = new ReferenceList(); + Assert.Throws(() => refList.Item(-1)); + Assert.Throws(() => refList.Item(0)); + } + } +} diff --git a/src/libraries/System.Security.Cryptography.Xml/tests/ReferenceTest.cs b/src/libraries/System.Security.Cryptography.Xml/tests/ReferenceTest.cs index db65e8de538167..697a0b157e0f08 100644 --- a/src/libraries/System.Security.Cryptography.Xml/tests/ReferenceTest.cs +++ b/src/libraries/System.Security.Cryptography.Xml/tests/ReferenceTest.cs @@ -288,5 +288,208 @@ public void KeepDocument() Assert.Equal(org, el); Assert.Equal(result, el.OuterXml); } + + [Fact] + public void LoadXml_Null() + { + Reference r = new Reference(); + Assert.Throws(() => r.LoadXml(null)); + } + + [Fact] + public void LoadXml_MissingDigestMethod() + { + string xml = @" + /Vvq6sXEVbtZC8GwNtLQnGOy/VI= + "; + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + Reference r = new Reference(); + Assert.Throws(() => r.LoadXml(doc.DocumentElement)); + } + + [Fact] + public void LoadXml_MissingDigestValue() + { + string xml = @" + + "; + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + Reference r = new Reference(); + Assert.Throws(() => r.LoadXml(doc.DocumentElement)); + } + + [Fact] + public void AddTransform_Null() + { + Reference r = new Reference(); + Assert.Throws(() => r.AddTransform(null)); + } + + [Fact] + public void DigestValue_Null() + { + Reference r = new Reference(); + r.DigestValue = null; + Assert.Null(r.DigestValue); + } + + [Fact] + public void GetXml_NoDigestMethod() + { + Reference r = new Reference(); + r.DigestValue = new byte[32]; + // Actually doesn't throw - just returns element without DigestMethod + XmlElement xml = r.GetXml(); + Assert.NotNull(xml); + } + + [Fact] + public void GetXml_NoDigestValue() + { + Reference r = new Reference(); + r.DigestMethod = SignedXml.XmlDsigSHA256Url; + Assert.Throws(() => r.GetXml()); + } + + [Fact] + public void Properties() + { + Reference r = new Reference(); + + r.Id = "ref1"; + Assert.Equal("ref1", r.Id); + + r.Type = "http://www.w3.org/2000/09/xmldsig#Object"; + Assert.Equal("http://www.w3.org/2000/09/xmldsig#Object", r.Type); + + r.Uri = "#obj1"; + Assert.Equal("#obj1", r.Uri); + + Assert.NotNull(r.TransformChain); + } + + [Fact] + public void Reference_TypeProperty() + { + Reference r = new Reference(); + + r.Type = null; + Assert.Null(r.Type); + + r.Type = "http://www.w3.org/2000/09/xmldsig#Object"; + Assert.Equal("http://www.w3.org/2000/09/xmldsig#Object", r.Type); + + r.Type = ""; + Assert.Equal("", r.Type); + } + + [Fact] + public void Reference_IdProperty() + { + Reference r = new Reference(); + + r.Id = null; + Assert.Null(r.Id); + + r.Id = "ref-id"; + Assert.Equal("ref-id", r.Id); + + r.Id = ""; + Assert.Equal("", r.Id); + } + + [Fact] + public void Reference_UriProperty() + { + Reference r = new Reference(); + + r.Uri = null; + Assert.Null(r.Uri); + + r.Uri = ""; + Assert.Equal("", r.Uri); + + r.Uri = "#id"; + Assert.Equal("#id", r.Uri); + } + + [Fact] + public void Reference_DigestMethodProperty() + { + Reference r = new Reference(); + + r.DigestMethod = SignedXml.XmlDsigSHA256Url; + Assert.Equal(SignedXml.XmlDsigSHA256Url, r.DigestMethod); + + r.DigestMethod = SignedXml.XmlDsigSHA512Url; + Assert.Equal(SignedXml.XmlDsigSHA512Url, r.DigestMethod); + + r.DigestMethod = null; + Assert.Null(r.DigestMethod); + } + + [Fact] + public void Reference_LoadXml_WithId() + { + string xml = @" + + AAAA + "; + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + Reference r = new Reference(); + r.LoadXml(doc.DocumentElement); + Assert.Equal("ref1", r.Id); + } + + [Fact] + public void Reference_LoadXml_WithType() + { + string xml = @" + + AAAA + "; + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + Reference r = new Reference(); + r.LoadXml(doc.DocumentElement); + Assert.Equal("http://www.w3.org/2000/09/xmldsig#Object", r.Type); + } + + [Fact] + public void Reference_LoadXml_EmptyUri() + { + string xml = @" + + AAAA + "; + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + Reference r = new Reference(); + r.LoadXml(doc.DocumentElement); + Assert.Equal("", r.Uri); + } + + [Fact] + public void Reference_LoadXml_NoUri() + { + string xml = @" + + AAAA + "; + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + Reference r = new Reference(); + r.LoadXml(doc.DocumentElement); + Assert.Null(r.Uri); // No URI attribute means null + } } } diff --git a/src/libraries/System.Security.Cryptography.Xml/tests/SignatureTest.cs b/src/libraries/System.Security.Cryptography.Xml/tests/SignatureTest.cs index 06b52ee4987522..e44701ac57eb03 100644 --- a/src/libraries/System.Security.Cryptography.Xml/tests/SignatureTest.cs +++ b/src/libraries/System.Security.Cryptography.Xml/tests/SignatureTest.cs @@ -70,5 +70,222 @@ public void LoadXmlMalformed2() doc.LoadXml(""); Assert.Throws(() => s.LoadXml(doc.DocumentElement)); } + + [Fact] + public void SignatureProperties() + { + Signature sig = new Signature(); + Assert.Null(sig.Id); + Assert.NotNull(sig.ObjectList); + Assert.Equal(0, sig.ObjectList.Count); + Assert.NotNull(sig.KeyInfo); // Auto-initialized + Assert.Equal(0, sig.KeyInfo.Count); + Assert.Null(sig.SignatureValue); + Assert.Null(sig.SignedInfo); + } + + [Fact] + public void SignatureIdProperty() + { + Signature sig = new Signature(); + sig.Id = "sig-id"; + Assert.Equal("sig-id", sig.Id); + } + + [Fact] + public void SignatureWithKeyInfo() + { + Signature sig = new Signature(); + sig.SignedInfo = new SignedInfo(); + sig.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigC14NTransformUrl; + sig.SignedInfo.SignatureMethod = SignedXml.XmlDsigRSASHA256Url; + + // Add a reference (required for GetXml) + Reference reference = new Reference(); + reference.DigestMethod = SignedXml.XmlDsigSHA256Url; + reference.DigestValue = new byte[] { 1, 2, 3, 4 }; + sig.SignedInfo.AddReference(reference); + + sig.SignatureValue = new byte[] { 1, 2, 3, 4 }; + sig.KeyInfo.AddClause(new KeyInfoName("TestKey")); + + XmlElement xml = sig.GetXml(); + Assert.NotNull(xml); + Assert.Equal("Signature", xml.LocalName); + } + + [Fact] + public void SignatureWithObjects() + { + Signature sig = new Signature(); + sig.SignedInfo = new SignedInfo(); + sig.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigC14NTransformUrl; + sig.SignedInfo.SignatureMethod = SignedXml.XmlDsigRSASHA256Url; + + // Add a reference (required for GetXml) + Reference reference = new Reference(); + reference.DigestMethod = SignedXml.XmlDsigSHA256Url; + reference.DigestValue = new byte[] { 1, 2, 3, 4 }; + sig.SignedInfo.AddReference(reference); + + sig.SignatureValue = new byte[] { 1, 2, 3, 4 }; + + DataObject obj1 = new DataObject(); + obj1.Id = "obj1"; + sig.AddObject(obj1); + + DataObject obj2 = new DataObject(); + obj2.Id = "obj2"; + sig.AddObject(obj2); + + Assert.Equal(2, sig.ObjectList.Count); + XmlElement xml = sig.GetXml(); + Assert.NotNull(xml); + } + + [Fact] + public void SignatureLoadXmlWithId() + { + string xml = @" + + + + + AQIDBA== + "; + + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + Signature sig = new Signature(); + sig.LoadXml(doc.DocumentElement); + Assert.Equal("sig1", sig.Id); + } + + [Fact] + public void SignatureLoadXmlWithKeyInfo() + { + string xml = @" + + + + + AQIDBA== + + MyKey + + "; + + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + Signature sig = new Signature(); + sig.LoadXml(doc.DocumentElement); + Assert.NotNull(sig.KeyInfo); + Assert.Equal(1, sig.KeyInfo.Count); + } + + [Fact] + public void SignatureLoadXmlWithObjects() + { + string xml = @" + + + + + AQIDBA== + data + data2 + "; + + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + Signature sig = new Signature(); + sig.LoadXml(doc.DocumentElement); + Assert.Equal(2, sig.ObjectList.Count); + } + + [Fact] + public void Signature_AddObject() + { + Signature sig = new Signature(); + DataObject obj = new DataObject(); + obj.Id = "obj1"; + + sig.AddObject(obj); + Assert.Equal(1, sig.ObjectList.Count); + Assert.Same(obj, sig.ObjectList[0]); + } + + [Fact] + public void Signature_ObjectList_NotNull() + { + Signature sig = new Signature(); + Assert.NotNull(sig.ObjectList); + Assert.Equal(0, sig.ObjectList.Count); + } + + [Fact] + public void Signature_LoadXml_Null() + { + Signature sig = new Signature(); + Assert.Throws(() => sig.LoadXml(null)); + } + + [Fact] + public void Signature_GetXml_SignatureValueNull() + { + Signature sig = new Signature(); + sig.SignedInfo = new SignedInfo(); + sig.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigC14NTransformUrl; + sig.SignedInfo.SignatureMethod = SignedXml.XmlDsigRSASHA256Url; + Reference r = new Reference(); + r.DigestMethod = SignedXml.XmlDsigSHA256Url; + r.DigestValue = new byte[32]; + sig.SignedInfo.AddReference(r); + + Assert.Throws(() => sig.GetXml()); + } + + [Fact] + public void Signature_LoadXml_EmptySignature() + { + string xml = @""; + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + Signature sig = new Signature(); + Assert.Throws(() => sig.LoadXml(doc.DocumentElement)); + } + + [Fact] + public void Signature_LoadXml_MissingSignedInfo() + { + string xml = @" + AQIDBA== + "; + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + Signature sig = new Signature(); + Assert.Throws(() => sig.LoadXml(doc.DocumentElement)); + } + + [Fact] + public void Signature_LoadXml_MissingSignatureValue() + { + string xml = @" + + + + + "; + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + Signature sig = new Signature(); + Assert.Throws(() => sig.LoadXml(doc.DocumentElement)); + } } } diff --git a/src/libraries/System.Security.Cryptography.Xml/tests/SignedInfoTest.cs b/src/libraries/System.Security.Cryptography.Xml/tests/SignedInfoTest.cs index 731064784de47a..df206454259dce 100644 --- a/src/libraries/System.Security.Cryptography.Xml/tests/SignedInfoTest.cs +++ b/src/libraries/System.Security.Cryptography.Xml/tests/SignedInfoTest.cs @@ -185,5 +185,66 @@ public void SignatureLength() Assert.Equal("http://www.w3.org/2000/09/xmldsig#rsa-sha1", si.SignatureLength); Assert.Equal("0", si.SignatureMethod); } + + [Fact] + public void LoadXml_Null() + { + SignedInfo si = new SignedInfo(); + Assert.Throws(() => si.LoadXml(null)); + } + + [Fact] + public void LoadXml_MissingCanonicalizationMethod() + { + string xml = @" + + "; + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + SignedInfo si = new SignedInfo(); + Assert.Throws(() => si.LoadXml(doc.DocumentElement)); + } + + [Fact] + public void LoadXml_MissingSignatureMethod() + { + string xml = @" + + "; + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + SignedInfo si = new SignedInfo(); + Assert.Throws(() => si.LoadXml(doc.DocumentElement)); + } + + [Fact] + public void AddReference_Null() + { + SignedInfo si = new SignedInfo(); + Assert.Throws(() => si.AddReference(null)); + } + + [Fact] + public void GetXml_NoSignatureMethod() + { + SignedInfo si = new SignedInfo(); + si.CanonicalizationMethod = SignedXml.XmlDsigC14NTransformUrl; + Reference r = new Reference(); + r.DigestMethod = SignedXml.XmlDsigSHA256Url; + r.DigestValue = new byte[32]; + si.AddReference(r); + Assert.Throws(() => si.GetXml()); + } + + [Fact] + public void GetXml_NoReferences() + { + SignedInfo si = new SignedInfo(); + si.CanonicalizationMethod = SignedXml.XmlDsigC14NTransformUrl; + si.SignatureMethod = SignedXml.XmlDsigRSASHA256Url; + Assert.Throws(() => si.GetXml()); + } } } diff --git a/src/libraries/System.Security.Cryptography.Xml/tests/SignedXmlTests.cs b/src/libraries/System.Security.Cryptography.Xml/tests/SignedXmlTests.cs index cafa5095a6c158..6a51635c5153c6 100644 --- a/src/libraries/System.Security.Cryptography.Xml/tests/SignedXmlTests.cs +++ b/src/libraries/System.Security.Cryptography.Xml/tests/SignedXmlTests.cs @@ -53,5 +53,294 @@ public void Constructor_NoArgs() Assert.Null(signedXml.SignatureMethod); Assert.Null(signedXml.SignatureValue); } + [Fact] + public void GetIdElement_MultipleIdAttributes() + { + string xml = @" + Content + "; + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + SignedXml signedXml = new SignedXml(doc); + XmlElement result = signedXml.GetIdElement(doc, "test1"); + Assert.NotNull(result); + } + + [Fact] + public void GetIdElement_NestedElements() + { + string xml = @" + + + Content + + + "; + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + SignedXml signedXml = new SignedXml(doc); + XmlElement result1 = signedXml.GetIdElement(doc, "nested1"); + Assert.NotNull(result1); + Assert.Equal("child", result1.LocalName); + + XmlElement result2 = signedXml.GetIdElement(doc, "nested2"); + Assert.NotNull(result2); + Assert.Equal("grandchild", result2.LocalName); + } + + [Fact] + public void GetIdElement_WithNamespace() + { + string xml = @" + Content + "; + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + SignedXml signedXml = new SignedXml(doc); + XmlElement result = signedXml.GetIdElement(doc, "ns-id"); + // May or may not find it depending on ID attribute handling + // Just ensuring it doesn't crash + } + + [Fact] + public void GetIdElement_NotFound() + { + string xml = @"Content"; + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + SignedXml signedXml = new SignedXml(doc); + XmlElement result = signedXml.GetIdElement(doc, "nonexistent"); + Assert.Null(result); + } + + [Fact] + public void SignedXml_MultipleReferences_DifferentTypes() + { + XmlDocument doc = new XmlDocument(); + doc.LoadXml(@" + First + Second + Third + "); + + using (RSA rsa = RSA.Create()) + { + SignedXml signedXml = new SignedXml(doc); + signedXml.SigningKey = rsa; + + // Add multiple references with different URIs + Reference ref1 = new Reference("#obj1"); + ref1.AddTransform(new XmlDsigC14NTransform()); + signedXml.AddReference(ref1); + + Reference ref2 = new Reference("#obj2"); + ref2.AddTransform(new XmlDsigC14NTransform()); + signedXml.AddReference(ref2); + + Reference ref3 = new Reference("#obj3"); + ref3.AddTransform(new XmlDsigC14NTransform()); + signedXml.AddReference(ref3); + + signedXml.ComputeSignature(); + + XmlElement sig = signedXml.GetXml(); + Assert.NotNull(sig); + + // Verify it has 3 references + XmlNodeList refs = sig.SelectNodes("//*[local-name()='Reference']"); + Assert.Equal(3, refs.Count); + } + } + + [Fact] + public void SignedXml_ReferenceWithMultipleTransforms() + { + XmlDocument doc = new XmlDocument(); + doc.LoadXml("Test"); + + using (RSA rsa = RSA.Create()) + { + SignedXml signedXml = new SignedXml(doc); + signedXml.SigningKey = rsa; + + Reference reference = new Reference("#data"); + reference.AddTransform(new XmlDsigEnvelopedSignatureTransform()); + reference.AddTransform(new XmlDsigC14NTransform()); + reference.AddTransform(new XmlDsigC14NWithCommentsTransform()); + + signedXml.AddReference(reference); + signedXml.ComputeSignature(); + + XmlElement sig = signedXml.GetXml(); + XmlNodeList transforms = sig.SelectNodes("//*[local-name()='Transform']"); + Assert.Equal(3, transforms.Count); + } + } + + [Fact] + public void SignedXml_AddObject_Multiple() + { + SignedXml signedXml = new SignedXml(); + + DataObject obj1 = new DataObject("obj1", "text/plain", "UTF-8", new XmlDocument().CreateElement("data1")); + signedXml.AddObject(obj1); + + DataObject obj2 = new DataObject("obj2", "text/xml", null, new XmlDocument().CreateElement("data2")); + signedXml.AddObject(obj2); + + DataObject obj3 = new DataObject("obj3", null, null, new XmlDocument().CreateElement("data3")); + signedXml.AddObject(obj3); + + Assert.Equal(3, signedXml.Signature.ObjectList.Count); + } + + [Fact] + public void SignedXml_EmptyUriReference() + { + XmlDocument doc = new XmlDocument(); + doc.LoadXml("content"); + + using (RSA rsa = RSA.Create()) + { + SignedXml signedXml = new SignedXml(doc); + signedXml.SigningKey = rsa; + + // Empty URI means sign entire document + Reference reference = new Reference(""); + reference.AddTransform(new XmlDsigEnvelopedSignatureTransform()); + signedXml.AddReference(reference); + + signedXml.ComputeSignature(); + Assert.NotNull(signedXml.SignatureValue); + } + } + + [Fact] + public void SignedXml_SignWithDataObject() + { + XmlDocument doc = new XmlDocument(); + doc.LoadXml(""); + + using (RSA rsa = RSA.Create()) + { + SignedXml signedXml = new SignedXml(); + signedXml.SigningKey = rsa; + + // Create a data object + XmlDocument dataDoc = new XmlDocument(); + XmlElement dataElem = dataDoc.CreateElement("MyData"); + dataElem.InnerText = "Secret Information"; + DataObject dataObject = new DataObject("data-id", null, null, dataElem); + signedXml.AddObject(dataObject); + + // Reference the data object + Reference reference = new Reference("#data-id"); + reference.Type = "http://www.w3.org/2000/09/xmldsig#Object"; + signedXml.AddReference(reference); + + signedXml.ComputeSignature(); + + XmlElement signature = signedXml.GetXml(); + Assert.NotNull(signature); + + // Verify the Object is in the signature + XmlNode objectNode = signature.SelectSingleNode("//*[local-name()='Object']"); + Assert.NotNull(objectNode); + } + } + + [Fact] + public void CheckSignature_NoKeyInfo() + { + SignedXml signedXml = new SignedXml(); + // No key info, no signature + bool result = signedXml.CheckSignature(); + Assert.False(result); + } + + [Fact] + public void CheckSignature_EmptyKeyInfo() + { + SignedXml signedXml = new SignedXml(); + signedXml.KeyInfo = new KeyInfo(); + // Empty key info + bool result = signedXml.CheckSignature(); + Assert.False(result); + } + + [Fact] + public void SignedXml_ReferenceWithId() + { + XmlDocument doc = new XmlDocument(); + doc.LoadXml("content"); + + using (RSA rsa = RSA.Create()) + { + SignedXml signedXml = new SignedXml(doc); + signedXml.SigningKey = rsa; + + Reference reference = new Reference("#root-id"); + reference.Id = "ref-1"; + reference.Type = "http://www.w3.org/2000/09/xmldsig#Object"; + reference.AddTransform(new XmlDsigC14NTransform()); + + signedXml.AddReference(reference); + signedXml.ComputeSignature(); + + XmlElement sig = signedXml.GetXml(); + XmlNode refNode = sig.SelectSingleNode("//*[local-name()='Reference']"); + Assert.Equal("ref-1", ((XmlElement)refNode).GetAttribute("Id")); + } + } + + [Fact] + public void SignedXml_SignatureWithId() + { + XmlDocument doc = new XmlDocument(); + doc.LoadXml(""); + + using (RSA rsa = RSA.Create()) + { + SignedXml signedXml = new SignedXml(doc); + signedXml.SigningKey = rsa; + + Reference reference = new Reference(""); + reference.AddTransform(new XmlDsigEnvelopedSignatureTransform()); + signedXml.AddReference(reference); + + signedXml.Signature.Id = "signature-1"; + signedXml.ComputeSignature(); + + XmlElement sig = signedXml.GetXml(); + Assert.Equal("signature-1", sig.GetAttribute("Id")); + } + } + + [Fact] + public void SignedXml_DifferentDigestMethods() + { + XmlDocument doc = new XmlDocument(); + doc.LoadXml("Test"); + + using (RSA rsa = RSA.Create()) + { + SignedXml signedXml = new SignedXml(doc); + signedXml.SigningKey = rsa; + + Reference ref1 = new Reference("#data"); + ref1.DigestMethod = SignedXml.XmlDsigSHA256Url; + signedXml.AddReference(ref1); + + signedXml.ComputeSignature(); + + XmlElement sig = signedXml.GetXml(); + XmlNode digestMethod = sig.SelectSingleNode("//*[local-name()='DigestMethod']"); + Assert.Contains("sha256", digestMethod.Attributes["Algorithm"].Value); + } + } } } diff --git a/src/libraries/System.Security.Cryptography.Xml/tests/System.Security.Cryptography.Xml.Tests.csproj b/src/libraries/System.Security.Cryptography.Xml/tests/System.Security.Cryptography.Xml.Tests.csproj index e384759699b1e6..76da856a6bb170 100644 --- a/src/libraries/System.Security.Cryptography.Xml/tests/System.Security.Cryptography.Xml.Tests.csproj +++ b/src/libraries/System.Security.Cryptography.Xml/tests/System.Security.Cryptography.Xml.Tests.csproj @@ -10,6 +10,7 @@ + diff --git a/src/libraries/System.Security.Cryptography.Xml/tests/TransformChainTest.cs b/src/libraries/System.Security.Cryptography.Xml/tests/TransformChainTest.cs index 498c8807a03ab5..0b19fe229a8f8c 100644 --- a/src/libraries/System.Security.Cryptography.Xml/tests/TransformChainTest.cs +++ b/src/libraries/System.Security.Cryptography.Xml/tests/TransformChainTest.cs @@ -60,5 +60,21 @@ public void FullChain() Assert.Equal(xslt, chain[5]); Assert.Equal(6, chain.Count); } + + [Fact] + public void Enumerator() + { + TransformChain chain = new TransformChain(); + chain.Add(new XmlDsigBase64Transform()); + chain.Add(new XmlDsigC14NTransform()); + + int count = 0; + foreach (Transform transform in chain) + { + Assert.NotNull(transform); + count++; + } + Assert.Equal(2, count); + } } }