Add verifyChecksum method to Mnemonics class.
- The verifyChecksum() method uses the calculateChecksumIndex() method internally to obtain the checksum index, which is then used to confirm that the checksum word is correct. - Added tests for all verifyChecksum() scenarios. - Created MnemonicsDataProvider to more easily provide the data used in MnemonicsTest.
This commit is contained in:
parent
53bc55ec9f
commit
c690d839da
4 changed files with 86 additions and 25 deletions
|
@ -1,11 +1,16 @@
|
||||||
package net.agorise.shared.crypto.crc
|
package net.agorise.shared.crypto.crc
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Provides functionality to calculate CRC-32 checksums.
|
||||||
|
*
|
||||||
* 0xEDB88320u is the reversed representation of the IEEE CRC-32 polynomial: 0x04C11DB7
|
* 0xEDB88320u is the reversed representation of the IEEE CRC-32 polynomial: 0x04C11DB7
|
||||||
*/
|
*/
|
||||||
class Crc32(private val polynomial: UInt = 0xEDB88320u) {
|
class Crc32(polynomial: UInt = 0xEDB88320u) {
|
||||||
internal val lookupTable: List<UInt> = populateLookupTable(polynomial)
|
internal val lookupTable: List<UInt> = populateLookupTable(polynomial)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the CRC-32 checksum on the given byte array.
|
||||||
|
*/
|
||||||
fun crc32(bytes: ByteArray): UInt {
|
fun crc32(bytes: ByteArray): UInt {
|
||||||
var crc = INITIAL_CRC32
|
var crc = INITIAL_CRC32
|
||||||
for (byte in bytes) {
|
for (byte in bytes) {
|
||||||
|
@ -15,6 +20,9 @@ class Crc32(private val polynomial: UInt = 0xEDB88320u) {
|
||||||
return crc.inv()
|
return crc.inv()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Populates the lookup table with the given polynomial to calculate CRC-32 checksums faster.
|
||||||
|
*/
|
||||||
private fun populateLookupTable(polynomial: UInt): List<UInt> {
|
private fun populateLookupTable(polynomial: UInt): List<UInt> {
|
||||||
return (0 until 256).map { index ->
|
return (0 until 256).map { index ->
|
||||||
(0 until 8).fold(index.toUInt()) { crc, _ ->
|
(0 until 8).fold(index.toUInt()) { crc, _ ->
|
||||||
|
|
|
@ -99,24 +99,23 @@ class Mnemonics {
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Verifies that the
|
* Obtains that the checksum index and verifies it corresponds to the checksum word.
|
||||||
*/
|
*/
|
||||||
// private fun verifyChecksum(words: Array<String>, prefixLen: Int): Boolean {
|
internal fun verifyChecksum(words: List<String>, prefixLen: Int): Boolean {
|
||||||
// val seedLength = SEED_LENGTH
|
if (words.size != SEED_LENGTH + 1) {
|
||||||
//
|
return false // Checksum word is not present, we cannot verify
|
||||||
// if (words.size != seedLength + 1) {
|
}
|
||||||
// return false // Checksum word is not present, we cannot verify
|
|
||||||
// }
|
val result = calculateChecksumIndex(words.dropLast(1), prefixLen)
|
||||||
//
|
|
||||||
// val (checksumIndex, err) = calculateChecksumIndex(words.sliceArray(0 until words.size - 1), prefixLen)
|
// Obtain checksum index, or return false if checksum index is not present
|
||||||
// if (err != null) {
|
val checksumIndex = result.getOrNull()?.toInt() ?: return false
|
||||||
// return false
|
|
||||||
// }
|
val calculatedChecksumWord = words[checksumIndex]
|
||||||
// val calculatedChecksumWord = words[checksumIndex]
|
val checksumWord = words[SEED_LENGTH]
|
||||||
// val checksumWord = words[seedLength]
|
|
||||||
//
|
return calculatedChecksumWord == checksumWord
|
||||||
// return calculatedChecksumWord == checksumWord
|
}
|
||||||
// }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates a checksum using CRC-32 algorithm on the seed (SEED_LENGTH words) as follows:
|
* Calculates a checksum using CRC-32 algorithm on the seed (SEED_LENGTH words) as follows:
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
package net.agorise.shared.stargate.mnemonics
|
||||||
|
|
||||||
|
object MnemonicsDataProvider {
|
||||||
|
val invalidSizeSeed = "invalid size seed".split(" ")
|
||||||
|
val invalidChecksumSeed =
|
||||||
|
("sequence atlas unveil summon pebbles tuesday beer rudely snake rockets different " +
|
||||||
|
"fuselage woven tagged bested dented vegan hover rapid fawns obvious muppet " +
|
||||||
|
"randomly seasons summon").split(" ")
|
||||||
|
val validEnglishSeed =
|
||||||
|
("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(" ")
|
||||||
|
val validSpanishSeed =
|
||||||
|
("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(" ")
|
||||||
|
}
|
|
@ -2,16 +2,17 @@ package net.agorise.shared.stargate.mnemonics
|
||||||
|
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
import kotlin.test.assertFalse
|
||||||
import kotlin.test.assertTrue
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
class MnemonicsTest {
|
class MnemonicsTest {
|
||||||
private val mnemonics = Mnemonics()
|
private val mnemonics = Mnemonics()
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `given an invalid seed - when calculateChecksumIndex is called - then result is failure`() {
|
fun `given an invalid size seed - when calculateChecksumIndex is called - then result is failure`() {
|
||||||
val invalidSeed = "invalid seed".split(" ")
|
val invalidSizeSeed = MnemonicsDataProvider.invalidSizeSeed
|
||||||
|
|
||||||
val result = mnemonics.calculateChecksumIndex(invalidSeed, 3)
|
val result = mnemonics.calculateChecksumIndex(invalidSizeSeed, 3)
|
||||||
|
|
||||||
assertTrue(result.isFailure)
|
assertTrue(result.isFailure)
|
||||||
}
|
}
|
||||||
|
@ -19,9 +20,9 @@ class MnemonicsTest {
|
||||||
@Test
|
@Test
|
||||||
fun `given a valid english seed - when calculateChecksumIndex is called - then result is correct`() {
|
fun `given a valid english seed - when calculateChecksumIndex is called - then result is correct`() {
|
||||||
val expectedChecksumIndex = 22u
|
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 validEnglishSeed = MnemonicsDataProvider.validEnglishSeed.dropLast(1)
|
||||||
|
|
||||||
val result = mnemonics.calculateChecksumIndex(seed, 3)
|
val result = mnemonics.calculateChecksumIndex(validEnglishSeed, 3)
|
||||||
val actualChecksumIndex = result.getOrThrow()
|
val actualChecksumIndex = result.getOrThrow()
|
||||||
|
|
||||||
assertEquals(expectedChecksumIndex, actualChecksumIndex)
|
assertEquals(expectedChecksumIndex, actualChecksumIndex)
|
||||||
|
@ -30,11 +31,47 @@ class MnemonicsTest {
|
||||||
@Test
|
@Test
|
||||||
fun `given a valid spanish seed - when calculateChecksumIndex is called - then result is correct`() {
|
fun `given a valid spanish seed - when calculateChecksumIndex is called - then result is correct`() {
|
||||||
val expectedChecksumIndex = 7u
|
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 validSpanishSeed = MnemonicsDataProvider.validSpanishSeed.dropLast(1)
|
||||||
|
|
||||||
val result = mnemonics.calculateChecksumIndex(seed, 4)
|
val result = mnemonics.calculateChecksumIndex(validSpanishSeed, 4)
|
||||||
val actualChecksumIndex = result.getOrThrow()
|
val actualChecksumIndex = result.getOrThrow()
|
||||||
|
|
||||||
assertEquals(expectedChecksumIndex, actualChecksumIndex)
|
assertEquals(expectedChecksumIndex, actualChecksumIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `given an invalid size seed - when verifyChecksum is called - then result is false`() {
|
||||||
|
val invalidSizeSeed = MnemonicsDataProvider.invalidSizeSeed
|
||||||
|
|
||||||
|
val result = mnemonics.verifyChecksum(invalidSizeSeed, 3)
|
||||||
|
|
||||||
|
assertFalse(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `given an invalid checksum seed - when verifyChecksum is called - then result is false`() {
|
||||||
|
val invalidChecksumSeed = MnemonicsDataProvider.invalidChecksumSeed
|
||||||
|
|
||||||
|
val result = mnemonics.verifyChecksum(invalidChecksumSeed, 3)
|
||||||
|
|
||||||
|
assertFalse(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `given a valid english seed - when verifyChecksum is called - then result is true`() {
|
||||||
|
val validEnglishSeed = MnemonicsDataProvider.validEnglishSeed
|
||||||
|
|
||||||
|
val result = mnemonics.verifyChecksum(validEnglishSeed, 3)
|
||||||
|
|
||||||
|
assertTrue(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `given a valid spanish seed - when verifyChecksum is called - then result is true`() {
|
||||||
|
val validSpanishSeed = MnemonicsDataProvider.validSpanishSeed
|
||||||
|
|
||||||
|
val result = mnemonics.verifyChecksum(validSpanishSeed, 4)
|
||||||
|
|
||||||
|
assertTrue(result)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue