[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.