Remove NovaCrypto dependency because of license issue.

Add Zcash implementation instead.
This commit is contained in:
Kevin Gorham 2020-06-04 13:50:43 -04:00
parent 7717612524
commit 901db38ee0
No known key found for this signature in database
GPG Key ID: CCA55602DF49FC38
5 changed files with 22 additions and 96 deletions

View File

@ -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"

View File

@ -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"
}
}

View File

@ -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
}

View File

@ -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<String> {
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<CharArray> {
@ -37,17 +30,11 @@ class Mnemonics @Inject constructor(): MnemonicPlugin {
}
override fun nextMnemonicList(entropy: ByteArray): List<CharArray> {
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<CharArray> {
@ -67,21 +54,4 @@ class Mnemonics @Inject constructor(): MnemonicPlugin {
}
return wordList
}
class WordListBuilder {
val wordList = mutableListOf<CharArray>()
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)
}
}
}
}

View File

@ -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<String>) {
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<CharSequence> {