gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[libeufin] 02/02: database rework, make INI succeed


From: gnunet
Subject: [libeufin] 02/02: database rework, make INI succeed
Date: Thu, 31 Oct 2019 19:01:25 +0100

This is an automated email from the git hooks/post-receive script.

dold pushed a commit to branch master
in repository libeufin.

commit bd6cbe43c27144b5537cd96e3745777351768272
Author: Florian Dold <address@hidden>
AuthorDate: Thu Oct 31 19:01:16 2019 +0100

    database rework, make INI succeed
---
 sandbox/build.gradle                               |   2 +-
 sandbox/src/main/kotlin/CryptoUtil.kt              |  37 +-
 sandbox/src/main/kotlin/DB.kt                      | 172 +++-----
 sandbox/src/main/kotlin/JSON.kt                    |  46 +-
 sandbox/src/main/kotlin/Main.kt                    | 491 ++++++++-------------
 sandbox/src/main/kotlin/ProtocolAndVersion.kt      |   6 -
 .../libeufin/schema/ebics_h004/EbicsMessages.kt    | 239 ++++++----
 sandbox/src/test/kotlin/DbTest.kt                  |  65 ---
 sandbox/src/test/kotlin/HiaLoadTest.kt             |   2 +-
 sandbox/src/test/kotlin/InnerIniLoadTest.kt        |  27 +-
 sandbox/src/test/kotlin/JaxbTest.kt                |  27 ++
 .../test/resources/ebics_ini_request_sample.xml    |  58 +--
 .../resources/ebics_ini_request_sample_patched.xml |  21 -
 .../test/resources/{HIA.xml => hia_request.xml}    |   0
 .../src/test/resources/hia_request_order_data.xml  |  23 +
 .../test/resources/{HPB.xml => hpb_request.xml}    |   0
 16 files changed, 576 insertions(+), 640 deletions(-)

diff --git a/sandbox/build.gradle b/sandbox/build.gradle
index 47b2e0b..04cb301 100644
--- a/sandbox/build.gradle
+++ b/sandbox/build.gradle
@@ -28,7 +28,7 @@ dependencies {
     implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
     implementation "io.ktor:ktor-gson:1.1.5"
     compile group: 'io.ktor', name: 'ktor-gson', version: '0.9.0'
-    compile "org.jetbrains.exposed:exposed:0.17.3"
+    compile "org.jetbrains.exposed:exposed:0.17.6"
     compile "io.ktor:ktor-server-netty:1.2.4"
     compile "ch.qos.logback:logback-classic:1.2.3"
     compile group: 'javax.xml.bind', name: 'jaxb-api', version: '2.3.1'
diff --git a/sandbox/src/main/kotlin/CryptoUtil.kt 
b/sandbox/src/main/kotlin/CryptoUtil.kt
index fb72d09..20f5d52 100644
--- a/sandbox/src/main/kotlin/CryptoUtil.kt
+++ b/sandbox/src/main/kotlin/CryptoUtil.kt
@@ -20,8 +20,10 @@
 package tech.libeufin.sandbox
 
 import java.lang.Exception
+import java.math.BigInteger
 import java.security.KeyFactory
 import java.security.KeyPairGenerator
+import java.security.PublicKey
 import java.security.interfaces.RSAPrivateCrtKey
 import java.security.interfaces.RSAPublicKey
 import java.security.spec.PKCS8EncodedKeySpec
@@ -38,6 +40,9 @@ data class RsaCrtKeyPair(val private: RSAPrivateCrtKey, val 
public: RSAPublicKey
  */
 class CryptoUtil {
     companion object {
+        /**
+         * Load an RSA private key from its binary PKCS#8 encoding.
+         */
         fun loadRsaPrivateKey(encodedPrivateKey: ByteArray): RSAPrivateCrtKey {
             val spec = PKCS8EncodedKeySpec(encodedPrivateKey)
             val priv = KeyFactory.getInstance("RSA").generatePrivate(spec)
@@ -45,6 +50,10 @@ class CryptoUtil {
                 throw Exception("wrong encoding")
             return priv
         }
+
+        /**
+         * Load an RSA public key from its binary X509 encoding.
+         */
         fun loadRsaPublicKey(encodedPublicKey: ByteArray): RSAPublicKey {
             val spec = X509EncodedKeySpec(encodedPublicKey)
             val pub = KeyFactory.getInstance("RSA").generatePublic(spec)
@@ -52,6 +61,10 @@ class CryptoUtil {
                 throw Exception("wrong encoding")
             return pub
         }
+
+        /**
+         * Load an RSA public key from its binary X509 encoding.
+         */
         fun getRsaPublicFromPrivate(rsaPrivateCrtKey: RSAPrivateCrtKey): 
RSAPublicKey {
             val spec = RSAPublicKeySpec(rsaPrivateCrtKey.modulus, 
rsaPrivateCrtKey.publicExponent)
             val pub = KeyFactory.getInstance("RSA").generatePublic(spec)
@@ -59,6 +72,12 @@ class CryptoUtil {
                 throw Exception("wrong encoding")
             return pub
         }
+
+        /**
+         * Generate a fresh RSA key pair.
+         *
+         * @param nbits size of the modulus in bits
+         */
         fun generateRsaKeyPair(nbits: Int): RsaCrtKeyPair {
             val gen = KeyPairGenerator.getInstance("RSA")
             gen.initialize(nbits)
@@ -71,5 +90,21 @@ class CryptoUtil {
                 throw Exception("key generation failed")
             return RsaCrtKeyPair(priv, pub)
         }
+
+        /**
+         * Load an RSA public key from its components.
+         *
+         * @param exponent
+         * @param modulus
+         * @return key
+         */
+        fun loadRsaPublicKeyFromComponents(modulus: ByteArray, exponent: 
ByteArray): RSAPublicKey {
+            val modulusBigInt = BigInteger(1, modulus)
+            val exponentBigInt = BigInteger(1, exponent)
+
+            val keyFactory = KeyFactory.getInstance("RSA")
+            val tmp = RSAPublicKeySpec(modulusBigInt, exponentBigInt)
+            return keyFactory.generatePublic(tmp) as RSAPublicKey
+        }
     }
-}
\ No newline at end of file
+}
diff --git a/sandbox/src/main/kotlin/DB.kt b/sandbox/src/main/kotlin/DB.kt
index 654e17b..ca95151 100644
--- a/sandbox/src/main/kotlin/DB.kt
+++ b/sandbox/src/main/kotlin/DB.kt
@@ -1,3 +1,22 @@
+/*
+ * This file is part of LibEuFin.
+ * Copyright (C) 2019 Stanisci and Dold.
+
+ * LibEuFin is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3, or
+ * (at your option) any later version.
+
+ * LibEuFin is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General
+ * Public License for more details.
+
+ * You should have received a copy of the GNU Affero General Public
+ * License along with LibEuFin; see the file COPYING.  If not, see
+ * <http://www.gnu.org/licenses/>
+ */
+
 package tech.libeufin.sandbox.db
 
 import org.jetbrains.exposed.dao.*
@@ -5,18 +24,14 @@ import org.jetbrains.exposed.sql.*
 import org.jetbrains.exposed.sql.transactions.transaction
 
 const val CUSTOMER_NAME_MAX_LENGTH = 20
+const val EBICS_HOST_ID_MAX_LENGTH = 10
 const val EBICS_USER_ID_MAX_LENGTH = 10
 const val EBICS_PARTNER_ID_MAX_LENGTH = 10
 const val EBICS_SYSTEM_ID_MAX_LENGTH = 10
-const val PUBLIC_KEY_MAX_MODULUS_LENGTH = 2048 // FIXME review this value!
-const val PUBLIC_KEY_MAX_EXPONENT_LENGTH = 64 // FIXME review this value!
-const val PRIVATE_KEY_MODULUS_LENGTH = 1024 // FIXME review this value!
-const val PRIVATE_KEY_EXPONENT_LENGTH = 10
-
 /**
  * All the states to give a subscriber.
  */
-enum class SubscriberStates {
+enum class SubscriberState {
     /**
      * No keys at all given to the bank.
      */
@@ -27,7 +42,7 @@ enum class SubscriberStates {
      */
     PARTIALLY_INITIALIZED_INI,
 
-    /**
+    /**r
      * Only HIA electronic message was successfully sent.
      */
     PARTIALLY_INITIALIZED_HIA,
@@ -47,7 +62,7 @@ enum class SubscriberStates {
 /**
  * All the states that one key can be assigned.
  */
-enum class KeyStates {
+enum class KeyState {
 
     /**
      * The key was never communicated.
@@ -83,89 +98,42 @@ class BankCustomer(id: EntityID<Int>) : IntEntity(id) {
     var ebicsSubscriber by EbicsSubscriber referencedOn 
BankCustomers.ebicsSubscriber
 }
 
-/**
- * The following tables define IDs that make a EBCIS
- * 'subscriber' exist.  Each EBICS subscriber is the tuple:
- *
- * - UserID, the human who is performing a EBICS task.
- * - PartnerID, the legal entity that signed a formal agreement with the 
financial institution.
- * - SystemID, (optional) the machine that is handling the EBICS task on 
behalf of the UserID.
- */
-
-object EbicsUsers: IntIdTable() {
-    /* EBICS user ID in the string form. */
-    val userId = varchar("userId", 
EBICS_USER_ID_MAX_LENGTH).primaryKey().nullable()
-
-}
-
-class EbicsUser(id: EntityID<Int>) : IntEntity(id){
-    companion object : IntEntityClass<EbicsUser>(EbicsUsers) {
-        override fun new(init: EbicsUser.() -> Unit): EbicsUser {
-            var row = super.new(init)
-            row.userId = "u${row.id}"
-            return row
-        }
-    }
-    var userId by EbicsUsers.userId
-}
 
 /**
- * Table for UserID.
+ * This table stores RSA public keys of subscribers.
  */
-object EbicsPartners: IntIdTable() {
-    val partnerId = varchar("partnerId", 
EBICS_PARTNER_ID_MAX_LENGTH).primaryKey().nullable()
-}
-
-
-class EbicsPartner(id: EntityID<Int>) : IntEntity(id) {
-    companion object : IntEntityClass<EbicsPartner>(EbicsPartners) {
-        override fun new(init: EbicsPartner.() -> Unit): EbicsPartner {
-            var row = super.new(init)
-            row.partnerId = "p${row.id}"
-            return row
-        }
-    }
-    var partnerId by EbicsPartners.partnerId
+object EbicsPublicKeys : IntIdTable() {
+    val rsaPublicKey = blob("rsaPublicKey")
+    val state = enumeration("state", KeyState::class)
 }
 
 
 /**
- * Table for UserID.
+ * Definition of a row in the [EbicsPublicKey] table
  */
-object EbicsSystems: IntIdTable() {
-    val systemId = EbicsPartners.varchar("systemId", 
EBICS_SYSTEM_ID_MAX_LENGTH).nullable()
+class EbicsPublicKey(id: EntityID<Int>) : IntEntity(id) {
+    companion object : IntEntityClass<EbicsPublicKey>(EbicsPublicKeys)
+    var rsaPublicKey by EbicsPublicKeys.rsaPublicKey
+    var state by EbicsPublicKeys.state
 }
 
-class EbicsSystem(id: EntityID<Int>) : IntEntity(id) {
-    companion object : IntEntityClass<EbicsSystem>(EbicsSystems) {
-        override fun new(init: EbicsSystem.() -> Unit): EbicsSystem {
-            val row = super.new(init)
-            row.systemId = "s${row.id}"
-            return row
-        }
-    }
-
-    var systemId by EbicsSystems.systemId
-}
 
-/**
- * This table stores RSA public keys.
- */
-object EbicsPublicKeys: IntIdTable() {
-    val modulus = binary("modulus", PUBLIC_KEY_MAX_MODULUS_LENGTH)
-    val exponent = binary("exponent", PUBLIC_KEY_MAX_EXPONENT_LENGTH)
-    val state = enumeration("state", KeyStates::class)
+object EbicsHosts : IntIdTable() {
+    val hostID = text("hostID")
+    val ebicsVersion = text("ebicsVersion")
+    val signaturePrivateKey = blob("signaturePrivateKey")
+    val encryptionPrivateKey = blob("encryptionPrivateKey")
+    val authenticationPrivateKey = blob("authenticationPrivateKey")
 }
 
 
-/**
- * Definition of a row in the keys table
- */
-class EbicsPublicKey(id: EntityID<Int>) : IntEntity(id) {
-    companion object : IntEntityClass<EbicsPublicKey>(EbicsPublicKeys)
-    var modulus by EbicsPublicKeys.modulus
-    var exponent by EbicsPublicKeys.exponent
-    var state by EbicsPublicKeys.state
+class EbicsHost(id: EntityID<Int>) : IntEntity(id) {
+    companion object : IntEntityClass<EbicsHost>(EbicsHosts)
+    var hostId by EbicsHosts.hostID
+    var ebicsVersion by EbicsHosts.ebicsVersion
+    var signaturePrivateKey by EbicsHosts.signaturePrivateKey
+    var encryptionPrivateKey by EbicsHosts.encryptionPrivateKey
+    var authenticationPrivateKey by EbicsHosts.authenticationPrivateKey
 }
 
 /**
@@ -173,60 +141,31 @@ class EbicsPublicKey(id: EntityID<Int>) : IntEntity(id) {
  * and systems.  Each value can appear multiple times in the same column.
  */
 object EbicsSubscribers: IntIdTable() {
-
-    val userId = reference("userId", EbicsUsers)
-    val partnerId = reference("partnerId", EbicsPartners)
-    val systemId = reference("systemId", EbicsSystems)
+    val userId = text("userID")
+    val partnerId = text("partnerID")
+    val systemId = text("systemID").nullable()
 
     val signatureKey = reference("signatureKey", EbicsPublicKeys).nullable()
     val encryptionKey = reference("encryptionKey", EbicsPublicKeys).nullable()
     val authenticationKey = reference("authorizationKey", 
EbicsPublicKeys).nullable()
 
-    val state = enumeration("state", SubscriberStates::class)
+    val state = enumeration("state", SubscriberState::class)
 }
 
 class EbicsSubscriber(id: EntityID<Int>) : IntEntity(id) {
     companion object : IntEntityClass<EbicsSubscriber>(EbicsSubscribers)
 
-    var userId by EbicsUser referencedOn EbicsSubscribers.userId
-    var partnerId by EbicsPartner referencedOn EbicsSubscribers.partnerId
-    var systemId by EbicsSystem referencedOn EbicsSubscribers.systemId
+    var userId by EbicsSubscribers.userId
+    var partnerId by EbicsSubscribers.partnerId
+    var systemId by EbicsSubscribers.systemId
 
     var signatureKey by EbicsPublicKey optionalReferencedOn 
EbicsSubscribers.signatureKey
     var encryptionKey by EbicsPublicKey optionalReferencedOn 
EbicsSubscribers.encryptionKey
     var authenticationKey by EbicsPublicKey optionalReferencedOn 
EbicsSubscribers.authenticationKey
-    var state by EbicsSubscribers.state
-}
-
-/**
- * Helper function that makes a new subscriber
- * @return new object
- */
-fun createSubscriber() : EbicsSubscriber {
-
-    return EbicsSubscriber.new {
-        userId = EbicsUser.new { }
-        partnerId = EbicsPartner.new { }
-        systemId = EbicsSystem.new { }
-        state = SubscriberStates.NEW
-    }
-}
-
 
-/**
- * This table stores RSA private keys.
- */
-object EbicsBankPrivateKeys: IntIdTable() {
-    val modulus = binary("modulus", PRIVATE_KEY_MODULUS_LENGTH)
-    val exponent = binary("exponent", PRIVATE_KEY_EXPONENT_LENGTH)
+    var state by EbicsSubscribers.state
 }
 
-class EbicsBankPrivateKey(id: EntityID<Int>) : IntEntity(id) {
-    companion object : 
IntEntityClass<EbicsBankPrivateKey>(EbicsBankPrivateKeys)
-
-    var modulus by EbicsBankPrivateKeys.modulus
-    var exponent by EbicsBankPrivateKeys.exponent
-}
 
 fun dbCreateTables() {
     Database.connect("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1", driver = 
"org.h2.Driver")
@@ -236,11 +175,8 @@ fun dbCreateTables() {
 
         SchemaUtils.create(
             BankCustomers,
-            EbicsUsers,
-            EbicsPartners,
-            EbicsSystems,
             EbicsSubscribers,
-            EbicsBankPrivateKeys
+            EbicsHosts
         )
     }
 }
diff --git a/sandbox/src/main/kotlin/JSON.kt b/sandbox/src/main/kotlin/JSON.kt
index 86a9629..157db79 100644
--- a/sandbox/src/main/kotlin/JSON.kt
+++ b/sandbox/src/main/kotlin/JSON.kt
@@ -1,3 +1,22 @@
+/*
+ * This file is part of LibEuFin.
+ * Copyright (C) 2019 Stanisci and Dold.
+
+ * LibEuFin is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3, or
+ * (at your option) any later version.
+
+ * LibEuFin is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General
+ * Public License for more details.
+
+ * You should have received a copy of the GNU Affero General Public
+ * License along with LibEuFin; see the file COPYING.  If not, see
+ * <http://www.gnu.org/licenses/>
+ */
+
 package tech.libeufin.sandbox
 
 /**
@@ -44,7 +63,6 @@ data class IniHiaLetters(
  * Request for INI letter.
  */
 data class IniLetter(
-
     val userId: String,
     val customerId: String,
     val name: String,
@@ -79,3 +97,29 @@ data class HiaLetter(
     val enc_public_modulus: String,
     val enc_hash: String
 )
+
+data class EbicsSubscribersResponse(
+    val subscribers: List<String>
+)
+
+data class EbicsSubscriberResponse(
+    val id: String,
+    val partnerID: String,
+    val userID: String,
+    val systemID: String?,
+    val state: String
+)
+
+data class EbicsHostsResponse(
+    val ebicsHosts: List<String>
+)
+
+data class EbicsHostResponse(
+    val hostID: String,
+    val ebicsVersion: String
+)
+
+data class EbicsHostCreateRequest(
+    val hostID: String,
+    val ebicsVersion: String
+)
\ No newline at end of file
diff --git a/sandbox/src/main/kotlin/Main.kt b/sandbox/src/main/kotlin/Main.kt
index b970a60..6b94078 100644
--- a/sandbox/src/main/kotlin/Main.kt
+++ b/sandbox/src/main/kotlin/Main.kt
@@ -20,15 +20,18 @@
 package tech.libeufin.sandbox
 
 import io.ktor.application.ApplicationCall
+import io.ktor.application.ApplicationCallPipeline
 import io.ktor.application.call
 import io.ktor.application.install
 import io.ktor.features.CallLogging
 import io.ktor.features.ContentNegotiation
+import io.ktor.features.StatusPages
 import io.ktor.gson.gson
 import io.ktor.http.ContentType
 import io.ktor.http.HttpStatusCode
 import io.ktor.request.receive
 import io.ktor.request.receiveText
+import io.ktor.request.uri
 import io.ktor.response.respond
 import io.ktor.response.respondText
 import io.ktor.routing.get
@@ -36,285 +39,86 @@ import io.ktor.routing.post
 import io.ktor.routing.routing
 import io.ktor.server.engine.embeddedServer
 import io.ktor.server.netty.Netty
-import org.jetbrains.exposed.dao.EntityID
+import org.jetbrains.exposed.sql.and
 import org.jetbrains.exposed.sql.transactions.transaction
+import org.slf4j.Logger
 import org.slf4j.LoggerFactory
 import org.w3c.dom.Document
 import tech.libeufin.sandbox.db.*
-import tech.libeufin.schema.ebics_h004.*
+import tech.libeufin.schema.ebics_h004.EbicsKeyManagementResponse
+import tech.libeufin.schema.ebics_h004.EbicsUnsecuredRequest
+import tech.libeufin.schema.ebics_h004.HIARequestOrderDataType
 import tech.libeufin.schema.ebics_hev.HEVResponse
 import tech.libeufin.schema.ebics_hev.SystemReturnCodeType
 import tech.libeufin.schema.ebics_s001.SignaturePubKeyOrderData
-import java.math.BigInteger
 import java.nio.charset.StandardCharsets.US_ASCII
 import java.nio.charset.StandardCharsets.UTF_8
-import java.security.KeyFactory
-import java.security.PrivateKey
-import java.security.PublicKey
-import java.security.spec.RSAPrivateKeySpec
-import java.security.spec.RSAPublicKeySpec
+import java.security.interfaces.RSAPublicKey
 import java.text.DateFormat
-import java.util.*
 import java.util.zip.InflaterInputStream
+import javax.sql.rowset.serial.SerialBlob
 
-val logger = LoggerFactory.getLogger("tech.libeufin.sandbox")
-val xmlProcess = XMLUtil()
-val getEbicsHostId = { "LIBEUFIN-SANDBOX" }
-val getEbicsVersion = { "H004" }
-val getEbicsRevision = { 1 }
-
-
-/**
- * Instantiate a new RSA public key.
- *
- * @param exponent
- * @param modulus
- * @return key
- */
-fun loadRsaPublicKey(modulus: ByteArray, exponent: ByteArray): PublicKey {
-
-    val modulusBigInt = BigInteger(1, modulus)
-    val exponentBigInt = BigInteger(1, exponent)
-
-    val keyFactory = KeyFactory.getInstance("RSA")
-    val tmp = RSAPublicKeySpec(modulusBigInt, exponentBigInt)
-    return keyFactory.generatePublic(tmp)
-}
-
-/**
- * The function tries to get the bank private key from the database.
- * If it does not find it, it generates a new one and stores it in
- * database.
- *
- * @return the key (whether from database or freshly created)
- */
-fun getOrMakePrivateKey(): PrivateKey {
-
-    // bank has always one private key in database.
-    var tmp = transaction {
-        EbicsBankPrivateKey.findById(1)
-    }
-
-    // must generate one now
-    if (tmp == null) {
-
-        val privateExponent =
-            BigInteger(PRIVATE_KEY_EXPONENT_LENGTH, Random()) // shall be set 
to some well-known value?
-        val privateModulus = BigInteger(PRIVATE_KEY_MODULUS_LENGTH, Random())
-
-        tmp = transaction {
-            EbicsBankPrivateKey.new {
-                modulus = privateModulus.toByteArray()
-                exponent = privateExponent.toByteArray()
-            }
-        }
-    }
-
-    val keySpec = RSAPrivateKeySpec(
-        BigInteger(tmp.modulus),
-        BigInteger(tmp.exponent)
-    )
-
-    val factory = KeyFactory.getInstance("RSA")
-    val privateKey = factory.generatePrivate(keySpec)
-
-    return privateKey
-}
-
-
-private suspend fun ApplicationCall.adminCustomers() {
-    val body = try {
-        receive<CustomerRequest>()
-    } catch (e: Exception) {
-        e.printStackTrace()
-        respond(
-            HttpStatusCode.BadRequest,
-            SandboxError(e.message.toString())
-        )
-        return
-    }
-    logger.info(body.toString())
-
-    val returnId = transaction {
-        val myUserId = EbicsUser.new { }
-        val myPartnerId = EbicsPartner.new { }
-        val mySystemId = EbicsSystem.new { }
-        val subscriber = EbicsSubscriber.new {
-            userId = myUserId
-            partnerId = myPartnerId
-            systemId = mySystemId
-            state = SubscriberStates.NEW
-        }
-        println("subscriber ID: ${subscriber.id.value}")
-        val customer = BankCustomer.new {
-            name = body.name
-            ebicsSubscriber = subscriber
-        }
-        println("name: ${customer.name}")
-        return@transaction customer.id.value
-    }
-
-    respond(
-        HttpStatusCode.OK,
-        CustomerResponse(id = returnId)
-    )
-}
-
-private suspend fun ApplicationCall.adminCustomersInfo() {
-    val id: Int = try {
-        parameters["id"]!!.toInt()
-    } catch (e: NumberFormatException) {
-        respond(
-            HttpStatusCode.BadRequest,
-            SandboxError(e.message.toString())
-        )
-        return
-    }
-
-    val customerInfo = transaction {
-        val customer = BankCustomer.findById(id) ?: return@transaction null
-        CustomerInfo(
-            customer.name,
-            ebicsInfo = CustomerEbicsInfo(
-                customer.ebicsSubscriber.userId.userId!!
-            )
-        )
-    }
-
-    if (null == customerInfo) {
-        respond(
-            HttpStatusCode.NotFound,
-            SandboxError("id $id not found")
-        )
-        return
-    }
-
-    respond(HttpStatusCode.OK, customerInfo)
-}
-
-private suspend fun ApplicationCall.adminCustomersKeyletter() {
-    val body = try {
-        receive<IniHiaLetters>()
-    } catch (e: Exception) {
-        e.printStackTrace()
-        respond(
-            HttpStatusCode.BadRequest,
-            SandboxError(e.message.toString())
-        )
-        return
-    }
-
-    val ebicsUserID = transaction {
-        EbicsUser.find { EbicsUsers.userId eq body.ini.userId }.firstOrNull()
-    }
-
-    if (ebicsUserID == null) {
-        respond(
-            HttpStatusCode.NotFound,
-            SandboxError("User ID not found")
-        )
-        return
-    }
-
-    val ebicsSubscriber = EbicsSubscriber.find {
-        EbicsSubscribers.userId eq EntityID(ebicsUserID.id.value, EbicsUsers)
-    }.firstOrNull()
-
-    if (ebicsSubscriber == null) {
-        respond(
-            HttpStatusCode.InternalServerError,
-            SandboxError("Bank had internal errors retrieving the Subscriber")
-        )
-        return
-    }
-
-    // check signature key
-    var modulusFromDd = BigInteger(ebicsSubscriber.signatureKey?.modulus)
-    var exponentFromDb = BigInteger(ebicsSubscriber.signatureKey?.exponent)
-    var modulusFromLetter = body.ini.public_modulus.toBigInteger(16)
-    var exponentFromLetter = body.ini.public_modulus.toBigInteger(16)
-
-    if (!((modulusFromDd == modulusFromLetter) && (exponentFromDb == 
exponentFromLetter))) {
-        logger.info("Signature key mismatches for ${ebicsUserID.userId}")
-        respond(
-            HttpStatusCode.NotAcceptable,
-            SandboxError("Signature Key mismatches!")
-        )
-        return
-    }
-
-    logger.info("Signature key from user ${ebicsUserID.userId} becomes 
RELEASED")
-    ebicsSubscriber.signatureKey?.state = KeyStates.RELEASED
-
-    // check identification and authentication key
-    modulusFromDd = BigInteger(ebicsSubscriber.authenticationKey?.modulus)
-    exponentFromDb = BigInteger(ebicsSubscriber.authenticationKey?.exponent)
-    modulusFromLetter = body.hia.ia_public_modulus.toBigInteger(16)
-    exponentFromLetter = body.hia.ia_public_exponent.toBigInteger(16)
-
-    if (!((modulusFromDd == modulusFromLetter) && (exponentFromDb == 
exponentFromLetter))) {
-        logger.info("Identification and authorization key mismatches for 
${ebicsUserID.userId}")
-        respond(
-            HttpStatusCode.NotAcceptable,
-            SandboxError("Identification and authorization key mismatches!")
-        )
-        return
-    }
-
-    logger.info("Authentication key from user ${ebicsUserID.userId} becomes 
RELEASED")
-    ebicsSubscriber.authenticationKey?.state = KeyStates.RELEASED
-
-    // check encryption key
-    modulusFromDd = BigInteger(ebicsSubscriber.encryptionKey?.modulus)
-    exponentFromDb = BigInteger(ebicsSubscriber.encryptionKey?.exponent)
-    modulusFromLetter = body.hia.enc_public_modulus.toBigInteger(16)
-    exponentFromLetter = body.hia.enc_public_exponent.toBigInteger(16)
-
-    if (!((modulusFromDd == modulusFromLetter) && (exponentFromDb == 
exponentFromLetter))) {
-        logger.info("Encryption key mismatches for ${ebicsUserID.userId}")
-        respond(
-            HttpStatusCode.NotAcceptable,
-            SandboxError("Encryption key mismatches!")
-        )
-        return
-    }
-
-    logger.info("Encryption key from user ${ebicsUserID.userId} becomes 
RELEASED")
-    ebicsSubscriber.encryptionKey?.state = KeyStates.RELEASED
+val logger: Logger = LoggerFactory.getLogger("tech.libeufin.sandbox")
 
+val xmlProcess = XMLUtil()
 
-    // TODO change subscriber status!
-    ebicsSubscriber.state = SubscriberStates.READY
-
-    respond(
-        HttpStatusCode.OK,
-        "Your status has changed to READY"
-    )
-}
+data class EbicsRequestError(val statusCode: HttpStatusCode) : 
Exception("Ebics request error")
 
 private suspend fun ApplicationCall.respondEbicsKeyManagement(
     errorText: String,
     errorCode: String,
-    statusCode: HttpStatusCode
+    statusCode: HttpStatusCode,
+    orderId: String? = null,
+    bankReturnCode: String? = null
 ) {
-    val responseXml = EbicsResponse().apply {
-        header = EbicsResponse.Header().apply {
-            mutable = ResponseMutableHeaderType().apply {
+    val responseXml = EbicsKeyManagementResponse().apply {
+        version = "H004"
+        header = EbicsKeyManagementResponse.Header().apply {
+            authenticate = true
+            mutable = 
EbicsKeyManagementResponse.Header.KeyManagementResponseMutableHeaderType().apply
 {
                 reportText = errorText
                 returnCode = errorCode
+                if (orderId != null) {
+                    this.orderID = orderId
+                }
+            }
+            _static = EbicsKeyManagementResponse.Header.EmptyStaticHeader()
+        }
+        body = EbicsKeyManagementResponse.Body().apply {
+            if (bankReturnCode != null) {
+                this.returnCode = 
EbicsKeyManagementResponse.Body.ReturnCode().apply {
+                    this.authenticate = true
+                    this.value = bankReturnCode
+                }
             }
         }
     }
     val text = XMLUtil.convertJaxbToString(responseXml)
+    logger.info("responding with:\n${text}")
     respondText(text, ContentType.Application.Xml, statusCode)
 }
 
+
 private suspend fun ApplicationCall.respondEbicsInvalidXml() {
     respondEbicsKeyManagement("[EBICS_INVALID_XML]", "091010", 
HttpStatusCode.BadRequest)
 }
 
-private suspend fun ApplicationCall.ebicsweb() {
 
+fun findEbicsSubscriber(partnerID: String, userID: String, systemID: String?): 
EbicsSubscriber? {
+    return if (systemID == null) {
+        EbicsSubscriber.find {
+            (EbicsSubscribers.partnerId eq partnerID) and 
(EbicsSubscribers.userId eq userID)
+        }
+    } else {
+        EbicsSubscriber.find {
+            (EbicsSubscribers.partnerId eq partnerID) and
+                    (EbicsSubscribers.userId eq userID) and
+                    (EbicsSubscribers.systemId eq systemID)
+        }
+    }.firstOrNull()
+}
+
+private suspend fun ApplicationCall.ebicsweb() {
     val body: String = receiveText()
     logger.debug("Data received: $body")
 
@@ -335,28 +139,16 @@ private suspend fun ApplicationCall.ebicsweb() {
                 bodyDocument
             )
 
-            if (bodyJaxb.value.header.static.hostID != getEbicsHostId()) {
-                respondEbicsKeyManagement("[EBICS_INVALID_HOST_ID]", "091011", 
HttpStatusCode.NotFound)
-                return
-            }
-
-            val ebicsUserID = transaction {
-                EbicsUser.find { EbicsUsers.userId eq 
bodyJaxb.value.header.static.userID }.firstOrNull()
-            }
+            val staticHeader = bodyJaxb.value.header.static
+            val requestHostID = bodyJaxb.value.header.static.hostID
 
-            if (ebicsUserID == null) {
-                respondEbicsKeyManagement("[EBICS_UNKNOWN_USER]", "091003", 
HttpStatusCode.NotFound)
-                return
+            val ebicsHost = transaction {
+                EbicsHost.find { EbicsHosts.hostID eq requestHostID 
}.firstOrNull()
             }
 
-            val ebicsSubscriber = transaction {
-                EbicsSubscriber.find {
-                    EbicsSubscribers.userId eq EntityID(ebicsUserID.id.value, 
EbicsUsers)
-                }.firstOrNull()
-            }
-
-            if (ebicsSubscriber == null) {
-                respondEbicsKeyManagement("[EBICS_INTERNAL_ERROR]", "061099", 
HttpStatusCode.InternalServerError)
+            if (ebicsHost == null) {
+                logger.warn("client requested unknown HostID")
+                respondEbicsKeyManagement("[EBICS_INVALID_HOST_ID]", "091011", 
HttpStatusCode.NotFound)
                 return
             }
 
@@ -403,12 +195,11 @@ private suspend fun ApplicationCall.ebicsweb() {
             logger.debug("Found payload: ${payload.toString(US_ASCII)}")
 
             when (bodyJaxb.value.header.static.orderDetails.orderType) {
-
                 "INI" -> {
                     val keyObject = 
XMLUtil.convertStringToJaxb<SignaturePubKeyOrderData>(payload.toString(UTF_8))
 
-                    try {
-                        loadRsaPublicKey(
+                    val rsaPublicKey: RSAPublicKey = try {
+                        CryptoUtil.loadRsaPublicKeyFromComponents(
                             
keyObject.value.signaturePubKeyInfo.pubKeyValue.rsaKeyValue.modulus,
                             
keyObject.value.signaturePubKeyInfo.pubKeyValue.rsaKeyValue.exponent
                         )
@@ -421,64 +212,93 @@ private suspend fun ApplicationCall.ebicsweb() {
 
                     // put try-catch block here? (FIXME)
                     transaction {
+                        val ebicsSubscriber =
+                            findEbicsSubscriber(staticHeader.partnerID, 
staticHeader.userID, staticHeader.systemID)
+                        if (ebicsSubscriber == null) {
+                            logger.warn("ebics subscriber 
('${staticHeader.partnerID}' / '${staticHeader.userID}' / 
'${staticHeader.systemID}') not found")
+                            throw EbicsRequestError(HttpStatusCode.NotFound)
+                        }
                         ebicsSubscriber.signatureKey = EbicsPublicKey.new {
-                            modulus = 
keyObject.value.signaturePubKeyInfo.pubKeyValue.rsaKeyValue.modulus
-                            exponent = 
keyObject.value.signaturePubKeyInfo.pubKeyValue.rsaKeyValue.exponent
-                            state = KeyStates.NEW
+                            this.rsaPublicKey = 
SerialBlob(rsaPublicKey.encoded)
+                            state = KeyState.NEW
                         }
 
-                        if (ebicsSubscriber.state == SubscriberStates.NEW) {
-                            ebicsSubscriber.state = 
SubscriberStates.PARTIALLY_INITIALIZED_INI
+                        if (ebicsSubscriber.state == SubscriberState.NEW) {
+                            ebicsSubscriber.state = 
SubscriberState.PARTIALLY_INITIALIZED_INI
                         }
 
-                        if (ebicsSubscriber.state == 
SubscriberStates.PARTIALLY_INITIALIZED_HIA) {
-                            ebicsSubscriber.state = 
SubscriberStates.INITIALIZED
+                        if (ebicsSubscriber.state == 
SubscriberState.PARTIALLY_INITIALIZED_HIA) {
+                            ebicsSubscriber.state = SubscriberState.INITIALIZED
                         }
                     }
 
                     logger.info("Signature key inserted in database _and_ 
subscriber state changed accordingly")
+                    respondEbicsKeyManagement(
+                        "[EBICS_OK]",
+                        "000000",
+                        HttpStatusCode.OK,
+                        bankReturnCode = "000000",
+                        orderId = "OR01"
+                    )
+                    return
                 }
 
                 "HIA" -> {
                     val keyObject = 
XMLUtil.convertStringToJaxb<HIARequestOrderDataType>(payload.toString(US_ASCII))
 
-                    try {
-                        loadRsaPublicKey(
+                    val authenticationPublicKey = try {
+                        CryptoUtil.loadRsaPublicKeyFromComponents(
                             
keyObject.value.authenticationPubKeyInfo.pubKeyValue.rsaKeyValue.modulus,
                             
keyObject.value.authenticationPubKeyInfo.pubKeyValue.rsaKeyValue.exponent
                         )
-                        loadRsaPublicKey(
+                    } catch (e: Exception) {
+                        logger.info("auth public key invalid")
+                        e.printStackTrace()
+                        respondEbicsInvalidXml()
+                        return
+                    }
+
+                    val encryptionPublicKey = try {
+                        CryptoUtil.loadRsaPublicKeyFromComponents(
                             
keyObject.value.encryptionPubKeyInfo.pubKeyValue.rsaKeyValue.modulus,
                             
keyObject.value.encryptionPubKeyInfo.pubKeyValue.rsaKeyValue.exponent
                         )
                     } catch (e: Exception) {
-                        logger.info("User gave at least one invalid HIA key")
+                        logger.info("auth public key invalid")
                         e.printStackTrace()
                         respondEbicsInvalidXml()
                         return
                     }
 
-                    // put try-catch block here? (FIXME)
                     transaction {
+                        val ebicsSubscriber =
+                            findEbicsSubscriber(staticHeader.partnerID, 
staticHeader.userID, staticHeader.systemID)
+                        if (ebicsSubscriber == null) {
+                            logger.warn("ebics subscriber not found")
+                            throw EbicsRequestError(HttpStatusCode.NotFound)
+                        }
                         ebicsSubscriber.authenticationKey = EbicsPublicKey.new 
{
-                            modulus = 
keyObject.value.authenticationPubKeyInfo.pubKeyValue.rsaKeyValue.modulus
-                            exponent = 
keyObject.value.authenticationPubKeyInfo.pubKeyValue.rsaKeyValue.exponent
-                            state = KeyStates.NEW
+                            this.rsaPublicKey = 
SerialBlob(authenticationPublicKey.encoded)
+                            state = KeyState.NEW
+                        }
+                        ebicsSubscriber.encryptionKey = EbicsPublicKey.new {
+                            this.rsaPublicKey = 
SerialBlob(encryptionPublicKey.encoded)
+                            state = KeyState.NEW
                         }
 
-                        if (ebicsSubscriber.state == SubscriberStates.NEW) {
-                            ebicsSubscriber.state = 
SubscriberStates.PARTIALLY_INITIALIZED_HIA
+                        if (ebicsSubscriber.state == SubscriberState.NEW) {
+                            ebicsSubscriber.state = 
SubscriberState.PARTIALLY_INITIALIZED_HIA
                         }
 
-                        if (ebicsSubscriber.state == 
SubscriberStates.PARTIALLY_INITIALIZED_INI) {
-                            ebicsSubscriber.state = 
SubscriberStates.INITIALIZED
+                        if (ebicsSubscriber.state == 
SubscriberState.PARTIALLY_INITIALIZED_INI) {
+                            ebicsSubscriber.state = SubscriberState.INITIALIZED
                         }
                     }
+                    respondEbicsKeyManagement("[EBICS_OK]", "000000", 
HttpStatusCode.OK)
                 }
             }
 
-            respondEbicsKeyManagement("[EBICS_OK]", "000000", 
HttpStatusCode.OK)
-            return
+            throw AssertionError("not reached")
         }
 
         "ebicsHEVRequest" -> {
@@ -509,8 +329,28 @@ private suspend fun ApplicationCall.ebicsweb() {
 
 fun main() {
     dbCreateTables()
-    val server = embeddedServer(Netty, port = 5000) {
 
+    transaction {
+        val pairA = CryptoUtil.generateRsaKeyPair(2048)
+        val pairB = CryptoUtil.generateRsaKeyPair(2048)
+        val pairC = CryptoUtil.generateRsaKeyPair(2048)
+        EbicsHost.new {
+            hostId = "host01"
+            ebicsVersion = "H004"
+            authenticationPrivateKey = SerialBlob(pairA.private.encoded)
+            encryptionPrivateKey = SerialBlob(pairB.private.encoded)
+            signaturePrivateKey = SerialBlob(pairC.private.encoded)
+        }
+
+        EbicsSubscriber.new {
+            partnerId = "PARTNER1"
+            userId = "USER1"
+            systemId = null
+            state = SubscriberState.NEW
+        }
+    }
+
+    val server = embeddedServer(Netty, port = 5000) {
         install(CallLogging)
         install(ContentNegotiation) {
             gson {
@@ -518,35 +358,72 @@ fun main() {
                 setPrettyPrinting()
             }
         }
+        install(StatusPages) {
+            exception<Throwable> { cause ->
+                logger.error("Exception while handling 
'${call.request.uri.toString()}'", cause)
+                call.respondText("Internal server error.", 
ContentType.Text.Plain, HttpStatusCode.InternalServerError)
+            }
+        }
+        intercept(ApplicationCallPipeline.Fallback) {
+            if (this.call.response.status() == null) {
+                call.respondText("Not found (no route matched).\n", 
ContentType.Text.Plain, HttpStatusCode.NotFound)
+                return@intercept finish()
+            }
+        }
         routing {
+            //trace { logger.info(it.buildText()) }
             get("/") {
-                logger.debug("GET: not implemented")
                 call.respondText("Hello LibEuFin!\n", ContentType.Text.Plain)
-                return@get
             }
-
-            post("/admin/customers") {
-                call.adminCustomers()
-                return@post
+            get("/ebics/hosts") {
+                val ebicsHosts = transaction {
+                    EbicsHost.all().map { it.hostId }
+                }
+                call.respond(EbicsHostsResponse(ebicsHosts))
             }
-
-            get("/admin/customers/{id}") {
-                call.adminCustomersInfo()
-                return@get
+            post("/ebics/hosts") {
+                val req = call.receive<EbicsHostCreateRequest>()
+                transaction {
+                    EbicsHost.new {
+                        this.ebicsVersion = req.ebicsVersion
+                        this.hostId = hostId
+                    }
+                }
             }
-
-            post("/admin/customers/{id}/ebics/keyletter") {
-                call.adminCustomersKeyletter()
-                return@post
+            get("/ebics/hosts/{id}") {
+                val resp = transaction {
+                    val host = EbicsHost.find { EbicsHosts.hostID eq 
call.parameters["id"]!! }.firstOrNull()
+                    if (host == null) null
+                    else EbicsHostResponse(host.hostId, host.ebicsVersion)
+                }
+                if (resp == null) call.respond(HttpStatusCode.NotFound, 
SandboxError("host not found"))
+                else call.respond(resp)
+            }
+            get("/ebics/subscribers") {
+                val subscribers = transaction {
+                    EbicsSubscriber.all().map { it.id.value.toString() }
+                }
+                call.respond(EbicsSubscribersResponse(subscribers))
+            }
+            get("/ebics/subscribers/{id}") {
+                val resp = transaction {
+                    val id = call.parameters["id"]!!
+                    val subscriber = EbicsSubscriber.findById(id.toInt())!!
+                    EbicsSubscriberResponse(
+                        id,
+                        subscriber.partnerId,
+                        subscriber.userId,
+                        subscriber.systemId,
+                        subscriber.state.name
+                    )
+                }
+                call.respond(resp)
             }
-
             post("/ebicsweb") {
                 call.ebicsweb()
-                return@post
             }
         }
     }
     logger.info("Up and running")
     server.start(wait = true)
 }
-
diff --git a/sandbox/src/main/kotlin/ProtocolAndVersion.kt 
b/sandbox/src/main/kotlin/ProtocolAndVersion.kt
deleted file mode 100644
index e69f08b..0000000
--- a/sandbox/src/main/kotlin/ProtocolAndVersion.kt
+++ /dev/null
@@ -1,6 +0,0 @@
-package tech.libeufin.sandbox
-
-class ProtocolAndVersion(protocol: String, version: String) {
-    val protocol = protocol
-    val version = version
-}
\ No newline at end of file
diff --git 
a/sandbox/src/main/kotlin/tech/libeufin/schema/ebics_h004/EbicsMessages.kt 
b/sandbox/src/main/kotlin/tech/libeufin/schema/ebics_h004/EbicsMessages.kt
index 986e7de..0ed892e 100644
--- a/sandbox/src/main/kotlin/tech/libeufin/schema/ebics_h004/EbicsMessages.kt
+++ b/sandbox/src/main/kotlin/tech/libeufin/schema/ebics_h004/EbicsMessages.kt
@@ -132,11 +132,11 @@ class EbicsUnsecuredRequest {
     @XmlType(name = "", propOrder = ["dataTransfer"])
     class Body {
         @get:XmlElement(name = "DataTransfer", required = true)
-        lateinit var dataTransfer: DataTransfer
+        lateinit var dataTransfer: UnsecuredDataTransfer
 
         @XmlAccessorType(XmlAccessType.NONE)
         @XmlType(name = "", propOrder = ["orderData"])
-        class DataTransfer {
+        class UnsecuredDataTransfer {
             @get:XmlElement(name = "OrderData", required = true)
             lateinit var orderData: OrderData
 
@@ -166,55 +166,32 @@ class EbicsUnsecuredRequest {
     lateinit var body: Body
 }
 
-
 @XmlAccessorType(XmlAccessType.NONE)
-@XmlType(name = "DataTransferResponseType", propOrder = ["dataEncryptionInfo", 
"orderData", "any"])
-class DataTransferResponse {
-    @get:XmlElement(name = "DataEncryptionInfo")
-    var dataEncryptionInfo: DataEncryptionInfo? = null
+class DataEncryptionInfo {
+    @get:XmlAttribute(name = "authenticate", required = true)
+    var authenticate: Boolean = false
+
+    @get:XmlElement(name = "EncryptionPubKeyDigest", required = true)
+    lateinit var encryptionPubKeyDigest: EncryptionPubKeyDigest
 
-    @get:XmlElement(name = "OrderData", required = true)
-    lateinit var orderData: OrderData
+    @get:XmlElement(name = "TransactionKey", required = true)
+    lateinit var transactionKey: ByteArray
 
     @get:XmlAnyElement(lax = true)
     var any: List<Any>? = null
 
     @XmlAccessorType(XmlAccessType.NONE)
-    class OrderData {
-        @get:XmlValue
-        lateinit var value: ByteArray
-
-        @get:XmlAnyAttribute
-        var otherAttributes = HashMap<QName, String>()
-    }
-
-    @XmlAccessorType(XmlAccessType.NONE)
-    class DataEncryptionInfo {
-        @get:XmlAttribute(name = "authenticate", required = true)
-        var authenticate: Boolean = false
-
-        @get:XmlElement(name = "EncryptionPubKeyDigest", required = true)
-        lateinit var encryptionPubKeyDigest: EncryptionPubKeyDigest
-
-        @get:XmlElement(name = "TransactionKey", required = true)
-        lateinit var transactionKey: ByteArray
-
-        @get:XmlAnyElement(lax = true)
-        var any: List<Any>? = null
-
-        @XmlAccessorType(XmlAccessType.NONE)
-        class EncryptionPubKeyDigest {
-            @get:XmlAttribute(name = "Version", required = true)
-            @get:XmlJavaTypeAdapter(CollapsedStringAdapter::class)
-            lateinit var version: String
+    class EncryptionPubKeyDigest {
+        @get:XmlAttribute(name = "Version", required = true)
+        @get:XmlJavaTypeAdapter(CollapsedStringAdapter::class)
+        lateinit var version: String
 
-            @XmlAttribute(name = "Algorithm", required = true)
-            @XmlSchemaType(name = "anyURI")
-            lateinit var algorithm: String
+        @XmlAttribute(name = "Algorithm", required = true)
+        @XmlSchemaType(name = "anyURI")
+        lateinit var algorithm: String
 
-            @get:XmlValue
-            lateinit var value: ByteArray
-        }
+        @get:XmlValue
+        lateinit var value: ByteArray
     }
 }
 
@@ -224,7 +201,7 @@ class DataTransferResponse {
     name = "ResponseMutableHeaderType",
     propOrder = ["transactionPhase", "segmentNumber", "orderID", "returnCode", 
"reportText", "any"]
 )
-class ResponseMutableHeaderType {
+class EbicsResponseMutableHeaderType {
     @XmlElement(name = "TransactionPhase", required = true)
     @XmlSchemaType(name = "token")
     lateinit var transactionPhase: TransactionPhaseType
@@ -295,6 +272,16 @@ class ResponseStaticHeaderType {
 }
 
 
+@XmlAccessorType(XmlAccessType.NONE)
+class TimestampBankParameter {
+    @XmlValue
+    lateinit var value: XMLGregorianCalendar
+
+    @XmlAttribute(name = "authenticate", required = true)
+    var authenticate: Boolean = false
+}
+
+
 @XmlAccessorType(XmlAccessType.NONE)
 @XmlType(name = "", propOrder = ["header", "authSignature", "body"])
 @XmlRootElement(name = "ebicsResponse")
@@ -321,16 +308,11 @@ class EbicsResponse {
     @XmlAccessorType(XmlAccessType.NONE)
     @XmlType(name = "", propOrder = ["_static", "mutable"])
     class Header {
-
-        init {
-            println("creating header")
-        }
-
         @get:XmlElement(name = "static", required = true)
-        var _static: ResponseStaticHeaderType? = null
+        lateinit var _static: ResponseStaticHeaderType
 
         @get:XmlElement(required = true)
-        var mutable: ResponseMutableHeaderType? = null
+        lateinit var mutable: EbicsResponseMutableHeaderType
 
         @get:XmlAttribute(name = "authenticate", required = true)
         var authenticate: Boolean = false
@@ -340,7 +322,7 @@ class EbicsResponse {
     @XmlType(name = "", propOrder = ["dataTransfer", "returnCode", 
"timestampBankParameter"])
     class Body {
         @XmlElement(name = "DataTransfer")
-        var dataTransfer: DataTransferResponse? = null
+        var dataTransfer: DataTransferResponseType? = null
 
         @XmlElement(name = "ReturnCode", required = true)
         lateinit var returnCode: ReturnCode
@@ -348,15 +330,6 @@ class EbicsResponse {
         @XmlElement(name = "TimestampBankParameter")
         var timestampBankParameter: TimestampBankParameter? = null
 
-        @XmlAccessorType(XmlAccessType.NONE)
-        class TimestampBankParameter {
-            @XmlValue
-            lateinit var value: XMLGregorianCalendar
-
-            @XmlAttribute(name = "authenticate", required = true)
-            var authenticate: Boolean = false
-        }
-
         @XmlAccessorType(XmlAccessType.NONE)
         class ReturnCode {
             @get:XmlValue
@@ -366,19 +339,48 @@ class EbicsResponse {
             @get:XmlAttribute(name = "authenticate", required = true)
             var authenticate: Boolean = false
         }
+
+        @XmlAccessorType(XmlAccessType.NONE)
+        @XmlType(name = "DataTransferResponseType", propOrder = 
["dataEncryptionInfo", "orderData", "any"])
+        class DataTransferResponseType {
+            @get:XmlElement(name = "DataEncryptionInfo")
+            var dataEncryptionInfo: DataEncryptionInfo? = null
+
+            @get:XmlElement(name = "OrderData", required = true)
+            lateinit var orderData: OrderData
+
+            @get:XmlAnyElement(lax = true)
+            var any: List<Any>? = null
+
+            @XmlAccessorType(XmlAccessType.NONE)
+            class OrderData {
+                @get:XmlValue
+                lateinit var value: ByteArray
+
+                @get:XmlAnyAttribute
+                var otherAttributes = HashMap<QName, String>()
+            }
+        }
     }
 }
 
 
+@XmlAccessorType(XmlAccessType.NONE)
+@XmlType(
+    name = "PubKeyValueType", propOrder = [
+        "rsaKeyValue",
+        "timeStamp"
+    ]
+)
 class PubKeyValueType {
-    @XmlElement(name = "RSAKeyValue", namespace = 
"http://www.w3.org/2000/09/xmldsig#";, required = true)
+    @get:XmlElement(name = "RSAKeyValue", namespace = 
"http://www.w3.org/2000/09/xmldsig#";, required = true)
     lateinit var rsaKeyValue: RSAKeyValueType
 
-    @XmlElement(name = "TimeStamp")
-    @XmlSchemaType(name = "dateTime")
+    @get:XmlElement(name = "TimeStamp", required = false)
+    @get:XmlSchemaType(name = "dateTime")
     var timeStamp: XMLGregorianCalendar? = null
 
-    @XmlAnyElement(lax = true)
+    @get:XmlAnyElement(lax = true)
     var any: List<Any>? = null
 }
 
@@ -407,7 +409,7 @@ class AuthenticationPubKeyInfoType {
 
 @XmlAccessorType(XmlAccessType.NONE)
 @XmlType(
-    name = "AuthenticationPubKeyInfoType", propOrder = [
+    name = "EncryptionPubKeyInfoType", propOrder = [
         "x509Data",
         "pubKeyValue",
         "encryptionVersion"
@@ -427,28 +429,115 @@ class EncryptionPubKeyInfoType {
 }
 
 
-@XmlAccessorType(XmlAccessType.FIELD)
+@XmlAccessorType(XmlAccessType.NONE)
 @XmlType(
     name = "HIARequestOrderDataType",
     propOrder = ["authenticationPubKeyInfo", "encryptionPubKeyInfo", 
"partnerID", "userID", "any"]
 )
 class HIARequestOrderDataType {
-    @XmlElement(name = "AuthenticationPubKeyInfo", required = true)
+    @get:XmlElement(name = "AuthenticationPubKeyInfo", required = true)
     lateinit var authenticationPubKeyInfo: AuthenticationPubKeyInfoType
 
-    @XmlElement(name = "EncryptionPubKeyInfo", required = true)
+    @get:XmlElement(name = "EncryptionPubKeyInfo", required = true)
     lateinit var encryptionPubKeyInfo: EncryptionPubKeyInfoType
 
-    @XmlElement(name = "PartnerID", required = true)
-    @XmlJavaTypeAdapter(CollapsedStringAdapter::class)
-    @XmlSchemaType(name = "token")
+    @get:XmlElement(name = "PartnerID", required = true)
+    @get:XmlJavaTypeAdapter(CollapsedStringAdapter::class)
+    @get:XmlSchemaType(name = "token")
     lateinit var partnerID: String
 
-    @XmlElement(name = "UserID", required = true)
-    @XmlJavaTypeAdapter(CollapsedStringAdapter::class)
-    @XmlSchemaType(name = "token")
+    @get:XmlElement(name = "UserID", required = true)
+    @get:XmlJavaTypeAdapter(CollapsedStringAdapter::class)
+    @get:XmlSchemaType(name = "token")
     lateinit var userID: String
 
-    @XmlAnyElement(lax = true)
+    @get:XmlAnyElement(lax = true)
     var any: List<Any>? = null
 }
+
+@XmlAccessorType(XmlAccessType.NONE)
+@XmlType(name = "", propOrder = ["header", "body"])
+@XmlRootElement(name = "ebicsKeyManagementResponse")
+class EbicsKeyManagementResponse {
+    @get:XmlElement(required = true)
+    lateinit var header: Header
+
+    @get:XmlElement(required = true)
+    lateinit var body: Body
+
+    @get:XmlAttribute(name = "Version", required = true)
+    @get:XmlJavaTypeAdapter(CollapsedStringAdapter::class)
+    lateinit var version: String
+
+    @get:XmlAttribute(name = "Revision")
+    var revision: Int? = null
+
+    @XmlAccessorType(XmlAccessType.NONE)
+    @XmlType(name = "", propOrder = ["_static", "mutable"])
+    class Header {
+        @get:XmlElement(name = "static", required = true)
+        lateinit var _static: EmptyStaticHeader
+
+        @get:XmlElement(required = true)
+        lateinit var mutable: KeyManagementResponseMutableHeaderType
+
+        @get:XmlAttribute(name = "authenticate", required = true)
+        var authenticate: Boolean = false
+
+        @XmlAccessorType(XmlAccessType.NONE)
+        @XmlType(name = "")
+        class EmptyStaticHeader
+
+        @XmlAccessorType(XmlAccessType.NONE)
+        @XmlType(name = "", propOrder = ["orderID", "returnCode", 
"reportText"])
+        class KeyManagementResponseMutableHeaderType {
+            @XmlElement(name = "OrderID")
+            @XmlJavaTypeAdapter(CollapsedStringAdapter::class)
+            @XmlSchemaType(name = "token")
+            var orderID: String? = null
+
+            @XmlElement(name = "ReturnCode", required = true)
+            @XmlJavaTypeAdapter(CollapsedStringAdapter::class)
+            @XmlSchemaType(name = "token")
+            lateinit var returnCode: String
+
+            @XmlElement(name = "ReportText", required = true)
+            @XmlJavaTypeAdapter(NormalizedStringAdapter::class)
+            @XmlSchemaType(name = "normalizedString")
+            lateinit var reportText: String
+        }
+    }
+
+    @XmlAccessorType(XmlAccessType.NONE)
+    @XmlType(name = "", propOrder = ["dataTransfer", "returnCode", 
"timestampBankParameter"])
+    class Body {
+        @XmlElement(name = "DataTransfer")
+        val dataTransfer: DataTransfer? = null
+
+        @XmlElement(name = "ReturnCode", required = true)
+        lateinit var returnCode: ReturnCode
+
+        @XmlElement(name = "TimestampBankParameter")
+        var timestampBankParameter: TimestampBankParameter? = null
+
+        @XmlAccessorType(XmlAccessType.NONE)
+        class ReturnCode {
+            @get:XmlValue
+            @get:XmlJavaTypeAdapter(CollapsedStringAdapter::class)
+            lateinit var value: String
+
+            @get:XmlAttribute(name = "authenticate", required = true)
+            var authenticate: Boolean = false
+        }
+
+        @XmlAccessorType(XmlAccessType.NONE)
+        @XmlType(name = "", propOrder = ["dataEncryptionInfo", "orderData"])
+        class DataTransfer {
+            @get:XmlElement(name = "DataEncryptionInfo")
+            var dataEncryptionInfo: DataEncryptionInfo? = null
+
+            @get:XmlElement(name = "OrderData", required = true)
+            lateinit var orderData: 
EbicsResponse.Body.DataTransferResponseType.OrderData
+        }
+    }
+}
diff --git a/sandbox/src/test/kotlin/DbTest.kt 
b/sandbox/src/test/kotlin/DbTest.kt
deleted file mode 100644
index 1c50dd1..0000000
--- a/sandbox/src/test/kotlin/DbTest.kt
+++ /dev/null
@@ -1,65 +0,0 @@
-package tech.libeufin.sandbox
-
-import junit.framework.TestCase.assertFalse
-import org.jetbrains.exposed.dao.EntityID
-import org.jetbrains.exposed.sql.transactions.transaction
-import org.junit.Test
-import org.junit.Before
-import tech.libeufin.sandbox.db.*
-
-class DbTest {
-
-    @Before
-    fun setUp() {
-        dbCreateTables()
-    }
-
-    /**
-     * This function creates a EBICS subscriber _first_, and
-     * subsequently tries to insert a mock bianry value into
-     * the keys columns of the subscriber.
-     */
-    @Test
-    fun storeBinary() {
-        transaction {
-            // join table
-            val subscriber = createSubscriber()
-
-            val key = EbicsPublicKey.new {
-                modulus = "BINARYVALUE".toByteArray()
-                exponent = "BINARYVALUE".toByteArray()
-                state = KeyStates.NEW
-            }
-            subscriber.authenticationKey = key
-        }
-    }
-
-    @Test
-    fun nestedQuery() {
-
-        /***
-         *  Some query like the following is needed:
-         *
-         *  val result = EbicsSubscriber.find {
-         *    EbicsSubscribers.userId.userId eq "u1"
-         *  }.first()
-         */
-
-         transaction {
-            createSubscriber()
-
-            val tmp = EbicsUser.find { EbicsUsers.userId eq "u1" 
}.firstOrNull()
-            if (tmp == null) {
-                logger.error("No such user found in database.")
-                return@transaction
-            }
-            println("Found user with id: ${tmp.id.value}")
-
-            val found = EbicsSubscriber.find {
-                EbicsSubscribers.userId eq EntityID(tmp.id.value, EbicsUsers)
-            }
-
-            assertFalse(found.empty())
-        }
-    }
-}
\ No newline at end of file
diff --git a/sandbox/src/test/kotlin/HiaLoadTest.kt 
b/sandbox/src/test/kotlin/HiaLoadTest.kt
index 489685a..9cb3f87 100644
--- a/sandbox/src/test/kotlin/HiaLoadTest.kt
+++ b/sandbox/src/test/kotlin/HiaLoadTest.kt
@@ -11,7 +11,7 @@ class HiaLoadTest {
 
         val processor = XMLUtil()
         val classLoader = ClassLoader.getSystemClassLoader()
-        val hia = classLoader.getResource("HIA.xml")
+        val hia = classLoader.getResource("<?xml version=\"1.0\" 
encoding=\"UTF-8\"?>\n<ebicsUnsecuredRequest xmlns=\"urn:org:ebics:H004\"\n     
                  xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\"\n             
          xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n             
          xsi:schemaLocation=\"urn:org:ebics:H004 
ebics_keymgmt_request_H004.xsd\"\n                       Version=\"H004\"\n     
                  Revision=\"1\">\n  <header authenticate [...]
         val hiaDom = XMLUtil.parseStringIntoDom(hia.readText())
         val x: Element = hiaDom.getElementsByTagNameNS(
             "urn:org:ebics:H004",
diff --git a/sandbox/src/test/kotlin/InnerIniLoadTest.kt 
b/sandbox/src/test/kotlin/InnerIniLoadTest.kt
index 664ece3..f181d3e 100644
--- a/sandbox/src/test/kotlin/InnerIniLoadTest.kt
+++ b/sandbox/src/test/kotlin/InnerIniLoadTest.kt
@@ -1,24 +1,31 @@
 package tech.libeufin.sandbox
 
 import org.junit.Test
+import tech.libeufin.schema.ebics_h004.EbicsUnsecuredRequest
 import tech.libeufin.schema.ebics_s001.SignaturePubKeyOrderData
+import kotlin.test.assertNotNull
 
 class InnerIniLoadTest {
-
-    val jaxbKey = {
-        val classLoader = ClassLoader.getSystemClassLoader()
-        val file = classLoader.getResource(
-            "ebics_ini_inner_key.xml"
-        )
-        XMLUtil.convertStringToJaxb<SignaturePubKeyOrderData>(file.readText())
-    }()
-
     @Test
     fun loadInnerKey() {
+        val jaxbKey = run {
+            val classLoader = ClassLoader.getSystemClassLoader()
+            val file = classLoader.getResource(
+                "ebics_ini_inner_key.xml"
+            )
+            assertNotNull(file)
+            
XMLUtil.convertStringToJaxb<SignaturePubKeyOrderData>(file.readText())
+        }
 
         val modulus = 
jaxbKey.value.signaturePubKeyInfo.pubKeyValue.rsaKeyValue.modulus
         val exponent = 
jaxbKey.value.signaturePubKeyInfo.pubKeyValue.rsaKeyValue.exponent
+        CryptoUtil.loadRsaPublicKeyFromComponents(modulus, exponent)
+    }
 
-        loadRsaPublicKey(modulus, exponent)
+    @Test
+    fun loadIniMessage() {
+        val classLoader = ClassLoader.getSystemClassLoader()
+        val text = 
classLoader.getResource("ebics_ini_request_sample.xml")!!.readText()
+        XMLUtil.convertStringToJaxb<EbicsUnsecuredRequest>(text)
     }
 }
\ No newline at end of file
diff --git a/sandbox/src/test/kotlin/JaxbTest.kt 
b/sandbox/src/test/kotlin/JaxbTest.kt
index 11942ac..fb2271c 100644
--- a/sandbox/src/test/kotlin/JaxbTest.kt
+++ b/sandbox/src/test/kotlin/JaxbTest.kt
@@ -2,10 +2,13 @@ package tech.libeufin.sandbox
 
 import junit.framework.TestCase.assertEquals
 import org.junit.Test
+import tech.libeufin.schema.ebics_h004.EbicsKeyManagementResponse
 import tech.libeufin.schema.ebics_h004.EbicsUnsecuredRequest
+import tech.libeufin.schema.ebics_h004.HIARequestOrderDataType
 import tech.libeufin.schema.ebics_hev.HEVResponse
 import tech.libeufin.schema.ebics_hev.SystemReturnCodeType
 import tech.libeufin.schema.ebics_s001.SignaturePubKeyOrderData
+import kotlin.test.assertTrue
 
 class JaxbTest {
     /**
@@ -65,4 +68,28 @@ class JaxbTest {
             iniDom
         )
     }
+
+    @Test
+    fun testKeyMgmgResponse() {
+        val responseXml = EbicsKeyManagementResponse().apply {
+            header = EbicsKeyManagementResponse.Header().apply {
+                mutable = 
EbicsKeyManagementResponse.Header.KeyManagementResponseMutableHeaderType().apply
 {
+                    reportText = "foo"
+                    returnCode = "bar"
+                }
+                _static = EbicsKeyManagementResponse.Header.EmptyStaticHeader()
+            }
+            version = "H004"
+            body = EbicsKeyManagementResponse.Body()
+        }
+        val text = XMLUtil.convertJaxbToString(responseXml)
+        assertTrue(text.isNotEmpty())
+    }
+
+    @Test
+    fun testParseHiaRequestOrderData() {
+        val classLoader = ClassLoader.getSystemClassLoader()
+        val hia = 
classLoader.getResource("hia_request_order_data.xml")!!.readText()
+        XMLUtil.convertStringToJaxb<HIARequestOrderDataType>(hia)
+    }
 }
\ No newline at end of file
diff --git a/sandbox/src/test/resources/ebics_ini_request_sample.xml 
b/sandbox/src/test/resources/ebics_ini_request_sample.xml
index 3015332..a9237a9 100644
--- a/sandbox/src/test/resources/ebics_ini_request_sample.xml
+++ b/sandbox/src/test/resources/ebics_ini_request_sample.xml
@@ -1,35 +1,25 @@
 <?xml version="1.0" encoding="utf-8"?>
-<ebicsUnsecuredRequest Revision="1" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="urn:org:ebics:H004 ebics_keymgmt_request_H004.xsd" 
Version="H004" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"; 
xmlns="urn:org:ebics:H004">
-  <header authenticate="true">
-    <static>
-      <HostID>LIBEUFIN-SANDBOX</HostID>
-      <PartnerID>flokid</PartnerID>
-      <UserID>u1</UserID>
-      <!--
-
-      Such a not allowed renaming like this fixes the import of DOM into JAXB.
-
-      <UnsecuredReqOrderDetails>
-        <OrderType>INI</OrderType>
-        <OrderAttribute>DZNNN</OrderAttribute>
-      </UnsecuredReqOrderDetails
-
-      Also putting the following attribute on OrderDetails fixes it.
-
-       xsi:type="UnsecuredReqOrderDetailsType"
-
-      -->
-      <OrderDetails>
-        <OrderType>INI</OrderType>
-        <OrderAttribute>DZNNN</OrderAttribute>
-      </OrderDetails>
-      <SecurityMedium>0000</SecurityMedium>
-    </static>
-    <mutable />
-  </header>
-  <body>
-    <DataTransfer>
-      
<OrderData>eJx9U1tzmkAUfu9M/wNDH524XIINjprBaLxSUASDL51FlvvFsIus/vpSYm3a1D6e7/vO/ZzeI00T5ogKHOZZn+XbHMugbJ+7Yeb32ZJ4dw/s4+Dzp54R+hkkZYH00lmgk1a4qBhBApnaP8NdisM+GxBy6AJQVVW7Ett54QOB43jwoi6NfYBSeBdmmMBsj1im1ndxAy7zPSRN8nfuyAn3uIlg1BGYmwxozO/4V3Ftil32UpKLb1TEAU4Gtcat3b5c1P/JztbtM8zfA5hlXt4QNfWGWDAp0QWqQRd314byAX9j1NwtkxIPsBSTgy/SSeTsdr61scm2xaEOxVufvxfM6pirYuqVauu1iGdQcnRzslpOO8P1Up6hyM6xHuRKJ6rUoUG1h6UHoY9OuzkRVKmaxsncPoueMiKrwuKdWFrLggZtIO927pRWIrVlkaTS3LMKdbSVR+OFNOQD82w/u1H5DbyWAsD
 [...]
-    </DataTransfer>
-  </body>
-</ebicsUnsecuredRequest>
+<ebicsUnsecuredRequest Revision="1" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+                       xsi:schemaLocation="urn:org:ebics:H004 
ebics_keymgmt_request_H004.xsd" Version="H004"
+                       xmlns="urn:org:ebics:H004">
+    <header authenticate="true">
+        <static>
+            <HostID>myhost</HostID>
+            <PartnerID>k1</PartnerID>
+            <UserID>u1</UserID>
+            <OrderDetails>
+                <OrderType>INI</OrderType>
+                <OrderAttribute>DZNNN</OrderAttribute>
+            </OrderDetails>
+            <SecurityMedium>0000</SecurityMedium>
+        </static>
+        <mutable/>
+    </header>
+    <body>
+        <DataTransfer>
+            <OrderData>
+                
eJx9U1tzmkAUfu9M/wNDH524XIINjprBaOIFCopg8CWzyHK/GHaR1V9fhtg0bWrf9nzfdy57LoN7mqXMEZU4KvIhy3c5lkH5vvCiPBiyFfFv7tj70dcvAzMKckiqEhmVu0QnvfRQOYEEMo1/jvsUR0M2JOTQB6Cu624tdosyAALH8eBZU819iDJ4E+WYwHyPWKbR93ELqsUekjb5B3fkRnvcRjCbCMxVBrTmC/5VXJdij72U5OErFXGAk0Gj8Rq3bxf1f7KzzfcZ5u8GzHO/aImGekNsmFboAjWgh/trU/mEvzFa4VVphUdYSsghEOlT7O52gb1xyLbDoR7F24C/Faz6WGhi5lda57VM5lByDetppc5647Uqz1HsFNgIC6UX19rYpPqd6kMYoNNuQQRNqmdJunDOoq9MyKq0eTeR1rKgQwfIu503o7VIHVkkmbTw7VKbbOXJdCmN+dA6O49eXP0Ar5UA
 [...]
+            </OrderData>
+        </DataTransfer>
+    </body>
+</ebicsUnsecuredRequest>
\ No newline at end of file
diff --git a/sandbox/src/test/resources/ebics_ini_request_sample_patched.xml 
b/sandbox/src/test/resources/ebics_ini_request_sample_patched.xml
deleted file mode 100644
index 821d7fd..0000000
--- a/sandbox/src/test/resources/ebics_ini_request_sample_patched.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<ebicsUnsecuredRequest Revision="1" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="urn:org:ebics:H004 ebics_keymgmt_request_H004.xsd" 
Version="H004" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"; 
xmlns="urn:org:ebics:H004">
-  <header authenticate="true">
-    <static>
-      <HostID>foo</HostID>
-      <PartnerID>flokid</PartnerID>
-      <UserID>flouid</UserID>
-      <OrderDetails xsi:type="UnsecuredReqOrderDetailsType">
-        <OrderType>INI</OrderType>
-        <OrderAttribute>DZNNN</OrderAttribute>
-      </OrderDetails>
-      <SecurityMedium>0000</SecurityMedium>
-    </static>
-    <mutable />
-  </header>
-  <body>
-    <DataTransfer>
-      
<OrderData>eJx9U1tzmkAUfu9M/wNDH524XIINjprBaLxSUASDL51FlvvFsIus/vpSYm3a1D6e7/vO/ZzeI00T5ogKHOZZn+XbHMugbJ+7Yeb32ZJ4dw/s4+Dzp54R+hkkZYH00lmgk1a4qBhBApnaP8NdisM+GxBy6AJQVVW7Ett54QOB43jwoi6NfYBSeBdmmMBsj1im1ndxAy7zPSRN8nfuyAn3uIlg1BGYmwxozO/4V3Ftil32UpKLb1TEAU4Gtcat3b5c1P/JztbtM8zfA5hlXt4QNfWGWDAp0QWqQRd314byAX9j1NwtkxIPsBSTgy/SSeTsdr61scm2xaEOxVufvxfM6pirYuqVauu1iGdQcnRzslpOO8P1Up6hyM6xHuRKJ6rUoUG1h6UHoY9OuzkRVKmaxsncPoueMiKrwuKdWFrLggZtIO927pRWIrVlkaTS3LMKdbSVR+OFNOQD82w/u1H5DbyWAsD
 [...]
-    </DataTransfer>
-  </body>
-</ebicsUnsecuredRequest>
diff --git a/sandbox/src/test/resources/HIA.xml 
b/sandbox/src/test/resources/hia_request.xml
similarity index 100%
rename from sandbox/src/test/resources/HIA.xml
rename to sandbox/src/test/resources/hia_request.xml
diff --git a/sandbox/src/test/resources/hia_request_order_data.xml 
b/sandbox/src/test/resources/hia_request_order_data.xml
new file mode 100644
index 0000000..cd1f4e4
--- /dev/null
+++ b/sandbox/src/test/resources/hia_request_order_data.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<HIARequestOrderData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="urn:org:ebics:H004 ebics_orders_H004.xsd" 
xmlns:ds="http://www.w3.org/2000/09/xmldsig#"; xmlns="urn:org:ebics:H004">
+    <AuthenticationPubKeyInfo>
+        <PubKeyValue>
+            <ds:RSAKeyValue>
+                
<ds:Modulus>0Ekicvrcj2+8tsF+DZsWihl9W7AyVwtMLxq3qefSWagpfnV7BVsKYIJ/OhiWpvr3dz6K5lHSatzhG1x//jrZt6VHn5Wkkb0M0vayPUiZbe5s2aLabqfOTrt8TPnHwjZMChDHRmGoKI0OzLyQJ6MIfQrHZ5t61ccWubYO/bgbSnP9H39k8QEp0kmW4Tf4u+28GTLgueNAaaPTdCozZjrST4fH9nyhBUZ3nl+vZ+AiUNdl5UfV109CXhCm3safLboUus6ZcYLm6gTaiwJEdRX7HYbnAQZ5gcoXVz/oyxJqTkicVOLPrTAfi3UmFrnIVF8XBtOPdIXHzSpxZ3yT8gH4zQ==</ds:Modulus>
+                <ds:Exponent>AQAB</ds:Exponent>
+            </ds:RSAKeyValue>
+        </PubKeyValue>
+        <AuthenticationVersion>X002</AuthenticationVersion>
+    </AuthenticationPubKeyInfo>
+    <EncryptionPubKeyInfo>
+        <PubKeyValue>
+            <ds:RSAKeyValue>
+                
<ds:Modulus>0Ekicvrcj2+8tsF+DZsWihl9W7AyVwtMLxq3qefSWagpfnV7BVsKYIJ/OhiWpvr3dz6K5lHSatzhG1x//jrZt6VHn5Wkkb0M0vayPUiZbe5s2aLabqfOTrt8TPnHwjZMChDHRmGoKI0OzLyQJ6MIfQrHZ5t61ccWubYO/bgbSnP9H39k8QEp0kmW4Tf4u+28GTLgueNAaaPTdCozZjrST4fH9nyhBUZ3nl+vZ+AiUNdl5UfV109CXhCm3safLboUus6ZcYLm6gTaiwJEdRX7HYbnAQZ5gcoXVz/oyxJqTkicVOLPrTAfi3UmFrnIVF8XBtOPdIXHzSpxZ3yT8gH4zQ==</ds:Modulus>
+                <ds:Exponent>AQAB</ds:Exponent>
+            </ds:RSAKeyValue>
+        </PubKeyValue>
+        <EncryptionVersion>E002</EncryptionVersion>
+    </EncryptionPubKeyInfo>
+    <PartnerID>PARTNER1</PartnerID>
+    <UserID>USER1</UserID>
+</HIARequestOrderData>
\ No newline at end of file
diff --git a/sandbox/src/test/resources/HPB.xml 
b/sandbox/src/test/resources/hpb_request.xml
similarity index 100%
rename from sandbox/src/test/resources/HPB.xml
rename to sandbox/src/test/resources/hpb_request.xml

-- 
To stop receiving notification emails like this one, please contact
address@hidden.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]