libeufin

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

CryptoUtilTest.kt (5349B)


      1 /*
      2  * This file is part of LibEuFin.
      3  * Copyright (C) 2024 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 org.junit.Test
     21 import tech.libeufin.common.crypto.CryptoUtil
     22 import tech.libeufin.common.crypto.PasswordHashCheck
     23 import tech.libeufin.common.crypto.PwCrypto
     24 import tech.libeufin.common.decodeUpHex
     25 import tech.libeufin.common.encodeBase64
     26 import tech.libeufin.common.encodeHex
     27 import tech.libeufin.common.encodeUpHex
     28 import kotlin.test.assertEquals
     29 import kotlin.test.assertTrue
     30 
     31 class CryptoUtilTest {
     32 
     33     @Test
     34     fun loadFromModulusAndExponent() {
     35         val public = CryptoUtil.genRSAPublic(1024)
     36         val pub2 = CryptoUtil.RSAPublicFromComponents(
     37             public.modulus.toByteArray(),
     38             public.publicExponent.toByteArray()
     39         )
     40         assertEquals(public, pub2)
     41     }
     42 
     43     @Test
     44     fun testCryptoUtilBasics() {
     45         val (private, public) = CryptoUtil.genRSAPair(1024)
     46         assertEquals(private, CryptoUtil.loadRSAPrivate(private.encoded))
     47         assertEquals(public, CryptoUtil.loadRSAPublic(public.encoded))
     48     }
     49 
     50     @Test
     51     fun testEbicsE002() {
     52         val data = "Hello, World!".toByteArray()
     53         val (private, public) = CryptoUtil.genRSAPair(1024)
     54         val (txKey, encryptedKey) = CryptoUtil.genEbicsE002Key(public)
     55         val enc = CryptoUtil.encryptEbicsE002(txKey, data.inputStream())
     56         val txKey2 = CryptoUtil.decryptEbicsE002Key(private, encryptedKey)
     57         val dec = CryptoUtil.decryptEbicsE002(txKey2, enc).readBytes()
     58         assertTrue(data.contentEquals(dec))
     59     }
     60 
     61     @Test
     62     fun testEbicsA006() {
     63         val (private, public) = CryptoUtil.genRSAPair(1024)
     64         val data = "Hello, World".toByteArray(Charsets.UTF_8)
     65         val sig = CryptoUtil.signEbicsA006(data, private)
     66         assertTrue(CryptoUtil.verifyEbicsA006(sig, data, public))
     67     }
     68 
     69     @Test
     70     fun testEbicsPublicKeyHashing() {
     71         val exponentStr = "01 00 01".replace(" ", "")
     72         val moduloStr = """
     73             EB BD B8 E3 73 45 60 06 44 A1 AD 6A 25 33 65 F5
     74             9C EB E5 93 E0 51 72 77 90 6B F0 58 A8 89 EB 00
     75             C6 0B 37 38 F3 3C 55 F2 4D 83 D0 33 C3 A8 F0 3C
     76             82 4E AF 78 51 D6 F4 71 6A CC 9C 10 2A 58 C9 5F
     77             3D 30 B4 31 D7 1B 79 6D 43 AA F9 75 B5 7E 0B 4A
     78             55 52 1D 7C AC 8F 92 B0 AE 9F CF 5F 16 5C 6A D1
     79             88 DB E2 48 E7 78 43 F9 18 63 29 45 ED 6C 08 6C
     80             16 1C DE F3 02 01 23 8A 58 35 43 2B 2E C5 3F 6F
     81             33 B7 A3 46 E1 75 BD 98 7C 6D 55 DE 71 11 56 3D
     82             7A 2C 85 42 98 42 DF 94 BF E8 8B 76 84 13 3E CA
     83             0E 8D 12 57 D6 8A CF 82 DE B7 D7 BB BC 45 AE 25
     84             95 76 00 19 08 AA D2 C8 A7 D8 10 37 88 96 B9 98
     85             14 B4 B0 65 F3 36 CE 93 F7 46 12 58 9F E7 79 33
     86             D5 BE 0D 0E F8 E7 E0 A9 C3 10 51 A1 3E A4 4F 67
     87             5E 75 8C 9D E6 FE 27 B6 3C CF 61 9B 31 D4 D0 22
     88             B9 2E 4C AF 5F D6 4B 1F F0 4D 06 5F 68 EB 0B 71
     89         """.trimIndent().replace(" ", "").replace("\n", "")
     90         val expectedHashStr = """
     91             72 71 D5 83 B4 24 A6 DA 0B 7B 22 24 3B E2 B8 8C
     92             6E A6 0F 9F 76 11 FD 18 BE 2C E8 8B 21 03 A9 41
     93         """.trimIndent()
     94 
     95         val expectedHash = expectedHashStr.replace(" ", "").replace("\n", "")
     96 
     97         val pub = CryptoUtil.RSAPublicFromComponents(moduloStr.decodeUpHex(), exponentStr.decodeUpHex())
     98 
     99         println("echoed pub exp: ${pub.publicExponent.encodeHex()}")
    100         println("echoed pub mod: ${pub.modulus.encodeHex()}")
    101 
    102         val pubHash = CryptoUtil.getEbicsPublicKeyHash(pub)
    103 
    104         println("our pubHash: ${pubHash.encodeUpHex()}")
    105         println("expected pubHash: ${expectedHash}")
    106 
    107         assertEquals(expectedHash, pubHash.encodeUpHex())
    108     }
    109 
    110     @Test
    111     fun passwordHashing() {
    112         val password = "myinsecurepw"
    113         val pwCrypto = PwCrypto.Bcrypt(cost = 4)
    114         // Check roundtrip
    115         val hash = pwCrypto.hashpw(password)
    116         assertEquals(pwCrypto.checkpw(password, hash), PasswordHashCheck(true, false))
    117         assertEquals(pwCrypto.checkpw("other", hash), PasswordHashCheck(false, false))
    118 
    119         // Check outdated algorithm
    120         val pwh = CryptoUtil.hashStringSHA256(password).encodeBase64()
    121         val outdatedHash = "sha256\$$pwh"
    122         assertEquals(pwCrypto.checkpw(password, outdatedHash), PasswordHashCheck(true, true))
    123         assertEquals(pwCrypto.checkpw("other", outdatedHash), PasswordHashCheck(false, true))
    124 
    125         // Check outdated options
    126         val betterCrypto = pwCrypto.copy(cost = 5)
    127         assertEquals(betterCrypto.checkpw(password, hash), PasswordHashCheck(true, true))
    128         assertEquals(betterCrypto.checkpw("other", hash), PasswordHashCheck(false, true))
    129     }
    130 }