Code development platform for open source projects from the European Union institutions :large_blue_circle: EU Login authentication by SMS will be completely phased out by mid-2025. To see alternatives please check here

Skip to content
Snippets Groups Projects
Commit 6236ffcb authored by Markus Quaritsch's avatar Markus Quaritsch
Browse files

draft implementation of computing hashes for VECTO purpose

parent 74fb25af
No related branches found
No related tags found
No related merge requests found
Showing
with 423 additions and 114 deletions
using System.Collections.Generic;
using System.Xml.Linq;
namespace TUGraz.VectoHashing
{
public interface IVectoHash {
IEnumerable<VectoComponents> GetContainigComponents();
string ComputeHash();
string ComputeHash(VectoComponents component);
XDocument AddHash();
string ReadHash();
string ReadHash(VectoComponents component);
bool ValidateHash();
bool ValidateHash(VectoComponents component);
}
}
\ No newline at end of file
using System;
using System.IO;
using System.Reflection;
using System.Security.Cryptography.Xml;
using System.Text;
using System.Xml;
namespace TUGraz.VectoHashing
{
public class XmlDsigVectoTransform : Transform
{
//private static readonly Type[] _inputTypes = { typeof(Stream), typeof(XmlDocument), typeof(XmlNodeList) };
//private static readonly Type[] _outputTypes = { typeof(Stream) };
//private XmlDocument _doc = new XmlDocument();
private XmlDsigXsltTransform _transform;
public XmlDsigVectoTransform()
{
Algorithm = "urn:vecto:xml:2017:canonicalization";
_transform = new XmlDsigXsltTransform();
XmlDocument doc = new XmlDocument();
doc.Load(ReadStream("TUGraz.VectoHashing.Resources.XSLT.SortInputData.xslt"));
_transform.LoadInnerXml(doc.ChildNodes);
}
public override void LoadInnerXml(XmlNodeList nodeList) {}
protected override XmlNodeList GetInnerXml()
{
return null;
}
public override void LoadInput(object obj)
{
_transform.LoadInput(obj);
}
public override object GetOutput()
{
return _transform.GetOutput();
}
public override object GetOutput(Type type)
{
return _transform.GetOutput(type);
}
public override Type[] InputTypes
{
get { return _transform.InputTypes; }
}
public override Type[] OutputTypes
{
get { return _transform.OutputTypes; }
}
private static Stream ReadStream(string resourceName)
{
var assembly = Assembly.GetExecutingAssembly();
var resource = assembly.GetManifestResourceStream(resourceName);
if (resource == null) {
throw new Exception("Resource file not found: " + resourceName);
}
return resource;
}
}
}
\ No newline at end of file
using System;
using System.Security.Cryptography;
using System.Security.Cryptography.Xml;
using System.Text;
using System.Xml;
namespace TUGraz.VectoHashing
namespace TUGraz.VectoHashing.Impl
{
public class XmlHashTest
public class XMLHashProvider
{
public string ComputeHash(XmlDocument doc)
public XmlDocument ComputeHash(XmlDocument doc, string elementId)
{
if (doc == null || doc.DocumentElement == null) {
throw new Exception("Invalid Document");
}
var signedXml = new SignedXml(doc);
var reference = new Reference("#elemID") {
var reference = new Reference("#" + elementId) {
DigestMethod = "http://www.w3.org/2001/04/xmlenc#sha256"
};
reference.AddTransform(new XmlDsigVectoTransform());
reference.AddTransform(new XmlDsigC14NTransform());
//reference.AddTransform(new XmlDsigVectoTransform());
signedXml.AddReference(reference);
signedXml.ComputeSignature(HMAC.Create());
......@@ -28,11 +31,7 @@ namespace TUGraz.VectoHashing
if (doc.FirstChild is XmlDeclaration) {
doc.RemoveChild(doc.FirstChild);
}
var xmltw = new XmlTextWriter("simple_document_hashed.xml", new UTF8Encoding(false));
doc.WriteTo(xmltw);
xmltw.Close();
var references = signedXml.SignedInfo.References;
return Convert.ToBase64String(((Reference)references[0]).DigestValue);
return doc;
}
}
}
\ No newline at end of file
<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<xsl:output omit-xml-declaration="no" indent="yes"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[name()='FuelConsumptionMap']">
<xsl:copy>
<xsl:for-each select="*">
<xsl:sort data-type="number" select="@engineSpeed" order="ascending"/>
<xsl:sort data-type="number" select="@torque" order="ascending"/>
<xsl:apply-templates select="."/>
</xsl:for-each>
</xsl:copy>
</xsl:template>
<xsl:template match="*[name()='FullLoadAndDragCurve']">
<xsl:copy>
<xsl:for-each select="*">
<xsl:sort data-type="number" select="@engineSpeed" order="ascending"/>
<xsl:apply-templates select="."/>
</xsl:for-each>
</xsl:copy>
</xsl:template>
<xsl:template match="*[name()='TorqueLossMap']">
<xsl:copy>
<xsl:for-each select="*">
<xsl:sort data-type="number" select="@inputSpeed" order="ascending"/>
<xsl:sort data-type="number" select="@inputTorque" order="ascending"/>
<xsl:apply-templates select="."/>
</xsl:for-each>
</xsl:copy>
</xsl:template>
<xsl:template match="*[name()='RetarderLossMap']">
<xsl:copy>
<xsl:for-each select="*">
<xsl:sort data-type="number" select="@retarderSpeed" order="ascending"/>
<xsl:apply-templates select="."/>
</xsl:for-each>
</xsl:copy>
</xsl:template>
<xsl:template match="*[name()='TorqueLimits']">
<xsl:copy>
<xsl:for-each select="*">
<xsl:sort data-type="number" select="@gear" order="ascending"/>
<xsl:apply-templates select="."/>
</xsl:for-each>
</xsl:copy>
</xsl:template>
<xsl:template match="*[name()='Gears']">
<xsl:copy>
<xsl:for-each select="*">
<xsl:sort data-type="number" select="@number" order="ascending"/>
<xsl:apply-templates select="."/>
</xsl:for-each>
</xsl:copy>
</xsl:template>
<xsl:template match="*[name()='Characteristics']">
<xsl:copy>
<xsl:for-each select="*">
<xsl:sort data-type="number" select="@speedRatio" order="ascending"/>
<xsl:apply-templates select="."/>
</xsl:for-each>
</xsl:copy>
</xsl:template>
<xsl:template match="*[name()='Axles']">
<xsl:copy>
<xsl:for-each select="*">
<xsl:sort data-type="number" select="@axleNumber" order="ascending"/>
<xsl:apply-templates select="."/>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:transform>
using System.Xml;
using System.Xml.Linq;
namespace TUGraz.VectoHashing.Util
{
public static class XmlDocumentExtensions
{
public static XDocument ToXDocument(this XmlDocument document)
{
return document.ToXDocument(LoadOptions.None);
}
public static XDocument ToXDocument(this XmlDocument document, LoadOptions options)
{
using (XmlNodeReader reader = new XmlNodeReader(document)) {
return XDocument.Load(reader, options);
}
}
}
}
\ No newline at end of file
namespace TUGraz.VectoHashing
{
public enum VectoComponents
{
Engine,
Gearbox,
Axlegear,
Retarder,
TorqueConverter,
Angledrive,
Airdrag,
Tyre,
Vehicle,
}
}
\ No newline at end of file
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Xml.Linq;
namespace TUGraz.VectoHashing
{
public class VectoHash : IVectoHash
{
public static VectoHash Load(string filename)
{
return null;
}
public static VectoHash Load(Stream stream)
{
return null;
}
public static VectoHash Load(XDocument doc)
{
return null;
}
public IEnumerable<VectoComponents> GetContainigComponents()
{
return null;
}
public string ComputeHash()
{
return null;
}
public string ComputeHash(VectoComponents component)
{
return null;
}
public XDocument AddHash()
{
return null;
}
public string ReadHash()
{
return null;
}
public string ReadHash(VectoComponents component)
{
return null;
}
public bool ValidateHash()
{
return false;
}
public bool ValidateHash(VectoComponents component)
{
return false;
}
}
}
\ No newline at end of file
......@@ -40,9 +40,16 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Impl\XmlDsigVectoTransform.cs" />
<Compile Include="IVectoHash.cs" />
<Compile Include="Util\XmlDocumentExtensions.cs" />
<Compile Include="VectoComponents.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="XmlHashProvider.cs" />
<Compile Include="XmlHashTest.cs" />
<Compile Include="VectoHash.cs" />
<Compile Include="Impl\XmlHashProvider.cs" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Resources\XSLT\SortInputData.xslt" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
......
using System;
using System.IO;
using System.Security.Cryptography;
using System.Security.Cryptography.Xml;
using System.Xml;
namespace TUGraz.VectoHashing
{
public class XmlHashProvider
{
protected string File;
public XmlHashProvider(string file)
{
File = file;
}
public string ComputeHash(string xpath)
{
var xml = new XmlDocument();
var manager = new XmlNamespaceManager(xml.NameTable);
manager.AddNamespace("ved", "urn:tugraz:ivt:VectoAPI:EngineeringDefinitions:v0.8");
manager.AddNamespace("tns", "urn:tugraz:ivt:VectoAPI:EngineeringInput:v0.8");
using (var fs = new FileStream(File, FileMode.Open)) {
using (var sr = new StreamReader(fs)) {
xml.Load(new LineCleaningTextReader(sr));
}
}
var nodeList = xml.SelectNodes(string.Format("{0}/descendant-or-self::node()|{0}//@*", xpath), manager);
if (nodeList == null || nodeList.Count == 0) {
throw new Exception(string.Format("Selected node '{0}' not found in input!", xpath));
}
var transform = new XmlDsigC14NTransform();
transform.LoadInput(nodeList);
var sha256 = new SHA256CryptoServiceProvider();
var hash = sha256.ComputeHash((Stream)transform.GetOutput(typeof(Stream)));
return Convert.ToBase64String(hash);
}
private class LineCleaningTextReader : TextReader
{
private readonly TextReader _src;
public LineCleaningTextReader(TextReader src)
{
_src = src;
}
public override int Read()
{
int r = _src.Read();
switch (r) {
case 0xD: // \r
switch (_src.Peek()) {
case 0xA:
case 0x85: // \n or NEL char
_src.Read();
break;
}
return 0xA;
case 0x85: //NEL
return 0xA;
default:
return r;
}
}
}
}
}
\ No newline at end of file
using System;
using System.Text;
using System.Xml;
using System.Xml.XPath;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using TUGraz.VectoHashing;
using TUGraz.VectoHashing.Impl;
using TUGraz.VectoHashing.Util;
namespace VectoHashingTest
{
[TestClass]
public class BasicHasingTests
{
public const string SimpleXML = @"Testdata\XML\simple_document.xml";
public const string ReferenceXMLEngine = @"Testdata\XML\Reference\vecto_engine-sample.xml";
public const string ReferenceXMLVehicle = @"Testdata\XML\Reference\vecto_vehicle-sample_FULL.xml";
public const string UnorderedXMLVehicle = @"Testdata\XML\Variations\vecto_vehicle-sample_FULL_Entry_Order.xml";
[TestMethod]
public void HashSimpleXml()
{
var elementToHash = "elemID";
var doc = new XmlDocument();
doc.Load(SimpleXML);
var hasher = new XMLHashProvider();
var hashed = hasher.ComputeHash(doc, elementToHash);
var hash = GetHashValue(hashed, elementToHash);
WriteSignedXML(doc, "simple_document_hashed.xml");
Assert.AreEqual("U2zic7KOnKw60rzh+KKQ1lwZL6NmXju+DXG7cYYmlxo=", hash);
}
[TestMethod]
public void HashReferenceEngineXML()
{
var elementToHash = "ENG-gooZah3D";
var doc = new XmlDocument();
doc.Load(ReferenceXMLEngine);
var hasher = new XMLHashProvider();
var hashed = hasher.ComputeHash(doc, elementToHash);
var hash = GetHashValue(hashed, elementToHash);
WriteSignedXML(doc, "reference_engine_hashed.xml");
Assert.AreEqual("VZ3s5f3JtWTTrEex4uNcwQqh9Nzzdo6gkAQ3vD5qGUo=", hash);
}
[TestMethod]
public void HashReferenceVehicleXML()
{
var elementToHash = "VEH-1234567890";
var doc = new XmlDocument();
doc.Load(ReferenceXMLVehicle);
var hasher = new XMLHashProvider();
var hashed = hasher.ComputeHash(doc, elementToHash);
var hash = GetHashValue(hashed, elementToHash);
WriteSignedXML(doc, "reference_vehicle_hashed.xml");
Assert.AreEqual("HhMqWPkLcgxex1qAfBS7e7gopytbW6k8svNyW/B9+iw=", hash);
}
[TestMethod]
public void HashUnorderedVehicleXML()
{
var elementToHash = "VEH-1234567890";
var doc = new XmlDocument();
doc.Load(UnorderedXMLVehicle);
var hasher = new XMLHashProvider();
var hashed = hasher.ComputeHash(doc, elementToHash);
var hash = GetHashValue(hashed, elementToHash);
WriteSignedXML(doc, "reference_vehicle_hashed.xml");
Assert.AreEqual("HhMqWPkLcgxex1qAfBS7e7gopytbW6k8svNyW/B9+iw=", hash);
}
private static string GetHashValue(XmlDocument hashed, string elementToHash)
{
var xdoc = hashed.ToXDocument();
var hash = xdoc.XPathSelectElement("//*[@URI='#" + elementToHash + "']/*[local-name() = 'DigestValue']").Value;
return hash;
}
private static void WriteSignedXML(XmlDocument doc, string filename)
{
var xmltw = new XmlTextWriter(filename, new UTF8Encoding(false));
doc.WriteTo(xmltw);
xmltw.Close();
}
}
}
\ No newline at end of file
using System;
using System.Xml;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using TUGraz.VectoHashing;
namespace VectoHashingTest
{
[TestClass]
public class UnitTest1
{
public const string SimpleXML = @"Testdata\XML\simple_document.xml";
[TestMethod]
public void TestCompareHashing()
{
var hasher1 = new XmlHashProvider(SimpleXML);
var hash1 = hasher1.ComputeHash("//*[@id='elemID']");
var doc = new XmlDocument();
doc.Load(SimpleXML);
var hasher2 = new XmlHashTest();
var hash2 = hasher2.ComputeHash(doc);
Assert.AreEqual(hash1, hash2);
}
}
}
\ No newline at end of file
......@@ -37,6 +37,7 @@
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Xml" />
<Reference Include="System.Xml.Linq" />
</ItemGroup>
<Choose>
<When Condition="('$(VisualStudioVersion)' == '10.0' or '$(VisualStudioVersion)' == '') and '$(TargetFrameworkVersion)' == 'v3.5'">
......@@ -51,14 +52,56 @@
</Otherwise>
</Choose>
<ItemGroup>
<Compile Include="UnitTest1.cs" />
<Compile Include="BasicHasingTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup />
<ItemGroup>
<Content Include="Testdata\XML\Reference\vecto_engine-sample.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Testdata\XML\Reference\vecto_vehicle-sample_FULL.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Testdata\XML\simple_document.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Testdata\XML\Variations\vecto_engine-sample Encoding ISO 8859-15.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Testdata\XML\Variations\vecto_engine-sample Encoding UTF-16 BE BOM.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Testdata\XML\Variations\vecto_engine-sample Encoding UTF-16 LE.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Testdata\XML\Variations\vecto_engine-sample Encoding UTF-8 BOM.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Testdata\XML\Variations\vecto_engine-sample Encoding UTF-8.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Testdata\XML\Variations\vecto_engine-sample Encoding windows-1292.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Testdata\XML\Variations\vecto_engine-sample_Whitespaces.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Testdata\XML\Variations\vecto_vehicle-sample_FULL_Comments.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Testdata\XML\Variations\vecto_vehicle-sample_FULL_Entry_Order.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Testdata\XML\Variations\vecto_vehicle-sample_FULL_Newlines_Linux_LF.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Testdata\XML\Variations\vecto_vehicle-sample_FULL_Newlines_Mac_CR.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Testdata\XML\Variations\vecto_vehicle-sample_FULL_Newlines_Windows_CRLF.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\VectoHashing\VectoHashing.csproj">
......
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