libeufin

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

XmlTest.kt (5445B)


      1 /*
      2  * This file is part of LibEuFin.
      3  * Copyright (C) 2024-2025 Taler Systems S.A.
      4 
      5  * LibEuFin is free software; you can redistribute it and/or modify
      6  * it under the terms of the GNU Affero General Public License as
      7  * published by the Free Software Foundation; either version 3, or
      8  * (at your option) any later version.
      9 
     10  * LibEuFin is distributed in the hope that it will be useful, but
     11  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     12  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General
     13  * Public License for more details.
     14 
     15  * You should have received a copy of the GNU Affero General Public
     16  * License along with LibEuFin; see the file COPYING.  If not, see
     17  * <http://www.gnu.org/licenses/>
     18  */
     19 
     20 import kotlin.test.*
     21 import org.w3c.dom.Document
     22 import org.junit.Test
     23 import tech.libeufin.ebics.*
     24 import tech.libeufin.common.asUtf8
     25 import tech.libeufin.common.crypto.CryptoUtil
     26 import tech.libeufin.common.decodeBase64
     27 import tech.libeufin.ebics.XMLUtil
     28 import java.security.KeyPairGenerator
     29 
     30 class XmlCombinatorsTest {
     31     fun testBuilder(expected: String, root: String, builder: XmlBuilder.() -> Unit): Document {
     32         val toBytes = XmlBuilder.toBytes(root, builder)
     33         val toDom = XmlBuilder.toDom(root, null, builder)
     34         //assertEquals(expected, toString) TODO fix empty tag being closed only with toString
     35         assertEquals(expected, XMLUtil.convertDomToBytes(toDom).asUtf8())
     36         return toDom
     37     }
     38 
     39     @Test
     40     fun testWithModularity() {
     41         fun module(base: XmlBuilder) {
     42             base.el("module")
     43         }
     44         testBuilder(
     45             "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><root><module/></root>",
     46             "root"
     47         ) {
     48             module(this)
     49         }
     50     }
     51 
     52     @Test
     53     fun testWithIterable() {
     54         testBuilder(
     55             "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><iterable><endOfDocument><e1><e11>111</e11></e1><e2><e22>222</e22></e2><e3><e33>333</e33></e3><e4><e44>444</e44></e4><e5><e55>555</e55></e5><e6><e66>666</e66></e6><e7><e77>777</e77></e7><e8><e88>888</e88></e8><e9><e99>999</e99></e9><e10><e1010>101010</e1010></e10></endOfDocument></iterable>", 
     56             "iterable"
     57         ) {
     58             el("endOfDocument") {
     59                 for (i in 1..10)
     60                     el("e$i/e$i$i", "$i$i$i")
     61             }
     62         }
     63     }
     64 
     65     @Test
     66     fun testBasicXmlBuilding() {
     67         testBuilder(
     68             "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><ebicsRequest version=\"H004\"><a><b><c attribute-of=\"c\"><d><e><f nested=\"true\"><g><h/></g></f></e></d></c></b></a><one_more/></ebicsRequest>",
     69             "ebicsRequest"
     70         ) {
     71             attr("version", "H004")
     72             el("a/b/c") {
     73                 attr("attribute-of", "c")
     74                 el("d/e/f") {
     75                     attr("nested", "true")
     76                     el("g/h")
     77                 }
     78             }
     79             el("one_more")
     80         }
     81     }
     82 
     83     @Test
     84     fun signed() {
     85         val trapped = XmlBuilder.toDom("document", "urn:org:ebics:test") {
     86             el("order") {
     87                 text("not signed")
     88             }
     89             el("order") {
     90                 attr("authenticate", "true")
     91                 text("signed")
     92             }
     93             el("order") {
     94                 attr("authenticate", "false")
     95                 text("not signed 2")
     96             }
     97         }
     98         XmlDestructor.parse(trapped, "document") {
     99             assertEquals(3, map("order") { text() }.size)
    100             one("order", signed = true) {
    101                 assertEquals("signed", text())
    102             }
    103         }
    104     }
    105 }
    106 
    107 class XmlUtilTest {
    108 
    109     @Test
    110     fun basicSigningTest() {
    111         val doc = XMLUtil.parseIntoDom("""
    112             <myMessage xmlns:ebics="urn:org:ebics:H004">
    113                 <ebics:AuthSignature />
    114                 <foo authenticate="true">Hello World</foo>
    115             </myMessage>
    116         """.trimIndent().toByteArray().inputStream())
    117         val kpg = KeyPairGenerator.getInstance("RSA")
    118         kpg.initialize(2048)
    119         val pair = kpg.genKeyPair()
    120         val otherPair = kpg.genKeyPair()
    121         XMLUtil.signEbicsDocument(doc, pair.private)
    122         XMLUtil.verifyEbicsDocument(doc, pair.public)
    123         assertFails { XMLUtil.verifyEbicsDocument(doc, otherPair.public) }
    124     }
    125 
    126     @Test
    127     fun multiAuthSigningTest() {
    128         val doc = XMLUtil.parseIntoDom("""
    129             <myMessage xmlns:ebics="urn:org:ebics:H004">
    130                 <ebics:AuthSignature />
    131                 <foo authenticate="true">Hello World</foo>
    132                 <bar authenticate="true">Another one!</bar>
    133             </myMessage>
    134         """.trimIndent().toByteArray().inputStream())
    135         val kpg = KeyPairGenerator.getInstance("RSA")
    136         kpg.initialize(2048)
    137         val pair = kpg.genKeyPair()
    138         XMLUtil.signEbicsDocument(doc, pair.private)
    139         XMLUtil.verifyEbicsDocument(doc, pair.public)
    140     }
    141 
    142     @Test
    143     fun testRefSignature() {
    144         val classLoader = ClassLoader.getSystemClassLoader()
    145         val docText = classLoader.getResourceAsStream("signature1/doc.xml")
    146         val doc = XMLUtil.parseIntoDom(docText)
    147         val keyStream = classLoader.getResourceAsStream("signature1/public_key.txt")
    148         val keyBytes = keyStream.decodeBase64().readAllBytes()
    149         val key = CryptoUtil.loadRSAPublic(keyBytes)
    150         XMLUtil.verifyEbicsDocument(doc, key)
    151     }
    152 }