add PIN/PUK/pairing validation/confirmation

This commit is contained in:
Michele Balistreri 2020-10-13 10:17:09 +02:00 committed by Ksenia Balistreri
parent 04398f58d7
commit 52cdd38147
10 changed files with 104 additions and 16 deletions

View File

@ -3,7 +3,7 @@
**NOTE**: _This app is a prototype. While it seems to work reasonably well and stable, the UI has not received any thought yet. **NOTE**: _This app is a prototype. While it seems to work reasonably well and stable, the UI has not received any thought yet.
It is fine to use but keep in mind that there isn't much error reporting, no progress indicators and some screens are crammed with info_ It is fine to use but keep in mind that there isn't much error reporting, no progress indicators and some screens are crammed with info_
Keycard Connect's main function is to enable using the Keycard with dApps outside of a web3 browser using WalletConnect. The dApp must of course support WalletConnect for this to work. Additionally, this app is a little toolbox for Keycardm allowing things like changing PIN, initializing cards, changing seed etc. Keycard Connect's main function is to enable using the Keycard with dApps outside of a web3 browser using WalletConnect. The dApp must of course support WalletConnect for this to work. Additionally, this app is a little toolbox for Keycard, allowing things like changing PIN, initializing cards, changing seed etc.
## What works ## What works

View File

@ -0,0 +1,4 @@
package im.status.keycard.connect.data
fun isValidPIN(pin: String) : Boolean = pin.length == 6 && pin.all { it.isDigit() }
fun isValidPUK(puk: String) : Boolean = puk.length == 12 && puk.all { it.isDigit() }

View File

@ -18,7 +18,7 @@ class EthereumRPC(endpointURL: String) {
init { init {
val moshi = Moshi.Builder().build() val moshi = Moshi.Builder().build()
val type: Type = Types.newParameterizedType(Map::class.java, String::class.java, Any::class.java) val type: Type = Types.newParameterizedType(Map::class.java, String::class.java, Any::class.java)
ethplorerJSONAdapter = moshi.adapter<Map<String, Any>>(type) ethplorerJSONAdapter = moshi.adapter(type)
} }
fun changeEndpoint(endpointURL: String) { fun changeEndpoint(endpointURL: String) {

View File

@ -2,18 +2,25 @@ package im.status.keycard.connect.ui
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import android.widget.Button
import android.widget.EditText import android.widget.EditText
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.widget.doAfterTextChanged
import im.status.keycard.connect.R import im.status.keycard.connect.R
import im.status.keycard.connect.Registry import im.status.keycard.connect.Registry
import im.status.keycard.connect.card.ChangePINCommand import im.status.keycard.connect.card.ChangePINCommand
import im.status.keycard.connect.card.scriptWithAuthentication import im.status.keycard.connect.card.scriptWithAuthentication
import im.status.keycard.connect.data.isValidPIN
class ChangePINActivity : AppCompatActivity() { class ChangePINActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
//TODO: pin validation and confirmation
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.activity_change_pin) setContentView(R.layout.activity_change_pin)
val pinText = findViewById<EditText>(R.id.newPINText)
val pinConfirmation = findViewById<EditText>(R.id.pinConfirmation)
pinText.doAfterTextChanged { validatePIN() }
pinConfirmation.doAfterTextChanged { validatePIN() }
} }
fun ok(@Suppress("UNUSED_PARAMETER") view: View) { fun ok(@Suppress("UNUSED_PARAMETER") view: View) {
@ -26,4 +33,11 @@ class ChangePINActivity : AppCompatActivity() {
fun cancel(@Suppress("UNUSED_PARAMETER") view: View) { fun cancel(@Suppress("UNUSED_PARAMETER") view: View) {
finish() finish()
} }
private fun validatePIN() {
val pinText = findViewById<EditText>(R.id.newPINText).text.toString()
val pinConfirmation = findViewById<EditText>(R.id.pinConfirmation).text.toString()
val button = findViewById<Button>(R.id.okButton)
button.isEnabled = (pinText == pinConfirmation) && isValidPIN(pinText)
}
} }

View File

@ -2,18 +2,25 @@ package im.status.keycard.connect.ui
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import android.widget.Button
import android.widget.EditText import android.widget.EditText
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.widget.doAfterTextChanged
import im.status.keycard.connect.R import im.status.keycard.connect.R
import im.status.keycard.connect.Registry import im.status.keycard.connect.Registry
import im.status.keycard.connect.card.ChangePUKCommand import im.status.keycard.connect.card.ChangePUKCommand
import im.status.keycard.connect.card.scriptWithAuthentication import im.status.keycard.connect.card.scriptWithAuthentication
import im.status.keycard.connect.data.isValidPUK
class ChangePUKActivity : AppCompatActivity() { class ChangePUKActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
//TODO: puk validation and confirmation
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.activity_change_puk) setContentView(R.layout.activity_change_puk)
val pukText = findViewById<EditText>(R.id.newPUKText)
val pukConfirmation = findViewById<EditText>(R.id.pukConfirmation)
pukText.doAfterTextChanged { validatePUK() }
pukConfirmation.doAfterTextChanged { validatePUK() }
} }
fun ok(@Suppress("UNUSED_PARAMETER") view: View) { fun ok(@Suppress("UNUSED_PARAMETER") view: View) {
@ -26,4 +33,11 @@ class ChangePUKActivity : AppCompatActivity() {
fun cancel(@Suppress("UNUSED_PARAMETER") view: View) { fun cancel(@Suppress("UNUSED_PARAMETER") view: View) {
finish() finish()
} }
private fun validatePUK() {
val pukText = findViewById<EditText>(R.id.newPUKText).text.toString()
val pukConfirmation = findViewById<EditText>(R.id.pukConfirmation).text.toString()
val button = findViewById<Button>(R.id.okButton)
button.isEnabled = (pukText == pukConfirmation) && isValidPUK(pukText)
}
} }

View File

@ -2,18 +2,25 @@ package im.status.keycard.connect.ui
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import android.widget.Button
import android.widget.EditText import android.widget.EditText
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.widget.doAfterTextChanged
import im.status.keycard.connect.R import im.status.keycard.connect.R
import im.status.keycard.connect.Registry import im.status.keycard.connect.Registry
import im.status.keycard.connect.card.ChangePairingPasswordCommand import im.status.keycard.connect.card.ChangePairingPasswordCommand
import im.status.keycard.connect.card.scriptWithAuthentication import im.status.keycard.connect.card.scriptWithAuthentication
import im.status.keycard.connect.data.isValidPUK
class ChangePairingPasswordActivity : AppCompatActivity() { class ChangePairingPasswordActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
//TODO: pairing password confirmation
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.activity_change_pairing_password) setContentView(R.layout.activity_change_pairing_password)
val pairingPasswordText = findViewById<EditText>(R.id.newPairingPasswordText)
val pairingPasswordConfirmation = findViewById<EditText>(R.id.pairingPasswordConfirmation)
pairingPasswordText.doAfterTextChanged { validatePairingPassword() }
pairingPasswordConfirmation.doAfterTextChanged { validatePairingPassword() }
} }
fun ok(@Suppress("UNUSED_PARAMETER") view: View) { fun ok(@Suppress("UNUSED_PARAMETER") view: View) {
@ -26,4 +33,11 @@ class ChangePairingPasswordActivity : AppCompatActivity() {
fun cancel(@Suppress("UNUSED_PARAMETER") view: View) { fun cancel(@Suppress("UNUSED_PARAMETER") view: View) {
finish() finish()
} }
private fun validatePairingPassword() {
val pairingPasswordText = findViewById<EditText>(R.id.newPairingPasswordText).text.toString()
val pairingPasswordConfirmation = findViewById<EditText>(R.id.pairingPasswordConfirmation).text.toString()
val button = findViewById<Button>(R.id.okButton)
button.isEnabled = (pairingPasswordText == pairingPasswordConfirmation) && pairingPasswordText.isNotEmpty()
}
} }

View File

@ -23,6 +23,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginEnd="88dp" android:layout_marginEnd="88dp"
android:enabled="false"
android:onClick="ok" android:onClick="ok"
android:text="@android:string/ok" android:text="@android:string/ok"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
@ -32,12 +33,12 @@
android:id="@+id/cancelButton" android:id="@+id/cancelButton"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="68dp" android:layout_marginStart="64dp"
android:layout_marginTop="76dp" android:layout_marginTop="88dp"
android:onClick="cancel" android:onClick="cancel"
android:text="@android:string/cancel" android:text="@android:string/cancel"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/newPairingPasswordText" /> app:layout_constraintTop_toBottomOf="@+id/pairingPasswordConfirmation" />
<EditText <EditText
android:id="@+id/newPairingPasswordText" android:id="@+id/newPairingPasswordText"
@ -50,4 +51,17 @@
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/newPairingPasswordPrompt" app:layout_constraintTop_toBottomOf="@+id/newPairingPasswordPrompt"
tools:text="password" /> tools:text="password" />
<EditText
android:id="@+id/pairingPasswordConfirmation"
android:layout_width="328dp"
android:layout_height="46dp"
android:layout_marginTop="68dp"
android:ems="10"
android:inputType="textPassword"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.493"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/newPairingPasswordText"
tools:text="password" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -22,6 +22,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginEnd="88dp" android:layout_marginEnd="88dp"
android:enabled="false"
android:onClick="ok" android:onClick="ok"
android:text="@android:string/ok" android:text="@android:string/ok"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
@ -31,12 +32,12 @@
android:id="@+id/cancelButton" android:id="@+id/cancelButton"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="68dp" android:layout_marginTop="68dp"
android:layout_marginTop="76dp"
android:onClick="cancel" android:onClick="cancel"
android:text="@android:string/cancel" android:text="@android:string/cancel"
app:layout_constraintEnd_toStartOf="@+id/okButton"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/newPINText" /> app:layout_constraintTop_toBottomOf="@+id/pinConfirmation" />
<EditText <EditText
android:id="@+id/newPINText" android:id="@+id/newPINText"
@ -49,4 +50,16 @@
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/newPinPrompt" app:layout_constraintTop_toBottomOf="@+id/newPinPrompt"
tools:text="123456" /> tools:text="123456" />
<EditText
android:id="@+id/pinConfirmation"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="64dp"
android:ems="10"
android:inputType="numberPassword"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/newPINText"
tools:text="123456" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -22,6 +22,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginEnd="88dp" android:layout_marginEnd="88dp"
android:enabled="false"
android:onClick="ok" android:onClick="ok"
android:text="@android:string/ok" android:text="@android:string/ok"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
@ -31,12 +32,13 @@
android:id="@+id/cancelButton" android:id="@+id/cancelButton"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="68dp" android:layout_marginTop="84dp"
android:layout_marginTop="76dp"
android:onClick="cancel" android:onClick="cancel"
android:text="@android:string/cancel" android:text="@android:string/cancel"
app:layout_constraintEnd_toStartOf="@+id/okButton"
app:layout_constraintHorizontal_bias="0.557"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/newPUKText" /> app:layout_constraintTop_toBottomOf="@+id/pukConfirmation" />
<EditText <EditText
android:id="@+id/newPUKText" android:id="@+id/newPUKText"
@ -48,5 +50,18 @@
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/newPukPrompt" app:layout_constraintTop_toBottomOf="@+id/newPukPrompt"
tools:text="123456" /> tools:text="123456123456" />
<EditText
android:id="@+id/pukConfirmation"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="60dp"
android:ems="10"
android:inputType="numberPassword"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.502"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/newPUKText"
tools:text="123456123456" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -10,7 +10,7 @@ buildscript {
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:4.0.2' classpath 'com.android.tools.build:gradle:4.1.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files // in the individual module build.gradle files