summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAntoine A <>2024-03-14 02:26:38 +0100
committerAntoine A <>2024-03-14 02:26:38 +0100
commit125b6e8d1efe839b7cc575767b812e2e406e296f (patch)
treef674f1a822cd18647b461a6e6938aea42d67f91e
parentbef953d9dd4a02910454d5f882077248fc6967e9 (diff)
downloadlibeufin-125b6e8d1efe839b7cc575767b812e2e406e296f.tar.gz
libeufin-125b6e8d1efe839b7cc575767b812e2e406e296f.tar.bz2
libeufin-125b6e8d1efe839b7cc575767b812e2e406e296f.zip
Support chunked EBICS upload
-rw-r--r--nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsBTS.kt25
-rw-r--r--nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsCommon.kt18
2 files changed, 24 insertions, 19 deletions
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsBTS.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsBTS.kt
index a6466366..9e5ee4e2 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsBTS.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsBTS.kt
@@ -112,7 +112,7 @@ class EbicsBTS(
}
fun downloadTransfer(
- howManySegments: Int,
+ nbSegment: Int,
segmentNumber: Int,
transactionId: String
): ByteArray {
@@ -126,7 +126,8 @@ class EbicsBTS(
el("mutable") {
el("TransactionPhase", "Transfer")
el("SegmentNumber") {
- attr("lastSegment", if (howManySegments == segmentNumber) "true" else "false")
+ attr("lastSegment", if (nbSegment == segmentNumber) "true" else "false")
+ text(segmentNumber.toString())
}
}
}
@@ -160,7 +161,7 @@ class EbicsBTS(
/* ----- Upload ----- */
- fun uploadInitialization(preparedUploadData: PreparedUploadData): ByteArray {
+ fun uploadInitialization(uploadData: PreparedUploadData): ByteArray {
val nonce = getNonce(128)
return signedRequest {
el("header") {
@@ -195,7 +196,7 @@ class EbicsBTS(
}
}
bankDigest()
- el("NumSegments", "1") // TODO test upload of many segment
+ el("NumSegments", uploadData.segments.size.toString())
}
el("mutable") {
@@ -212,15 +213,15 @@ class EbicsBTS(
attr("Algorithm", "http://www.w3.org/2001/04/xmlenc#sha256")
text(CryptoUtil.getEbicsPublicKeyHash(bankKeys.bank_encryption_public_key).encodeBase64())
}
- el("TransactionKey", preparedUploadData.transactionKey.encodeBase64())
+ el("TransactionKey", uploadData.transactionKey.encodeBase64())
}
el("SignatureData") {
attr("authenticate", "true")
- text(preparedUploadData.userSignatureDataEncrypted.encodeBase64())
+ text(uploadData.userSignatureDataEncrypted.encodeBase64())
}
el("DataDigest") {
attr("SignatureVersion", "A006")
- text(preparedUploadData.dataDigest.encodeBase64())
+ text(uploadData.dataDigest.encodeBase64())
}
}
}
@@ -229,9 +230,9 @@ class EbicsBTS(
fun uploadTransfer(
transactionId: String,
- uploadData: PreparedUploadData
+ uploadData: PreparedUploadData,
+ segmentNumber: Int
): ByteArray {
- val chunkIndex = 1 // TODO test upload of many segment
return signedRequest {
el("header") {
attr("authenticate", "true")
@@ -242,13 +243,13 @@ class EbicsBTS(
el("mutable") {
el("TransactionPhase", "Transfer")
el("SegmentNumber") {
- attr("lastSegment", "true")
- text(chunkIndex.toString())
+ attr("lastSegment", if (uploadData.segments.size == segmentNumber) "true" else "false")
+ text(segmentNumber.toString())
}
}
}
el("AuthSignature")
- el("body/DataTransfer/OrderData", uploadData.encryptedPayloadChunks[chunkIndex - 1])
+ el("body/DataTransfer/OrderData", uploadData.segments[segmentNumber-1])
}
}
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsCommon.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsCommon.kt
index 77cefeb3..3c8120d9 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsCommon.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsCommon.kt
@@ -301,13 +301,14 @@ fun prepareUploadPayload(
bankKeys.bank_encryption_public_key,
encryptionResult.plainTransactionKey
)
- val encodedEncryptedPayload = encryptedPayload.encryptedData.encodeBase64()
+ val segment = encryptedPayload.encryptedData.encodeBase64()
+ // Split 1MB segment when we have payloads that big
return PreparedUploadData(
encryptionResult.encryptedTransactionKey, // ephemeral key
encryptionResult.encryptedData, // bank-pub-encrypted A006 signature.
CryptoUtil.digestEbicsOrderA006(payload), // used by EBICS 3
- listOf(encodedEncryptedPayload) // actual payload E002 encrypted.
+ listOf(segment) // actual payload E002 encrypted.
)
}
@@ -341,12 +342,14 @@ suspend fun doEbicsUpload(
val tId = requireNotNull(initResp.transactionID) {
"Upload init phase: missing transaction ID"
}
+ val orderId = requireNotNull(initResp.orderID) {
+ "Upload init phase: missing order ID"
+ }
// Transfer phase
- val transferXml = impl.uploadTransfer(tId, preparedPayload)
- val transferResp = impl.postBTS(client, transferXml, "Upload transfer phase").okOrFail("Upload transfer phase")
- val orderId = requireNotNull(transferResp.orderID) {
- "Upload transfer phase: missing order ID"
+ for (i in 1..preparedPayload.segments.size) {
+ val transferXml = impl.uploadTransfer(tId, preparedPayload, i)
+ val transferResp = impl.postBTS(client, transferXml, "Upload transfer phase").okOrFail("Upload transfer phase")
}
orderId
}
@@ -365,7 +368,7 @@ class PreparedUploadData(
val transactionKey: ByteArray,
val userSignatureDataEncrypted: ByteArray,
val dataDigest: ByteArray,
- val encryptedPayloadChunks: List<String>
+ val segments: List<String>
)
class DataEncryptionInfo(
@@ -412,6 +415,7 @@ enum class EbicsReturnCode(val code: String) {
EBICS_UNSUPPORTED_ORDER_TYPE("091006"),
EBICS_INVALID_XML("091010"),
EBICS_TX_MESSAGE_REPLAY("091103"),
+ EBICS_TX_SEGMENT_NUMBER_EXCEEDED("091104"),
EBICS_INVALID_REQUEST_CONTENT("091113"),
EBICS_PROCESSING_ERROR("091116"),
EBICS_ACCOUNT_AUTHORISATION_FAILED("091302"),