Add calculateChecksumIndex() method to Mnemonics class.
- The calculateChecksumIndex() method uses the newly added method to calculate the CRC-32 to obtain the index of the word to be used for the seed checksum. - Added a few unit tests to validate the correct functionality of the calculateChecksumIndex() method.
This commit is contained in:
parent
7dab5227dc
commit
53bc55ec9f
3 changed files with 73 additions and 28 deletions
|
@ -20,11 +20,16 @@ kotlin {
|
||||||
|
|
||||||
sourceSets {
|
sourceSets {
|
||||||
commonMain.dependencies {
|
commonMain.dependencies {
|
||||||
|
implementation(projects.shared.crypto)
|
||||||
|
|
||||||
|
implementation(libs.cryptography.bigint)
|
||||||
implementation(libs.ktor.client.cio)
|
implementation(libs.ktor.client.cio)
|
||||||
implementation(libs.ktor.client.core)
|
implementation(libs.ktor.client.core)
|
||||||
implementation(libs.ktor.client.websockets)
|
implementation(libs.ktor.client.websockets)
|
||||||
|
}
|
||||||
|
|
||||||
implementation(libs.cryptography.bigint)
|
commonTest.dependencies {
|
||||||
|
implementation(libs.kotlin.test)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,8 @@ package net.agorise.shared.stargate.mnemonics
|
||||||
|
|
||||||
import dev.whyoleg.cryptography.bigint.BigInt
|
import dev.whyoleg.cryptography.bigint.BigInt
|
||||||
import dev.whyoleg.cryptography.bigint.toBigInt
|
import dev.whyoleg.cryptography.bigint.toBigInt
|
||||||
|
import io.ktor.utils.io.core.toByteArray
|
||||||
|
import net.agorise.shared.crypto.crc.Crc32
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides functionality to create and validate mnemonics.
|
* Provides functionality to create and validate mnemonics.
|
||||||
|
@ -115,33 +117,31 @@ class Mnemonics {
|
||||||
//
|
//
|
||||||
// return calculatedChecksumWord == checksumWord
|
// return calculatedChecksumWord == checksumWord
|
||||||
// }
|
// }
|
||||||
//
|
|
||||||
// /**
|
/**
|
||||||
// * Calculates a checksum (using CRC algorithm) on first 24 words.
|
* Calculates a checksum using CRC-32 algorithm on the seed (SEED_LENGTH words) as follows:
|
||||||
// */
|
* - Takes prefixLen chars (not bytes) from each word and concatenates them
|
||||||
// @OptIn(ExperimentalUnsignedTypes::class)
|
* - Calculates the CRC-32 checksum on the concatenated bytes
|
||||||
// private fun calculateChecksumIndex(words: Array<String>, prefixLen: Int): Result<UInt> {
|
* - Returns the mod of checksum by SEED_LENGTH, to get the checksum word
|
||||||
// val trimmedRunes = mutableListOf<Char>()
|
*/
|
||||||
//
|
internal fun calculateChecksumIndex(words: List<String>, prefixLen: Int): Result<UInt> {
|
||||||
// if (words.size != SEED_LENGTH) {
|
if (words.size != SEED_LENGTH) {
|
||||||
// return Result.failure(Exception("Words not equal to seed length"))
|
return Result.failure(Exception("Words not equal to seed length"))
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// for (word in words) {
|
val trimmedWords = mutableListOf<Char>()
|
||||||
// val trimmedWord = if (word.length > prefixLen) {
|
|
||||||
// word.substring(0, prefixLen)
|
words.forEach { word ->
|
||||||
// } else {
|
trimmedWords.addAll(word.take(prefixLen).toList())
|
||||||
// word
|
}
|
||||||
// }
|
|
||||||
// trimmedRunes.addAll(trimmedWord.toCharArray().toList())
|
// TODO Use DI to get an instance of CRC32
|
||||||
// }
|
val crc32 = Crc32()
|
||||||
//
|
|
||||||
// val checksum = CRC32().apply {
|
val checksum = crc32.crc32(trimmedWords.joinToString("").toByteArray())
|
||||||
// update(trimmedRunes.toCharArray().concatToString().toByteArray(Charsets.UTF_8))
|
|
||||||
// }.value
|
return Result.success(checksum % SEED_LENGTH.toUInt())
|
||||||
//
|
}
|
||||||
// return Result.success(checksum % SEED_LENGTH.toUInt())
|
|
||||||
// }
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
// Each language should have exactly this number of words
|
// Each language should have exactly this number of words
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
package net.agorise.shared.stargate.mnemonics
|
||||||
|
|
||||||
|
import kotlin.test.Test
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
|
class MnemonicsTest {
|
||||||
|
private val mnemonics = Mnemonics()
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `given an invalid seed - when calculateChecksumIndex is called - then result is failure`() {
|
||||||
|
val invalidSeed = "invalid seed".split(" ")
|
||||||
|
|
||||||
|
val result = mnemonics.calculateChecksumIndex(invalidSeed, 3)
|
||||||
|
|
||||||
|
assertTrue(result.isFailure)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `given a valid english seed - when calculateChecksumIndex is called - then result is correct`() {
|
||||||
|
val expectedChecksumIndex = 22u
|
||||||
|
val seed = "sequence atlas unveil summon pebbles tuesday beer rudely snake rockets different fuselage woven tagged bested dented vegan hover rapid fawns obvious muppet randomly seasons randomly".split(" ").dropLast(1)
|
||||||
|
|
||||||
|
val result = mnemonics.calculateChecksumIndex(seed, 3)
|
||||||
|
val actualChecksumIndex = result.getOrThrow()
|
||||||
|
|
||||||
|
assertEquals(expectedChecksumIndex, actualChecksumIndex)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `given a valid spanish seed - when calculateChecksumIndex is called - then result is correct`() {
|
||||||
|
val expectedChecksumIndex = 7u
|
||||||
|
val seed = "perfil lujo faja puma favor pedir detalle doble carbón neón paella cuarto ánimo cuento conga correr dental moneda león donar entero logro realidad acceso doble".split(" ").dropLast(1)
|
||||||
|
|
||||||
|
val result = mnemonics.calculateChecksumIndex(seed, 4)
|
||||||
|
val actualChecksumIndex = result.getOrThrow()
|
||||||
|
|
||||||
|
assertEquals(expectedChecksumIndex, actualChecksumIndex)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue