From b4ede585eab62c41de626f07f79590ae88468c2a Mon Sep 17 00:00:00 2001 From: Markus Quaritsch <markus.quaritsch@tugraz.at> Date: Thu, 4 May 2017 16:26:15 +0200 Subject: [PATCH] implementing hashing functionality --- VectoCommon/VectoHashing/IVectoHash.cs | 16 ++- .../VectoHashing/Impl/XmlHashProvider.cs | 13 +-- VectoCommon/VectoHashing/VectoComponents.cs | 34 +++++- VectoCommon/VectoHashing/VectoHash.cs | 102 +++++++++++++++--- VectoCommon/VectoHashing/VectoHashing.csproj | 10 ++ .../VectoHashingTest/BasicHasingTests.cs | 23 ++-- .../Reference/vecto_vehicle-sample_FULL.xml | 6 +- .../vecto_vehicle-sample_FULL_Entry_Order.xml | 6 +- VectoCommon/VectoHashingTest/VectoHashTest.cs | 52 +++++++++ .../VectoHashingTest/VectoHashingTest.csproj | 8 +- VectoCommon/VectoHashingTest/packages.config | 4 + packages/repositories.config | 1 + 12 files changed, 232 insertions(+), 43 deletions(-) create mode 100644 VectoCommon/VectoHashingTest/VectoHashTest.cs create mode 100644 VectoCommon/VectoHashingTest/packages.config diff --git a/VectoCommon/VectoHashing/IVectoHash.cs b/VectoCommon/VectoHashing/IVectoHash.cs index b8c5200f3f..abde7e5a40 100644 --- a/VectoCommon/VectoHashing/IVectoHash.cs +++ b/VectoCommon/VectoHashing/IVectoHash.cs @@ -3,14 +3,22 @@ using System.Xml.Linq; namespace TUGraz.VectoHashing { - public interface IVectoHash { + public interface IVectoHash + { IEnumerable<VectoComponents> GetContainigComponents(); + string ComputeHash(); - string ComputeHash(VectoComponents component); + + string ComputeHash(VectoComponents component, int index = 0); + XDocument AddHash(); + string ReadHash(); - string ReadHash(VectoComponents component); + + string ReadHash(VectoComponents component, int index = 0); + bool ValidateHash(); - bool ValidateHash(VectoComponents component); + + bool ValidateHash(VectoComponents component, int index = 0); } } \ No newline at end of file diff --git a/VectoCommon/VectoHashing/Impl/XmlHashProvider.cs b/VectoCommon/VectoHashing/Impl/XmlHashProvider.cs index 10f318210f..8d1564f390 100644 --- a/VectoCommon/VectoHashing/Impl/XmlHashProvider.cs +++ b/VectoCommon/VectoHashing/Impl/XmlHashProvider.cs @@ -7,7 +7,7 @@ namespace TUGraz.VectoHashing.Impl { public class XMLHashProvider { - public XmlDocument ComputeHash(XmlDocument doc, string elementId) + public static XmlDocument ComputeHash(XmlDocument doc, string elementId) { if (doc == null || doc.DocumentElement == null) { throw new Exception("Invalid Document"); @@ -24,14 +24,11 @@ namespace TUGraz.VectoHashing.Impl signedXml.ComputeSignature(HMAC.Create()); var xmlDigitalSignature = reference.GetXml(); - var sig = doc.CreateElement("Signature"); - sig.AppendChild(doc.ImportNode(xmlDigitalSignature, true)); + var sigdoc = new XmlDocument(); + sigdoc.CreateElement("Signature"); + sigdoc.AppendChild(sigdoc.ImportNode(xmlDigitalSignature, true)); - doc.DocumentElement.AppendChild(sig); - if (doc.FirstChild is XmlDeclaration) { - doc.RemoveChild(doc.FirstChild); - } - return doc; + return sigdoc; } } } \ No newline at end of file diff --git a/VectoCommon/VectoHashing/VectoComponents.cs b/VectoCommon/VectoHashing/VectoComponents.cs index 4daae7fff2..256599f30f 100644 --- a/VectoCommon/VectoHashing/VectoComponents.cs +++ b/VectoCommon/VectoHashing/VectoComponents.cs @@ -1,4 +1,7 @@ -namespace TUGraz.VectoHashing +using System; +using TUGraz.VectoCore.Resources; + +namespace TUGraz.VectoHashing { public enum VectoComponents { @@ -12,4 +15,33 @@ Tyre, Vehicle, } + + public static class VectoComponentsExtensionMethods + { + public static string XMLElementName(this VectoComponents component) + { + switch (component) { + case VectoComponents.Engine: + return XMLNames.Component_Engine; + case VectoComponents.Gearbox: + return XMLNames.Component_Gearbox; + case VectoComponents.Axlegear: + return XMLNames.Component_Axlegear; + case VectoComponents.Retarder: + return XMLNames.Component_Retarder; + case VectoComponents.TorqueConverter: + return XMLNames.Component_TorqueConverter; + case VectoComponents.Angledrive: + return XMLNames.Component_Angledrive; + case VectoComponents.Airdrag: + return XMLNames.Component_AirDrag; + case VectoComponents.Tyre: + return XMLNames.AxleWheels_Axles_Axle_Tyre; + case VectoComponents.Vehicle: + return XMLNames.Component_Vehicle; + default: + throw new ArgumentOutOfRangeException("VectoComponents", component, null); + } + } + } } \ No newline at end of file diff --git a/VectoCommon/VectoHashing/VectoHash.cs b/VectoCommon/VectoHashing/VectoHash.cs index 7ebd177cb3..293b4976f5 100644 --- a/VectoCommon/VectoHashing/VectoHash.cs +++ b/VectoCommon/VectoHashing/VectoHash.cs @@ -1,65 +1,137 @@ -using System.Collections; +using System; +using System.Collections; using System.Collections.Generic; using System.IO; +using System.Linq; +using System.Xml; using System.Xml.Linq; +using System.Xml.XPath; +using TUGraz.VectoCommon.Models; +using TUGraz.VectoCommon.Utils; +using TUGraz.VectoCore.Resources; +using TUGraz.VectoCore.Utils; +using TUGraz.VectoHashing.Impl; +using TUGraz.VectoHashing.Util; namespace TUGraz.VectoHashing { public class VectoHash : IVectoHash { + protected XmlDocument document; + private XPathNavigator Navigator; + private XmlNamespaceManager Manager; + private XPathHelper Helper; + public static VectoHash Load(string filename) { - return null; + var doc = new XmlDocument(); + doc.Load(new XmlTextReader(filename)); + return new VectoHash(doc); } public static VectoHash Load(Stream stream) { - return null; + var doc = new XmlDocument(); + doc.Load(new XmlTextReader(stream)); + return new VectoHash(doc); } - public static VectoHash Load(XDocument doc) + public static VectoHash Load(XmlDocument doc) { - return null; + return new VectoHash(doc); + } + + protected VectoHash(XmlDocument doc) + { + document = doc; + Navigator = doc.CreateNavigator(); + Manager = new XmlNamespaceManager(Navigator.NameTable); + Helper = new XPathHelper(ExecutionMode.Declaration); + Helper.AddNamespaces(Manager); } public IEnumerable<VectoComponents> GetContainigComponents() { - return null; + var retVal = new List<VectoComponents>(); + foreach (var component in EnumHelper.GetValues<VectoComponents>()) { + if (Navigator.Select(string.Format("//*[local-name()='{0}']", component.XMLElementName()), Manager).Count == 0) { + continue; + } + if (!retVal.Contains(component)) { + retVal.Add(component); + } + } + return retVal; } public string ComputeHash() { - return null; + var toSign = GetIdForElement(GetComponentQueryString()); + var hash = XMLHashProvider.ComputeHash(document, toSign); + return GetHashValue(hash, toSign); } - public string ComputeHash(VectoComponents component) + public string ComputeHash(VectoComponents component, int index = 0) { - return null; + var toSign = GetIdForElement(GetComponentQueryString(component), index); + var hash = XMLHashProvider.ComputeHash(document, toSign); + return GetHashValue(hash, toSign); + } + + private static string GetComponentQueryString(VectoComponents? component = null) + { + if (component == null) { + return "(//*[@id]/@id)[1]"; + } + return component == VectoComponents.Vehicle + ? string.Format("//*[local-name()='{0}'/@id", component.Value.XMLElementName()) + : string.Format("//*[local-name()='{0}']/*[local-name()='Data']/@id", component.Value.XMLElementName()); + } + + private string GetIdForElement(string query, int index = 0) + { + var node = document.SelectNodes(query); + if (node == null) { + return null; + } + var toSign = node[index].Value; + return toSign; } public XDocument AddHash() { + var toSign = GetIdForElement(GetComponentQueryString()); + var hash = XMLHashProvider.ComputeHash(document, toSign); + return null; } public string ReadHash() { - return null; + var toRead = GetIdForElement(GetComponentQueryString()); + return GetHashValue(document, toRead); } - public string ReadHash(VectoComponents component) + public string ReadHash(VectoComponents component, int index = 0) { - return null; + var toRead = GetIdForElement(GetComponentQueryString(component), index); + return GetHashValue(document, toRead); } public bool ValidateHash() { - return false; + return ReadHash().Equals(ComputeHash(), StringComparison.Ordinal); + } + + public bool ValidateHash(VectoComponents component, int index = 0) + { + return StructuralComparisons.StructuralEqualityComparer.Equals(ReadHash(component), ComputeHash(component)); } - public bool ValidateHash(VectoComponents component) + private static string GetHashValue(XmlDocument hashed, string elementToHash) { - return false; + var node = hashed.SelectSingleNode("//*[@URI='#" + elementToHash + "']/*[local-name() = 'DigestValue']"); + return node == null ? null : node.InnerText; } } } \ No newline at end of file diff --git a/VectoCommon/VectoHashing/VectoHashing.csproj b/VectoCommon/VectoHashing/VectoHashing.csproj index 1bb5201925..20269e024a 100644 --- a/VectoCommon/VectoHashing/VectoHashing.csproj +++ b/VectoCommon/VectoHashing/VectoHashing.csproj @@ -51,6 +51,16 @@ <ItemGroup> <EmbeddedResource Include="Resources\XSLT\SortInputData.xslt" /> </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\..\VectoCore\VectoCore\VectoCore.csproj"> + <Project>{CD36938A-ADD9-4C65-96DA-B397CDEEA90A}</Project> + <Name>VectoCore</Name> + </ProjectReference> + <ProjectReference Include="..\VectoCommon\VectoCommon.csproj"> + <Project>{79A066AD-69A9-4223-90F6-6ED5D2D084F4}</Project> + <Name>VectoCommon</Name> + </ProjectReference> + </ItemGroup> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <!-- To modify your build process, add your task inside one of the targets below and uncomment it. Other similar extension points exist, see Microsoft.Common.targets. diff --git a/VectoCommon/VectoHashingTest/BasicHasingTests.cs b/VectoCommon/VectoHashingTest/BasicHasingTests.cs index 32046519de..226d787ed2 100644 --- a/VectoCommon/VectoHashingTest/BasicHasingTests.cs +++ b/VectoCommon/VectoHashingTest/BasicHasingTests.cs @@ -18,6 +18,13 @@ namespace VectoHashingTest public const string UnorderedXMLVehicle = @"Testdata\XML\Variations\vecto_vehicle-sample_FULL_Entry_Order.xml"; + public const string HashSimpleXML = "U2zic7KOnKw60rzh+KKQ1lwZL6NmXju+DXG7cYYmlxo="; + public const string HashEngineXML = "VZ3s5f3JtWTTrEex4uNcwQqh9Nzzdo6gkAQ3vD5qGUo="; + + public const string HashVehicleXML = "EMVWU3nhpMX5g6KGWLaQiRjNnz3WhJS/2TIlyiiV9wE="; + //"HhMqWPkLcgxex1qAfBS7e7gopytbW6k8svNyW/B9+iw="; + + [TestMethod] public void HashSimpleXml() { @@ -25,13 +32,13 @@ namespace VectoHashingTest var doc = new XmlDocument(); doc.Load(SimpleXML); var hasher = new XMLHashProvider(); - var hashed = hasher.ComputeHash(doc, elementToHash); + var hashed = XMLHashProvider.ComputeHash(doc, elementToHash); var hash = GetHashValue(hashed, elementToHash); WriteSignedXML(doc, "simple_document_hashed.xml"); - Assert.AreEqual("U2zic7KOnKw60rzh+KKQ1lwZL6NmXju+DXG7cYYmlxo=", hash); + Assert.AreEqual(HashSimpleXML, hash); } [TestMethod] @@ -41,13 +48,13 @@ namespace VectoHashingTest var doc = new XmlDocument(); doc.Load(ReferenceXMLEngine); var hasher = new XMLHashProvider(); - var hashed = hasher.ComputeHash(doc, elementToHash); + var hashed = XMLHashProvider.ComputeHash(doc, elementToHash); var hash = GetHashValue(hashed, elementToHash); WriteSignedXML(doc, "reference_engine_hashed.xml"); - Assert.AreEqual("VZ3s5f3JtWTTrEex4uNcwQqh9Nzzdo6gkAQ3vD5qGUo=", hash); + Assert.AreEqual(HashEngineXML, hash); } [TestMethod] @@ -57,13 +64,13 @@ namespace VectoHashingTest var doc = new XmlDocument(); doc.Load(ReferenceXMLVehicle); var hasher = new XMLHashProvider(); - var hashed = hasher.ComputeHash(doc, elementToHash); + var hashed = XMLHashProvider.ComputeHash(doc, elementToHash); var hash = GetHashValue(hashed, elementToHash); WriteSignedXML(doc, "reference_vehicle_hashed.xml"); - Assert.AreEqual("HhMqWPkLcgxex1qAfBS7e7gopytbW6k8svNyW/B9+iw=", hash); + Assert.AreEqual(HashVehicleXML, hash); } [TestMethod] @@ -73,13 +80,13 @@ namespace VectoHashingTest var doc = new XmlDocument(); doc.Load(UnorderedXMLVehicle); var hasher = new XMLHashProvider(); - var hashed = hasher.ComputeHash(doc, elementToHash); + var hashed = XMLHashProvider.ComputeHash(doc, elementToHash); var hash = GetHashValue(hashed, elementToHash); WriteSignedXML(doc, "reference_vehicle_hashed.xml"); - Assert.AreEqual("HhMqWPkLcgxex1qAfBS7e7gopytbW6k8svNyW/B9+iw=", hash); + Assert.AreEqual(HashVehicleXML, hash); } private static string GetHashValue(XmlDocument hashed, string elementToHash) diff --git a/VectoCommon/VectoHashingTest/Testdata/XML/Reference/vecto_vehicle-sample_FULL.xml b/VectoCommon/VectoHashingTest/Testdata/XML/Reference/vecto_vehicle-sample_FULL.xml index bece65ce50..79733d8b87 100644 --- a/VectoCommon/VectoHashingTest/Testdata/XML/Reference/vecto_vehicle-sample_FULL.xml +++ b/VectoCommon/VectoHashingTest/Testdata/XML/Reference/vecto_vehicle-sample_FULL.xml @@ -3218,7 +3218,7 @@ <TwinTyres>true</TwinTyres> <Steered>false</Steered> <Tyre certificationNumber="e12*0815/8051*2017/05E0000*00"> - <Data id="WHL-5432198760-315-70-R22.5"> + <Data id="WHL-6432198760-315-70-R22.5"> <Manufacturer>Generic Wheels Manufacturer</Manufacturer> <Model>Generic Wheel</Model> <TechnicalReportId>WHL-1234567890</TechnicalReportId> @@ -3229,13 +3229,13 @@ <FzISO>31300</FzISO> </Data> <Signature> - <di:Reference URI="#WHL-5432198760-315-70-R22.5"> + <di:Reference URI="#WHL-6432198760-315-70-R22.5"> <di:Transforms> <di:Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithoutComments" /> <di:Transform Algorithm="urn:vecto:xml:2017:canonicalization" /> </di:Transforms> <di:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" /> - <di:DigestValue>5074334bb2c090c5e258e9a664f5d19689a3f13d</di:DigestValue> + <di:DigestValue>6074334bb2c090c5e258e9a664f5d19689a3f13d</di:DigestValue> </di:Reference> </Signature> </Tyre> diff --git a/VectoCommon/VectoHashingTest/Testdata/XML/Variations/vecto_vehicle-sample_FULL_Entry_Order.xml b/VectoCommon/VectoHashingTest/Testdata/XML/Variations/vecto_vehicle-sample_FULL_Entry_Order.xml index 658ded40e4..a820e231cb 100644 --- a/VectoCommon/VectoHashingTest/Testdata/XML/Variations/vecto_vehicle-sample_FULL_Entry_Order.xml +++ b/VectoCommon/VectoHashingTest/Testdata/XML/Variations/vecto_vehicle-sample_FULL_Entry_Order.xml @@ -3194,7 +3194,7 @@ <TwinTyres>true</TwinTyres> <Steered>false</Steered> <Tyre certificationNumber="e12*0815/8051*2017/05E0000*00"> - <Data id="WHL-5432198760-315-70-R22.5"> + <Data id="WHL-6432198760-315-70-R22.5"> <Manufacturer>Generic Wheels Manufacturer</Manufacturer> <Model>Generic Wheel</Model> <TechnicalReportId>WHL-1234567890</TechnicalReportId> @@ -3205,13 +3205,13 @@ <FzISO>31300</FzISO> </Data> <Signature> - <di:Reference URI="#WHL-5432198760-315-70-R22.5"> + <di:Reference URI="#WHL-6432198760-315-70-R22.5"> <di:Transforms> <di:Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithoutComments" /> <di:Transform Algorithm="urn:vecto:xml:2017:canonicalization" /> </di:Transforms> <di:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" /> - <di:DigestValue>5074334bb2c090c5e258e9a664f5d19689a3f13d</di:DigestValue> + <di:DigestValue>6074334bb2c090c5e258e9a664f5d19689a3f13d</di:DigestValue> </di:Reference> </Signature> </Tyre> diff --git a/VectoCommon/VectoHashingTest/VectoHashTest.cs b/VectoCommon/VectoHashingTest/VectoHashTest.cs new file mode 100644 index 0000000000..56c569f13b --- /dev/null +++ b/VectoCommon/VectoHashingTest/VectoHashTest.cs @@ -0,0 +1,52 @@ +using System.Linq; +using NUnit.Framework; +using TUGraz.VectoHashing; +using Assert = NUnit.Framework.Assert; + +namespace VectoHashingTest +{ + [TestFixture] + public class VectoHashTest + { + public const string ReferenceXMLEngine = @"Testdata\XML\Reference\vecto_engine-sample.xml"; + public const string ReferenceXMLVehicle = @"Testdata\XML\Reference\vecto_vehicle-sample_FULL.xml"; + + [TestCase] + public void TestComponentsEngineFile() + { + var h = VectoHash.Load(ReferenceXMLEngine); + var components = h.GetContainigComponents().ToList(); + + Assert.AreEqual(1, components.Count); + Assert.AreEqual(VectoComponents.Engine, components[0]); + } + + [TestCase] + public void TestComponentsVehicleFile() + { + var h = VectoHash.Load(ReferenceXMLVehicle); + var components = h.GetContainigComponents().ToList(); + + Assert.AreEqual(9, components.Count); + } + + [TestCase(ReferenceXMLEngine, VectoComponents.Engine, BasicHasingTests.HashEngineXML)] + public void TestHashComputationSelected(string file, VectoComponents component, string expectedHash) + { + var h = VectoHash.Load(file); + var hash = h.ComputeHash(component); + + Assert.AreEqual(expectedHash, hash); + } + + [TestCase(ReferenceXMLVehicle, BasicHasingTests.HashVehicleXML), + TestCase(ReferenceXMLEngine, BasicHasingTests.HashEngineXML)] + public void TestHashComputation(string file, string expectedHash) + { + var h = VectoHash.Load(file); + var hash = h.ComputeHash(); + + Assert.AreEqual(expectedHash, hash); + } + } +} \ No newline at end of file diff --git a/VectoCommon/VectoHashingTest/VectoHashingTest.csproj b/VectoCommon/VectoHashingTest/VectoHashingTest.csproj index a23c00df3a..5b72742a8a 100644 --- a/VectoCommon/VectoHashingTest/VectoHashingTest.csproj +++ b/VectoCommon/VectoHashingTest/VectoHashingTest.csproj @@ -35,6 +35,9 @@ <WarningLevel>4</WarningLevel> </PropertyGroup> <ItemGroup> + <Reference Include="nunit.framework"> + <HintPath>..\..\packages\NUnit.2.6.3\lib\nunit.framework.dll</HintPath> + </Reference> <Reference Include="System" /> <Reference Include="System.Xml" /> <Reference Include="System.Xml.Linq" /> @@ -54,8 +57,11 @@ <ItemGroup> <Compile Include="BasicHasingTests.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="VectoHashTest.cs" /> + </ItemGroup> + <ItemGroup> + <None Include="packages.config" /> </ItemGroup> - <ItemGroup /> <ItemGroup> <Content Include="Testdata\XML\Reference\vecto_engine-sample.xml"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> diff --git a/VectoCommon/VectoHashingTest/packages.config b/VectoCommon/VectoHashingTest/packages.config new file mode 100644 index 0000000000..ad37a5282e --- /dev/null +++ b/VectoCommon/VectoHashingTest/packages.config @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<packages> + <package id="NUnit" version="2.6.3" targetFramework="net45" /> +</packages> \ No newline at end of file diff --git a/packages/repositories.config b/packages/repositories.config index bb868d9ee6..96750bd818 100644 --- a/packages/repositories.config +++ b/packages/repositories.config @@ -8,6 +8,7 @@ <repository path="..\VECTOAux\VectoAuxiliariesTests\packages.config" /> <repository path="..\VectoCommon\AdvancedAuxiliaryInterfaces\packages.config" /> <repository path="..\VectoCommon\VectoCommon\packages.config" /> + <repository path="..\VectoCommon\VectoHashingTest\packages.config" /> <repository path="..\VectoConsole\packages.config" /> <repository path="..\VectoCore\ModelbasedTests\packages.config" /> <repository path="..\VectoCore\VectoCore\packages.config" /> -- GitLab