Skip to content

Commit

Permalink
feat: add mnemonic validation
Browse files Browse the repository at this point in the history
Add mnemomic validation
Also changing a public API to receive an array of Mnemonics words instead of a pre processed string that could complicate logic on user side
  • Loading branch information
goncalo-frade-iohk committed Sep 25, 2023
1 parent e6f6d46 commit ceeae56
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,33 @@ final class Mnemonic {

private const val PBKDF2C = 2048
private const val PBKDF2DKLen = 64
class InvalidMnemonicCode(code: String) : RuntimeException(code)

fun isValidMnemonicCode(code: Array<String>): Boolean {
return code.all { it in MnemonicCodeEnglish.wordList }
}

fun createRandomMnemonics(): Array<String> {
val entropyBytes = SecureRandom.generateSeed(SEED_ENTROPY_BITS_24_WORDS / 8)
return MnemonicCode(MnemonicCodeEnglish.wordList.toTypedArray()).toMnemonic(entropyBytes)
}

fun createSeed(mnemonics: String, passphrase: String = "AtalaPrism"): ByteArray {
@Throws(InvalidMnemonicCode::class)
fun createSeed(mnemonics: Array<String>, passphrase: String = "AtalaPrism"): ByteArray {
if (!isValidMnemonicCode(mnemonics)) {
throw InvalidMnemonicCode(mnemonics.joinToString(separator = " "))
}
val mnemonicString = mnemonics.joinToString(separator = " ")
return PBKDF2SHA512.derive(
mnemonics,
mnemonicString,
passphrase,
PBKDF2C,
PBKDF2DKLen
)
}

fun createRandomSeed(passphrase: String = "AtalaPrism"): ByteArray {
val mnemonics = this.createRandomMnemonics().joinToString(separator = " ")
val mnemonics = this.createRandomMnemonics()
return this.createSeed(mnemonics, passphrase)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,20 @@ import io.iohk.atala.prism.apollo.hashing.internal.toHexString
import kotlin.test.Test
import kotlin.test.assertContains
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith
import kotlin.test.assertFalse

class MnemonicTests {

@Test
fun testValidateMnemonics() {
val invalidMnemonics = arrayOf("abc", "ddd", "inv")
assertFalse(Mnemonic.isValidMnemonicCode(invalidMnemonics))
}

@Test
fun testCreateRandomMnemonics() {
val mnemonics = Mnemonic.createRandomMnemonics().joinToString(separator = " ")
val mnemonics = Mnemonic.createRandomMnemonics()
val seed = Mnemonic.createSeed(mnemonics)
assertEquals(seed.size, 64)
}
Expand All @@ -21,24 +30,34 @@ class MnemonicTests {

@Test
fun testCreateSeed() {
val mnemonics = "random seed mnemonic words"
val mnemonics = arrayOf("adjust", "animal", "anger", "around")
val seed = Mnemonic.createSeed(mnemonics)

assertEquals(seed.size, 64)

val privateKey = seed.slice(IntRange(0, 31))
assertContains(privateKey.toByteArray().toHexString(), "feac83cecc84531575eb67250a03d8ac112d4d6678674968bf3f6576ad028ae3")
assertContains(privateKey.toByteArray().toHexString(), "a078d8a0f3beca52ef17a1d0279eb6e9c410cd3837d3db38d31e43df6da95ac6")
}

@Test
fun testCreateSeedInvalidMnemonics() {
val mnemonics = arrayOf("abc", "ddd", "adsada", "testing")

assertFailsWith<Mnemonic.Companion.InvalidMnemonicCode> {
Mnemonic.createSeed(mnemonics)
}
}

@Test
fun testCreateSeedWithPW() {
val mnemonics = "random seed mnemonic words"
val mnemonics = arrayOf("adjust", "animal", "anger", "around")
val password = "123456"
val seed = Mnemonic.createSeed(mnemonics, password)

assertEquals(seed.size, 64)

val privateKey = seed.slice(IntRange(0, 31))
assertContains(privateKey.toByteArray().toHexString(), "b3a8af66eca002e8b4ca868c5b55a8c865f15e0cfea483d6a164a6fbecf83625")

assertContains(privateKey.toByteArray().toHexString(), "815b70655ca4c9675f5fc15fe8f82315f07521d034eec45bf4d5912bd3a61218")
}
}

0 comments on commit ceeae56

Please sign in to comment.