gnunet-svn
[Top][All Lists]
Advanced

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

[taler-wallet-kotlin] 02/02: Add incremental hashing (needed for creatin


From: gnunet
Subject: [taler-wallet-kotlin] 02/02: Add incremental hashing (needed for creating refresh sessions)
Date: Tue, 30 Jun 2020 21:04:28 +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 08f5f3618b5a9d9f38f7da0dbff39164c8b5f77b
Author: Torsten Grote <t@grobox.de>
AuthorDate: Tue Jun 30 16:04:04 2020 -0300

    Add incremental hashing (needed for creating refresh sessions)
---
 build.gradle                                       |  2 +-
 .../taler/wallet/kotlin/crypto/CryptoFactory.kt    | 25 +++++++++++
 .../net/taler/wallet/kotlin/crypto/Crypto.kt       |  5 +++
 .../net/taler/wallet/kotlin/crypto/Sha512Test.kt   | 40 ++++++++++++++++-
 .../taler/wallet/kotlin/crypto/CryptoFactory.kt    | 36 ++++++++++++++--
 .../taler/wallet/kotlin/crypto/CryptoFactory.kt    | 50 +++++++++++++++++++++-
 6 files changed, 151 insertions(+), 7 deletions(-)

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