Code development platform for open source projects from the European Union institutions

Skip to content
Snippets Groups Projects
Commit 7ebcfe86 authored by Markus QUARITSCH's avatar Markus QUARITSCH
Browse files

refactoring of hashing to handle multiple identical components

parent 66a2cc9e
No related branches found
No related tags found
No related merge requests found
...@@ -9,7 +9,7 @@ namespace TUGraz.VectoHashing.Impl ...@@ -9,7 +9,7 @@ namespace TUGraz.VectoHashing.Impl
{ {
public static XmlDocument ComputeHash(XmlDocument doc, string elementId) public static XmlDocument ComputeHash(XmlDocument doc, string elementId)
{ {
if (doc == null || doc.DocumentElement == null) { if (doc == null /*|| doc.DocumentElement == null*/) {
throw new Exception("Invalid Document"); throw new Exception("Invalid Document");
} }
var signedXml = new SignedXml(doc); var signedXml = new SignedXml(doc);
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq;
using System.Xml; using System.Xml;
using System.Xml.Linq; using System.Xml.Linq;
using TUGraz.VectoCommon.Utils; using TUGraz.VectoCommon.Utils;
...@@ -14,7 +15,6 @@ namespace TUGraz.VectoHashing ...@@ -14,7 +15,6 @@ namespace TUGraz.VectoHashing
public class VectoHash : IVectoHash public class VectoHash : IVectoHash
{ {
protected XmlDocument Document; protected XmlDocument Document;
private XmlNamespaceManager Manager;
public static VectoHash Load(string filename) public static VectoHash Load(string filename)
{ {
...@@ -46,7 +46,6 @@ namespace TUGraz.VectoHashing ...@@ -46,7 +46,6 @@ namespace TUGraz.VectoHashing
protected VectoHash(XmlDocument doc) protected VectoHash(XmlDocument doc)
{ {
Document = doc; Document = doc;
Manager = new XmlNamespaceManager(doc.NameTable);
} }
public IList<VectoComponents> GetContainigComponents() public IList<VectoComponents> GetContainigComponents()
...@@ -54,7 +53,7 @@ namespace TUGraz.VectoHashing ...@@ -54,7 +53,7 @@ namespace TUGraz.VectoHashing
var retVal = new List<VectoComponents>(); var retVal = new List<VectoComponents>();
foreach (var component in EnumHelper.GetValues<VectoComponents>()) { foreach (var component in EnumHelper.GetValues<VectoComponents>()) {
var count = var count =
Document.SelectNodes(string.Format("//*[local-name()='{0}']", component.XMLElementName()), Manager).Count; Document.SelectNodes(string.Format("//*[local-name()='{0}']", component.XMLElementName())).Count;
for (var i = 0; i < count; i++) { for (var i = 0; i < count; i++) {
retVal.Add(component); retVal.Add(component);
} }
...@@ -64,16 +63,43 @@ namespace TUGraz.VectoHashing ...@@ -64,16 +63,43 @@ namespace TUGraz.VectoHashing
public string ComputeHash() public string ComputeHash()
{ {
var toSign = GetIdForElement(GetComponentQueryString()); var nodes = Document.SelectNodes(GetComponentQueryString());
var hash = XMLHashProvider.ComputeHash(Document, toSign); if (nodes == null || nodes.Count == 0) {
return GetHashValue(hash, toSign); throw new Exception("No component found");
}
return DoComputeHash(nodes[0]);
} }
public string ComputeHash(VectoComponents component, int index = 0) public string ComputeHash(VectoComponents component, int index = 0)
{ {
var toSign = GetIdForElement(GetComponentQueryString(component), index); var nodes = Document.SelectNodes(GetComponentQueryString(component));
var hash = XMLHashProvider.ComputeHash(Document, toSign);
return GetHashValue(hash, toSign);
if (nodes == null || nodes.Count == 0) {
throw new Exception(string.Format("Component {0} not found", component.XMLElementName()));
}
if (index >= nodes.Count) {
throw new Exception(string.Format("index exceeds number of components found! index: {0}, #components: {1}", index,
nodes.Count));
}
return DoComputeHash(nodes[index]);
}
private static string DoComputeHash(XmlNode dataNode)
{
var parent = dataNode.ParentNode;
var componentId = dataNode.Attributes[XMLNames.Component_ID_Attr].Value;
if (parent == null) {
throw new Exception("Invalid structure of input XML!");
}
var newDoc = new XmlDocument();
var node = newDoc.CreateElement("Dummy");
newDoc.AppendChild(node);
var newNode = newDoc.ImportNode(parent, true);
node.AppendChild(newNode);
var hash = XMLHashProvider.ComputeHash(newDoc, componentId);
return GetHashValueFromSig(hash, componentId);
} }
public XDocument AddHash() public XDocument AddHash()
...@@ -128,16 +154,27 @@ namespace TUGraz.VectoHashing ...@@ -128,16 +154,27 @@ namespace TUGraz.VectoHashing
public string ReadHash() public string ReadHash()
{ {
var toRead = GetIdForElement(GetComponentQueryString()); var nodes = Document.SelectNodes(GetComponentQueryString());
return GetHashValue(Document, toRead); if (nodes == null || nodes.Count == 0) {
throw new Exception(string.Format("Component {0} not found", nodes.Count));
}
return ReadHashValue(nodes[0]);
} }
public string ReadHash(VectoComponents component, int index = 0) public string ReadHash(VectoComponents component, int index = 0)
{ {
var toRead = GetIdForElement(GetComponentQueryString(component), index); var nodes = Document.SelectNodes(GetComponentQueryString(component));
return GetHashValue(Document, toRead); if (nodes == null || nodes.Count == 0) {
throw new Exception(string.Format("Component {0} not found", component.XMLElementName()));
}
if (index >= nodes.Count) {
throw new Exception(string.Format("index exceeds number of components found! index: {0}, #components: {1}", index,
nodes.Count));
}
return ReadHashValue(nodes[index]);
} }
public bool ValidateHash() public bool ValidateHash()
{ {
return ReadHash().Equals(ComputeHash(), StringComparison.Ordinal); return ReadHash().Equals(ComputeHash(), StringComparison.Ordinal);
...@@ -149,30 +186,37 @@ namespace TUGraz.VectoHashing ...@@ -149,30 +186,37 @@ namespace TUGraz.VectoHashing
ComputeHash(component, index)); ComputeHash(component, index));
} }
private static string GetComponentQueryString(VectoComponents? component = null) private static string GetComponentQueryString(VectoComponents? component = null)
{ {
if (component == null) { if (component == null) {
return "(//*[@id]/@id)[1]"; return "(//*[@id])[1]";
} }
return component == VectoComponents.Vehicle return component == VectoComponents.Vehicle
? string.Format("//*[local-name()='{0}']/@id", component.Value.XMLElementName()) ? string.Format("//*[local-name()='{0}']", component.Value.XMLElementName())
: string.Format("//*[local-name()='{0}']/*[local-name()='Data']/@id", component.Value.XMLElementName()); : string.Format("//*[local-name()='{0}']/*[local-name()='Data']", component.Value.XMLElementName());
} }
private string GetIdForElement(string query, int index = 0) private static string GetHashValueFromSig(XmlDocument hashed, string elementId)
{ {
var node = Document.SelectNodes(query); var nodes = hashed.SelectNodes("//*[@URI='#" + elementId + "']/*[local-name() = 'DigestValue']");
if (node == null) { if (nodes == null || nodes.Count == 0) {
return null; return null;
} }
var toSign = node[index].Value; if (nodes.Count > 1) {
return toSign; throw new Exception("Multiple DigestValue elements found!");
}
return nodes[0].InnerText;
} }
private static string GetHashValue(XmlDocument hashed, string elementToHash) private static string ReadHashValue(XmlNode dataNode)
{ {
//var node = hashed.SelectSingleNode("//*[@URI='#" + elementToHash + "']/*[local-name() = 'DigestValue']"); var parent = dataNode.ParentNode;
var nodes = hashed.SelectNodes("//*[@URI='#" + elementToHash + "']/*[local-name() = 'DigestValue']"); if (parent == null) {
throw new Exception("Invalid structure of input XML!");
}
var elementToHash = dataNode.Attributes[XMLNames.Component_ID_Attr].Value;
var nodes = parent.SelectNodes(".//*[@URI='#" + elementToHash + "']/*[local-name() = 'DigestValue']");
if (nodes == null || nodes.Count == 0) { if (nodes == null || nodes.Count == 0) {
return null; return null;
} }
......
...@@ -60,6 +60,20 @@ namespace VectoHashingTest ...@@ -60,6 +60,20 @@ namespace VectoHashingTest
Assert.AreEqual(expectedHash, hash); Assert.AreEqual(expectedHash, hash);
} }
[TestCase(ReferenceXMLEngine)]
public void TestHashComputationInvalidComponent(string file)
{
var h = VectoHash.Load(file);
AssertHelper.Exception<Exception>(() => h.ComputeHash(VectoComponents.Gearbox), "Component Gearbox not found");
}
[TestCase(ReferenceXMLEngine)]
public void TestReadHashInvalidComponent(string file)
{
var h = VectoHash.Load(file);
AssertHelper.Exception<Exception>(() => h.ReadHash(VectoComponents.Gearbox), "Component Gearbox not found");
}
[TestCase(ReferenceXMLVehicle, VectoComponents.Engine, "e0c253b643f7f8f09b963aca4a264d06fbfa599f"), [TestCase(ReferenceXMLVehicle, VectoComponents.Engine, "e0c253b643f7f8f09b963aca4a264d06fbfa599f"),
TestCase(ReferenceXMLVehicle, VectoComponents.Gearbox, "d14189366134120e08fa3f2c6e3328dd13c08a23")] TestCase(ReferenceXMLVehicle, VectoComponents.Gearbox, "d14189366134120e08fa3f2c6e3328dd13c08a23")]
public void TestReadHash(string file, VectoComponents component, string expectedHash) public void TestReadHash(string file, VectoComponents component, string expectedHash)
...@@ -80,6 +94,75 @@ namespace VectoHashingTest ...@@ -80,6 +94,75 @@ namespace VectoHashingTest
Assert.AreEqual(expectedHash, existingHash); Assert.AreEqual(expectedHash, existingHash);
} }
[TestCase]
public void TestReadTyres1Index()
{
var file = @"Testdata\XML\ToHash\vecto_vehicle-sample_3axle1.xml";
var h = VectoHash.Load(file);
var expectedHash = new[] {
"5074334bb2c090c5e258e9a664f5d19689a3f13d",
"6074334bb2c090c5e258e9a664f5d19689a3f13d",
"6074334bb2c090c5e258e9a664f5d19689a3f13d"
};
for (int i = 0; i < expectedHash.Length; i++) {
var existingHash = h.ReadHash(VectoComponents.Tyre, i);
Assert.AreEqual(expectedHash[i], existingHash);
}
}
[TestCase]
public void TestReadTyres2Index()
{
var file = @"Testdata\XML\ToHash\vecto_vehicle-sample_3axle2.xml";
var h = VectoHash.Load(file);
var expectedHash = new[] {
"5074334bb2c090c5e258e9a664f5d19689a3f13d",
"5074334bb2c090c5e258e9a664f5d19689a3f13d",
"6074334bb2c090c5e258e9a664f5d19689a3f13d"
};
for (int i = 0; i < expectedHash.Length; i++) {
var existingHash = h.ReadHash(VectoComponents.Tyre, i);
Assert.AreEqual(expectedHash[i], existingHash);
}
AssertHelper.Exception<Exception>(() => h.ReadHash(VectoComponents.Tyre, 3),
"index exceeds number of components found! index: 3, #components: 3");
}
[TestCase]
public void TestComputeTyres1Index()
{
var file = @"Testdata\XML\ToHash\vecto_vehicle-sample_3axle1.xml";
var h = VectoHash.Load(file);
var hash1 = h.ComputeHash(VectoComponents.Tyre, 1);
var hash2 = h.ComputeHash(VectoComponents.Tyre, 2);
Assert.AreEqual(hash1, hash2);
AssertHelper.Exception<Exception>(() => h.ComputeHash(VectoComponents.Tyre, 3),
"index exceeds number of components found! index: 3, #components: 3");
}
[TestCase]
public void TestComputeTyres2Index()
{
var file = @"Testdata\XML\ToHash\vecto_vehicle-sample_3axle2.xml";
var h = VectoHash.Load(file);
var hash1 = h.ComputeHash(VectoComponents.Tyre, 0);
var hash2 = h.ComputeHash(VectoComponents.Tyre, 1);
Assert.AreEqual(hash1, hash2);
AssertHelper.Exception<Exception>(() => h.ComputeHash(VectoComponents.Tyre, 3),
"index exceeds number of components found! index: 3, #components: 3");
}
[TestCase("vecto_vehicle-sample_FULL_Comments.xml", BasicHasingTests.HashVehicleXML), [TestCase("vecto_vehicle-sample_FULL_Comments.xml", BasicHasingTests.HashVehicleXML),
TestCase("vecto_vehicle-sample_FULL_Entry_Order.xml", BasicHasingTests.HashVehicleXML), TestCase("vecto_vehicle-sample_FULL_Entry_Order.xml", BasicHasingTests.HashVehicleXML),
TestCase("vecto_vehicle-sample_FULL_Newlines_Linux_LF.xml", BasicHasingTests.HashVehicleXML), TestCase("vecto_vehicle-sample_FULL_Newlines_Linux_LF.xml", BasicHasingTests.HashVehicleXML),
...@@ -178,6 +261,15 @@ namespace VectoHashingTest ...@@ -178,6 +261,15 @@ namespace VectoHashingTest
AssertHelper.Exception<Exception>(() => { var r = h.AddHash(); }, expectedExceptionMsg); AssertHelper.Exception<Exception>(() => { var r = h.AddHash(); }, expectedExceptionMsg);
} }
[TestCase]
public void TestDuplicateSigElement()
{
var filename = @"Testdata\XML\Invalid\duplicate-sig.xml";
var h = VectoHash.Load(filename);
AssertHelper.Exception<Exception>(() => { var r = h.ReadHash(); }, "Multiple DigestValue elements found!");
}
[TestCase()] [TestCase()]
public void TestLoadFromStream() public void TestLoadFromStream()
...@@ -246,6 +338,22 @@ namespace VectoHashingTest ...@@ -246,6 +338,22 @@ namespace VectoHashingTest
Assert.AreEqual(expectedHash, hash); Assert.AreEqual(expectedHash, hash);
} }
[TestCase()]
public void TestInvalidXMLAsFile()
{
var file = @"Testdata\XML\Invalid\invalid-comp.xml";
AssertHelper.Exception<Exception>(() => VectoHash.Load(file), "failed to read XML document");
}
[TestCase()]
public void TestInvalidXMLAsStream()
{
var file = @"Testdata\XML\Invalid\invalid-comp.xml";
var stream = File.Open(file, FileMode.Open);
AssertHelper.Exception<Exception>(() => VectoHash.Load(stream), "failed to read XML document");
}
private static XmlSchemaSet GetXMLSchema(bool job) private static XmlSchemaSet GetXMLSchema(bool job)
{ {
var resource = RessourceHelper.LoadResourceAsStream(RessourceHelper.ResourceType.XMLSchema, var resource = RessourceHelper.LoadResourceAsStream(RessourceHelper.ResourceType.XMLSchema,
......
...@@ -65,6 +65,12 @@ ...@@ -65,6 +65,12 @@
<None Include="packages.config" /> <None Include="packages.config" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Content Include="Testdata\XML\Invalid\duplicate-sig.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Testdata\XML\Invalid\invalid-comp.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Testdata\XML\Reference\vecto_engine-sample.xml"> <Content Include="Testdata\XML\Reference\vecto_engine-sample.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
...@@ -92,6 +98,12 @@ ...@@ -92,6 +98,12 @@
<Content Include="Testdata\XML\ToHash\vecto_gearbox-input_nodata.xml"> <Content Include="Testdata\XML\ToHash\vecto_gearbox-input_nodata.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
<Content Include="Testdata\XML\ToHash\vecto_vehicle-sample_3axle1.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Testdata\XML\ToHash\vecto_vehicle-sample_3axle2.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Testdata\XML\ToHash\vecto_vehicle-sample.xml"> <Content Include="Testdata\XML\ToHash\vecto_vehicle-sample.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment