libeufin

Integration and sandbox testing for FinTech APIs and data formats
Log | Files | Refs | Submodules | README | LICENSE

commit 00317a0f36225bbae9450b4f66dac2cbfde90c7a
parent 923b242021397f14011e9d5abab8a5519361cd2d
Author: Florian Dold <florian.dold@gmail.com>
Date:   Wed, 13 Nov 2019 18:31:30 +0100

implement A006 canonicalization

Diffstat:
Msandbox/src/main/kotlin/tech/libeufin/sandbox/CryptoUtil.kt | 17+++++++++++++++--
Msandbox/src/main/kotlin/tech/libeufin/sandbox/EbicsProtocolBackend.kt | 21++++++++++++++++-----
2 files changed, 31 insertions(+), 7 deletions(-)

diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/CryptoUtil.kt b/sandbox/src/main/kotlin/tech/libeufin/sandbox/CryptoUtil.kt @@ -165,6 +165,13 @@ object CryptoUtil { return data } + /** + * Signing algorithm corresponding to the EBICS A006 signing process. + * + * Note that while [data] can be arbitrary-length data, in EBICS, the order + * data is *always* hashed *before* passing it to the signing algorithm, which again + * uses a hash internally. + */ fun signEbicsA006(data: ByteArray, privateKey: RSAPrivateCrtKey): ByteArray { val signature = Signature.getInstance("SHA256withRSA/PSS", bouncyCastleProvider) signature.setParameter(PSSParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA256, 32, 1)) @@ -181,8 +188,14 @@ object CryptoUtil { return signature.verify(sig) } - fun digestEbicsA006(data: ByteArray): ByteArray { + fun digestEbicsOrderA006(orderData: ByteArray): ByteArray { val digest = MessageDigest.getInstance("SHA-256") - return digest.digest(data) + for (b in orderData) { + when (b) { + '\r'.toByte(), '\n'.toByte(), (26).toByte() -> Unit + else -> digest.update(b) + } + } + return digest.digest() } } diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/EbicsProtocolBackend.kt b/sandbox/src/main/kotlin/tech/libeufin/sandbox/EbicsProtocolBackend.kt @@ -27,6 +27,7 @@ import io.ktor.request.receiveText import io.ktor.response.respond import io.ktor.response.respondText import org.apache.xml.security.binding.xmldsig.RSAKeyValueType +import org.apache.xml.security.c14n.Canonicalizer import org.jetbrains.exposed.sql.and import org.jetbrains.exposed.sql.transactions.transaction import org.jetbrains.exposed.sql.upperCase @@ -109,6 +110,11 @@ private suspend fun ApplicationCall.respondEbicsKeyManagement( private suspend fun ApplicationCall.handleEbicsHia(header: EbicsUnsecuredRequest.Header, orderData: ByteArray) { + val plainOrderData = InflaterInputStream(orderData.inputStream()).use { + it.readAllBytes() + } + println("hia order data: ${plainOrderData.toString(Charsets.UTF_8)}") + val keyObject = EbicsOrderUtil.decodeOrderDataXml<HIARequestOrderData>(orderData) val encPubXml = keyObject.encryptionPubKeyInfo.pubKeyValue.rsaKeyValue val authPubXml = keyObject.authenticationPubKeyInfo.pubKeyValue.rsaKeyValue @@ -140,6 +146,11 @@ private suspend fun ApplicationCall.handleEbicsHia(header: EbicsUnsecuredRequest private suspend fun ApplicationCall.handleEbicsIni(header: EbicsUnsecuredRequest.Header, orderData: ByteArray) { + val plainOrderData = InflaterInputStream(orderData.inputStream()).use { + it.readAllBytes() + } + println("ini order data: ${plainOrderData.toString(Charsets.UTF_8)}") + val keyObject = EbicsOrderUtil.decodeOrderDataXml<SignatureTypes.SignaturePubKeyOrderData>(orderData) val sigPubXml = keyObject.signaturePubKeyInfo.pubKeyValue.rsaKeyValue val sigPub = CryptoUtil.loadRsaPublicKeyFromComponents(sigPubXml.modulus, sigPubXml.exponent) @@ -661,14 +672,14 @@ suspend fun ApplicationCall.ebicsweb() { throw EbicsInvalidRequestError() } + val customCanon = unzippedData.filter { it != '\r'.toByte() && it != '\n'.toByte() && it != (26).toByte()}.toByteArray() + for (sig in sigs) { if (sig.signatureAlgorithm == "A006") { - val signedData = CryptoUtil.digestEbicsA006(unzippedData) - val res = CryptoUtil.verifyEbicsA006(sig.signatureValue.toByteArray(), signedData, clientSigPub) - println("VEU verification result: $res") - if (!res) { + val signedData = CryptoUtil.digestEbicsOrderA006(unzippedData) + val res1 = CryptoUtil.verifyEbicsA006(sig.signatureValue.toByteArray(), signedData, clientSigPub) + if (res1) throw EbicsInvalidRequestError() - } } else { throw NotImplementedError() }