Remove NovaCrypto dependency because of license issue.
Add Zcash implementation instead.
This commit is contained in:
parent
7717612524
commit
901db38ee0
|
@ -142,11 +142,6 @@ dependencies {
|
||||||
kapt Deps.Dagger.ANDROID_PROCESSOR
|
kapt Deps.Dagger.ANDROID_PROCESSOR
|
||||||
kapt Deps.Dagger.COMPILER
|
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
|
// grpc-java
|
||||||
implementation "io.grpc:grpc-okhttp:1.25.0"
|
implementation "io.grpc:grpc-okhttp:1.25.0"
|
||||||
implementation "io.grpc:grpc-android:1.25.0"
|
implementation "io.grpc:grpc-android:1.25.0"
|
||||||
|
|
|
@ -45,16 +45,12 @@ object Deps {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
object Zcash {
|
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 Misc {
|
||||||
object Plugins {
|
object Plugins {
|
||||||
val SECURE_STORAGE = "de.adorsys.android:securestoragelibrary:1.2.2"
|
val SECURE_STORAGE = "de.adorsys.android:securestoragelibrary:1.2.2"
|
||||||
object Mnemonics {
|
val ANDROID_BIP39 = "cash.z.ecc.android:android-bip39:1.0.0-beta07"
|
||||||
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 QR_SCANNER = "com.google.zxing:core:3.2.1"
|
val QR_SCANNER = "com.google.zxing:core:3.2.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,10 +8,7 @@ dependencies {
|
||||||
|
|
||||||
// Zcash
|
// Zcash
|
||||||
implementation Deps.Zcash.ANDROID_WALLET_PLUGINS
|
implementation Deps.Zcash.ANDROID_WALLET_PLUGINS
|
||||||
|
implementation Deps.Misc.Plugins.ANDROID_BIP39
|
||||||
implementation Deps.Misc.Plugins.Mnemonics.SPONGY_CASTLE
|
|
||||||
implementation Deps.Misc.Plugins.Mnemonics.NOVACRYPTO_BIP39
|
|
||||||
implementation Deps.Misc.Plugins.Mnemonics.NOVACRYPTO_SECURESTRING
|
|
||||||
|
|
||||||
testImplementation Deps.Test.JUNIT
|
testImplementation Deps.Test.JUNIT
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,22 +1,20 @@
|
||||||
package cash.z.ecc.kotlin.mnemonic
|
package cash.z.ecc.kotlin.mnemonic
|
||||||
|
|
||||||
import cash.z.android.plugin.MnemonicPlugin
|
import cash.z.android.plugin.MnemonicPlugin
|
||||||
import io.github.novacrypto.bip39.MnemonicGenerator
|
import cash.z.ecc.android.bip39.Mnemonics.MnemonicCode
|
||||||
import io.github.novacrypto.bip39.SeedCalculator
|
import cash.z.ecc.android.bip39.Mnemonics.WordCount
|
||||||
import io.github.novacrypto.bip39.Words
|
import cash.z.ecc.android.bip39.toEntropy
|
||||||
import io.github.novacrypto.bip39.wordlists.English
|
import cash.z.ecc.android.bip39.toSeed
|
||||||
import java.security.SecureRandom
|
import java.util.*
|
||||||
import javax.inject.Inject
|
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 {
|
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 {
|
override fun nextEntropy(): ByteArray {
|
||||||
return ByteArray(Words.TWENTY_FOUR.byteLength()).apply {
|
return WordCount.COUNT_24.toEntropy()
|
||||||
SecureRandom().nextBytes(this)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun nextMnemonic(): CharArray {
|
override fun nextMnemonic(): CharArray {
|
||||||
|
@ -24,12 +22,7 @@ class Mnemonics @Inject constructor(): MnemonicPlugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun nextMnemonic(entropy: ByteArray): CharArray {
|
override fun nextMnemonic(entropy: ByteArray): CharArray {
|
||||||
return StringBuilder().let { builder ->
|
return MnemonicCode(entropy).chars
|
||||||
MnemonicGenerator(English.INSTANCE).createMnemonic(entropy) { c ->
|
|
||||||
builder.append(c)
|
|
||||||
}
|
|
||||||
builder.toString().toCharArray()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun nextMnemonicList(): List<CharArray> {
|
override fun nextMnemonicList(): List<CharArray> {
|
||||||
|
@ -37,17 +30,11 @@ class Mnemonics @Inject constructor(): MnemonicPlugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun nextMnemonicList(entropy: ByteArray): List<CharArray> {
|
override fun nextMnemonicList(entropy: ByteArray): List<CharArray> {
|
||||||
return WordListBuilder().let { builder ->
|
return MnemonicCode(entropy).map { it.toCharArray() }
|
||||||
MnemonicGenerator(English.INSTANCE).createMnemonic(entropy) { c ->
|
|
||||||
builder.append(c)
|
|
||||||
}
|
|
||||||
builder.wordList
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toSeed(mnemonic: CharArray): ByteArray {
|
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 MnemonicCode(mnemonic).toSeed()
|
||||||
return SeedCalculator().calculateSeed(String(mnemonic), "")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toWordList(mnemonic: CharArray): List<CharArray> {
|
override fun toWordList(mnemonic: CharArray): List<CharArray> {
|
||||||
|
@ -67,21 +54,4 @@ class Mnemonics @Inject constructor(): MnemonicPlugin {
|
||||||
}
|
}
|
||||||
return wordList
|
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -1,23 +1,17 @@
|
||||||
package cash.z.ecc.android.util
|
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 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.assertEquals
|
||||||
import org.junit.Assert.assertTrue
|
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.lang.Math.max
|
import java.lang.Math.max
|
||||||
import java.security.SecureRandom
|
import java.util.*
|
||||||
|
|
||||||
|
|
||||||
class MnemonicTest {
|
class MnemonicTest {
|
||||||
|
|
||||||
lateinit var mnemonics: MnemonicProvider
|
lateinit var mnemonics: MnemonicPlugin
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun start() {
|
fun start() {
|
||||||
|
@ -58,18 +52,20 @@ class MnemonicTest {
|
||||||
@Test
|
@Test
|
||||||
fun testMnemonic_longestWord() {
|
fun testMnemonic_longestWord() {
|
||||||
var max = 0
|
var max = 0
|
||||||
|
val englishWordList = mnemonics.fullWordList(Locale.ENGLISH.language)
|
||||||
repeat(2048) {
|
repeat(2048) {
|
||||||
max = max(max, English.INSTANCE.getWord(it).length)
|
max = max(max, englishWordList[it].length)
|
||||||
}
|
}
|
||||||
assertEquals(8, max)
|
assertEquals(8, max)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun validate(words: List<String>) {
|
private fun validate(words: List<String>) {
|
||||||
|
val englishWordList = mnemonics.fullWordList(Locale.ENGLISH.language)
|
||||||
// return or crash!
|
// return or crash!
|
||||||
words.forEach { word ->
|
words.forEach { word ->
|
||||||
var i = 0
|
var i = 0
|
||||||
while (true) {
|
while (true) {
|
||||||
if (English.INSTANCE.getWord(i++) == word) {
|
if (englishWordList[i++] == word) {
|
||||||
println(word)
|
println(word)
|
||||||
break
|
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> {
|
private fun CharSequence.toWords(): List<CharSequence> {
|
||||||
|
|
Loading…
Reference in New Issue