[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[libeufin] 02/03: EbicsRequest helper.
From: |
gnunet |
Subject: |
[libeufin] 02/03: EbicsRequest helper. |
Date: |
Mon, 25 Nov 2019 22:08:12 +0100 |
This is an automated email from the git hooks/post-receive script.
marcello pushed a commit to branch master
in repository libeufin.
commit dcac56ce7860a880f7c54b3e9a2275c16e37f700
Author: Marcello Stanisci <address@hidden>
AuthorDate: Mon Nov 25 19:00:06 2019 +0100
EbicsRequest helper.
---
nexus/src/main/kotlin/Containers.kt | 11 +-
nexus/src/main/kotlin/Main.kt | 241 ++++++++-------------
.../libeufin/schema/ebics_h004/EbicsRequest.kt | 124 +++++++++++
.../libeufin/schema/ebics_h004/EbicsResponse.kt | 2 +-
4 files changed, 227 insertions(+), 151 deletions(-)
diff --git a/nexus/src/main/kotlin/Containers.kt
b/nexus/src/main/kotlin/Containers.kt
index b3a6a09..370e1c2 100644
--- a/nexus/src/main/kotlin/Containers.kt
+++ b/nexus/src/main/kotlin/Containers.kt
@@ -2,6 +2,9 @@ package tech.libeufin.nexus
import javax.crypto.SecretKey
import org.w3c.dom.Document
+import java.security.PrivateKey
+import java.security.interfaces.RSAPrivateCrtKey
+import java.security.interfaces.RSAPublicKey
import javax.xml.bind.JAXBElement
@@ -14,9 +17,9 @@ import javax.xml.bind.JAXBElement
data class EbicsContainer<T>(
// needed to verify responses
- val bankAuthPubBlob: ByteArray? = null,
+ val bankAuthPub: RSAPublicKey? = null,
- val bankEncPubBlob: ByteArray? = null,
+ val bankEncPub: RSAPublicKey? = null,
// needed to send the message
val ebicsUrl: String? = null,
@@ -28,10 +31,10 @@ data class EbicsContainer<T>(
val plainTransactionKey: SecretKey? = null,
// needed to decrypt data coming from the bank
- val customerEncPrivBlob: ByteArray? = null,
+ val customerEncPriv: RSAPrivateCrtKey? = null,
// needed to sign documents
- val customerAuthPrivBlob: ByteArray? = null,
+ val customerAuthPriv: RSAPrivateCrtKey? = null,
val jaxb: T? = null
)
\ No newline at end of file
diff --git a/nexus/src/main/kotlin/Main.kt b/nexus/src/main/kotlin/Main.kt
index 61a41d5..2969502 100644
--- a/nexus/src/main/kotlin/Main.kt
+++ b/nexus/src/main/kotlin/Main.kt
@@ -30,7 +30,6 @@ import io.ktor.features.ContentNegotiation
import io.ktor.features.StatusPages
import io.ktor.gson.gson
import io.ktor.http.ContentType
-import io.ktor.http.HttpMethod
import io.ktor.http.HttpStatusCode
import io.ktor.request.receive
import io.ktor.request.uri
@@ -39,7 +38,6 @@ import io.ktor.response.respondText
import io.ktor.routing.*
import io.ktor.server.engine.embeddedServer
import io.ktor.server.netty.Netty
-import org.apache.commons.codec.digest.Crypt
import org.apache.xml.security.binding.xmldsig.RSAKeyValueType
import org.apache.xml.security.binding.xmldsig.SignatureType
import org.jetbrains.exposed.sql.transactions.transaction
@@ -49,22 +47,19 @@ import tech.libeufin.schema.ebics_h004.*
import java.text.DateFormat
import javax.sql.rowset.serial.SerialBlob
import javax.xml.bind.JAXBElement
-import org.w3c.dom.Document
import tech.libeufin.schema.ebics_s001.SignatureTypes
import tech.libeufin.schema.ebics_s001.UserSignatureData
-import java.awt.Container
import java.math.BigInteger
import java.security.PrivateKey
-import java.security.PublicKey
import java.security.SecureRandom
+import java.security.interfaces.RSAPrivateCrtKey
import java.text.SimpleDateFormat
-import java.time.Instant.now
import java.util.*
import java.util.zip.DeflaterInputStream
-import java.util.zip.InflaterInputStream
import javax.crypto.EncryptedPrivateKeyInfo
import javax.xml.datatype.DatatypeFactory
import javax.xml.datatype.XMLGregorianCalendar
+import java.security.interfaces.RSAPublicKey
fun testData() {
@@ -125,6 +120,32 @@ fun expectId(param: String?): Int {
}
}
+fun signOrder(
+ orderBlob: ByteArray,
+ signKey: ByteArray,
+ partnerId: String,
+ userId: String
+): UserSignatureData {
+
+ val ES_signature = CryptoUtil.signEbicsA006(
+ CryptoUtil.digestEbicsOrderA006(orderBlob),
+ CryptoUtil.loadRsaPrivateKey(signKey)
+ )
+ val userSignatureData = UserSignatureData().apply {
+ orderSignatureList = listOf(
+ UserSignatureData.OrderSignatureData().apply {
+ signatureVersion = "A006"
+ signatureValue = ES_signature
+ partnerID = partnerId
+ userID = userId
+ }
+ )
+ }
+
+ return userSignatureData
+}
+
+
/**
* @return null when the bank could not be reached, otherwise returns the
* response already converted in JAXB.
@@ -151,8 +172,8 @@ suspend inline fun HttpClient.postToBank(url: String, body:
String): String {
suspend inline fun <reified T, reified S>HttpClient.postToBankSignedAndVerify(
url: String,
body: T,
- pub: PublicKey,
- priv: PrivateKey): JAXBElement<S> {
+ pub: RSAPublicKey,
+ priv: RSAPrivateCrtKey): JAXBElement<S> {
val doc = XMLUtil.convertJaxbToDocument(body)
XMLUtil.signEbicsDocument(doc, priv)
@@ -396,8 +417,8 @@ fun main() {
EbicsContainer(
ebicsUrl = subscriber.ebicsURL,
- customerEncPrivBlob =
subscriber.encryptionPrivateKey.toByteArray(),
- customerAuthPrivBlob =
subscriber.authenticationPrivateKey.toByteArray(),
+ customerEncPriv =
CryptoUtil.loadRsaPrivateKey(subscriber.encryptionPrivateKey.toByteArray()),
+ customerAuthPriv =
CryptoUtil.loadRsaPrivateKey(subscriber.authenticationPrivateKey.toByteArray()),
jaxb = request,
hostId = subscriber.hostID
@@ -420,7 +441,10 @@ fun main() {
Base64.getDecoder().decode(response.value.body.dataTransfer!!.orderData.value)
)
- val dataCompr = CryptoUtil.decryptEbicsE002(er,
CryptoUtil.loadRsaPrivateKey(bundle.customerEncPrivBlob!!))
+ val dataCompr = CryptoUtil.decryptEbicsE002(
+ er,
+ bundle.customerEncPriv!!
+ )
val data =
EbicsOrderUtil.decodeOrderDataXml<HTDResponseOrderData>(dataCompr)
@@ -453,8 +477,8 @@ fun main() {
val ackResponse =
client.postToBankSignedAndVerify<EbicsRequest, EbicsResponse>(
bundle.ebicsUrl,
ackRequest,
- CryptoUtil.loadRsaPublicKey(bundle.bankAuthPubBlob!!),
- CryptoUtil.loadRsaPrivateKey(bundle.customerAuthPrivBlob!!)
+ bundle.bankAuthPub!!,
+ bundle.customerAuthPriv!!
)
logger.debug("HTD final response: " +
XMLUtil.convertJaxbToString<EbicsResponse>(response.value))
@@ -826,29 +850,19 @@ fun main() {
val id = expectId(call.parameters["id"])
val innerPayload = "ES-PAYLOAD"
-
-
val container = transaction {
val subscriber = EbicsSubscriberEntity.findById(id) ?:
throw SubscriberNotFoundError(HttpStatusCode.NotFound)
- // first prepare ES content
- val ES_signature = CryptoUtil.signEbicsA006(
-
CryptoUtil.digestEbicsOrderA006(innerPayload.toByteArray()),
-
CryptoUtil.loadRsaPrivateKey(subscriber.signaturePrivateKey.toByteArray())
- )
+ val usd_compressed = EbicsOrderUtil.encodeOrderDataXml(
- val userSignatureData = UserSignatureData().apply {
- orderSignatureList = listOf(
- UserSignatureData.OrderSignatureData().apply {
- signatureVersion = "A006"
- signatureValue = ES_signature
- partnerID = subscriber.partnerID
- userID = subscriber.userID
- }
+ signOrder(
+ innerPayload.toByteArray(),
+ subscriber.signaturePrivateKey.toByteArray(),
+ subscriber.partnerID,
+ subscriber.userID
)
- }
- val usd_compressed =
EbicsOrderUtil.encodeOrderDataXml(userSignatureData)
+ )
val usd_encrypted = CryptoUtil.encryptEbicsE002(
usd_compressed,
CryptoUtil.loadRsaPublicKey(
@@ -856,97 +870,46 @@ fun main() {
)
)
- val tmp = EbicsRequest().apply {
- header = EbicsRequest.Header().apply {
- version = "H004"
- revision = 1
- authenticate = true
- static = EbicsRequest.StaticHeaderType().apply {
- hostID = subscriber.hostID
- nonce = getNonce(128)
- timestamp = getGregorianDate()
- partnerID = subscriber.partnerID
- userID = subscriber.userID
- orderDetails =
EbicsRequest.OrderDetails().apply {
- orderType = "TST"
- orderAttribute = "OZHNN"
- orderParams =
EbicsRequest.StandardOrderParams()
- }
- bankPubKeyDigests =
EbicsRequest.BankPubKeyDigests().apply {
- authentication =
EbicsTypes.PubKeyDigest().apply {
- algorithm =
"http://www.w3.org/2001/04/xmlenc#sha256"
- version = "X002"
- value =
CryptoUtil.getEbicsPublicKeyHash(
- CryptoUtil.loadRsaPublicKey(
-
subscriber.bankAuthenticationPublicKey?.toByteArray() ?: throw BankKeyMissing(
-
HttpStatusCode.PreconditionFailed)
- )
- )
- }
- encryption =
EbicsTypes.PubKeyDigest().apply {
- algorithm =
"http://www.w3.org/2001/04/xmlenc#sha256"
- version = "E002"
- value =
CryptoUtil.getEbicsPublicKeyHash(
- CryptoUtil.loadRsaPublicKey(
-
subscriber.bankEncryptionPublicKey?.toByteArray() ?: throw BankKeyMissing(
-
HttpStatusCode.PreconditionFailed
- )
- )
- )
- }
- }
- securityMedium = "0000"
- numSegments = BigInteger.ONE
- }
- mutable = EbicsRequest.MutableHeader().apply {
- transactionPhase =
EbicsTypes.TransactionPhaseType.INITIALISATION
- }
- }
- authSignature = SignatureType()
- body = EbicsRequest.Body().apply {
- dataTransfer = EbicsRequest.DataTransfer().apply {
- signatureData =
EbicsRequest.SignatureData().apply {
- authenticate = true
- value = usd_encrypted.encryptedData
- }
- dataEncryptionInfo =
EbicsTypes.DataEncryptionInfo().apply {
- transactionKey =
usd_encrypted.encryptedTransactionKey
- authenticate = true
- encryptionPubKeyDigest =
EbicsTypes.PubKeyDigest().apply {
- algorithm =
"http://www.w3.org/2001/04/xmlenc#sha256"
- version = "E002"
- value =
CryptoUtil.getEbicsPublicKeyHash(
- CryptoUtil.loadRsaPublicKey(
-
subscriber.bankEncryptionPublicKey?.toByteArray() ?: throw BankKeyMissing(
-
HttpStatusCode.PreconditionFailed
- )
- )
- )
- }
- }
- }
- }
- }
-
EbicsContainer(
- jaxb = tmp,
+ jaxb = EbicsRequest.createForUploadInitializationPhase(
+ usd_encrypted,
+ subscriber.hostID,
+ getNonce(128),
+ subscriber.partnerID,
+ subscriber.userID,
+ getGregorianDate(),
+
CryptoUtil.loadRsaPublicKey(subscriber.bankAuthenticationPublicKey?.toByteArray()
?: throw BankKeyMissing(
+ HttpStatusCode.PreconditionFailed
+ )),
+
CryptoUtil.loadRsaPublicKey(subscriber.bankEncryptionPublicKey?.toByteArray()
?: throw BankKeyMissing(
+ HttpStatusCode.PreconditionFailed
+ )),
+ BigInteger.ONE
+ ),
+
ebicsUrl = subscriber.ebicsURL,
- bankAuthPubBlob =
subscriber.bankAuthenticationPublicKey?.toByteArray() ?: throw BankKeyMissing(
- HttpStatusCode.PreconditionFailed
+ bankAuthPub = CryptoUtil.loadRsaPublicKey(
+
subscriber.bankAuthenticationPublicKey?.toByteArray() ?: throw
BankKeyMissing(HttpStatusCode.PreconditionFailed)
),
+
plainTransactionKey =
usd_encrypted.plainTransactionKey,
- customerAuthPrivBlob =
subscriber.authenticationPrivateKey.toByteArray(),
- bankEncPubBlob =
subscriber.bankEncryptionPublicKey?.toByteArray() ?: throw BankKeyMissing(
- HttpStatusCode.PreconditionFailed
+ customerAuthPriv = CryptoUtil.loadRsaPrivateKey(
+ subscriber.authenticationPrivateKey.toByteArray()
),
+
+ bankEncPub = CryptoUtil.loadRsaPublicKey(
+ subscriber.bankEncryptionPublicKey?.toByteArray()
?: throw BankKeyMissing(
+ HttpStatusCode.PreconditionFailed)
+ ),
+
hostId = subscriber.hostID
)
}
val response = client.postToBankSignedAndVerify<EbicsRequest,
EbicsResponse>(
container.ebicsUrl!!,
container.jaxb!!,
- CryptoUtil.loadRsaPublicKey(container.bankAuthPubBlob!!),
-
CryptoUtil.loadRsaPrivateKey(container.customerAuthPrivBlob!!)
+ container.bankAuthPub!!,
+ container.customerAuthPriv!!
)
if (response.value.body.returnCode.value != "000000") {
@@ -961,41 +924,22 @@ fun main() {
val encryptedPayload =
CryptoUtil.encryptEbicsE002withTransactionKey(
compressedInnerPayload,
- CryptoUtil.loadRsaPublicKey(container.bankEncPubBlob!!),
+ container.bankEncPub!!,
container.plainTransactionKey!!
)
- val tmp = EbicsRequest().apply {
- header = EbicsRequest.Header().apply {
- version = "H004"
- revision = 1
- authenticate = true
- static = EbicsRequest.StaticHeaderType().apply {
- hostID = container.hostId!!
- transactionID =
response.value.header._static.transactionID
- }
- mutable = EbicsRequest.MutableHeader().apply {
- transactionPhase =
EbicsTypes.TransactionPhaseType.TRANSFER
- segmentNumber = EbicsTypes.SegmentNumber().apply {
- lastSegment = true
- value = BigInteger.ONE
- }
- }
- }
-
- authSignature = SignatureType()
- body = EbicsRequest.Body().apply {
- dataTransfer = EbicsRequest.DataTransfer().apply {
- orderData = encryptedPayload.encryptedData
- }
- }
- }
+ val tmpTmp = EbicsRequest.createForUploadTransferPhase(
+ container.hostId!!,
+ response.value.header._static.transactionID!!,
+ BigInteger.ONE,
+ encryptedPayload.encryptedData
+ )
val responseTransaction =
client.postToBankSignedAndVerify<EbicsRequest, EbicsResponse>(
container.ebicsUrl,
- tmp,
- CryptoUtil.loadRsaPublicKey(container.bankAuthPubBlob),
-
CryptoUtil.loadRsaPrivateKey(container.customerAuthPrivBlob)
+ tmpTmp,
+ container.bankAuthPub,
+ container.customerAuthPriv
)
if (responseTransaction.value.body.returnCode.value !=
"000000") {
@@ -1036,19 +980,23 @@ fun main() {
authSignature = SignatureType()
}
- EbicsContainer<EbicsNpkdRequest>(
+ EbicsContainer(
ebicsUrl = subscriber.ebicsURL,
- customerEncPrivBlob =
subscriber.encryptionPrivateKey.toByteArray(),
- customerAuthPrivBlob =
subscriber.authenticationPrivateKey.toByteArray(),
- jaxb = hpbRequest
+ customerEncPriv = CryptoUtil.loadRsaPrivateKey(
+ subscriber.encryptionPrivateKey.toByteArray()
+ ),
+ customerAuthPriv = CryptoUtil.loadRsaPrivateKey(
+ subscriber.authenticationPrivateKey.toByteArray()
+ ),
+ jaxb = hpbRequest
)
}
val response = client.postToBankSigned<EbicsNpkdRequest,
EbicsKeyManagementResponse>(
bundle.ebicsUrl!!,
bundle.jaxb!!,
- CryptoUtil.loadRsaPrivateKey(bundle.customerAuthPrivBlob!!)
+ bundle.customerAuthPriv!!
)
if (response.value.body.returnCode.value != "000000") {
@@ -1064,7 +1012,8 @@ fun main() {
val dataCompr = CryptoUtil.decryptEbicsE002(
er,
- CryptoUtil.loadRsaPrivateKey(bundle.customerEncPrivBlob!!))
+ bundle.customerEncPriv!!
+ )
val data =
EbicsOrderUtil.decodeOrderDataXml<HPBResponseOrderData>(dataCompr)
val bankAuthPubBlob =
CryptoUtil.loadRsaPublicKeyFromComponents(
diff --git
a/sandbox/src/main/kotlin/tech/libeufin/schema/ebics_h004/EbicsRequest.kt
b/sandbox/src/main/kotlin/tech/libeufin/schema/ebics_h004/EbicsRequest.kt
index ffe797d..65e956b 100644
--- a/sandbox/src/main/kotlin/tech/libeufin/schema/ebics_h004/EbicsRequest.kt
+++ b/sandbox/src/main/kotlin/tech/libeufin/schema/ebics_h004/EbicsRequest.kt
@@ -1,7 +1,11 @@
package tech.libeufin.schema.ebics_h004
+import io.ktor.http.HttpStatusCode
import org.apache.xml.security.binding.xmldsig.SignatureType
+import tech.libeufin.sandbox.CryptoUtil
+import tech.libeufin.sandbox.toByteArray
import java.math.BigInteger
+import java.security.interfaces.RSAPublicKey
import javax.xml.bind.annotation.*
import javax.xml.bind.annotation.adapters.CollapsedStringAdapter
import javax.xml.bind.annotation.adapters.HexBinaryAdapter
@@ -265,4 +269,124 @@ class EbicsRequest {
@get:XmlElement(name = "Encryption")
lateinit var encryption: EbicsTypes.PubKeyDigest
}
+
+ companion object {
+
+ fun createForUploadInitializationPhase(
+ cryptoBundle: CryptoUtil.EncryptionResult,
+ hostId: String,
+ nonceArg: ByteArray,
+ partnerId: String,
+ userId: String,
+ date: XMLGregorianCalendar,
+ bankAuthPub: RSAPublicKey,
+ bankEncPub: RSAPublicKey,
+ segmentsNumber: BigInteger
+ ): EbicsRequest {
+
+ return EbicsRequest().apply {
+ header = EbicsRequest.Header().apply {
+ version = "H004"
+ revision = 1
+ authenticate = true
+ static = EbicsRequest.StaticHeaderType().apply {
+ hostID = hostId
+ nonce = nonceArg
+ timestamp = date
+ partnerID = partnerId
+ userID = userId
+ orderDetails = EbicsRequest.OrderDetails().apply {
+ orderType = "TST"
+ orderAttribute = "OZHNN"
+ orderParams = EbicsRequest.StandardOrderParams()
+ }
+ bankPubKeyDigests =
EbicsRequest.BankPubKeyDigests().apply {
+ authentication = EbicsTypes.PubKeyDigest().apply {
+ algorithm =
"http://www.w3.org/2001/04/xmlenc#sha256"
+ version = "X002"
+ value =
CryptoUtil.getEbicsPublicKeyHash(bankAuthPub)
+ }
+ encryption = EbicsTypes.PubKeyDigest().apply {
+ algorithm =
"http://www.w3.org/2001/04/xmlenc#sha256"
+ version = "E002"
+ value =
CryptoUtil.getEbicsPublicKeyHash(bankEncPub)
+ }
+ }
+ securityMedium = "0000"
+ numSegments = segmentsNumber
+ }
+ mutable = EbicsRequest.MutableHeader().apply {
+ transactionPhase =
EbicsTypes.TransactionPhaseType.INITIALISATION
+ }
+ }
+ authSignature = SignatureType()
+ body = EbicsRequest.Body().apply {
+ dataTransfer = EbicsRequest.DataTransfer().apply {
+ signatureData = EbicsRequest.SignatureData().apply {
+ authenticate = true
+ value = cryptoBundle.encryptedData
+ }
+ dataEncryptionInfo =
EbicsTypes.DataEncryptionInfo().apply {
+ transactionKey =
cryptoBundle.encryptedTransactionKey
+ authenticate = true
+ encryptionPubKeyDigest =
EbicsTypes.PubKeyDigest().apply {
+ algorithm =
"http://www.w3.org/2001/04/xmlenc#sha256"
+ version = "E002"
+ value =
CryptoUtil.getEbicsPublicKeyHash(bankEncPub)
+ }
+ }
+ }
+ }
+ }
+
+
+ }
+
+ fun createForUploadTransferPhase(
+ hostId: String,
+ transactionId: String,
+ segNumber: BigInteger,
+ encryptedData: ByteArray
+
+ ): EbicsRequest {
+
+ return EbicsRequest().apply {
+ header = Header().apply {
+ version = "H004"
+ revision = 1
+ authenticate = true
+ static = StaticHeaderType().apply {
+ hostID = hostId
+ transactionID = transactionId
+ }
+ mutable = MutableHeader().apply {
+ transactionPhase =
EbicsTypes.TransactionPhaseType.TRANSFER
+ segmentNumber = EbicsTypes.SegmentNumber().apply {
+ lastSegment = true
+ value = segNumber
+ }
+ }
+ }
+
+ authSignature = SignatureType()
+ body = EbicsRequest.Body().apply {
+ dataTransfer = EbicsRequest.DataTransfer().apply {
+ orderData = encryptedData
+ }
+ }
+ }
+
+ fun createForDownloadInitializationPhase(): EbicsRequest {
+
+ }
+
+ fun createForDownloadTransferPhase(): EbicsRequest {
+
+
+ }
+
+ fun createForDownloadReceiptPhase(): EbicsRequest {
+
+ }
+ }
}
diff --git
a/sandbox/src/main/kotlin/tech/libeufin/schema/ebics_h004/EbicsResponse.kt
b/sandbox/src/main/kotlin/tech/libeufin/schema/ebics_h004/EbicsResponse.kt
index c2dc841..4ba6949 100644
--- a/sandbox/src/main/kotlin/tech/libeufin/schema/ebics_h004/EbicsResponse.kt
+++ b/sandbox/src/main/kotlin/tech/libeufin/schema/ebics_h004/EbicsResponse.kt
@@ -22,7 +22,7 @@ class EbicsResponse {
var revision: Int? = null
@get:XmlElement(required = true)
- lateinit var header: EbicsResponse.Header
+ lateinit var header: Header
@get:XmlElement(name = "AuthSignature", required = true)
lateinit var authSignature: SignatureType
--
To stop receiving notification emails like this one, please contact
address@hidden.