summaryrefslogtreecommitdiff
path: root/wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/crypto/KdfTest.kt
diff options
context:
space:
mode:
Diffstat (limited to 'wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/crypto/KdfTest.kt')
-rw-r--r--wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/crypto/KdfTest.kt213
1 files changed, 213 insertions, 0 deletions
diff --git a/wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/crypto/KdfTest.kt b/wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/crypto/KdfTest.kt
new file mode 100644
index 0000000..974f9aa
--- /dev/null
+++ b/wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/crypto/KdfTest.kt
@@ -0,0 +1,213 @@
+/*
+ * This file is part of GNU Taler
+ * (C) 2020 Taler Systems S.A.
+ *
+ * GNU Taler is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 3, or (at your option) any later version.
+ *
+ * GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+
+package net.taler.wallet.kotlin.crypto
+
+import net.taler.wallet.kotlin.Base32Crockford
+import net.taler.wallet.kotlin.crypto.Kdf.HMAC_SHA256_BLOCK_SIZE
+import net.taler.wallet.kotlin.crypto.Kdf.HMAC_SHA512_BLOCK_SIZE
+import kotlin.test.Test
+import kotlin.test.assertEquals
+import kotlin.test.assertTrue
+
+class KdfTest {
+
+ private val crypto = CryptoFactory.getCrypto()
+
+ @Test
+ fun testHmacSha256() {
+ // key smaller than block size
+ val key1 = "EDJP6WK5EG"
+ val message1 = "91JPRV3F41BPYWKCCGGG"
+ val expectedOut1 = "DYKV9QN2HVHMHQRGZ6XNJPPSGQZHA2JAVZB1676ACXYSNKQ0FQ30"
+ val out1 = Kdf.hmacSha256(Base32Crockford.decode(key1), Base32Crockford.decode(message1)) { crypto.sha256(it) }
+ assertTrue(Base32Crockford.decode(key1).size < HMAC_SHA256_BLOCK_SIZE)
+ assertEquals(expectedOut1, Base32Crockford.encode(out1))
+
+ // key bigger than block size
+ val key2 =
+ "AHM6JWS089GQ6S9K68G7CRBJD5GPWX10EXGQ6833E9JP2X35CGG64Y908HQQASVCC5SJ0GVJDXHPPSKFE9J20X3F41GQCVV9CGG66VVECSTQ6TBFDRQ0"
+ val message2 = "89P62RVB4166JXK5ECG4TRBMEHJQ488"
+ val expectedOut2 = "QGEK8853DW3GSQ4RHDYXZ0KX9R6E356R5495Z10KDNFNZ98V9FQG"
+ val out2 = Kdf.hmacSha256(Base32Crockford.decode(key2), Base32Crockford.decode(message2)) { crypto.sha256(it) }
+ assertTrue(Base32Crockford.decode(key2).size > HMAC_SHA256_BLOCK_SIZE)
+ assertEquals(expectedOut2, Base32Crockford.encode(out2))
+
+ // key exactly block size
+ val key3 =
+ "AHM6JWS0EDJP6WK5EGG6PSBS41MQ6831ECG6RVVECWG62WS0EHM6A832DHQP6TS0EDMQMS90DXK20J2D851J0MT884S3ADH07MG3CD0"
+ val message3 = "89P62RVB4166JXK5ECG4TRBMEHJQ488"
+ val expectedOut3 = "HAEWRWXEWWPRMT4W6E32GS0P6QMW85MMZZA5CX2BMJW36QZQFJ2G"
+ val out3 = Kdf.hmacSha256(Base32Crockford.decode(key3), Base32Crockford.decode(message3)) { crypto.sha256(it) }
+ assertEquals(HMAC_SHA256_BLOCK_SIZE, Base32Crockford.decode(key3).size)
+ assertEquals(expectedOut3, Base32Crockford.encode(out3))
+ }
+
+ @Test
+ fun testHmacSha512() {
+ // key smaller than block size
+ val key1 = "EDJP6WK5EG"
+ val message1 = "91JPRV3F41BPYWKCCGGG"
+ val expectedOut1 =
+ "ZMVHDTWE341YSE6YQ4S0Y6XESW7RVFG4WK2CE7K4ZESQ10125JJ2VTRBCHPAQTTKW9MT4H350ZXN8GMP2SBFG03SB6YK63QMHQRE2FG"
+ val out1 = Kdf.hmacSha512(Base32Crockford.decode(key1), Base32Crockford.decode(message1)) { crypto.sha512(it) }
+ assertTrue(Base32Crockford.decode(key1).size < HMAC_SHA512_BLOCK_SIZE)
+ assertEquals(expectedOut1, Base32Crockford.encode(out1))
+
+ // key bigger than block size
+ val key2 =
+ "AHM6JWS089GQ6S9K68G7CRBJD5GPWX10EXGQ6833E9JP2X35CGG64Y908HQQASVCC5SJ0GVJDXHPPSKFE9J2W829EGG6AY33DHTP8SBK414JR82C5GG4Y83MDWG62XKFD5J20RVFDSK7AWV9DXQ20XV9EHM20S39CXMQ8WS0C5Q6882N41T6Y83GE9JQCSBEEGG62RV3D5J6AVKMC5P20VV2EDHPAVK9EHWJW"
+ val message2 = "89P62RVB4166JXK5ECG4TRBMEHJQ488"
+ val expectedOut2 =
+ "0N9GF90FES6HXS344WB396CF78SQDRZ7CS9MRAVCVZPJ3PJ97HYSB5A3C7RCXTTYYSS4CV11X3DANKQD71YMTA46R3NS1X8A99YVAE0"
+ val out2 = Kdf.hmacSha512(Base32Crockford.decode(key2), Base32Crockford.decode(message2)) { crypto.sha512(it) }
+ assertTrue(Base32Crockford.decode(key2).size > HMAC_SHA512_BLOCK_SIZE)
+ assertEquals(expectedOut2, Base32Crockford.encode(out2))
+
+ // key exactly block size
+ val key3 =
+ "AHM6JWS0ESJQ4Y90EDJP6WK5EGG6PSBS41MQ6835F1GP6X3CF4G62WS0DHQPWSS0C5SJ0X38CMG64V3FCDNJ0WV9F9JJ0VV641T6GS90916M2GS0AD44281N64S20RBCCXQQ4TBMD1PJ0XV8D5HPG839ECG32CHR41H7JX35ECG62VK441GJ0V3FEGG6YSH0EHJQGX1E5RQ2W"
+ val message3 = "89P62RVB4166JXK5ECG4TRBMEHJQ488"
+ val expectedOut3 =
+ "A3ZAKHA0EADSBP832KBCPDNVB4GP876PMQEEB2F55ERTQFQ7KMYNTJ3SEWJEQRNH3EV2H0HSA740JE4JQH7GM8FC708KHF4A5FG9QNG"
+ val out3 = Kdf.hmacSha512(Base32Crockford.decode(key3), Base32Crockford.decode(message3)) { crypto.sha512(it) }
+ assertEquals(HMAC_SHA512_BLOCK_SIZE, Base32Crockford.decode(key3).size)
+ assertEquals(expectedOut3, Base32Crockford.encode(out3))
+ }
+
+ @Test
+ fun testRfc4231() {
+ val key1 = ByteArray(20) { 0x0b }
+ val data1 = "91MJ0N38CNS6A"
+ assertEquals(
+ "P0T4RRERVCW56Q58NZ7AY2ZH5E41VGG0S61KV9S6X4VPRBHJSZVG",
+ Base32Crockford.encode(Kdf.hmacSha256(key1, Base32Crockford.decode(data1)) { crypto.sha256(it) })
+ )
+ assertEquals(
+ "GYN7SQN5XXGSTKZGPGJ1M7BCP0HQKX72SS7C4Y3TT2SGAHF1FKFDNA1KPZBBH9R20E5JEKNEMFTE9FMXJ57EPRFHE0Q6JV107896GN0",
+ Base32Crockford.encode(Kdf.hmacSha512(key1, Base32Crockford.decode(data1)) { crypto.sha512(it) })
+ )
+
+ val key2 = Base32Crockford.decode("99JPCS8")
+ val data2 = "EXM62X10CHQJ0YB141VP2VKM41K6YWH0DSQQ8T39DSKKY"
+ assertEquals(
+ "BFEC2HNZC1TMWTG44GK0H5BNRXD00FR8KMKKK0WXXHCBJS7C711G",
+ Base32Crockford.encode(Kdf.hmacSha256(key2, Base32Crockford.decode(data2)) { crypto.sha256(it) })
+ )
+ assertEquals(
+ "2S5QMYZWZ0CY5RWNZFKKPNQ0ME3VTS125T1HZNGG4W6DFTH50NA9EP5ZEQ05N6AADM1MYSFRY3KFVJQAP6HMTJKB9DHPW1RA72YEEDR",
+ Base32Crockford.encode(Kdf.hmacSha512(key2, Base32Crockford.decode(data2)) { crypto.sha512(it) })
+ )
+
+ val key3 = ByteArray(20) { 0xaa.toByte() }
+ val data3 = "VQEXVQEXVQEXVQEXVQEXVQEXVQEXVQEXVQEXVQEXVQEXVQEXVQEXVQEXVQEXVQEXVQEXVQEXVQEXVQEX"
+ assertEquals(
+ "EWZAJ7HPG074D1ADQ3NX14C1MWMNJ2CB7VWC28PSCDAH9KPNCQZ0",
+ Base32Crockford.encode(Kdf.hmacSha256(key3, Base32Crockford.decode(data3)) { crypto.sha256(it) })
+ )
+ assertEquals(
+ "Z9SV024XATH89VXGY1TPS28BX6RVBPYXHVM1MDJNZ0Z37CH7KMWVYFM4G9WTE8P80TT8B93YCZ40FEA6MCVVXT4M4ST2F22SW4S95YR",
+ Base32Crockford.encode(Kdf.hmacSha512(key3, Base32Crockford.decode(data3)) { crypto.sha512(it) })
+ )
+
+ val key4 = Base32Crockford.decode("041061050R3GG28A1C60T3GF208H44RM2MB1E60S")
+ val data4 = "SQ6WVKEDSQ6WVKEDSQ6WVKEDSQ6WVKEDSQ6WVKEDSQ6WVKEDSQ6WVKEDSQ6WVKEDSQ6WVKEDSQ6WVKED"
+ assertEquals(
+ "G9ARME4T8GY0X96CG6C9KWG87A2Z1YN3WNWFG1VT5RZZ8SS9CSDG",
+ Base32Crockford.encode(Kdf.hmacSha256(key4, Base32Crockford.decode(data4)) { crypto.sha256(it) })
+ )
+ assertEquals(
+ "P2X4CNHQ8P66K475N32ZC7AAYZJQDPBZZ55REBF7DY050DGYWFDTJ755R4DA4QNMTSWJEQ65F20679FHJX0H432F5QHAVTZB22H9HQ8",
+ Base32Crockford.encode(Kdf.hmacSha512(key4, Base32Crockford.decode(data4)) { crypto.sha512(it) })
+ )
+
+ val key5 = ByteArray(20) { 0x0c.toByte() }
+ val data5 = "AHJQ6X10AXMQ8T10AHS7AVK3C5T6JVVE"
+ assertEquals(
+ "MEV1CX3K207E0VGCF5P2JNAN5C",
+ Base32Crockford.encode(Kdf.hmacSha256(key5, Base32Crockford.decode(data5)) { crypto.sha256(it) }
+ .copyOfRange(0, 16))
+ )
+ assertEquals(
+ "85FTTRKHB05567A1F6Y8J7C7MR",
+ Base32Crockford.encode(Kdf.hmacSha512(key5, Base32Crockford.decode(data5)) { crypto.sha512(it) }
+ .copyOfRange(0, 16))
+ )
+
+ val key6 = ByteArray(131) { 0xaa.toByte() }
+ val data6 = "AHJQ6X10ANSPJVK741662WK7CNS20N38C5Q20GKCDXHPPBAKD5X6A82BCNWJ0B9091GQ6T109DJQJ826D5S76X0"
+ assertEquals(
+ "C3J32P8YW2V7Y3CA4TNCQXDQFY70QHH16WMCA5058R20Y3Q3FXA0",
+ Base32Crockford.encode(Kdf.hmacSha256(key6, Base32Crockford.decode(data6)) { crypto.sha256(it) })
+ )
+ assertEquals(
+ "G2S44RY7R6HYQDRMJF0XTYZ8PJDMDMFM3D5EXG8J3C0KF0ZRYD96PNPG6ZG5Y9CRQM7X48AXD8F555F69XSZCFRAXJ5S2PMRBNW6B60",
+ Base32Crockford.encode(Kdf.hmacSha512(key6, Base32Crockford.decode(data6)) { crypto.sha512(it) })
+ )
+
+ val key7 = ByteArray(131) { 0xaa.toByte() }
+ val data7 =
+ "AHM6JWS0D5SJ0R90EHJQ6X10ENSPJVK741GJ0V31E9KPAWH0EHM62VH0C9P6YRVB5NSPJYK541NPAY90C5Q6883141P62WK7CNS20X38C5Q20RKCDXHPPBBKD5X6A834C5T62BH0AHM6A83BCNWJ0VK5CNJ7683MDWG64S90D1GQ6T35CGG64SB6DXS6A832CNMPWSS0ENSPAS10C9WJ0X38CMG4GKA18CG62V37DXS6JX38DMQ0"
+ assertEquals(
+ "KC4ZZ9RVJGQWP9V3BYYDBC798JZXRRV49W3H74WAFX8N6Q1T6QH0",
+ Base32Crockford.encode(Kdf.hmacSha256(key7, Base32Crockford.decode(data7)) { crypto.sha256(it) })
+ )
+ assertEquals(
+ "WDXPMXTXS1YVN96ZN7WPWQHZZQFBTWFRGSS8K1JXYPHJT86DS52BC0HCNGY4K0NH1NFEPNE3WKF1A4T6EVXPVR24C1JWJX20ZA66MP0",
+ Base32Crockford.encode(Kdf.hmacSha512(key7, Base32Crockford.decode(data7)) { crypto.sha512(it) })
+ )
+ }
+
+ @Test
+ fun testKdf() {
+ val salt = "94KPT83PCNS7J83KC5P78Y8"
+ val ikm = "94KPT83MD1JJ0WV5CDS6AX10D5Q70XBM41NPAY90DNGQ8SBJD5GPR"
+ val ctx = "94KPT83141HPYVKMCNW78833D1TPWTSC41GPRWVF41NPWVVQDRG62WS04XMPWSKF4WG6JVH0EHM6A82J8S1G"
+ val expectedOut =
+ "GTMR4QT05Z9WF5HKVG0WK9RPXGHSMHJNW377G9GJXCA8B0FEKPF4D27RJMSJZYWSQNTBJ5EYVV7ZW18B48Z0JVJJ80RHB706Y96Q358"
+ val out =
+ crypto.kdf(64, Base32Crockford.decode(ikm), Base32Crockford.decode(salt), Base32Crockford.decode(ctx))
+ assertEquals(expectedOut, Base32Crockford.encode(out))
+
+ val salt2 = "94KPT83141V6AWKS41SP2V3MF4G76VK1CDNG"
+ val ikm2 =
+ "94KPT83MD1JJ0WV5CDS6AX10D5Q70XBM41NPAY90DNGQ8SBJD5GPR83MD1GQ8838C5SJ0RK5CNQ20RV8C5Q6ESB441K6YWH08X75A82MC5P6AWG"
+ val ctx2 =
+ "94KPT83141HPYVKMCNW78833D1TPWTSC41GPRWVF41NPWVVQDRG62WS04XMPWSKF4WG6JVH0EHM6A82J8S1J0WVF41VPGY90DSQQ8833C5P6R83DCMG6JVK6DWZG"
+ val expectedOut2 =
+ "C6TXT6GMVZ8JNWZF27SPD6939FK035Y3FTWXYT0W4EZX9FNJ5KH24MQSK9D0MW3G7T1BBZ4ERVQC1RE24BNDPJQ68ZRQ8S3XN4GNHC8"
+ val out2 =
+ crypto.kdf(64, Base32Crockford.decode(ikm2), Base32Crockford.decode(salt2), Base32Crockford.decode(ctx2))
+ assertEquals(expectedOut2, Base32Crockford.encode(out2))
+
+ val salt3 = "C4G76RBCEG"
+ val ikm3 = "ESJQ4Y90EDJP6WK5EGG6PSBS"
+ val ctx3 = "D5Q6CVR"
+ val expectedOut3 = "ZYMG67TD51XYS0ZM3QZKH8HF8FW7CTVT91NAWD0PGZM2QGTNYKMXAA4ZJBH5V633TJW9E124CRYEY"
+ val out3 =
+ crypto.kdf(48, Base32Crockford.decode(ikm3), Base32Crockford.decode(salt3), Base32Crockford.decode(ctx3))
+ assertEquals(expectedOut3, Base32Crockford.encode(out3))
+
+ val salt4 = "84G76XV5CNT20WV1DHT20EH9"
+ val ikm4 = "9NWJ0SBREHS6AVB5DHWJ0WV5CDS6AX10DDJQJ"
+ val ctx4 = "CDQPWX35F1T20TBECSQKY88"
+ val expectedOut4 = "YM46SN0HYJ0RNGY1V5S7WY1SD2RQ1Y17G5Z37JD46E2Z8KY11PH5EV772RQ5NQ9SBMGG"
+ val out4 =
+ crypto.kdf(42, Base32Crockford.decode(ikm4), Base32Crockford.decode(salt4), Base32Crockford.decode(ctx4))
+ assertEquals(expectedOut4, Base32Crockford.encode(out4))
+ }
+
+}