gnunet-svn
[Top][All Lists]
Advanced

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

[taler-wallet-kotlin] branch master updated (ba7e1cc -> 08f5f36)


From: gnunet
Subject: [taler-wallet-kotlin] branch master updated (ba7e1cc -> 08f5f36)
Date: Tue, 30 Jun 2020 21:04:26 +0200

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

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

    from ba7e1cc  Add signing of RecoupRequest with tests
     new 1a6121d  Add Deposit signing and test
     new 08f5f36  Add incremental hashing (needed for creating refresh sessions)

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 build.gradle                                       |  2 +-
 .../taler/wallet/kotlin/crypto/CryptoFactory.kt    | 25 ++++++
 .../net/taler/wallet/kotlin/crypto/Crypto.kt       |  5 ++
 .../net/taler/wallet/kotlin/crypto/Deposit.kt      | 94 ++++++++++++++++++++++
 .../net/taler/wallet/kotlin/crypto/DepositTest.kt  | 74 +++++++++++++++++
 .../net/taler/wallet/kotlin/crypto/Sha512Test.kt   | 40 ++++++++-
 .../taler/wallet/kotlin/crypto/CryptoFactory.kt    | 36 ++++++++-
 .../taler/wallet/kotlin/crypto/CryptoFactory.kt    | 50 +++++++++++-
 8 files changed, 319 insertions(+), 7 deletions(-)
 create mode 100644 
src/commonMain/kotlin/net/taler/wallet/kotlin/crypto/Deposit.kt
 create mode 100644 
src/commonTest/kotlin/net/taler/wallet/kotlin/crypto/DepositTest.kt

diff --git a/build.gradle b/build.gradle
index 727b42c..8ae318e 100644
--- a/build.gradle
+++ b/build.gradle
@@ -67,7 +67,7 @@ kotlin {
                 implementation kotlin('stdlib-js')
                 implementation npm('tweetnacl', '1.0.3')
                 implementation npm('ed2curve', '0.3.0')
-                implementation npm('fast-sha256', '1.3.0')
+                implementation npm('hash.js', '1.1.7')
             }
         }
         jsTest {
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 7435c3f..b54d93e 100644
--- a/src/androidMain/kotlin/net/taler/wallet/kotlin/crypto/CryptoFactory.kt
+++ b/src/androidMain/kotlin/net/taler/wallet/kotlin/crypto/CryptoFactory.kt
@@ -3,6 +3,7 @@ package net.taler.wallet.kotlin.crypto
 import com.goterl.lazycode.lazysodium.LazySodiumJava
 import com.goterl.lazycode.lazysodium.SodiumJava
 import com.goterl.lazycode.lazysodium.interfaces.Hash
+import com.goterl.lazycode.lazysodium.interfaces.Hash.State512
 import com.goterl.lazycode.lazysodium.interfaces.KeyExchange
 import com.goterl.lazycode.lazysodium.interfaces.Sign
 import com.goterl.lazycode.lazysodium.utils.Key
@@ -27,6 +28,10 @@ internal object CryptoJvmImpl : CryptoImpl() {
         return output
     }
 
+    override fun getHashSha512State(): HashSha512State {
+        return JvmHashSha512State()
+    }
+
     override fun getRandomBytes(num: Int): ByteArray {
         return sodium.randomBytesBuf(num)
     }
@@ -88,4 +93,24 @@ internal object CryptoJvmImpl : CryptoImpl() {
         return RsaBlinding.rsaVerify(hm, rsaSig, rsaPubEnc)
     }
 
+    private class JvmHashSha512State : HashSha512State {
+        private val state = State512()
+
+        init {
+            check(sodium.cryptoHashSha512Init(state)) { "Error doing 
cryptoHashSha512Init" }
+        }
+
+        override fun update(data: ByteArray): HashSha512State {
+            sodium.cryptoHashSha512Update(state, data, data.size.toLong())
+            return this
+        }
+
+        override fun final(): ByteArray {
+            val output = ByteArray(Hash.SHA512_BYTES)
+            sodium.cryptoHashSha512Final(state, output)
+            return output
+        }
+
+    }
+
 }
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 7019310..7c5fa29 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 getHashSha512State(): HashSha512State
     fun getRandomBytes(num: Int): ByteArray
     fun eddsaGetPublic(eddsaPrivateKey: ByteArray): ByteArray
     fun ecdheGetPublic(ecdhePrivateKey: ByteArray): ByteArray
@@ -19,6 +20,10 @@ internal interface Crypto {
     fun setupRefreshPlanchet(secretSeed: ByteArray, coinNumber: Int): FreshCoin
 }
 
+interface HashSha512State {
+    fun update(data: ByteArray): HashSha512State
+    fun final(): ByteArray
+}
 class EddsaKeyPair(val privateKey: ByteArray, val publicKey: ByteArray)
 class EcdheKeyPair(val privateKey: ByteArray, val publicKey: ByteArray)
 data class FreshCoin(val coinPublicKey: ByteArray, val coinPrivateKey: 
ByteArray, val bks: ByteArray) {
diff --git a/src/commonMain/kotlin/net/taler/wallet/kotlin/crypto/Deposit.kt 
b/src/commonMain/kotlin/net/taler/wallet/kotlin/crypto/Deposit.kt
new file mode 100644
index 0000000..6b4fa94
--- /dev/null
+++ b/src/commonMain/kotlin/net/taler/wallet/kotlin/crypto/Deposit.kt
@@ -0,0 +1,94 @@
+package net.taler.wallet.kotlin.crypto
+
+import net.taler.wallet.kotlin.Amount
+import net.taler.wallet.kotlin.Base32Crockford
+import net.taler.wallet.kotlin.Timestamp
+import net.taler.wallet.kotlin.crypto.Signature.Companion.WALLET_COIN_DEPOSIT
+
+/**
+ * Deposit operations are requested by a merchant during a transaction.
+ * For the deposit operation, the merchant has to obtain the deposit 
permission for a coin
+ * from their customer who owns the coin.
+ *
+ * When depositing a coin, the merchant is credited an amount specified in the 
deposit permission,
+ * possibly a fraction of the total coin’s value,
+ * minus the deposit fee as specified by the coin’s denomination.
+ */
+internal class Deposit(private val crypto: Crypto) {
+
+    /**
+     * Private data required to make a deposit permission.
+     */
+    data class DepositInfo(
+        val exchangeBaseUrl: String,
+        val contractTermsHash: String,
+        val coinPublicKey: String,
+        val coinPrivateKey: String,
+        val spendAmount: Amount,
+        val timestamp: Timestamp,
+        val refundDeadline: Timestamp,
+        val merchantPublicKey: String,
+        val feeDeposit: Amount,
+        val wireInfoHash: String,
+        val denomPublicKey: String,
+        val denomSignature: String
+    )
+
+    /**
+     * Deposit permission for a single coin.
+     */
+    // TODO rename _
+    data class CoinDepositPermission(
+        /**
+         * Signature by the coin.
+         */
+        val coinSignature: String,
+        /**
+         * Public key of the coin being spend.
+         */
+        val coinPublicKey: String,
+        /**
+         * Signature made by the denomination public key.
+         */
+        val denomSignature: String,
+        /**
+         * The denomination public key associated with this coin.
+         */
+        val denomPublicKey: String,
+        /**
+         * The amount that is subtracted from this coin with this payment.
+         */
+        val contribution: String,
+        /**
+         * URL of the exchange this coin was withdrawn from.
+         */
+        val exchangeBaseUrl: String
+    )
+
+    /**
+     * Generate updated coins (to store in the database) and deposit 
permissions for each given coin.
+     */
+    fun signDepositPermission(depositInfo: DepositInfo): CoinDepositPermission 
{
+        val d = Signature.PurposeBuilder(WALLET_COIN_DEPOSIT)
+            .put(Base32Crockford.decode(depositInfo.contractTermsHash))
+            .put(Base32Crockford.decode(depositInfo.wireInfoHash))
+            .put(depositInfo.timestamp.roundedToByteArray())
+            .put(depositInfo.refundDeadline.roundedToByteArray())
+            .put(depositInfo.spendAmount.toByteArray())
+            .put(depositInfo.feeDeposit.toByteArray())
+            .put(Base32Crockford.decode(depositInfo.merchantPublicKey))
+            .put(Base32Crockford.decode(depositInfo.coinPublicKey))
+            .build()
+        val coinPriv = Base32Crockford.decode(depositInfo.coinPrivateKey);
+        val coinSig = crypto.eddsaSign(d, coinPriv)
+        return CoinDepositPermission(
+            coinPublicKey = depositInfo.coinPublicKey,
+            coinSignature = Base32Crockford.encode(coinSig),
+            contribution = depositInfo.spendAmount.toJSONString(),
+            denomPublicKey = depositInfo.denomPublicKey,
+            exchangeBaseUrl = depositInfo.exchangeBaseUrl,
+            denomSignature = depositInfo.denomSignature
+        )
+    }
+
+}
diff --git 
a/src/commonTest/kotlin/net/taler/wallet/kotlin/crypto/DepositTest.kt 
b/src/commonTest/kotlin/net/taler/wallet/kotlin/crypto/DepositTest.kt
new file mode 100644
index 0000000..6e74fb2
--- /dev/null
+++ b/src/commonTest/kotlin/net/taler/wallet/kotlin/crypto/DepositTest.kt
@@ -0,0 +1,74 @@
+package net.taler.wallet.kotlin.crypto
+
+import net.taler.wallet.kotlin.Amount
+import net.taler.wallet.kotlin.Timestamp
+import net.taler.wallet.kotlin.crypto.Deposit.CoinDepositPermission
+import net.taler.wallet.kotlin.crypto.Deposit.DepositInfo
+import kotlin.test.Test
+import kotlin.test.assertEquals
+
+class DepositTest {
+
+    private val crypto = CryptoFactory.getCrypto()
+    private val deposit = Deposit(crypto)
+
+    private class DepositVector(val depositInfo: DepositInfo, val permission: 
CoinDepositPermission)
+
+    @Test
+    fun test() {
+        val vectors = listOf(
+            DepositVector(
+                DepositInfo(
+                    exchangeBaseUrl = "example.org",
+                    contractTermsHash = 
"QS3RK40J3262QRAJG4SVZB0C60N45W7D71ZXFTP385E05PKR7RGH22QTPA109Z0EBD120SHA09WHA72K4PCFM6JTFMCZEGVW2T9FT2R",
+                    coinPublicKey = 
"6DMP3NPY6DZD0QDMEW6955R6ZCX3T052PRJE0FYHTKRA837VMQT0",
+                    coinPrivateKey = 
"XWVF454Q600NGSMF7RYXY369N2DJKC1YQZG0RFAF8EMRRY8DJE50",
+                    spendAmount = Amount("TESTKUDOS", 8, 0),
+                    timestamp = Timestamp(1593522039000),
+                    refundDeadline = Timestamp(1593522939000),
+                    merchantPublicKey = 
"RQSR35MJJDP5Y27XMBEV7QBG4HTE3JXR1JCE4NCYCAQHKJ8CB5T0",
+                    feeDeposit = Amount("TESTKUDOS", 0, 2000000),
+                    wireInfoHash = 
"5C3WXB9PVPXAGGQVRJGAMBJJQBBYPHZEZZYVHQ8RS97F9EZABPAWNWSGD1VH6YNFB58GPJWX1A17DFNCK0S9YPP7PED3ZXR76E2A0XR",
+                    denomPublicKey = 
"020000YQX8JZNBMJ8PTVRZZT27TTSJN5HM0037K0BSY3YWP0VF8GFYYAN06J0PTQVQGQJGVJ91CHWD6QCH9MKADR1VH31P5WEMTMWWTX6KWA3KX0FD1RWQSPJ8W8ZXVWPVDJVVJ08W12VWV39A9W4SDCMWBSQ17QV4RP86JJFMTEWB540KKYHY3ZYJEQYVN9XD7CM7SCAMM8WV03P0VG2001",
+                    denomSignature = 
"9F3M4AZ8BN3MJRH6T49TD9R4EVTF6C5NH365DHCC73F39N3SAK422NY9ZWN7WANGW3M4XZTJDDV1B1E7MSW03VCESKSF8889EDTRE1VHF0FT3E5CT0Q449JAQQ6DSDY4D9JMPP99TRKZX86VAXN45FBSBXTJZ2FN85Y67T9ADDNDXMV060J0HP7G5YXXJQ0V7KHACEZFVXFH6"
+                ),
+                CoinDepositPermission(
+                    coinSignature = 
"CZX4HMBR6H3W1KAN1T0HZ11VBSERZ6JM715MKSDAJJSXWQTZ0GDCZX92MAKMH0DB7B389E24XGP6X7ZSAQVW540KTQZJ9RMR0R9CM08",
+                    coinPublicKey = 
"6DMP3NPY6DZD0QDMEW6955R6ZCX3T052PRJE0FYHTKRA837VMQT0",
+                    denomSignature = 
"9F3M4AZ8BN3MJRH6T49TD9R4EVTF6C5NH365DHCC73F39N3SAK422NY9ZWN7WANGW3M4XZTJDDV1B1E7MSW03VCESKSF8889EDTRE1VHF0FT3E5CT0Q449JAQQ6DSDY4D9JMPP99TRKZX86VAXN45FBSBXTJZ2FN85Y67T9ADDNDXMV060J0HP7G5YXXJQ0V7KHACEZFVXFH6",
+                    denomPublicKey = 
"020000YQX8JZNBMJ8PTVRZZT27TTSJN5HM0037K0BSY3YWP0VF8GFYYAN06J0PTQVQGQJGVJ91CHWD6QCH9MKADR1VH31P5WEMTMWWTX6KWA3KX0FD1RWQSPJ8W8ZXVWPVDJVVJ08W12VWV39A9W4SDCMWBSQ17QV4RP86JJFMTEWB540KKYHY3ZYJEQYVN9XD7CM7SCAMM8WV03P0VG2001",
+                    contribution = "TESTKUDOS:8",
+                    exchangeBaseUrl = "example.org"
+                )
+            ),
+            DepositVector(
+                DepositInfo(
+                    exchangeBaseUrl = "example.org",
+                    contractTermsHash = 
"CWWDVCEX745A092KB3W7K98M7EVK4G5HJRHKR0RTPKAFR1VSK147ER131PT23P8ZWH2VMWAWENTVTAXP4KDRQ9YY0951N2G2JZFGEXG",
+                    coinPublicKey = 
"ZR6BER43XSR3NK705HFKGC842Q3Q2R4G3T6VQ5JEK8EAC34JYW6G",
+                    coinPrivateKey = 
"CP8WW83V239DTXD84M87TZ0DG1TGM4RC3D77NN936554B7GDVBRG",
+                    spendAmount = Amount("TESTKUDOS", 1, 0),
+                    timestamp = Timestamp(1593522635000),
+                    refundDeadline = Timestamp(1593523535000),
+                    merchantPublicKey = 
"S8WFGCK6CJGFWYWHAY56NTZTD84S31TGM244GTVKTCETKW5HDBQG",
+                    feeDeposit = Amount("TESTKUDOS", 0, 2000000),
+                    wireInfoHash = 
"8GQFCMQXHHTF7VG73WVJN8PFCPH4Y0ZRSWAQ01A6A9F0Y0HY59H3RDPMBPVNJJDJP1S3E8JJVE7MGAC9YDACWAVCTE75QZ8ZRNAH3X8",
+                    denomPublicKey = 
"020000X1NCWC14MNXTAJ17W6HY5AMGXKGV392BESTESJJ8TQ41W9W2RBN69Q3WQYQQXS7KS5ZMDSSGHY0H7921X0RRA6ZNW2RSKJGXJNQM66KRDEFTQ50B6ZK60CSCY3KZ0RSGAYBG8VHC2A87Z6DQS361G8BAJS937J9YX89MGVMG896MKVEZ3H3NGRJTT89QNGN5KZWFSE6G5129GG2001",
+                    denomSignature = 
"7XJDMABJHV01GX7S764ZY3XR3AX2KAK4AXWKZJHBRV8BBQ7KQ5FHC372GE8RF8M2NT128G85RWW87CNNVYNWWPEPSFN8QXTA2H6SGTR0EFRDF4CXAJRXHWPB450YMJM7MNNPJKXDDXCFN87RSHFZ4ESH06S0SBX6185DX2HD6JWQ3BESCK8PYCB6A09KP5ZD0EZSQKDGNGMEG"
+                ),
+                CoinDepositPermission(
+                    coinSignature = 
"A8N1NSMSPZ4H1VR1YANYMAE74VAJ7W88EMRNDY74YXPK2WFEEHHM28VVQ3HAK6J0P9YX61XGNHRP08AEX59M0YGJ7AW8ZG2Y5FQD23G",
+                    coinPublicKey = 
"ZR6BER43XSR3NK705HFKGC842Q3Q2R4G3T6VQ5JEK8EAC34JYW6G",
+                    denomSignature = 
"7XJDMABJHV01GX7S764ZY3XR3AX2KAK4AXWKZJHBRV8BBQ7KQ5FHC372GE8RF8M2NT128G85RWW87CNNVYNWWPEPSFN8QXTA2H6SGTR0EFRDF4CXAJRXHWPB450YMJM7MNNPJKXDDXCFN87RSHFZ4ESH06S0SBX6185DX2HD6JWQ3BESCK8PYCB6A09KP5ZD0EZSQKDGNGMEG",
+                    denomPublicKey = 
"020000X1NCWC14MNXTAJ17W6HY5AMGXKGV392BESTESJJ8TQ41W9W2RBN69Q3WQYQQXS7KS5ZMDSSGHY0H7921X0RRA6ZNW2RSKJGXJNQM66KRDEFTQ50B6ZK60CSCY3KZ0RSGAYBG8VHC2A87Z6DQS361G8BAJS937J9YX89MGVMG896MKVEZ3H3NGRJTT89QNGN5KZWFSE6G5129GG2001",
+                    contribution = "TESTKUDOS:1",
+                    exchangeBaseUrl = "example.org"
+                )
+            )
+        )
+        for (v in vectors) {
+            assertEquals(v.permission, 
deposit.signDepositPermission(v.depositInfo))
+        }
+    }
+
+}
diff --git a/src/commonTest/kotlin/net/taler/wallet/kotlin/crypto/Sha512Test.kt 
b/src/commonTest/kotlin/net/taler/wallet/kotlin/crypto/Sha512Test.kt
index c401b73..309e053 100644
--- a/src/commonTest/kotlin/net/taler/wallet/kotlin/crypto/Sha512Test.kt
+++ b/src/commonTest/kotlin/net/taler/wallet/kotlin/crypto/Sha512Test.kt
@@ -1,10 +1,10 @@
 package net.taler.wallet.kotlin.crypto
 
 import net.taler.wallet.kotlin.Base32Crockford
+import kotlin.random.Random
 import kotlin.test.Test
 import kotlin.test.assertEquals
 
-@kotlin.ExperimentalStdlibApi
 class Sha512Test {
 
     private val crypto = CryptoFactory.getCrypto()
@@ -59,4 +59,42 @@ class Sha512Test {
         assertEquals(output, 
Base32Crockford.encode(crypto.sha512(Base32Crockford.decode(input))))
     }
 
+    @Test
+    fun testIncrementalHashing() {
+        val n = 1024
+        val d = Random.nextBytes(n)
+
+        val h1 = crypto.sha512(d)
+        val h2 = crypto.getHashSha512State().update(d).final()
+        assertEquals(Base32Crockford.encode(h1), Base32Crockford.encode(h2))
+
+        val s = crypto.getHashSha512State()
+        for (i in 0 until n) {
+            val b = ByteArray(1)
+            b[0] = d[i]
+            s.update(b)
+        }
+        val h3 = s.final()
+        assertEquals(Base32Crockford.encode(h1), Base32Crockford.encode(h3))
+    }
+
+    @Test
+    fun testIncrementalHashing2() {
+        val n = 10
+        val d = Random.nextBytes(n)
+
+        val h1 = crypto.sha512(d)
+        val h2 = crypto.getHashSha512State().update(d).final()
+        assertEquals(Base32Crockford.encode(h1), Base32Crockford.encode(h2))
+
+        val s = crypto.getHashSha512State()
+        for (i in 0 until n) {
+            val b = ByteArray(1)
+            b[0] = d[i]
+            s.update(b)
+        }
+        val h3 = s.final()
+        assertEquals(Base32Crockford.encode(h1), Base32Crockford.encode(h3))
+    }
+
 }
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 7cf210a..dab9ecc 100644
--- a/src/jsMain/kotlin/net/taler/wallet/kotlin/crypto/CryptoFactory.kt
+++ b/src/jsMain/kotlin/net/taler/wallet/kotlin/crypto/CryptoFactory.kt
@@ -10,13 +10,17 @@ internal actual object CryptoFactory {
 internal object CryptoJsImpl : CryptoImpl() {
 
     override fun sha256(input: ByteArray): ByteArray {
-        return sha256(input.toUint8Array()).toByteArray()
+        return 
hash.sha256().update(input.toUint8Array()).digest().toByteArray()
     }
 
     override fun sha512(input: ByteArray): ByteArray {
         return nacl.hash(input.toUint8Array()).toByteArray()
     }
 
+    override fun getHashSha512State(): HashSha512State {
+        return JsHashSha512State()
+    }
+
     override fun getRandomBytes(num: Int): ByteArray {
         return nacl.randomBytes(num).toByteArray()
     }
@@ -77,6 +81,19 @@ internal object CryptoJsImpl : CryptoImpl() {
         TODO("Not yet implemented")
     }
 
+    private class JsHashSha512State : HashSha512State {
+        private val state = hash.sha512()
+
+        override fun update(data: ByteArray): HashSha512State {
+            state.update(data.toUint8Array())
+            return this
+        }
+
+        override fun final(): ByteArray {
+            return state.digest().toByteArray()
+        }
+    }
+
     private fun Uint8Array.toByteArray(): ByteArray {
         val result = ByteArray(this.length)
         for (i in 0 until this.length) result[i] = this[i]
@@ -110,11 +127,13 @@ private external class nacl {
         companion object {
             fun detached(msg: Uint8Array, secretKey: Uint8Array): Uint8Array
         }
+
         class detached {
             companion object {
                 fun verify(msg: Uint8Array, sig: Uint8Array, publicKey: 
Uint8Array): Boolean
             }
         }
+
         class keyPair {
             companion object {
                 fun fromSeed(seed: Uint8Array): KeyPair
@@ -134,6 +153,17 @@ private external class ed2curve {
     }
 }
 
-@JsModule("fast-sha256")
+@Suppress("ClassName")
+@JsModule("hash.js")
 @JsNonModule
-private external fun sha256(message: Uint8Array): Uint8Array
+private external class hash {
+    class sha256 {
+        fun update(message: Uint8Array): sha256
+        fun digest(): Uint8Array
+    }
+
+    class sha512 {
+        fun update(message: Uint8Array): sha512
+        fun digest(): Uint8Array
+    }
+}
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 a44bc46..b0bb5b2 100644
--- a/src/linuxMain/kotlin/net/taler/wallet/kotlin/crypto/CryptoFactory.kt
+++ b/src/linuxMain/kotlin/net/taler/wallet/kotlin/crypto/CryptoFactory.kt
@@ -2,11 +2,19 @@ package net.taler.wallet.kotlin.crypto
 
 import kotlinx.cinterop.CValuesRef
 import kotlinx.cinterop.UByteVar
+import kotlinx.cinterop.alloc
+import kotlinx.cinterop.free
+import kotlinx.cinterop.nativeHeap
+import kotlinx.cinterop.ptr
 import kotlinx.cinterop.refTo
 import org.libsodium.crypto_hash_sha256
 import org.libsodium.crypto_hash_sha256_bytes
 import org.libsodium.crypto_hash_sha512
 import org.libsodium.crypto_hash_sha512_bytes
+import org.libsodium.crypto_hash_sha512_final
+import org.libsodium.crypto_hash_sha512_init
+import org.libsodium.crypto_hash_sha512_state
+import org.libsodium.crypto_hash_sha512_update
 import org.libsodium.crypto_scalarmult
 import org.libsodium.crypto_scalarmult_BYTES
 import org.libsodium.crypto_scalarmult_base
@@ -41,6 +49,10 @@ internal object CryptoNativeImpl : CryptoImpl() {
         return output
     }
 
+    override fun getHashSha512State(): HashSha512State {
+        return NativeHashSha512State()
+    }
+
     override fun getRandomBytes(num: Int): ByteArray {
         val bytes = ByteArray(num)
         randombytes(bytes.toCValuesRef(), num.toULong())
@@ -80,12 +92,23 @@ internal object CryptoNativeImpl : CryptoImpl() {
         crypto_sign_seed_keypair(publicKey.toCValuesRef(), 
privateKey.toCValuesRef(), eddsaPrivateKey.toCValuesRef())
 
         val signatureBytes = ByteArray(crypto_sign_BYTES.toInt())
-        crypto_sign_detached(signatureBytes.toCValuesRef(), null, 
msg.toCValuesRef(), msg.size.toULong(), privateKey.toCValuesRef())
+        crypto_sign_detached(
+            signatureBytes.toCValuesRef(),
+            null,
+            msg.toCValuesRef(),
+            msg.size.toULong(),
+            privateKey.toCValuesRef()
+        )
         return signatureBytes
     }
 
     override fun eddsaVerify(msg: ByteArray, sig: ByteArray, eddsaPub: 
ByteArray): Boolean {
-        return crypto_sign_verify_detached(sig.toCValuesRef(), 
msg.toCValuesRef(), msg.size.toULong(), eddsaPub.toCValuesRef()) == 0
+        return crypto_sign_verify_detached(
+            sig.toCValuesRef(),
+            msg.toCValuesRef(),
+            msg.size.toULong(),
+            eddsaPub.toCValuesRef()
+        ) == 0
     }
 
     override fun keyExchangeEddsaEcdhe(eddsaPrivateKey: ByteArray, 
ecdhePublicKey: ByteArray): ByteArray {
@@ -117,6 +140,29 @@ internal object CryptoNativeImpl : CryptoImpl() {
         TODO("Not yet implemented")
     }
 
+    private class NativeHashSha512State : HashSha512State {
+        private val state = nativeHeap.alloc<crypto_hash_sha512_state>()
+        private val statePointer = state.ptr
+
+        init {
+            check(crypto_hash_sha512_init(statePointer) == 0) { "Error doing 
crypto_hash_sha512_init" }
+        }
+
+        override fun update(data: ByteArray): HashSha512State {
+            val cInput = if (data.isEmpty()) null else data.toCValuesRef()
+            crypto_hash_sha512_update(statePointer, cInput, 
data.size.toULong())
+            return this
+        }
+
+        override fun final(): ByteArray {
+            val output = ByteArray(crypto_hash_sha512_bytes().toInt())
+            crypto_hash_sha512_final(statePointer, output.toCValuesRef())
+            nativeHeap.free(statePointer)
+            return output
+        }
+
+    }
+
     private fun ByteArray.toCValuesRef(): CValuesRef<UByteVar> {
         @Suppress("UNCHECKED_CAST")
         return this.refTo(0) as CValuesRef<UByteVar>

-- 
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]