From 901db38ee07e4f4c0653749d33eb6282f89b8ff7 Mon Sep 17 00:00:00 2001 From: Kevin Gorham Date: Thu, 4 Jun 2020 13:50:43 -0400 Subject: [PATCH] Remove NovaCrypto dependency because of license issue. Add Zcash implementation instead. --- app/build.gradle | 5 -- .../java/cash/z/ecc/android/Dependencies.kt | 8 +-- mnemonic/build.gradle | 5 +- .../cash/z/ecc/kotlin/mnemonic/Mnemonics.kt | 54 +++++-------------- .../cash/z/ecc/android/util/MnemonicTest.kt | 46 +++------------- 5 files changed, 22 insertions(+), 96 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 054c3db..7a14477 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -142,11 +142,6 @@ dependencies { kapt Deps.Dagger.ANDROID_PROCESSOR kapt Deps.Dagger.COMPILER - // Testing these BIP39 dependencies - implementation 'com.madgag.spongycastle:core:1.58.0.0' - implementation 'io.github.novacrypto:BIP39:2019.01.27' - implementation 'io.github.novacrypto:securestring:2019.01.27' - // grpc-java implementation "io.grpc:grpc-okhttp:1.25.0" implementation "io.grpc:grpc-android:1.25.0" diff --git a/buildSrc/src/main/java/cash/z/ecc/android/Dependencies.kt b/buildSrc/src/main/java/cash/z/ecc/android/Dependencies.kt index d4adc87..f21ec55 100644 --- a/buildSrc/src/main/java/cash/z/ecc/android/Dependencies.kt +++ b/buildSrc/src/main/java/cash/z/ecc/android/Dependencies.kt @@ -45,16 +45,12 @@ object Deps { } } object Zcash { - val ANDROID_WALLET_PLUGINS = "com.github.zcash:zcash-android-wallet-plugins:1.0.0" + val ANDROID_WALLET_PLUGINS = "com.github.zcash:zcash-android-wallet-plugins:1.0.1" } object Misc { object Plugins { val SECURE_STORAGE = "de.adorsys.android:securestoragelibrary:1.2.2" - object Mnemonics { - val SPONGY_CASTLE = "com.madgag.spongycastle:core:1.58.0.0" - val NOVACRYPTO_BIP39 = "io.github.novacrypto:BIP39:2019.01.27" - val NOVACRYPTO_SECURESTRING = "io.github.novacrypto:securestring:2019.01.27" - } + val ANDROID_BIP39 = "cash.z.ecc.android:android-bip39:1.0.0-beta07" val QR_SCANNER = "com.google.zxing:core:3.2.1" } } diff --git a/mnemonic/build.gradle b/mnemonic/build.gradle index d0067b8..b3d61be 100644 --- a/mnemonic/build.gradle +++ b/mnemonic/build.gradle @@ -8,10 +8,7 @@ dependencies { // Zcash implementation Deps.Zcash.ANDROID_WALLET_PLUGINS - - implementation Deps.Misc.Plugins.Mnemonics.SPONGY_CASTLE - implementation Deps.Misc.Plugins.Mnemonics.NOVACRYPTO_BIP39 - implementation Deps.Misc.Plugins.Mnemonics.NOVACRYPTO_SECURESTRING + implementation Deps.Misc.Plugins.ANDROID_BIP39 testImplementation Deps.Test.JUNIT } diff --git a/mnemonic/src/main/java/cash/z/ecc/kotlin/mnemonic/Mnemonics.kt b/mnemonic/src/main/java/cash/z/ecc/kotlin/mnemonic/Mnemonics.kt index 937c200..28dfa81 100644 --- a/mnemonic/src/main/java/cash/z/ecc/kotlin/mnemonic/Mnemonics.kt +++ b/mnemonic/src/main/java/cash/z/ecc/kotlin/mnemonic/Mnemonics.kt @@ -1,22 +1,20 @@ package cash.z.ecc.kotlin.mnemonic import cash.z.android.plugin.MnemonicPlugin -import io.github.novacrypto.bip39.MnemonicGenerator -import io.github.novacrypto.bip39.SeedCalculator -import io.github.novacrypto.bip39.Words -import io.github.novacrypto.bip39.wordlists.English -import java.security.SecureRandom +import cash.z.ecc.android.bip39.Mnemonics.MnemonicCode +import cash.z.ecc.android.bip39.Mnemonics.WordCount +import cash.z.ecc.android.bip39.toEntropy +import cash.z.ecc.android.bip39.toSeed +import java.util.* import javax.inject.Inject -// TODO: either find another library that allows for doing this without strings or modify this code -// to leverage SecureCharBuffer (which doesn't work well with SeedCalculator.calculateSeed, -// which expects a string so for that reason, we just use Strings here) class Mnemonics @Inject constructor(): MnemonicPlugin { + override fun fullWordList(languageCode: String): List { + return cash.z.ecc.android.bip39.Mnemonics.getCachedWords(Locale.ENGLISH.language) + } override fun nextEntropy(): ByteArray { - return ByteArray(Words.TWENTY_FOUR.byteLength()).apply { - SecureRandom().nextBytes(this) - } + return WordCount.COUNT_24.toEntropy() } override fun nextMnemonic(): CharArray { @@ -24,12 +22,7 @@ class Mnemonics @Inject constructor(): MnemonicPlugin { } override fun nextMnemonic(entropy: ByteArray): CharArray { - return StringBuilder().let { builder -> - MnemonicGenerator(English.INSTANCE).createMnemonic(entropy) { c -> - builder.append(c) - } - builder.toString().toCharArray() - } + return MnemonicCode(entropy).chars } override fun nextMnemonicList(): List { @@ -37,17 +30,11 @@ class Mnemonics @Inject constructor(): MnemonicPlugin { } override fun nextMnemonicList(entropy: ByteArray): List { - return WordListBuilder().let { builder -> - MnemonicGenerator(English.INSTANCE).createMnemonic(entropy) { c -> - builder.append(c) - } - builder.wordList - } + return MnemonicCode(entropy).map { it.toCharArray() } } override fun toSeed(mnemonic: CharArray): ByteArray { - // TODO: either find another library that allows for doing this without strings or modify this code to leverage SecureCharBuffer (which doesn't work well with SeedCalculator.calculateSeed, which expects a string so for that reason, we just use Strings here) - return SeedCalculator().calculateSeed(String(mnemonic), "") + return MnemonicCode(mnemonic).toSeed() } override fun toWordList(mnemonic: CharArray): List { @@ -67,21 +54,4 @@ class Mnemonics @Inject constructor(): MnemonicPlugin { } return wordList } - - class WordListBuilder { - val wordList = mutableListOf() - fun append(c: CharSequence) { - if (c[0] != English.INSTANCE.space) addWord(c) - } - - private fun addWord(c: CharSequence) { - c.length.let { size -> - val word = CharArray(size) - repeat(size) { - word[it] = c[it] - } - wordList.add(word) - } - } - } } \ No newline at end of file diff --git a/mnemonic/src/test/java/cash/z/ecc/android/util/MnemonicTest.kt b/mnemonic/src/test/java/cash/z/ecc/android/util/MnemonicTest.kt index fb1dfae..184242a 100644 --- a/mnemonic/src/test/java/cash/z/ecc/android/util/MnemonicTest.kt +++ b/mnemonic/src/test/java/cash/z/ecc/android/util/MnemonicTest.kt @@ -1,23 +1,17 @@ package cash.z.ecc.android.util -import cash.z.ecc.kotlin.mnemonic.MnemonicProvider +import cash.z.android.plugin.MnemonicPlugin import cash.z.ecc.kotlin.mnemonic.Mnemonics -import io.github.novacrypto.SecureCharBuffer -import io.github.novacrypto.bip39.MnemonicGenerator -import io.github.novacrypto.bip39.SeedCalculator -import io.github.novacrypto.bip39.Words -import io.github.novacrypto.bip39.wordlists.English import org.junit.Assert.assertEquals -import org.junit.Assert.assertTrue import org.junit.Before import org.junit.Test import java.lang.Math.max -import java.security.SecureRandom +import java.util.* class MnemonicTest { - lateinit var mnemonics: MnemonicProvider + lateinit var mnemonics: MnemonicPlugin @Before fun start() { @@ -58,18 +52,20 @@ class MnemonicTest { @Test fun testMnemonic_longestWord() { var max = 0 + val englishWordList = mnemonics.fullWordList(Locale.ENGLISH.language) repeat(2048) { - max = max(max, English.INSTANCE.getWord(it).length) + max = max(max, englishWordList[it].length) } assertEquals(8, max) } private fun validate(words: List) { + val englishWordList = mnemonics.fullWordList(Locale.ENGLISH.language) // return or crash! words.forEach { word -> var i = 0 while (true) { - if (English.INSTANCE.getWord(i++) == word) { + if (englishWordList[i++] == word) { println(word) break } @@ -77,34 +73,6 @@ class MnemonicTest { } } } - - - //////////////////////////////////////////////////////////////////////////////////////////////// - // Sample code for working with SecureCharBuffer - // (but the underlying implementation isn't compatible with SeedCalculator.calculateSeed) - //////////////////////////////////////////////////////////////////////////////////////////////// - - @Test - fun testMneumonicFromSeed_secure() { - SecureCharBuffer().use { secure -> - val entropy = ByteArray(Words.TWENTY_FOUR.byteLength()).also { - SecureRandom().nextBytes(it) - MnemonicGenerator(English.INSTANCE).createMnemonic(it, secure::append) - } - val words = secure.toWords() - assertEquals(24, words.size) - - words.forEach { word -> - // verify no spaces - assertTrue(word.all { it != ' ' }) - } - - val mnemonic = secure.toStringAble().toString() - val seed = SeedCalculator().calculateSeed(mnemonic, "") - - assertEquals(64, seed.size) - } - } } private fun CharSequence.toWords(): List {