[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[libeufin] 02/03: signing / verification WIP
From: |
gnunet |
Subject: |
[libeufin] 02/03: signing / verification WIP |
Date: |
Mon, 28 Oct 2019 22:46:42 +0100 |
This is an automated email from the git hooks/post-receive script.
dold pushed a commit to branch master
in repository libeufin.
commit 264d6c496a6df8b32a5c7aca7b9ecce1947d3998
Author: Florian Dold <address@hidden>
AuthorDate: Mon Oct 28 18:37:39 2019 +0100
signing / verification WIP
---
sandbox/build.gradle | 2 ++
sandbox/src/main/kotlin/Main.kt | 16 +++++-----
sandbox/src/main/kotlin/{XML.kt => XMLUtil.kt} | 42 ++++++++++++++++++-------
sandbox/src/test/kotlin/HiaLoadTest.kt | 4 +--
sandbox/src/test/kotlin/JaxbTest.kt | 4 +--
sandbox/src/test/kotlin/MarshalNonJaxbTest.kt | 2 +-
sandbox/src/test/kotlin/ResponseTest.kt | 2 +-
sandbox/src/test/kotlin/XmlSigTest.kt | 24 +++++---------
sandbox/src/test/kotlin/XmlTest.kt | 5 +--
sandbox/src/test/kotlin/XsiTypeAttributeTest.kt | 6 ++--
10 files changed, 58 insertions(+), 49 deletions(-)
diff --git a/sandbox/build.gradle b/sandbox/build.gradle
index 4c14e89..912ec8c 100644
--- a/sandbox/build.gradle
+++ b/sandbox/build.gradle
@@ -33,6 +33,8 @@ dependencies {
compile "javax.activation:activation:1.1"
compile "org.glassfish.jaxb:jaxb-runtime:2.3.1"
testCompile group: 'junit', name: 'junit', version: '4.12'
+ testImplementation 'org.jetbrains.kotlin:kotlin-test-junit:1.3.50'
+ testImplementation 'org.jetbrains.kotlin:kotlin-test:1.3.50'
compile 'org.apache.santuario:xmlsec:2.1.4'
runtime rootProject.files("resources")
}
diff --git a/sandbox/src/main/kotlin/Main.kt b/sandbox/src/main/kotlin/Main.kt
index 4cca079..9e64892 100644
--- a/sandbox/src/main/kotlin/Main.kt
+++ b/sandbox/src/main/kotlin/Main.kt
@@ -36,6 +36,7 @@ import io.ktor.routing.post
import io.ktor.routing.routing
import io.ktor.server.engine.embeddedServer
import io.ktor.server.netty.Netty
+import io.ktor.util.pipeline.PipelineContext
import org.jetbrains.exposed.dao.EntityID
import org.jetbrains.exposed.sql.transactions.transaction
import org.slf4j.LoggerFactory
@@ -48,17 +49,15 @@ import java.math.BigInteger
import java.nio.charset.StandardCharsets.US_ASCII
import java.text.DateFormat
import java.security.KeyFactory
-import java.security.KeyPairGenerator
import java.security.PrivateKey
import java.security.PublicKey
-import java.security.interfaces.RSAPrivateKey
import java.security.spec.RSAPrivateKeySpec
import java.security.spec.RSAPublicKeySpec
import java.util.*
import java.util.zip.InflaterInputStream
val logger = LoggerFactory.getLogger("tech.libeufin.sandbox")
-val xmlProcess = XML()
+val xmlProcess = XMLUtil()
val getEbicsHostId = {"LIBEUFIN-SANDBOX"}
val getEbicsVersion = {"H004"}
val getEbicsRevision = {1}
@@ -149,7 +148,7 @@ object OkHelper {
* @return the modified document
*/
fun downcastXml(document: Document, node: String, type: String) : Document {
- logger.debug("Downcasting: ${XML.convertDomToString(document)}")
+ logger.debug("Downcasting: ${XMLUtil.convertDomToString(document)}")
val x: Element = document.getElementsByTagNameNS(
"urn:org:ebics:H004",
"OrderDetails"
@@ -234,7 +233,7 @@ private suspend fun ApplicationCall.adminCustomers() {
logger.info(body.toString())
val returnId = transaction {
- var myUserId = EbicsUser.new { }
+ val myUserId = EbicsUser.new { }
val myPartnerId = EbicsPartner.new { }
val mySystemId = EbicsSystem.new { }
val subscriber = EbicsSubscriber.new {
@@ -395,10 +394,10 @@ private suspend fun ApplicationCall.ebicsweb() {
val body: String = receiveText()
logger.debug("Data received: $body")
- val bodyDocument: Document? = XML.parseStringIntoDom(body)
+ val bodyDocument: Document? = XMLUtil.parseStringIntoDom(body)
if (bodyDocument == null || (!xmlProcess.validateFromDom(bodyDocument))) {
- var response = EbicsResponse(
+ val response = EbicsResponse(
returnCode = InvalidXmlHelper.getCode(),
reportText = InvalidXmlHelper.getMessage()
)
@@ -493,7 +492,7 @@ private suspend fun ApplicationCall.ebicsweb() {
*/
if (zkey.isEmpty()) {
logger.info("0-length key element given, invalid request")
- var response = KeyManagementResponse(
+ val response = KeyManagementResponse(
returnCode = InvalidXmlHelper.getCode(),
reportText = InvalidXmlHelper.getMessage("Key field was
empty")
)
@@ -678,6 +677,7 @@ private suspend fun ApplicationCall.ebicsweb() {
}
}
+
fun main() {
dbCreateTables()
val server = embeddedServer(Netty, port = 5000) {
diff --git a/sandbox/src/main/kotlin/XML.kt b/sandbox/src/main/kotlin/XMLUtil.kt
similarity index 89%
rename from sandbox/src/main/kotlin/XML.kt
rename to sandbox/src/main/kotlin/XMLUtil.kt
index 5d0b124..5f16bf9 100644
--- a/sandbox/src/main/kotlin/XML.kt
+++ b/sandbox/src/main/kotlin/XMLUtil.kt
@@ -42,6 +42,7 @@ import javax.xml.crypto.*
import javax.xml.crypto.dom.DOMURIReference
import javax.xml.crypto.dsig.*
import javax.xml.crypto.dsig.dom.DOMSignContext
+import javax.xml.crypto.dsig.dom.DOMValidateContext
import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec
import javax.xml.crypto.dsig.spec.TransformParameterSpec
import javax.xml.parsers.DocumentBuilderFactory
@@ -58,10 +59,13 @@ import javax.xml.xpath.XPathConstants
import javax.xml.xpath.XPathFactory
/**
- * This class takes care of importing XSDs and validate
- * XMLs against those.
+ * Helpers for dealing with XML in EBICS.
*/
-class XML {
+class XMLUtil {
+ /**
+ * This URI dereferencer allows handling the resource reference used for
+ * XML signatures in EBICS.
+ */
private class EbicsSigUriDereferencer : URIDereferencer {
override fun dereference(myRef: URIReference?, myCtx:
XMLCryptoContext?): Data {
val ebicsXpathExpr = "//*[@authenticate='true']"
@@ -141,15 +145,11 @@ class XML {
fun validate(xmlDoc: StreamSource): Boolean {
try {
validator?.validate(xmlDoc)
- } catch (e: SAXException) {
- println(e.message)
- return false
- } catch (e: IOException) {
- e.printStackTrace()
+ } catch (e: Exception) {
+ logger.warn("Validation failed: {}", e)
return false
}
-
- return true
+ return true;
}
/**
@@ -321,6 +321,9 @@ class XML {
}
+ /**
+ * Sign an EBICS document with the authentication and identity
signature.
+ */
fun signEbicsDocument(doc: Document, signingPriv: PrivateKey): Unit {
val xpath = XPathFactory.newInstance().newXPath()
val authSigNode =
xpath.compile("/*[1]/AuthSignature").evaluate(doc, XPathConstants.NODE)
@@ -355,7 +358,24 @@ class XML {
}
fun verifyEbicsDocument(doc: Document, signingPub: PublicKey): Boolean
{
- return false
+ val xpath = XPathFactory.newInstance().newXPath()
+ val doc2: Document = doc.cloneNode(true) as Document
+ val authSigNode =
xpath.compile("/*[1]/AuthSignature").evaluate(doc2, XPathConstants.NODE)
+ if (authSigNode !is Node)
+ throw java.lang.Exception("no AuthSignature")
+ val sigEl =
doc2.createElementNS("http://www.w3.org/2000/09/xmldsig#", "ds:Signature")
+ authSigNode.parentNode.insertBefore(sigEl, authSigNode)
+ while (authSigNode.hasChildNodes()) {
+ sigEl.appendChild(authSigNode.firstChild)
+ }
+ authSigNode.parentNode.removeChild(authSigNode)
+ val fac = XMLSignatureFactory.getInstance("DOM")
+ println(convertDomToString(doc2))
+ val dvc = DOMValidateContext(signingPub, sigEl)
+ dvc.uriDereferencer = EbicsSigUriDereferencer()
+ val sig = fac.unmarshalXMLSignature(dvc)
+ // FIXME: check that parameters are okay!
+ return sig.validate(dvc)
}
}
}
\ No newline at end of file
diff --git a/sandbox/src/test/kotlin/HiaLoadTest.kt
b/sandbox/src/test/kotlin/HiaLoadTest.kt
index 89810a1..bf34ccb 100644
--- a/sandbox/src/test/kotlin/HiaLoadTest.kt
+++ b/sandbox/src/test/kotlin/HiaLoadTest.kt
@@ -9,10 +9,10 @@ class HiaLoadTest {
@Test
fun hiaLoad() {
- val processor = XML()
+ val processor = XMLUtil()
val classLoader = ClassLoader.getSystemClassLoader()
val hia = classLoader.getResource("HIA.xml")
- val hiaDom = XML.parseStringIntoDom(hia.readText())
+ val hiaDom = XMLUtil.parseStringIntoDom(hia.readText())
val x: Element = hiaDom.getElementsByTagNameNS(
"urn:org:ebics:H004",
"OrderDetails"
diff --git a/sandbox/src/test/kotlin/JaxbTest.kt
b/sandbox/src/test/kotlin/JaxbTest.kt
index f4c9f90..a5a788f 100644
--- a/sandbox/src/test/kotlin/JaxbTest.kt
+++ b/sandbox/src/test/kotlin/JaxbTest.kt
@@ -7,7 +7,7 @@ import
tech.libeufin.messages.ebics.keyrequest.SignaturePubKeyOrderDataType
class JaxbTest {
- val processor = XML()
+ val processor = XMLUtil()
val classLoader = ClassLoader.getSystemClassLoader()
val hevResponseJaxb = HEVResponse(
"000000",
@@ -81,7 +81,7 @@ class JaxbTest {
@Test
fun domToJaxb() {
val ini =
classLoader.getResource("ebics_ini_request_sample_patched.xml")
- val iniDom = XML.parseStringIntoDom(ini.readText())
+ val iniDom = XMLUtil.parseStringIntoDom(ini.readText())
processor.convertDomToJaxb<EbicsUnsecuredRequest>(
EbicsUnsecuredRequest::class.java,
iniDom
diff --git a/sandbox/src/test/kotlin/MarshalNonJaxbTest.kt
b/sandbox/src/test/kotlin/MarshalNonJaxbTest.kt
index cc4759b..ce88953 100644
--- a/sandbox/src/test/kotlin/MarshalNonJaxbTest.kt
+++ b/sandbox/src/test/kotlin/MarshalNonJaxbTest.kt
@@ -34,7 +34,7 @@ class MarshalNonJaxbTest {
"EBICS_NON_OK"
)
- val proc = XML()
+ val proc = XMLUtil()
println(proc.convertJaxbToString(obj.get()))
}
}
\ No newline at end of file
diff --git a/sandbox/src/test/kotlin/ResponseTest.kt
b/sandbox/src/test/kotlin/ResponseTest.kt
index 8a5d942..d13c1c3 100644
--- a/sandbox/src/test/kotlin/ResponseTest.kt
+++ b/sandbox/src/test/kotlin/ResponseTest.kt
@@ -4,7 +4,7 @@ import org.junit.Test
class ResponseTest {
- val xmlprocess = XML()
+ val xmlprocess = XMLUtil()
@Test
fun loadResponse() {
diff --git a/sandbox/src/test/kotlin/XmlSigTest.kt
b/sandbox/src/test/kotlin/XmlSigTest.kt
index e80b880..febd0b2 100644
--- a/sandbox/src/test/kotlin/XmlSigTest.kt
+++ b/sandbox/src/test/kotlin/XmlSigTest.kt
@@ -1,27 +1,16 @@
package tech.libeufin.sandbox
import org.junit.Test
-import org.w3c.dom.Node
-import org.w3c.dom.NodeList
import java.security.KeyPairGenerator
-import java.util.*
-import javax.xml.crypto.NodeSetData
-import javax.xml.crypto.URIDereferencer
-import javax.xml.crypto.dom.DOMURIReference
-import javax.xml.crypto.dsig.*
-import javax.xml.crypto.dsig.dom.DOMSignContext
-import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec
-import javax.xml.crypto.dsig.spec.TransformParameterSpec
-import javax.xml.xpath.XPath
-import javax.xml.xpath.XPathConstants
-import javax.xml.xpath.XPathFactory
+import kotlin.test.*
+
class XmlSigTest {
@Test
fun basicSigningTest() {
- val doc = XML.parseStringIntoDom("""
+ val doc = XMLUtil.parseStringIntoDom("""
<foo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<AuthSignature />
<bar authenticate='true'>bla</bar>Hello World
@@ -35,7 +24,10 @@ class XmlSigTest {
val kpg = KeyPairGenerator.getInstance("RSA")
kpg.initialize(2048)
val pair = kpg.genKeyPair()
- XML.signEbicsDocument(doc, pair.private)
- println(XML.convertDomToString(doc))
+ val otherPair = kpg.genKeyPair()
+ XMLUtil.signEbicsDocument(doc, pair.private)
+ println(XMLUtil.convertDomToString(doc))
+ assertTrue(XMLUtil.verifyEbicsDocument(doc, pair.public))
+ assertFalse(XMLUtil.verifyEbicsDocument(doc, otherPair.public))
}
}
\ No newline at end of file
diff --git a/sandbox/src/test/kotlin/XmlTest.kt
b/sandbox/src/test/kotlin/XmlTest.kt
index ca3176b..121e198 100644
--- a/sandbox/src/test/kotlin/XmlTest.kt
+++ b/sandbox/src/test/kotlin/XmlTest.kt
@@ -1,15 +1,12 @@
package tech.libeufin.sandbox
-import org.junit.Assert
import org.junit.Test
import org.junit.Assert.*
-import java.io.File
-import javax.xml.transform.Source
import javax.xml.transform.stream.StreamSource
class XmlTest {
- val processor = tech.libeufin.sandbox.XML()
+ val processor = tech.libeufin.sandbox.XMLUtil()
@Test
fun hevValidation(){
diff --git a/sandbox/src/test/kotlin/XsiTypeAttributeTest.kt
b/sandbox/src/test/kotlin/XsiTypeAttributeTest.kt
index 030f9a9..84eb1eb 100644
--- a/sandbox/src/test/kotlin/XsiTypeAttributeTest.kt
+++ b/sandbox/src/test/kotlin/XsiTypeAttributeTest.kt
@@ -3,18 +3,16 @@ package tech.libeufin.sandbox
import org.junit.Test
import org.w3c.dom.Element
import tech.libeufin.messages.ebics.keyrequest.EbicsUnsecuredRequest
-import tech.libeufin.messages.ebics.keyrequest.OrderDetailsType
-import tech.libeufin.messages.ebics.keyrequest.UnsecuredReqOrderDetailsType
class XsiTypeAttributeTest {
@Test
fun domToJaxb() {
- val processor = XML()
+ val processor = XMLUtil()
val classLoader = ClassLoader.getSystemClassLoader()
val ini = classLoader.getResource("ebics_ini_request_sample.xml")
- val iniDom = XML.parseStringIntoDom(ini.readText())
+ val iniDom = XMLUtil.parseStringIntoDom(ini.readText())
val x: Element = iniDom.getElementsByTagName("OrderDetails")?.item(0)
as Element
x.setAttributeNS(
--
To stop receiving notification emails like this one, please contact
address@hidden.