diff options
author | Antoine A <> | 2024-03-14 02:26:38 +0100 |
---|---|---|
committer | Antoine A <> | 2024-03-14 02:26:38 +0100 |
commit | 125b6e8d1efe839b7cc575767b812e2e406e296f (patch) | |
tree | f674f1a822cd18647b461a6e6938aea42d67f91e | |
parent | bef953d9dd4a02910454d5f882077248fc6967e9 (diff) | |
download | libeufin-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.kt | 25 | ||||
-rw-r--r-- | nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsCommon.kt | 18 |
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"), |