mirror of
https://github.com/oxen-io/session-android.git
synced 2025-04-03 03:45:39 +00:00
Accept mnemonic as hex in QR codes
This commit is contained in:
parent
578c471f1e
commit
ff6c0fb6f5
@ -4,13 +4,11 @@ import android.app.Application
|
|||||||
import androidx.lifecycle.AndroidViewModel
|
import androidx.lifecycle.AndroidViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.channels.BufferOverflow
|
import kotlinx.coroutines.channels.BufferOverflow
|
||||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.asSharedFlow
|
import kotlinx.coroutines.flow.asSharedFlow
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
import kotlinx.coroutines.flow.flowOn
|
|
||||||
import kotlinx.coroutines.flow.mapNotNull
|
import kotlinx.coroutines.flow.mapNotNull
|
||||||
import kotlinx.coroutines.flow.update
|
import kotlinx.coroutines.flow.update
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@ -18,7 +16,6 @@ import network.loki.messenger.R
|
|||||||
import org.session.libsignal.crypto.MnemonicCodec
|
import org.session.libsignal.crypto.MnemonicCodec
|
||||||
import org.session.libsignal.crypto.MnemonicCodec.DecodingError.InputTooShort
|
import org.session.libsignal.crypto.MnemonicCodec.DecodingError.InputTooShort
|
||||||
import org.session.libsignal.crypto.MnemonicCodec.DecodingError.InvalidWord
|
import org.session.libsignal.crypto.MnemonicCodec.DecodingError.InvalidWord
|
||||||
import org.session.libsignal.utilities.Hex
|
|
||||||
import org.thoughtcrime.securesms.crypto.MnemonicUtilities
|
import org.thoughtcrime.securesms.crypto.MnemonicUtilities
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@ -48,7 +45,7 @@ internal class LinkDeviceViewModel @Inject constructor(
|
|||||||
fun onContinue() {
|
fun onContinue() {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
try {
|
try {
|
||||||
decode(state.value.recoveryPhrase).let(::onSuccess)
|
codec.decodeAsByteArray(state.value.recoveryPhrase).let(::onSuccess)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
onFailure(e)
|
onFailure(e)
|
||||||
}
|
}
|
||||||
@ -58,7 +55,7 @@ internal class LinkDeviceViewModel @Inject constructor(
|
|||||||
fun onScanQrCode(string: String) {
|
fun onScanQrCode(string: String) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
try {
|
try {
|
||||||
decode(string).let(::onSuccess)
|
codec.decodeMnemonicOrHexAsByteArray(string).let(::onSuccess)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
onQrCodeScanFailure(e)
|
onQrCodeScanFailure(e)
|
||||||
}
|
}
|
||||||
@ -68,6 +65,7 @@ internal class LinkDeviceViewModel @Inject constructor(
|
|||||||
fun onChange(recoveryPhrase: String) {
|
fun onChange(recoveryPhrase: String) {
|
||||||
state.value = State(recoveryPhrase)
|
state.value = State(recoveryPhrase)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onSuccess(seed: ByteArray) {
|
private fun onSuccess(seed: ByteArray) {
|
||||||
viewModelScope.launch { _events.emit(LoadAccountEvent(seed)) }
|
viewModelScope.launch { _events.emit(LoadAccountEvent(seed)) }
|
||||||
}
|
}
|
||||||
@ -87,6 +85,4 @@ internal class LinkDeviceViewModel @Inject constructor(
|
|||||||
private fun onQrCodeScanFailure(error: Throwable) {
|
private fun onQrCodeScanFailure(error: Throwable) {
|
||||||
viewModelScope.launch { _qrErrors.emit(error) }
|
viewModelScope.launch { _qrErrors.emit(error) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun decode(mnemonic: String) = codec.decode(mnemonic).let(Hex::fromStringCondensed)!!
|
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import androidx.compose.foundation.background
|
|||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.aspectRatio
|
import androidx.compose.foundation.layout.aspectRatio
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.material.Card
|
import androidx.compose.material.Card
|
||||||
import androidx.compose.material.Icon
|
import androidx.compose.material.Icon
|
||||||
@ -30,6 +31,7 @@ import androidx.compose.ui.unit.dp
|
|||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
|
import org.thoughtcrime.securesms.ui.LocalDimensions
|
||||||
import org.thoughtcrime.securesms.ui.color.LocalColors
|
import org.thoughtcrime.securesms.ui.color.LocalColors
|
||||||
import org.thoughtcrime.securesms.util.QRCodeUtilities
|
import org.thoughtcrime.securesms.util.QRCodeUtilities
|
||||||
|
|
||||||
@ -69,6 +71,7 @@ private fun Content(
|
|||||||
) {
|
) {
|
||||||
Box(
|
Box(
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
|
.padding(LocalDimensions.current.xxxsItemSpacing)
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.aspectRatio(1f)
|
.aspectRatio(1f)
|
||||||
) {
|
) {
|
||||||
|
@ -19,7 +19,7 @@ object QRCodeUtilities {
|
|||||||
): Bitmap? = runCatching {
|
): Bitmap? = runCatching {
|
||||||
val hints = hashMapOf(
|
val hints = hashMapOf(
|
||||||
EncodeHintType.MARGIN to 0,
|
EncodeHintType.MARGIN to 0,
|
||||||
EncodeHintType.ERROR_CORRECTION to ErrorCorrectionLevel.H
|
EncodeHintType.ERROR_CORRECTION to ErrorCorrectionLevel.M
|
||||||
)
|
)
|
||||||
val color = if (isInverted) light else dark
|
val color = if (isInverted) light else dark
|
||||||
val background = if (isInverted) dark else light
|
val background = if (isInverted) dark else light
|
||||||
|
File diff suppressed because one or more lines are too long
@ -1,5 +1,6 @@
|
|||||||
package org.session.libsignal.crypto
|
package org.session.libsignal.crypto
|
||||||
|
|
||||||
|
import org.session.libsignal.utilities.Hex
|
||||||
import java.util.zip.CRC32
|
import java.util.zip.CRC32
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -40,6 +41,9 @@ class MnemonicCodec(private val loadFileContents: (String) -> String) {
|
|||||||
object VerificationFailed : DecodingError("Your mnemonic couldn't be verified. Please check what you entered and try again.")
|
object VerificationFailed : DecodingError("Your mnemonic couldn't be verified. Please check what you entered and try again.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accepts a [hexEncodedString] and return s a mnemonic.
|
||||||
|
*/
|
||||||
fun encode(hexEncodedString: String, languageConfiguration: Language.Configuration = Language.Configuration.english): String {
|
fun encode(hexEncodedString: String, languageConfiguration: Language.Configuration = Language.Configuration.english): String {
|
||||||
var string = hexEncodedString
|
var string = hexEncodedString
|
||||||
val language = Language(loadFileContents, languageConfiguration)
|
val language = Language(loadFileContents, languageConfiguration)
|
||||||
@ -68,6 +72,9 @@ class MnemonicCodec(private val loadFileContents: (String) -> String) {
|
|||||||
}.joinToString(" ")
|
}.joinToString(" ")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accepts a [mnemonic] and returns a hexEncodedString
|
||||||
|
*/
|
||||||
fun decode(mnemonic: String, languageConfiguration: Language.Configuration = Language.Configuration.english): String {
|
fun decode(mnemonic: String, languageConfiguration: Language.Configuration = Language.Configuration.english): String {
|
||||||
val words = mnemonic.split(" ")
|
val words = mnemonic.split(" ")
|
||||||
val language = Language(loadFileContents, languageConfiguration)
|
val language = Language(loadFileContents, languageConfiguration)
|
||||||
@ -107,6 +114,18 @@ class MnemonicCodec(private val loadFileContents: (String) -> String) {
|
|||||||
}.joinToString(separator = "") { it }
|
}.joinToString(separator = "") { it }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun decodeAsByteArray(mnemonic: String): ByteArray = decode(mnemonic = mnemonic).let(Hex::fromStringCondensed)
|
||||||
|
|
||||||
|
fun decodeMnemonicOrHexAsByteArray(mnemonicOrHex: String): ByteArray = try {
|
||||||
|
decode(mnemonic = mnemonicOrHex).let(Hex::fromStringCondensed)
|
||||||
|
} catch (decodeException: Exception) {
|
||||||
|
try {
|
||||||
|
Hex.fromStringCondensed(mnemonicOrHex)
|
||||||
|
} catch (_: Exception) {
|
||||||
|
throw decodeException
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun swap(x: String): String {
|
private fun swap(x: String): String {
|
||||||
val p1 = x.substring(6 until 8)
|
val p1 = x.substring(6 until 8)
|
||||||
val p2 = x.substring(4 until 6)
|
val p2 = x.substring(4 until 6)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user