diff options
Diffstat (limited to 'nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsKeyMng.kt')
-rw-r--r-- | nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsKeyMng.kt | 148 |
1 files changed, 74 insertions, 74 deletions
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsKeyMng.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsKeyMng.kt index 666ed2ed..48d10d18 100644 --- a/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsKeyMng.kt +++ b/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsKeyMng.kt @@ -36,37 +36,22 @@ import java.security.interfaces.* /** EBICS protocol for key management */ class EbicsKeyMng( private val cfg: EbicsSetupConfig, - private val clientKeys: ClientPrivateKeysFile + private val clientKeys: ClientPrivateKeysFile, + private val ebics3: Boolean ) { + private val schema = if (ebics3) "H005" else "H004" fun INI(): ByteArray { - val inner = XMLOrderData(cfg, "SignaturePubKeyOrderData", "http://www.ebics.org/S001") { + val data = XMLOrderData(cfg, "SignaturePubKeyOrderData", "http://www.ebics.org/S00${if (ebics3) 2 else 1}") { el("SignaturePubKeyInfo") { RSAKeyXml(clientKeys.signature_private_key) el("SignatureVersion", "A006") } } - val doc = request("ebicsUnsecuredRequest") { - el("header") { - attr("authenticate", "true") - el("static") { - el("HostID", cfg.ebicsHostId) - el("PartnerID", cfg.ebicsPartnerId) - el("UserID", cfg.ebicsUserId) - el("OrderDetails") { - el("OrderType", "INI") - el("OrderAttribute", "DZNNN") - } - el("SecurityMedium", "0200") - } - el("mutable") - } - el("body/DataTransfer/OrderData", inner) - } - return XMLUtil.convertDomToBytes(doc) + return request("ebicsUnsecuredRequest", "INI", "0200", data) } fun HIA(): ByteArray { - val inner = XMLOrderData(cfg, "HIARequestOrderData", "urn:org:ebics:H004") { + val data = XMLOrderData(cfg, "HIARequestOrderData", "urn:org:ebics:$schema") { el("AuthenticationPubKeyInfo") { RSAKeyXml(clientKeys.authentication_private_key) el("AuthenticationVersion", "X002") @@ -76,69 +61,72 @@ class EbicsKeyMng( el("EncryptionVersion", "E002") } } - val doc = request("ebicsUnsecuredRequest") { - el("header") { - attr("authenticate", "true") - el("static") { - el("HostID", cfg.ebicsHostId) - el("PartnerID", cfg.ebicsPartnerId) - el("UserID", cfg.ebicsUserId) - el("OrderDetails") { - el("OrderType", "HIA") - el("OrderAttribute", "DZNNN") - } - el("SecurityMedium", "0200") - } - el("mutable") - } - el("body/DataTransfer/OrderData", inner) - } - return XMLUtil.convertDomToBytes(doc) + return request("ebicsUnsecuredRequest", "HIA", "0200", data) } fun HPB(): ByteArray { val nonce = getNonce(128) - val doc = request("ebicsNoPubKeyDigestsRequest") { + return request("ebicsNoPubKeyDigestsRequest", "HPB", "0000", timestamp = Instant.now(), sign = true) + } + + /* ----- Helpers ----- */ + + private fun request( + name: String, + order: String, + securityMedium: String, + data: String? = null, + timestamp: Instant? = null, + sign: Boolean = false + ): ByteArray { + val doc = XmlBuilder.toDom(name, "urn:org:ebics:$schema") { + attr("http://www.w3.org/2000/xmlns/", "xmlns", "urn:org:ebics:$schema") + attr("http://www.w3.org/2000/xmlns/", "xmlns:ds", "http://www.w3.org/2000/09/xmldsig#") + attr("Version", "$schema") + attr("Revision", "1") el("header") { attr("authenticate", "true") el("static") { el("HostID", cfg.ebicsHostId) - el("Nonce", nonce.encodeUpHex()) - el("Timestamp", Instant.now().xmlDateTime()) + if (timestamp != null) { + el("Nonce", getNonce(128).encodeUpHex()) + el("Timestamp", timestamp.xmlDateTime()) + } el("PartnerID", cfg.ebicsPartnerId) el("UserID", cfg.ebicsUserId) el("OrderDetails") { - el("OrderType", "HPB") - el("OrderAttribute", "DZHNN") + if (ebics3) { + el("AdminOrderType", order) + } else { + el("OrderType", order) + el("OrderAttribute", if (order == "HPB") "DZHNN" else "DZNNN") + } } - el("SecurityMedium", "0000") + el("SecurityMedium", securityMedium) } el("mutable") } - el("AuthSignature") - el("body") + if (sign) el("AuthSignature") + el("body") { + if (data != null) el("DataTransfer/OrderData", data) + } } - XMLUtil.signEbicsDocument(doc, clientKeys.authentication_private_key, "H004") + if (sign) XMLUtil.signEbicsDocument(doc, clientKeys.authentication_private_key, schema) return XMLUtil.convertDomToBytes(doc) } - /* ----- Helpers ----- */ - - private fun request(name: String, build: XmlBuilder.() -> Unit): Document { - return XmlBuilder.toDom(name, "urn:org:ebics:H004") { - attr("http://www.w3.org/2000/xmlns/", "xmlns", "urn:org:ebics:H004") - attr("http://www.w3.org/2000/xmlns/", "xmlns:ds", "http://www.w3.org/2000/09/xmldsig#") - attr("Version", "H004") - attr("Revision", "1") - build() - } - } - private fun XmlBuilder.RSAKeyXml(key: RSAPrivateCrtKey) { - el("PubKeyValue") { - el("ds:RSAKeyValue") { - el("ds:Modulus", key.modulus.encodeBase64()) - el("ds:Exponent", key.publicExponent.encodeBase64()) + if (ebics3) { + val cert = CryptoUtil.certificateFromPrivate(key) + el("ds:X509Data") { + el("ds:X509Certificate", cert.encoded.encodeBase64()) + } + } else { + el("PubKeyValue") { + el("ds:RSAKeyValue") { + el("ds:Modulus", key.modulus.encodeBase64()) + el("ds:Exponent", key.publicExponent.encodeBase64()) + } } } } @@ -190,18 +178,30 @@ class EbicsKeyMng( } fun parseHpbOrder(data: InputStream): Pair<RSAPublicKey, RSAPublicKey> { + fun XmlDestructor.rsaPubKey(): RSAPublicKey { + val cert = opt("X509Data")?.one("X509Certificate")?.text()?.decodeBase64() + return if (cert != null) { + CryptoUtil.loadRsaPublicKeyFromCertificate(cert) + } else { + one("PubKeyValue").one("RSAKeyValue") { + CryptoUtil.loadRsaPublicKeyFromComponents( + one("Modulus").text().decodeBase64(), + one("Exponent").text().decodeBase64(), + ) + } + + } + } return XmlDestructor.fromStream(data, "HPBResponseOrderData") { - val authPub = one("AuthenticationPubKeyInfo").one("PubKeyValue").one("RSAKeyValue") { - CryptoUtil.loadRsaPublicKeyFromComponents( - one("Modulus").text().decodeBase64(), - one("Exponent").text().decodeBase64(), - ) + val authPub = one("AuthenticationPubKeyInfo") { + val version = one("AuthenticationVersion").text() + require(version == "X002") { "Expected authentication version X002 got unsupported $version" } + rsaPubKey() } - val encPub = one("EncryptionPubKeyInfo").one("PubKeyValue").one("RSAKeyValue") { - CryptoUtil.loadRsaPublicKeyFromComponents( - one("Modulus").text().decodeBase64(), - one("Exponent").text().decodeBase64(), - ) + val encPub = one("EncryptionPubKeyInfo") { + val version = one("EncryptionVersion").text() + require(version == "E002") { "Expected encryption version E002 got unsupported $version" } + rsaPubKey() } Pair(authPub, encPub) } |