diff --git a/src/libraries/System.Security.Cryptography.Xml/tests/AdditionalCoverageTests.cs b/src/libraries/System.Security.Cryptography.Xml/tests/AdditionalCoverageTests.cs new file mode 100644 index 00000000000000..d4e2cce274f78e --- /dev/null +++ b/src/libraries/System.Security.Cryptography.Xml/tests/AdditionalCoverageTests.cs @@ -0,0 +1,400 @@ +// 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 EncryptedDataCoverageTests + { + [Fact] + public void EncryptedData_GetXml() + { + EncryptedData encryptedData = new EncryptedData(); + encryptedData.Id = "ED1"; + encryptedData.Type = EncryptedXml.XmlEncElementUrl; + encryptedData.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncAES256Url); + encryptedData.CipherData = new CipherData(new byte[] { 1, 2, 3, 4 }); + + XmlElement element = encryptedData.GetXml(); + Assert.NotNull(element); + Assert.Equal("EncryptedData", element.LocalName); + Assert.Equal("ED1", element.GetAttribute("Id")); + } + + [Fact] + public void EncryptedData_CipherDataWithValue() + { + EncryptedData encryptedData = new EncryptedData(); + encryptedData.CipherData = new CipherData(new byte[] { 1, 2, 3, 4 }); + + XmlElement element = encryptedData.GetXml(); + Assert.NotNull(element); + Assert.Contains("CipherData", element.OuterXml); + } + + [Fact] + public void EncryptedData_WithKeyInfo() + { + EncryptedData encryptedData = new EncryptedData(); + encryptedData.KeyInfo = new KeyInfo(); + encryptedData.KeyInfo.AddClause(new KeyInfoName("MyKey")); + encryptedData.CipherData = new CipherData(new byte[] { 1, 2, 3 }); + + XmlElement element = encryptedData.GetXml(); + Assert.Contains("KeyInfo", element.OuterXml); + Assert.Contains("KeyName", element.OuterXml); + } + } + + public class EncryptedKeyCoverageTests + { + [Fact] + public void EncryptedKey_Constructor() + { + EncryptedKey encryptedKey = new EncryptedKey(); + Assert.NotNull(encryptedKey); + } + + [Fact] + public void EncryptedKey_WithCarriedKeyName() + { + EncryptedKey encryptedKey = new EncryptedKey(); + encryptedKey.CarriedKeyName = "MyCarriedKey"; + encryptedKey.CipherData = new CipherData(new byte[] { 1, 2, 3, 4, 5 }); + + XmlElement element = encryptedKey.GetXml(); + Assert.Contains("CarriedKeyName", element.OuterXml); + Assert.Contains("MyCarriedKey", element.OuterXml); + } + + [Fact] + public void EncryptedKey_AddReference() + { + EncryptedKey encryptedKey = new EncryptedKey(); + encryptedKey.CipherData = new CipherData(new byte[] { 1, 2, 3 }); + + DataReference dataRef = new DataReference("#data1"); + encryptedKey.AddReference(dataRef); + + XmlElement element = encryptedKey.GetXml(); + Assert.Contains("ReferenceList", element.OuterXml); + Assert.Contains("DataReference", element.OuterXml); + } + + [Fact] + public void EncryptedKey_WithRecipient() + { + EncryptedKey encryptedKey = new EncryptedKey(); + encryptedKey.Recipient = "recipient@example.com"; + encryptedKey.CipherData = new CipherData(new byte[] { 1, 2, 3 }); + + XmlElement element = encryptedKey.GetXml(); + Assert.Contains("recipient@example.com", element.OuterXml); + } + } + + public class KeyInfoEncryptedKeyCoverageTests + { + [Fact] + public void KeyInfoEncryptedKey_Constructor() + { + EncryptedKey encryptedKey = new EncryptedKey(); + encryptedKey.CipherData = new CipherData(new byte[] { 1, 2, 3 }); + + KeyInfoEncryptedKey keyInfoEncryptedKey = new KeyInfoEncryptedKey(encryptedKey); + Assert.NotNull(keyInfoEncryptedKey); + Assert.Equal(encryptedKey, keyInfoEncryptedKey.EncryptedKey); + } + + [Fact] + public void KeyInfoEncryptedKey_GetXml() + { + EncryptedKey encryptedKey = new EncryptedKey(); + encryptedKey.Id = "EK1"; + encryptedKey.CipherData = new CipherData(new byte[] { 1, 2, 3 }); + + KeyInfoEncryptedKey keyInfoEncryptedKey = new KeyInfoEncryptedKey(encryptedKey); + XmlElement element = keyInfoEncryptedKey.GetXml(); + + Assert.NotNull(element); + Assert.Equal("EncryptedKey", element.LocalName); + Assert.Contains("EK1", element.OuterXml); + } + + [Fact] + public void KeyInfoEncryptedKey_LoadXml() + { + string xml = @" + AQIDBA== + "; + + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + KeyInfoEncryptedKey keyInfoEncryptedKey = new KeyInfoEncryptedKey(); + keyInfoEncryptedKey.LoadXml(doc.DocumentElement); + + Assert.NotNull(keyInfoEncryptedKey.EncryptedKey); + Assert.Equal("EK1", keyInfoEncryptedKey.EncryptedKey.Id); + } + } + + public class EncryptionPropertyCollectionCoverageTests + { + [Fact] + public void EncryptionPropertyCollection_ItemGet() + { + EncryptionPropertyCollection collection = new EncryptionPropertyCollection(); + EncryptionProperty prop1 = new EncryptionProperty(); + + collection.Add(prop1); + + EncryptionProperty retrieved = collection.Item(0); + Assert.Equal(prop1, retrieved); + } + + [Fact] + public void EncryptionPropertyCollection_IndexerGet() + { + EncryptionPropertyCollection collection = new EncryptionPropertyCollection(); + EncryptionProperty prop1 = new EncryptionProperty(); + + collection.Add(prop1); + + EncryptionProperty retrieved = collection[0]; + Assert.Equal(prop1, retrieved); + } + + [Fact] + public void EncryptionPropertyCollection_AddMultiple() + { + EncryptionPropertyCollection collection = new EncryptionPropertyCollection(); + EncryptionProperty prop1 = new EncryptionProperty(); + EncryptionProperty prop2 = new EncryptionProperty(); + + int index1 = collection.Add(prop1); + int index2 = collection.Add(prop2); + + Assert.Equal(0, index1); + Assert.Equal(1, index2); + Assert.Equal(2, collection.Count); + } + + [Fact] + public void EncryptionPropertyCollection_Remove() + { + EncryptionPropertyCollection collection = new EncryptionPropertyCollection(); + EncryptionProperty prop1 = new EncryptionProperty(); + + collection.Add(prop1); + collection.Remove(prop1); + + Assert.Equal(0, collection.Count); + } + + [Fact] + public void EncryptionPropertyCollection_Clear() + { + EncryptionPropertyCollection collection = new EncryptionPropertyCollection(); + collection.Add(new EncryptionProperty()); + collection.Add(new EncryptionProperty()); + + collection.Clear(); + Assert.Equal(0, collection.Count); + } + + [Fact] + public void EncryptionPropertyCollection_Insert() + { + EncryptionPropertyCollection collection = new EncryptionPropertyCollection(); + EncryptionProperty prop1 = new EncryptionProperty(); + EncryptionProperty prop2 = new EncryptionProperty(); + EncryptionProperty prop3 = new EncryptionProperty(); + + collection.Add(prop1); + collection.Add(prop3); + collection.Insert(1, prop2); + + Assert.Equal(3, collection.Count); + Assert.Equal(prop2, collection[1]); + } + + [Fact] + public void EncryptionPropertyCollection_Contains() + { + EncryptionPropertyCollection collection = new EncryptionPropertyCollection(); + EncryptionProperty prop1 = new EncryptionProperty(); + + collection.Add(prop1); + + Assert.True(collection.Contains(prop1)); + } + + [Fact] + public void EncryptionPropertyCollection_IndexOf() + { + EncryptionPropertyCollection collection = new EncryptionPropertyCollection(); + EncryptionProperty prop1 = new EncryptionProperty(); + EncryptionProperty prop2 = new EncryptionProperty(); + + collection.Add(prop1); + collection.Add(prop2); + + Assert.Equal(0, collection.IndexOf(prop1)); + Assert.Equal(1, collection.IndexOf(prop2)); + } + + [Fact] + public void EncryptionPropertyCollection_RemoveAt() + { + EncryptionPropertyCollection collection = new EncryptionPropertyCollection(); + EncryptionProperty prop1 = new EncryptionProperty(); + EncryptionProperty prop2 = new EncryptionProperty(); + + collection.Add(prop1); + collection.Add(prop2); + collection.RemoveAt(0); + + Assert.Equal(1, collection.Count); + Assert.Equal(prop2, collection[0]); + } + + [Fact] + public void EncryptionPropertyCollection_CopyTo() + { + EncryptionPropertyCollection collection = new EncryptionPropertyCollection(); + EncryptionProperty prop1 = new EncryptionProperty(); + EncryptionProperty prop2 = new EncryptionProperty(); + + collection.Add(prop1); + collection.Add(prop2); + + EncryptionProperty[] array = new EncryptionProperty[2]; + collection.CopyTo(array, 0); + + Assert.Equal(prop1, array[0]); + Assert.Equal(prop2, array[1]); + } + + [Fact] + public void EncryptionPropertyCollection_GetEnumerator() + { + EncryptionPropertyCollection collection = new EncryptionPropertyCollection(); + collection.Add(new EncryptionProperty()); + collection.Add(new EncryptionProperty()); + + int count = 0; + foreach (EncryptionProperty prop in collection) + { + Assert.NotNull(prop); + count++; + } + Assert.Equal(2, count); + } + } + + public class KeyInfoRetrievalMethodCoverageTests + { + [Fact] + public void KeyInfoRetrievalMethod_ConstructorWithUri() + { + string uri = "#KeyValue"; + KeyInfoRetrievalMethod retrievalMethod = new KeyInfoRetrievalMethod(uri); + Assert.Equal(uri, retrievalMethod.Uri); + } + + [Fact] + public void KeyInfoRetrievalMethod_ConstructorWithUriAndType() + { + string uri = "#KeyValue"; + string type = "http://www.w3.org/2001/04/xmlenc#EncryptedKey"; + KeyInfoRetrievalMethod retrievalMethod = new KeyInfoRetrievalMethod(uri, type); + + Assert.Equal(uri, retrievalMethod.Uri); + Assert.Equal(type, retrievalMethod.Type); + } + + [Fact] + public void KeyInfoRetrievalMethod_GetXml() + { + KeyInfoRetrievalMethod retrievalMethod = new KeyInfoRetrievalMethod("#KeyValue"); + XmlElement element = retrievalMethod.GetXml(); + + Assert.NotNull(element); + Assert.Equal("RetrievalMethod", element.LocalName); + } + + [Fact] + public void KeyInfoRetrievalMethod_LoadXml() + { + string xml = @""; + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + KeyInfoRetrievalMethod retrievalMethod = new KeyInfoRetrievalMethod(); + retrievalMethod.LoadXml(doc.DocumentElement); + + Assert.Equal("#KeyValue", retrievalMethod.Uri); + } + } + + public class XmlDsigExcC14NTransformCoverageTests + { + [Fact] + public void XmlDsigExcC14NTransform_ConstructorWithComments() + { + XmlDsigExcC14NTransform transform = new XmlDsigExcC14NTransform(true); + Assert.Equal("http://www.w3.org/2001/10/xml-exc-c14n#WithComments", transform.Algorithm); + } + + [Fact] + public void XmlDsigExcC14NTransform_ConstructorWithoutComments() + { + XmlDsigExcC14NTransform transform = new XmlDsigExcC14NTransform(false); + Assert.Equal("http://www.w3.org/2001/10/xml-exc-c14n#", transform.Algorithm); + } + + [Fact] + public void XmlDsigExcC14NTransform_ConstructorWithInclusiveNamespaces() + { + XmlDsigExcC14NTransform transform = new XmlDsigExcC14NTransform(false, "ds xsi"); + Assert.Equal("ds xsi", transform.InclusiveNamespacesPrefixList); + } + + [Fact] + public void XmlDsigExcC14NTransform_LoadInput() + { + string xml = @"data"; + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + XmlDsigExcC14NTransform transform = new XmlDsigExcC14NTransform(); + transform.LoadInput(doc); + + object output = transform.GetOutput(); + Assert.NotNull(output); + } + + [Fact] + public void XmlDsigExcC14NTransform_GetDigestedOutput() + { + string xml = @"data"; + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + XmlDsigExcC14NTransform transform = new XmlDsigExcC14NTransform(); + transform.LoadInput(doc); + + using (SHA256 hash = SHA256.Create()) + { + byte[] digest = transform.GetDigestedOutput(hash); + Assert.NotNull(digest); + Assert.Equal(32, digest.Length); + } + } + } +} 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/CoverageImprovementTests.cs b/src/libraries/System.Security.Cryptography.Xml/tests/CoverageImprovementTests.cs new file mode 100644 index 00000000000000..5d2417e4a40d4d --- /dev/null +++ b/src/libraries/System.Security.Cryptography.Xml/tests/CoverageImprovementTests.cs @@ -0,0 +1,545 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections; +using System.IO; +using System.Text; +using System.Xml; +using Xunit; + +namespace System.Security.Cryptography.Xml.Tests +{ + public class KeyReferenceTests + { + [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); + } + } + + public class DataReferenceTests + { + [Fact] + public void Constructor_Default() + { + DataReference dataRef = new DataReference(); + Assert.NotNull(dataRef); + } + + [Fact] + public void Constructor_WithUri() + { + string uri = "#EncryptedData1"; + DataReference dataRef = new DataReference(uri); + Assert.Equal(uri, dataRef.Uri); + } + + [Fact] + public void Constructor_WithUriAndTransformChain() + { + string uri = "#EncryptedData1"; + TransformChain tc = new TransformChain(); + tc.Add(new XmlDsigBase64Transform()); + + DataReference dataRef = new DataReference(uri, tc); + Assert.Equal(uri, dataRef.Uri); + Assert.NotNull(dataRef.TransformChain); + } + + [Fact] + public void GetXml_ReturnsValidXml() + { + DataReference dataRef = new DataReference("#data1"); + XmlElement element = dataRef.GetXml(); + Assert.NotNull(element); + Assert.Equal("DataReference", element.LocalName); + } + } + + 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"); + + int index = refList.Add(dataRef); + Assert.Equal(0, index); + Assert.Equal(1, refList.Count); + } + + [Fact] + public void Add_KeyReference() + { + ReferenceList refList = new ReferenceList(); + KeyReference keyRef = new KeyReference("#key1"); + + int index = refList.Add(keyRef); + Assert.Equal(0, index); + Assert.Equal(1, refList.Count); + } + + [Fact] + public void Add_InvalidType_ThrowsArgumentException() + { + ReferenceList refList = new ReferenceList(); + Assert.Throws(() => refList.Add("invalid")); + } + + [Fact] + public void Add_Null_ThrowsArgumentNullException() + { + ReferenceList refList = new ReferenceList(); + Assert.Throws(() => refList.Add(null)); + } + + [Fact] + public void Contains_ExistingItem_ReturnsTrue() + { + ReferenceList refList = new ReferenceList(); + DataReference dataRef = new DataReference("#data1"); + refList.Add(dataRef); + + Assert.True(refList.Contains(dataRef)); + } + + [Fact] + public void Contains_NonExistingItem_ReturnsFalse() + { + ReferenceList refList = new ReferenceList(); + DataReference dataRef1 = new DataReference("#data1"); + DataReference dataRef2 = new DataReference("#data2"); + refList.Add(dataRef1); + + Assert.False(refList.Contains(dataRef2)); + } + + [Fact] + public void IndexOf_ReturnsCorrectIndex() + { + ReferenceList refList = new ReferenceList(); + DataReference dataRef1 = new DataReference("#data1"); + DataReference dataRef2 = new DataReference("#data2"); + refList.Add(dataRef1); + refList.Add(dataRef2); + + Assert.Equal(0, refList.IndexOf(dataRef1)); + Assert.Equal(1, refList.IndexOf(dataRef2)); + } + + [Fact] + public void Insert_InsertsAtCorrectPosition() + { + ReferenceList refList = new ReferenceList(); + DataReference dataRef1 = new DataReference("#data1"); + DataReference dataRef2 = new DataReference("#data2"); + DataReference dataRef3 = new DataReference("#data3"); + + refList.Add(dataRef1); + refList.Add(dataRef3); + refList.Insert(1, dataRef2); + + Assert.Equal(3, refList.Count); + Assert.Equal(dataRef2, refList[1]); + } + + [Fact] + public void Insert_Null_ThrowsArgumentNullException() + { + ReferenceList refList = new ReferenceList(); + Assert.Throws(() => refList.Insert(0, null)); + } + + [Fact] + public void Insert_InvalidType_ThrowsArgumentException() + { + ReferenceList refList = new ReferenceList(); + Assert.Throws(() => refList.Insert(0, "invalid")); + } + + [Fact] + public void Remove_RemovesItem() + { + ReferenceList refList = new ReferenceList(); + DataReference dataRef = new DataReference("#data1"); + refList.Add(dataRef); + + refList.Remove(dataRef); + Assert.Equal(0, refList.Count); + } + + [Fact] + public void Clear_RemovesAllItems() + { + ReferenceList refList = new ReferenceList(); + refList.Add(new DataReference("#data1")); + refList.Add(new KeyReference("#key1")); + + refList.Clear(); + Assert.Equal(0, refList.Count); + } + + [Fact] + public void GetEnumerator_EnumeratesAllItems() + { + ReferenceList refList = new ReferenceList(); + refList.Add(new DataReference("#data1")); + refList.Add(new KeyReference("#key1")); + + int count = 0; + foreach (var item in refList) + { + Assert.NotNull(item); + count++; + } + Assert.Equal(2, count); + } + + [Fact] + public void Item_SetValue_ReplacesItem() + { + ReferenceList refList = new ReferenceList(); + DataReference dataRef1 = new DataReference("#data1"); + DataReference dataRef2 = new DataReference("#data2"); + refList.Add(dataRef1); + + refList[0] = dataRef2; + Assert.Equal(dataRef2, refList[0]); + } + + [Fact] + public void Item_SetNull_ThrowsArgumentNullException() + { + ReferenceList refList = new ReferenceList(); + refList.Add(new DataReference("#data1")); + + Assert.Throws(() => refList[0] = null); + } + + [Fact] + public void RemoveAt_RemovesItemAtIndex() + { + ReferenceList refList = new ReferenceList(); + DataReference dataRef1 = new DataReference("#data1"); + DataReference dataRef2 = new DataReference("#data2"); + refList.Add(dataRef1); + refList.Add(dataRef2); + + refList.RemoveAt(0); + Assert.Equal(1, refList.Count); + Assert.Equal(dataRef2, refList[0]); + } + + [Fact] + public void IList_Properties() + { + ReferenceList refList = new ReferenceList(); + IList iList = refList; + Assert.False(iList.IsFixedSize); + Assert.False(iList.IsReadOnly); + Assert.False(refList.IsSynchronized); + Assert.NotNull(refList.SyncRoot); + } + + [Fact] + public void CopyTo_CopiesItemsToArray() + { + ReferenceList refList = new ReferenceList(); + DataReference dataRef1 = new DataReference("#data1"); + DataReference dataRef2 = new DataReference("#data2"); + refList.Add(dataRef1); + refList.Add(dataRef2); + + object[] array = new object[2]; + refList.CopyTo(array, 0); + + Assert.Equal(dataRef1, array[0]); + Assert.Equal(dataRef2, array[1]); + } + } + + public class CanonicalXmlSignificantWhitespaceTests + { + [Fact] + public void SignificantWhitespaceInCanonicalization() + { + // Test with XML containing significant whitespace + string xml = @" + text +"; + + 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(); + + Assert.Contains(" + text +"; + + 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); + Assert.NotNull(digest); + Assert.Equal(32, digest.Length); + } + } + } + + public class CanonicalXmlCommentTests + { + [Fact] + public void CommentInCanonicalizationWithComments() + { + string xml = @"text"; + + 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(); + + Assert.Contains("", result); + } + + [Fact] + public void MultipleCommentsInCanonicalization() + { + string xml = @"text"; + + 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(); + + Assert.Contains("", result); + Assert.Contains("", result); + Assert.Contains("", result); + } + } + + public class CanonicalXmlCDataSectionTests + { + [Fact] + public void CDataInCanonicalization() + { + string xml = @" content with special & characters]]>"; + + 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(); + + // CDATA should be output as text in canonical form + Assert.Contains("This is ", result); + Assert.Contains(" content with special ", result); + } + + [Fact] + public void CDataWithHash() + { + string xml = @""; + + 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); + Assert.NotNull(digest); + Assert.Equal(32, digest.Length); + } + } + } + + public class TransformChainTests + { + [Fact] + public void Constructor_CreatesEmptyChain() + { + TransformChain chain = new TransformChain(); + Assert.NotNull(chain); + Assert.Equal(0, chain.Count); + } + + [Fact] + public void Add_AddsTransform() + { + TransformChain chain = new TransformChain(); + XmlDsigBase64Transform transform = new XmlDsigBase64Transform(); + + chain.Add(transform); + Assert.Equal(1, chain.Count); + } + + [Fact] + public void Add_MultipleTransforms() + { + TransformChain chain = new TransformChain(); + chain.Add(new XmlDsigBase64Transform()); + chain.Add(new XmlDsigC14NTransform()); + + Assert.Equal(2, chain.Count); + } + + [Fact] + public void Indexer_ReturnsCorrectTransform() + { + TransformChain chain = new TransformChain(); + XmlDsigBase64Transform transform1 = new XmlDsigBase64Transform(); + XmlDsigC14NTransform transform2 = new XmlDsigC14NTransform(); + + chain.Add(transform1); + chain.Add(transform2); + + Assert.Equal(transform1, chain[0]); + Assert.Equal(transform2, chain[1]); + } + + [Fact] + public void GetEnumerator_EnumeratesTransforms() + { + 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); + } + } + + public class XmlDsigEnvelopedSignatureTransformTests + { + [Fact] + public void Constructor_SetsAlgorithm() + { + XmlDsigEnvelopedSignatureTransform transform = new XmlDsigEnvelopedSignatureTransform(); + Assert.Equal("http://www.w3.org/2000/09/xmldsig#enveloped-signature", transform.Algorithm); + } + + [Fact] + public void GetInnerXml_ReturnsNull() + { + XmlDsigEnvelopedSignatureTransform transform = new XmlDsigEnvelopedSignatureTransform(); + // Protected method, but we can test behavior indirectly + Assert.Equal("http://www.w3.org/2000/09/xmldsig#enveloped-signature", transform.Algorithm); + } + + [Fact] + public void LoadInput_WithDocument() + { + string xml = @"data"; + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + XmlDsigEnvelopedSignatureTransform transform = new XmlDsigEnvelopedSignatureTransform(); + transform.LoadInput(doc); + + object output = transform.GetOutput(); + Assert.NotNull(output); + Assert.IsAssignableFrom(output); + } + + [Fact] + public void InputTypes_ContainsExpectedTypes() + { + XmlDsigEnvelopedSignatureTransform transform = new XmlDsigEnvelopedSignatureTransform(); + Type[] inputTypes = transform.InputTypes; + + Assert.Contains(typeof(Stream), inputTypes); + Assert.Contains(typeof(XmlDocument), inputTypes); + Assert.Contains(typeof(XmlNodeList), inputTypes); + } + + [Fact] + public void OutputTypes_ContainsExpectedTypes() + { + XmlDsigEnvelopedSignatureTransform transform = new XmlDsigEnvelopedSignatureTransform(); + Type[] outputTypes = transform.OutputTypes; + + Assert.Contains(typeof(XmlDocument), outputTypes); + Assert.Contains(typeof(XmlNodeList), outputTypes); + } + } +} diff --git a/src/libraries/System.Security.Cryptography.Xml/tests/Cycle1CoverageTests.cs b/src/libraries/System.Security.Cryptography.Xml/tests/Cycle1CoverageTests.cs new file mode 100644 index 00000000000000..7d31db74f25890 --- /dev/null +++ b/src/libraries/System.Security.Cryptography.Xml/tests/Cycle1CoverageTests.cs @@ -0,0 +1,387 @@ +// 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 +{ + // Tests targeting SignedXml gaps + public class SignedXmlCoverageTests + { + [Fact] + public void SignedXml_ComputeSignature_WithKeyedHashAlgorithm() + { + XmlDocument doc = new XmlDocument(); + doc.LoadXml("test"); + + SignedXml signedXml = new SignedXml(doc); + Reference reference = new Reference(""); + reference.AddTransform(new XmlDsigEnvelopedSignatureTransform()); + signedXml.AddReference(reference); + + using (HMACSHA256 hmac = new HMACSHA256()) + { + signedXml.ComputeSignature(hmac); + XmlElement signature = signedXml.GetXml(); + Assert.NotNull(signature); + } + } + + [Fact] + public void SignedXml_CheckSignature_WithKeyedHashAlgorithm() + { + XmlDocument doc = new XmlDocument(); + doc.LoadXml("test"); + + SignedXml signedXml = new SignedXml(doc); + Reference reference = new Reference(""); + reference.AddTransform(new XmlDsigEnvelopedSignatureTransform()); + signedXml.AddReference(reference); + + byte[] key = new byte[32]; + using (HMACSHA256 hmac = new HMACSHA256(key)) + { + signedXml.ComputeSignature(hmac); + + SignedXml verifyXml = new SignedXml(doc); + verifyXml.LoadXml(signedXml.GetXml()); + + using (HMACSHA256 verifyHmac = new HMACSHA256(key)) + { + bool valid = verifyXml.CheckSignature(verifyHmac); + Assert.True(valid); + } + } + } + + [Fact] + public void SignedXml_SignatureMethod_Property() + { + XmlDocument doc = new XmlDocument(); + doc.LoadXml("test"); + + SignedXml signedXml = new SignedXml(doc); + Reference reference = new Reference(""); + signedXml.AddReference(reference); + + using (RSA rsa = RSA.Create()) + { + signedXml.SigningKey = rsa; + signedXml.SignedInfo.SignatureMethod = SignedXml.XmlDsigRSASHA256Url; + signedXml.ComputeSignature(); + + Assert.Equal(SignedXml.XmlDsigRSASHA256Url, signedXml.SignedInfo.SignatureMethod); + } + } + + [Fact] + public void SignedXml_GetIdElement_WithMultipleIds() + { + string xml = @"firstsecond"; + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + SignedXml signedXml = new SignedXml(doc); + Reference reference = new Reference("#item1"); + signedXml.AddReference(reference); + + using (RSA rsa = RSA.Create()) + { + signedXml.SigningKey = rsa; + signedXml.ComputeSignature(); + Assert.NotNull(signedXml.GetXml()); + } + } + } + + // Tests targeting TransformChain gaps + public class TransformChainCoverageTests + { + [Fact] + public void TransformChain_WithMultipleTransforms() + { + XmlDocument doc = new XmlDocument(); + doc.LoadXml("test data"); + + Reference reference = new Reference(""); + reference.AddTransform(new XmlDsigEnvelopedSignatureTransform()); + reference.AddTransform(new XmlDsigC14NTransform()); + reference.AddTransform(new XmlDsigBase64Transform()); + + Assert.Equal(3, reference.TransformChain.Count); + } + + [Fact] + public void TransformChain_Indexer_OutOfRange() + { + TransformChain chain = new TransformChain(); + chain.Add(new XmlDsigC14NTransform()); + + Assert.Throws(() => chain[5]); + } + + [Fact] + public void TransformChain_AddNull_Ignored() + { + TransformChain chain = new TransformChain(); + int countBefore = chain.Count; + + chain.Add(null); + + // Null transforms are ignored + Assert.Equal(countBefore, chain.Count); + } + } + + // Tests targeting XmlDsigEnvelopedSignatureTransform gaps + public class XmlDsigEnvelopedSignatureTransformCoverageTests + { + [Fact] + public void XmlDsigEnvelopedSignatureTransform_WithStream() + { + string xml = @"test"; + + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + XmlDsigEnvelopedSignatureTransform transform = new XmlDsigEnvelopedSignatureTransform(); + + // Convert to stream + MemoryStream ms = new MemoryStream(); + using (XmlWriter writer = XmlWriter.Create(ms)) + { + doc.WriteTo(writer); + } + ms.Position = 0; + + transform.LoadInput(ms); + object output = transform.GetOutput(); + Assert.NotNull(output); + } + + [Fact] + public void XmlDsigEnvelopedSignatureTransform_WithXmlNodeList() + { + string xml = @"test1test2"; + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + XmlNodeList nodeList = doc.SelectNodes("//data"); + + XmlDsigEnvelopedSignatureTransform transform = new XmlDsigEnvelopedSignatureTransform(); + transform.LoadInput(nodeList); + + object output = transform.GetOutput(); + Assert.NotNull(output); + } + + [Fact] + public void XmlDsigEnvelopedSignatureTransform_GetOutput_TypedStream() + { + string xml = @"test"; + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + XmlDsigEnvelopedSignatureTransform transform = new XmlDsigEnvelopedSignatureTransform(); + transform.LoadInput(doc); + + object output = transform.GetOutput(typeof(XmlDocument)); + Assert.IsType(output); + } + } + + // Tests targeting ExcCanonicalXml and XmlDsigExcC14NTransform gaps + public class ExclusiveCanonicalizationCoverageTests + { + [Fact] + public void XmlDsigExcC14NTransform_WithInclusiveNamespacesList() + { + string xml = @" + content + "; + + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + XmlDsigExcC14NTransform transform = new XmlDsigExcC14NTransform(false, "ex test"); + transform.LoadInput(doc); + + Stream output = (Stream)transform.GetOutput(); + Assert.NotNull(output); + + string result = new StreamReader(output, Encoding.UTF8).ReadToEnd(); + Assert.Contains("example.com", result); + } + + [Fact] + public void XmlDsigExcC14NTransform_LoadInnerXml() + { + string innerXml = @""; + XmlDocument doc = new XmlDocument(); + doc.LoadXml(innerXml); + + XmlDsigExcC14NTransform transform = new XmlDsigExcC14NTransform(); + transform.LoadInnerXml(doc.ChildNodes); + + Assert.Equal("ds xsi", transform.InclusiveNamespacesPrefixList); + } + + [Fact] + public void XmlDsigExcC14NTransform_GetXml() + { + XmlDsigExcC14NTransform transform = new XmlDsigExcC14NTransform(false, "ds xml"); + XmlElement xml = transform.GetXml(); + + Assert.NotNull(xml); + Assert.Equal("Transform", xml.LocalName); + } + + [Fact] + public void XmlDsigExcC14NTransform_WithStream() + { + string xml = @"data"; + + MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(xml)); + + XmlDsigExcC14NTransform transform = new XmlDsigExcC14NTransform(); + transform.LoadInput(ms); + + Stream output = (Stream)transform.GetOutput(); + Assert.NotNull(output); + } + } + + // Tests targeting EncryptedXml gaps + public class EncryptedXmlCoverageTests + { + [Fact] + public void EncryptedXml_XmlEncNamespaceUrl() + { + string expectedUrl = "http://www.w3.org/2001/04/xmlenc#"; + Assert.Equal(EncryptedXml.XmlEncNamespaceUrl, expectedUrl); + } + + [Fact] + public void EncryptedXml_DecryptKey_TripleDES() + { + using (TripleDES tripleDES = TripleDES.Create()) + { + byte[] keyData = new byte[24]; + using (RandomNumberGenerator rng = RandomNumberGenerator.Create()) + { + rng.GetBytes(keyData); + } + tripleDES.Key = keyData; + + byte[] encryptedKey = EncryptedXml.EncryptKey(keyData, tripleDES); + byte[] decryptedKey = EncryptedXml.DecryptKey(encryptedKey, tripleDES); + + Assert.Equal(keyData, decryptedKey); + } + } + + [Fact] + public void EncryptedXml_ReplaceData_WithEncryptedData() + { + XmlDocument doc = new XmlDocument(); + doc.LoadXml("sensitive"); + + XmlElement elementToEncrypt = (XmlElement)doc.SelectSingleNode("//data"); + + EncryptedData encryptedData = new EncryptedData(); + encryptedData.Type = EncryptedXml.XmlEncElementUrl; + encryptedData.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncAES256Url); + encryptedData.CipherData = new CipherData(new byte[] { 1, 2, 3, 4 }); + + EncryptedXml.ReplaceElement(elementToEncrypt, encryptedData, false); + + Assert.Contains("EncryptedData", doc.OuterXml); + } + + [Fact] + public void EncryptedXml_ClearKeyNameMappings() + { + XmlDocument doc = new XmlDocument(); + doc.LoadXml(""); + + EncryptedXml encryptedXml = new EncryptedXml(doc); + + using (Aes aes = Aes.Create()) + { + encryptedXml.AddKeyNameMapping("key1", aes); + encryptedXml.ClearKeyNameMappings(); + + // After clearing, key should not be found + Assert.NotNull(encryptedXml); + } + } + + [Fact] + public void EncryptedXml_GetDecryptionKey_WithKeyName() + { + XmlDocument doc = new XmlDocument(); + doc.LoadXml(""); + + EncryptedXml encryptedXml = new EncryptedXml(doc); + + using (Aes aes = Aes.Create()) + { + encryptedXml.AddKeyNameMapping("testkey", aes); + + EncryptedData encryptedData = new EncryptedData(); + encryptedData.KeyInfo = new KeyInfo(); + encryptedData.KeyInfo.AddClause(new KeyInfoName("testkey")); + + SymmetricAlgorithm key = encryptedXml.GetDecryptionKey(encryptedData, null); + Assert.NotNull(key); + } + } + } + + // Tests targeting Reference gaps + public class ReferenceCoverageTests + { + [Fact] + public void Reference_Uri_Modification() + { + Reference reference = new Reference("#test"); + Assert.Equal("#test", reference.Uri); + + reference.Uri = "#modified"; + Assert.Equal("#modified", reference.Uri); + } + + [Fact] + public void Reference_DigestValue_Setter() + { + Reference reference = new Reference(); + byte[] digestValue = new byte[] { 1, 2, 3, 4, 5 }; + + reference.DigestValue = digestValue; + Assert.Equal(digestValue, reference.DigestValue); + } + + [Fact] + public void Reference_Type_Property() + { + Reference reference = new Reference(); + string type = "http://www.w3.org/2000/09/xmldsig#Object"; + + reference.Type = type; + Assert.Equal(type, reference.Type); + } + + [Fact] + public void Reference_DigestMethod_Property() + { + Reference reference = new Reference(); + string digestMethod = EncryptedXml.XmlEncSHA256Url; + + reference.DigestMethod = digestMethod; + Assert.Equal(digestMethod, reference.DigestMethod); + } + } +} 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..a333d09c111f11 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,7 +10,11 @@ + + + +