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
{
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");
}
var signedXml = new SignedXml(doc);
......
......@@ -2,6 +2,7 @@
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml;
using System.Xml.Linq;
using TUGraz.VectoCommon.Utils;
......@@ -14,7 +15,6 @@ namespace TUGraz.VectoHashing
public class VectoHash : IVectoHash
{
protected XmlDocument Document;
private XmlNamespaceManager Manager;
public static VectoHash Load(string filename)
{
......@@ -46,7 +46,6 @@ namespace TUGraz.VectoHashing
protected VectoHash(XmlDocument doc)
{
Document = doc;
Manager = new XmlNamespaceManager(doc.NameTable);
}
public IList<VectoComponents> GetContainigComponents()
......@@ -54,7 +53,7 @@ namespace TUGraz.VectoHashing
var retVal = new List<VectoComponents>();
foreach (var component in EnumHelper.GetValues<VectoComponents>()) {
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++) {
retVal.Add(component);
}
......@@ -64,16 +63,43 @@ namespace TUGraz.VectoHashing
public string ComputeHash()
{
var toSign = GetIdForElement(GetComponentQueryString());
var hash = XMLHashProvider.ComputeHash(Document, toSign);
return GetHashValue(hash, toSign);
var nodes = Document.SelectNodes(GetComponentQueryString());
if (nodes == null || nodes.Count == 0) {
throw new Exception("No component found");
}
return DoComputeHash(nodes[0]);
}
public string ComputeHash(VectoComponents component, int index = 0)
{
var toSign = GetIdForElement(GetComponentQueryString(component), index);
var hash = XMLHashProvider.ComputeHash(Document, toSign);
return GetHashValue(hash, toSign);
var nodes = Document.SelectNodes(GetComponentQueryString(component));
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()
......@@ -128,16 +154,27 @@ namespace TUGraz.VectoHashing
public string ReadHash()
{
var toRead = GetIdForElement(GetComponentQueryString());
return GetHashValue(Document, toRead);
var nodes = Document.SelectNodes(GetComponentQueryString());
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)
{
var toRead = GetIdForElement(GetComponentQueryString(component), index);
return GetHashValue(Document, toRead);
var nodes = Document.SelectNodes(GetComponentQueryString(component));
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()
{
return ReadHash().Equals(ComputeHash(), StringComparison.Ordinal);
......@@ -149,30 +186,37 @@ namespace TUGraz.VectoHashing
ComputeHash(component, index));
}
private static string GetComponentQueryString(VectoComponents? component = null)
{
if (component == null) {
return "(//*[@id]/@id)[1]";
return "(//*[@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());
? string.Format("//*[local-name()='{0}']", 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);
if (node == null) {
var nodes = hashed.SelectNodes("//*[@URI='#" + elementId + "']/*[local-name() = 'DigestValue']");
if (nodes == null || nodes.Count == 0) {
return null;
}
var toSign = node[index].Value;
return toSign;
if (nodes.Count > 1) {
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 nodes = hashed.SelectNodes("//*[@URI='#" + elementToHash + "']/*[local-name() = 'DigestValue']");
var parent = dataNode.ParentNode;
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) {
return null;
}
......
......@@ -60,6 +60,20 @@ namespace VectoHashingTest
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.Gearbox, "d14189366134120e08fa3f2c6e3328dd13c08a23")]
public void TestReadHash(string file, VectoComponents component, string expectedHash)
......@@ -80,6 +94,75 @@ namespace VectoHashingTest
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_Entry_Order.xml", BasicHasingTests.HashVehicleXML),
TestCase("vecto_vehicle-sample_FULL_Newlines_Linux_LF.xml", BasicHasingTests.HashVehicleXML),
......@@ -178,6 +261,15 @@ namespace VectoHashingTest
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()]
public void TestLoadFromStream()
......@@ -246,6 +338,22 @@ namespace VectoHashingTest
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)
{
var resource = RessourceHelper.LoadResourceAsStream(RessourceHelper.ResourceType.XMLSchema,
......
......@@ -65,6 +65,12 @@
<None Include="packages.config" />
</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">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
......@@ -92,6 +98,12 @@
<Content Include="Testdata\XML\ToHash\vecto_gearbox-input_nodata.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</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">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</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