gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-wallet-kotlin] 04/04: Add Planchet creation with tests and platfo


From: gnunet
Subject: [taler-wallet-kotlin] 04/04: Add Planchet creation with tests and platform specific secure random bytes
Date: Wed, 24 Jun 2020 22:54:00 +0200

This is an automated email from the git hooks/post-receive script.

torsten-grote pushed a commit to branch master
in repository wallet-kotlin.

commit 86bd04302b8691aa3e518a70bafa9d95d8358e82
Author: Torsten Grote <t@grobox.de>
AuthorDate: Wed Jun 24 17:53:20 2020 -0300

    Add Planchet creation with tests and platform specific secure random bytes
---
 .idea/dictionaries/user.xml                        |   1 +
 .../taler/wallet/kotlin/crypto/CryptoFactory.kt    |   4 +
 .../net/taler/wallet/kotlin/crypto/PlanchetTest.kt | 125 +++++++++++++++++++++
 .../net/taler/wallet/kotlin/crypto/Crypto.kt       |   1 +
 .../net/taler/wallet/kotlin/crypto/Planchet.kt     |  68 +++++++++++
 .../net/taler/wallet/kotlin/crypto/Signature.kt    |  26 ++---
 .../taler/wallet/kotlin/crypto/CryptoFactory.kt    |   4 +
 .../taler/wallet/kotlin/crypto/CryptoFactory.kt    |   6 +
 8 files changed, 222 insertions(+), 13 deletions(-)

diff --git a/.idea/dictionaries/user.xml b/.idea/dictionaries/user.xml
index 02282e7..c5ce0d6 100644
--- a/.idea/dictionaries/user.xml
+++ b/.idea/dictionaries/user.xml
@@ -7,6 +7,7 @@
       <w>nacl</w>
       <w>planchet</w>
       <w>planchets</w>
+      <w>taler</w>
     </words>
   </dictionary>
 </component>
\ No newline at end of file
diff --git 
a/src/androidMain/kotlin/net/taler/wallet/kotlin/crypto/CryptoFactory.kt 
b/src/androidMain/kotlin/net/taler/wallet/kotlin/crypto/CryptoFactory.kt
index cf754f2..7435c3f 100644
--- a/src/androidMain/kotlin/net/taler/wallet/kotlin/crypto/CryptoFactory.kt
+++ b/src/androidMain/kotlin/net/taler/wallet/kotlin/crypto/CryptoFactory.kt
@@ -27,6 +27,10 @@ internal object CryptoJvmImpl : CryptoImpl() {
         return output
     }
 
+    override fun getRandomBytes(num: Int): ByteArray {
+        return sodium.randomBytesBuf(num)
+    }
+
     override fun eddsaGetPublic(eddsaPrivateKey: ByteArray): ByteArray {
         return sodium.cryptoSignSeedKeypair(eddsaPrivateKey).publicKey.asBytes
     }
diff --git 
a/src/androidTest/kotlin/net/taler/wallet/kotlin/crypto/PlanchetTest.kt 
b/src/androidTest/kotlin/net/taler/wallet/kotlin/crypto/PlanchetTest.kt
new file mode 100644
index 0000000..d7f1dae
--- /dev/null
+++ b/src/androidTest/kotlin/net/taler/wallet/kotlin/crypto/PlanchetTest.kt
@@ -0,0 +1,125 @@
+/*
+ * 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.Amount
+import net.taler.wallet.kotlin.Base32Crockford
+import net.taler.wallet.kotlin.crypto.Planchet.CreationRequest
+import net.taler.wallet.kotlin.crypto.Planchet.CreationResult
+import kotlin.random.Random
+import kotlin.test.Test
+import kotlin.test.assertEquals
+import kotlin.test.assertNotEquals
+
+// TODO move to commonTest once RsaBlinding is implemented everywhere
+class PlanchetTest {
+
+    private val crypto = CryptoFactory.getCrypto()
+    private val planchet = Planchet(crypto)
+
+    private class PlanchetVector(val request: CreationRequest, val 
eddsaKeyPair: EddsaKeyPair, val blindingFactor: String, val result: 
CreationResult)
+
+    @Test
+    fun testCreate() {
+        val vectors = listOf(
+            PlanchetVector(
+                CreationRequest(
+                    denomPub = 
"040000XVGVWCHVQVTQ06Q5V0XRAVQKPPZQZ68GYVXSC5RAG37VDCG0CEQHS4876BX6DDABB2WFY7TRJ7MFKTMMDF7A7ZW9PKQ8S3RQ15TVTKWBFGGKBKYSP6CVHNG9AY738NCPC8AFWYGP8J2VJE9HRR7M1GQK19E2M7Q2Y54KCSZ583BTNX275DW6EYYE1KBV4FK009Z621EHF5R87S6VQDSBCKSK15JCH1JYC2VPRHHAEGRA2WYX1HD9KFET0C9G1CZJB1MHZ5Z7Y803YZJH441P3PJJTRB9WCTA03H6M43CJ9MB33BEJ3KR22R8CS0D6QC2E7ZQS5MGBWCF51FK97SHCJW93SAT7VHB3YX5VVDNTW9N3SDW56HNWT11D306H9VN7BTP84T404VF482Y09K4SHEF5704002",
+                    feeWithdraw = 
Amount.fromJSONString("KOADwTb3:9329564218.42023"),
+                    reservePriv = 
"9TM70AKDTS57AWY9JK2J4TMBTMW6K62WHHGZWYDG0VM5ABPZKD40",
+                    reservePub = 
"8GSJZ649T2PXMKZC01Y4ANNBE7MF14QVK9SQEC4E46ZHKCVG8AS0",
+                    value = 
Amount.fromJSONString("KOADwTb3:3932974019564218.48282023")
+                ),
+                EddsaKeyPair(
+                    
Base32Crockford.decode("GX5DGW3RJ4HMXS53W29TK2667NWA3Z4WB41X7GPAX3WX4036VQGG"),
+                    
Base32Crockford.decode("Z6DXSXGEQ8C4G50FF6TG6ZKBH11APJ2HSNS21BAR72VY3KV7CC90")
+                ),
+                "H58V73J73HXTA9CPT8ZZ5G7VVKCWZFAE1TMCCV176QBQTPBB2H40",
+                CreationResult(
+                    blindingKey = 
"H58V73J73HXTA9CPT8ZZ5G7VVKCWZFAE1TMCCV176QBQTPBB2H40",
+                    coinEv = 
"AK23AD09K8462T621RPER66WQRNE845JAMBT4Y1AA39M22M5K0DZFPH2P5V9E8RD0VC1Z915WB432D2C1BHKHZGP62X9A424JZRPVTFJGYCFYHH52BG0VTJ58ZK70S52KYC2DW4Z0XHKBW0BW3F8NAGGTTGE6NF6EJ3SXYBVYTN0TDJE7HED3ZEGM34N73656TADK0VNZN04BQQNZYW7WWDGT5A06CZTCS4HTSD74CVNJ70CQQQ1C9D14AA75NJ902K6FC7ANBHFGENZXAYNAC0WQQQ6J7XW0TCC3N39TYSCC7TJVH7FZQEXKE8RDGT873QX4C7XDVV6TNWEBBCPM9AABW9PXBEQSM55DT79GVZ7156MZWJKGZAGNVX1FASAY0J3CW507672300R603MW1RRRC",
+                    coinPriv = 
"GX5DGW3RJ4HMXS53W29TK2667NWA3Z4WB41X7GPAX3WX4036VQGG",
+                    coinPub = 
"Z6DXSXGEQ8C4G50FF6TG6ZKBH11APJ2HSNS21BAR72VY3KV7CC90",
+                    coinValue = 
Amount.fromJSONString("KOADwTb3:3932974019564218.48282023"),
+                    denomPub = 
"040000XVGVWCHVQVTQ06Q5V0XRAVQKPPZQZ68GYVXSC5RAG37VDCG0CEQHS4876BX6DDABB2WFY7TRJ7MFKTMMDF7A7ZW9PKQ8S3RQ15TVTKWBFGGKBKYSP6CVHNG9AY738NCPC8AFWYGP8J2VJE9HRR7M1GQK19E2M7Q2Y54KCSZ583BTNX275DW6EYYE1KBV4FK009Z621EHF5R87S6VQDSBCKSK15JCH1JYC2VPRHHAEGRA2WYX1HD9KFET0C9G1CZJB1MHZ5Z7Y803YZJH441P3PJJTRB9WCTA03H6M43CJ9MB33BEJ3KR22R8CS0D6QC2E7ZQS5MGBWCF51FK97SHCJW93SAT7VHB3YX5VVDNTW9N3SDW56HNWT11D306H9VN7BTP84T404VF482Y09K4SHEF5704002",
+                    denomPubHash = 
"XB6T8NRGSRPWBM2YGS3R0AQYGEMK7PAM3CQRX6XM04B4N48PWRVZ5DG5JTT0NNQAGHN5HTGSCPR06R6B5NJBZ2DT5VZSQRD8FTNFPEG",
+                    reservePub = 
"8GSJZ649T2PXMKZC01Y4ANNBE7MF14QVK9SQEC4E46ZHKCVG8AS0",
+                    withdrawSig = 
"SNTZ4DWRVJBK89YGAZ60EDV0T7BM80MD6J6P88BRKDQFP331CXPSGM45CMCVBB7GR6X2FWQC5EJGR0J8KBR459PSGT18DA5PMQZKG08",
+                    coinEvHash = 
"FW36XSCBJCBQMSTT798CYG363481MASXGH5W73G24D2F9C7J76YZ2644PGQ6346XBYDXW7Z61JJZN2C2Y8152NNKW3NB0DHTMKHZ5BR"
+
+                )
+            ),
+            PlanchetVector(
+                CreationRequest(
+                    denomPub = 
"040000YE5QYTJTCYF7YDWN2ECYAMBNENHQT7YT740XNC88V5F1K4YC2QD94WABBVHZY597B2BTGBD2NJJV028JKJTD1KBPKXF4D87B7ZJYZVQSA4ZB5H1FVPE7X7YQVG668YZ2YY229X29NM4B6QR0G3TH821QBT1J5EDPKS0RP8E6X4654DTAAYBEN14H96E8D1JFVE40773FVVPXXMX7ZXT7TCVC2EZFMZR1HQ2DDXD8KJZ9AEGS1YH4D629Y08T9X2533MS6R4X58VVKHN1YQVKJT2044A0S8B4AKCW2GJHMQM10XC3K7C3D1C841A6R96GRXPC02QVBQSA1D5VY5VG2T4HVC6NKVK5WAXDEYZNKYVPD9AV4MNCYGK23AZWGHX5E16BQTNG47C9DEETP2D87XFC9D04002",
+                    feeWithdraw = 
Amount.fromJSONString("cRai6j:32749022734.44771"),
+                    reservePriv = 
"H58V73J73HXTA9CPT8ZZ5G7VVKCWZFAE1TMCCV176QBQTPBB2H40",
+                    reservePub = 
"G3R433316Z9PW1H8XRSATJWZJNMKPZ3EE20Z386X7CYM29JDFE0G",
+                    value = 
Amount.fromJSONString("cRai6j:166032749022734.69444771")
+                ),
+                EddsaKeyPair(
+                    
Base32Crockford.decode("5QNA3FX8NA7SETDNEEFJK5W3MNP8AJ8WSBY8FYDVZEYQ1BD21EW0"),
+                    
Base32Crockford.decode("54NDT04NA3TRA38T0D8TMR52PH1EWQP2S4J279GMQWQHKN4W9850")
+                ),
+                "7EKNT64GV5MX0KHZZNB1NREPWCZ7KF9K815M8CQN3B8AKJYF1JV0",
+                CreationResult(
+                    blindingKey = 
"7EKNT64GV5MX0KHZZNB1NREPWCZ7KF9K815M8CQN3B8AKJYF1JV0",
+                    coinEv = 
"AATPF1TXN84PV5P7HE7274B7KT525MFRSPT62MDNYXJXJ2TDGKTMNGPJRH6CMWBD3QQENAEFNS7CZ7P27CBFN6W3EFCFNAS12EWGM6GTTV643RH3A5YJA2R93G0PZPXW9HZP3KZZYFG6MGCRHMHEXTA7T5WKVH6KWE9SM64X9SVKV856VY7TPPWZ0MKZV24KF6TDJ9QC74D2X2FEBDSK7CEA870JENBXC7PZZWJDN8CVN1ZDY4Q0SV8Y4B0YX6CZZ6KVX10PXW56FQ4SSP34EBZCPXCHRZPCQCQRAJ78H4GBP8Y8394QQV1TRH35JQ20R98JSH0WFNAMPQZ246QY8MRFTAT816EY7FEX74ENNKX8494K476BN9VM6CJ5CD0FZYRFSR7DRC5RG9V84SK71EXEDR",
+                    coinPriv = 
"5QNA3FX8NA7SETDNEEFJK5W3MNP8AJ8WSBY8FYDVZEYQ1BD21EW0",
+                    coinPub = 
"54NDT04NA3TRA38T0D8TMR52PH1EWQP2S4J279GMQWQHKN4W9850",
+                    coinValue = 
Amount.fromJSONString("cRai6j:166032749022734.69444771"),
+                    denomPub = 
"040000YE5QYTJTCYF7YDWN2ECYAMBNENHQT7YT740XNC88V5F1K4YC2QD94WABBVHZY597B2BTGBD2NJJV028JKJTD1KBPKXF4D87B7ZJYZVQSA4ZB5H1FVPE7X7YQVG668YZ2YY229X29NM4B6QR0G3TH821QBT1J5EDPKS0RP8E6X4654DTAAYBEN14H96E8D1JFVE40773FVVPXXMX7ZXT7TCVC2EZFMZR1HQ2DDXD8KJZ9AEGS1YH4D629Y08T9X2533MS6R4X58VVKHN1YQVKJT2044A0S8B4AKCW2GJHMQM10XC3K7C3D1C841A6R96GRXPC02QVBQSA1D5VY5VG2T4HVC6NKVK5WAXDEYZNKYVPD9AV4MNCYGK23AZWGHX5E16BQTNG47C9DEETP2D87XFC9D04002",
+                    denomPubHash = 
"RJKMJ93AJ0NYC7X514FPVJ82ST4GW6WZKGK64R69880XBMMGE7H7R8QW71FGWCTKD3KZPW4D3QM854M4YHMYSZ5K3YEA2S7B2GJ9XTR",
+                    reservePub = 
"G3R433316Z9PW1H8XRSATJWZJNMKPZ3EE20Z386X7CYM29JDFE0G",
+                    withdrawSig = 
"X2015X2KE7Z0Q407QEKQ01TKBVV62QT07V9GJGP8GYH04K09TATB9KJG5K4VZG72Y79M1SM1EETVPARSETMN0J7Q057RB6V2F2B2P1G",
+                    coinEvHash = 
"DZ0TEHNTRCXQB3YDZNQYGA0S4RRNKD96Y0PKMG9QQX1KD534RPNRW526CQ5FWESKDT8AJ8R79A9TD20V3JJG3ZQ5JJCMPK9DTF3A8B0"
+                )
+            )
+        )
+        for (v in vectors) testPlanchetVector(v)
+    }
+
+    private fun testPlanchetVector(v: PlanchetVector) {
+        // test vector should match expected result
+        val blindingFactor = Base32Crockford.decode(v.blindingFactor)
+        assertEquals(v.result, planchet.create(v.request, v.eddsaKeyPair, 
blindingFactor))
+
+        // different value should produce different signature
+        val diffValue = v.request.value - Amount.min(v.request.value.currency)
+        val requestDiffValue = v.request.copy(value = diffValue)
+        val requestDiffResult = v.result.copy(coinValue = diffValue)
+        val result = planchet.create(requestDiffValue, v.eddsaKeyPair, 
blindingFactor)
+        assertNotEquals(v.result.withdrawSig, result.withdrawSig)
+        assertNotEquals(requestDiffResult, result)
+
+        // different fee should produce different signature
+        val diffFee = v.request.feeWithdraw - 
Amount.min(v.request.feeWithdraw.currency)
+        val requestDiffFee = v.request.copy(feeWithdraw = diffFee)
+        val resultDiffFee = planchet.create(requestDiffFee, v.eddsaKeyPair, 
blindingFactor)
+        assertNotEquals(v.result.withdrawSig, resultDiffFee.withdrawSig)
+        assertNotEquals(v.result, resultDiffFee)
+
+        // different blinding factor should change result
+        val diffBlindingFactor = Random.nextBytes(32)
+        assertNotEquals(v.result, planchet.create(v.request, v.eddsaKeyPair, 
diffBlindingFactor))
+
+        // different coin keys should change result
+        val diffEddsaKeyPair = crypto.createEddsaKeyPair()
+        assertNotEquals(v.result, planchet.create(v.request, diffEddsaKeyPair, 
blindingFactor))
+    }
+
+}
diff --git a/src/commonMain/kotlin/net/taler/wallet/kotlin/crypto/Crypto.kt 
b/src/commonMain/kotlin/net/taler/wallet/kotlin/crypto/Crypto.kt
index 620dd84..7019310 100644
--- a/src/commonMain/kotlin/net/taler/wallet/kotlin/crypto/Crypto.kt
+++ b/src/commonMain/kotlin/net/taler/wallet/kotlin/crypto/Crypto.kt
@@ -3,6 +3,7 @@ package net.taler.wallet.kotlin.crypto
 internal interface Crypto {
     fun sha256(input: ByteArray): ByteArray
     fun sha512(input: ByteArray): ByteArray
+    fun getRandomBytes(num: Int): ByteArray
     fun eddsaGetPublic(eddsaPrivateKey: ByteArray): ByteArray
     fun ecdheGetPublic(ecdhePrivateKey: ByteArray): ByteArray
     fun createEddsaKeyPair(): EddsaKeyPair
diff --git a/src/commonMain/kotlin/net/taler/wallet/kotlin/crypto/Planchet.kt 
b/src/commonMain/kotlin/net/taler/wallet/kotlin/crypto/Planchet.kt
new file mode 100644
index 0000000..617441d
--- /dev/null
+++ b/src/commonMain/kotlin/net/taler/wallet/kotlin/crypto/Planchet.kt
@@ -0,0 +1,68 @@
+package net.taler.wallet.kotlin.crypto
+
+import net.taler.wallet.kotlin.Amount
+import net.taler.wallet.kotlin.Base32Crockford
+
+internal class Planchet(private val crypto: Crypto) {
+
+    data class CreationRequest(
+        val value: Amount,
+        val feeWithdraw: Amount,
+        val denomPub: String,
+        val reservePub: String,
+        val reservePriv: String
+    )
+
+    data class CreationResult(
+        val coinPub: String,
+        val coinPriv: String,
+        val reservePub: String,
+        val denomPubHash: String,
+        val denomPub: String,
+        val blindingKey: String,
+        val withdrawSig: String,
+        val coinEv: String,
+        val coinValue: Amount,
+        val coinEvHash: String
+    )
+
+    fun create(req: CreationRequest, coinKeyPair: EddsaKeyPair, 
blindingFactor: ByteArray): CreationResult {
+        val reservePub = Base32Crockford.decode(req.reservePub)
+        val reservePriv = Base32Crockford.decode(req.reservePriv)
+        val denomPub = Base32Crockford.decode(req.denomPub)
+        val coinPubHash = crypto.sha512(coinKeyPair.publicKey)
+        val ev = crypto.rsaBlind(coinPubHash, blindingFactor, denomPub)
+        val amountWithFee = req.value + req.feeWithdraw
+        val denomPubHash = crypto.sha512(denomPub)
+        val evHash = crypto.sha512(ev)
+
+        val withdrawRequest = 
Signature.PurposeBuilder(Signature.RESERVE_WITHDRAW)
+            .put(reservePub)
+            .put(amountWithFee.toByteArray())
+            .put(req.feeWithdraw.toByteArray())
+            .put(denomPubHash)
+            .put(evHash)
+            .build()
+
+        val sig = crypto.eddsaSign(withdrawRequest, reservePriv)
+        return CreationResult(
+            blindingKey = Base32Crockford.encode(blindingFactor),
+            coinEv = Base32Crockford.encode(ev),
+            coinPriv = Base32Crockford.encode(coinKeyPair.privateKey),
+            coinPub = Base32Crockford.encode(coinKeyPair.publicKey),
+            coinValue = req.value,
+            denomPub = req.denomPub,
+            denomPubHash = Base32Crockford.encode(denomPubHash),
+            reservePub = req.reservePub,
+            withdrawSig = Base32Crockford.encode(sig),
+            coinEvHash = Base32Crockford.encode(evHash)
+        )
+    }
+
+    fun create(req: CreationRequest): CreationResult {
+        val coinKeyPair = crypto.createEddsaKeyPair()
+        val blindingFactor = crypto.getRandomBytes(32)
+        return create(req, coinKeyPair, blindingFactor)
+    }
+
+}
diff --git a/src/commonMain/kotlin/net/taler/wallet/kotlin/crypto/Signature.kt 
b/src/commonMain/kotlin/net/taler/wallet/kotlin/crypto/Signature.kt
index 881ace2..30db04f 100644
--- a/src/commonMain/kotlin/net/taler/wallet/kotlin/crypto/Signature.kt
+++ b/src/commonMain/kotlin/net/taler/wallet/kotlin/crypto/Signature.kt
@@ -4,19 +4,19 @@ import 
net.taler.wallet.kotlin.crypto.CryptoImpl.Companion.toByteArray
 
 class Signature {
 
-    internal enum class Purpose(val num: Int) {
-        RESERVE_WITHDRAW(1200),
-        WALLET_COIN_DEPOSIT(1201),
-        MASTER_DENOMINATION_KEY_VALIDITY(1025),
-        MASTER_WIRE_FEES(1028),
-        MASTER_WIRE_DETAILS(1030),
-        WALLET_COIN_MELT(1202),
-        TEST(4242),
-        MERCHANT_PAYMENT_OK(1104),
-        WALLET_COIN_RECOUP(1203),
-        WALLET_COIN_LINK(1204),
-        EXCHANGE_CONFIRM_RECOUP(1039),
-        EXCHANGE_CONFIRM_RECOUP_REFRESH(1041)
+    companion object {
+        const val RESERVE_WITHDRAW = 1200
+        const val WALLET_COIN_DEPOSIT = 1201
+        const val MASTER_DENOMINATION_KEY_VALIDITY = 1025
+        const val MASTER_WIRE_FEES = 1028
+        const val MASTER_WIRE_DETAILS = 1030
+        const val WALLET_COIN_MELT = 1202
+        const val TEST = 4242
+        const val MERCHANT_PAYMENT_OK = 1104
+        const val WALLET_COIN_RECOUP = 1203
+        const val WALLET_COIN_LINK = 1204
+        const val EXCHANGE_CONFIRM_RECOUP = 1039
+        const val EXCHANGE_CONFIRM_RECOUP_REFRESH = 1041
     }
 
     internal class PurposeBuilder(private val purposeNum: Int) {
diff --git a/src/jsMain/kotlin/net/taler/wallet/kotlin/crypto/CryptoFactory.kt 
b/src/jsMain/kotlin/net/taler/wallet/kotlin/crypto/CryptoFactory.kt
index 2602244..7cf210a 100644
--- a/src/jsMain/kotlin/net/taler/wallet/kotlin/crypto/CryptoFactory.kt
+++ b/src/jsMain/kotlin/net/taler/wallet/kotlin/crypto/CryptoFactory.kt
@@ -17,6 +17,10 @@ internal object CryptoJsImpl : CryptoImpl() {
         return nacl.hash(input.toUint8Array()).toByteArray()
     }
 
+    override fun getRandomBytes(num: Int): ByteArray {
+        return nacl.randomBytes(num).toByteArray()
+    }
+
     override fun eddsaGetPublic(eddsaPrivateKey: ByteArray): ByteArray {
         val pair = nacl.sign.keyPair.fromSeed(eddsaPrivateKey.toUint8Array())
         return pair.publicKey.toByteArray()
diff --git 
a/src/linuxMain/kotlin/net/taler/wallet/kotlin/crypto/CryptoFactory.kt 
b/src/linuxMain/kotlin/net/taler/wallet/kotlin/crypto/CryptoFactory.kt
index 40a11ce..a44bc46 100644
--- a/src/linuxMain/kotlin/net/taler/wallet/kotlin/crypto/CryptoFactory.kt
+++ b/src/linuxMain/kotlin/net/taler/wallet/kotlin/crypto/CryptoFactory.kt
@@ -41,6 +41,12 @@ internal object CryptoNativeImpl : CryptoImpl() {
         return output
     }
 
+    override fun getRandomBytes(num: Int): ByteArray {
+        val bytes = ByteArray(num)
+        randombytes(bytes.toCValuesRef(), num.toULong())
+        return bytes
+    }
+
     override fun eddsaGetPublic(eddsaPrivateKey: ByteArray): ByteArray {
         val publicKey = ByteArray(crypto_sign_PUBLICKEYBYTES.toInt())
         val privateKey = ByteArray(crypto_sign_SECRETKEYBYTES.toInt())

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]