diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 0e28f85..f53c982 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -10,13 +10,14 @@ android:required="true" /> + diff --git a/app/src/main/java/im/status/keycard/connect/data/Constants.kt b/app/src/main/java/im/status/keycard/connect/data/Constants.kt index 2eb00f0..b056cae 100644 --- a/app/src/main/java/im/status/keycard/connect/data/Constants.kt +++ b/app/src/main/java/im/status/keycard/connect/data/Constants.kt @@ -11,6 +11,9 @@ const val INIT_ACTIVITY_PIN = "initPIN" const val INIT_ACTIVITY_PUK = "initPUK" const val INIT_ACTIVITY_PAIRING = "initPairing" +const val SIGN_TEXT_MESSAGE = "signMessage" + const val REQ_INTERACTIVE_SCRIPT = 0x01 +const val REQ_WALLETCONNECT = 0x02 const val CACHE_VALIDITY = 15 * 60 * 1000 \ No newline at end of file diff --git a/app/src/main/java/im/status/keycard/connect/ui/MainActivity.kt b/app/src/main/java/im/status/keycard/connect/ui/MainActivity.kt index afe3203..bceeeb3 100644 --- a/app/src/main/java/im/status/keycard/connect/ui/MainActivity.kt +++ b/app/src/main/java/im/status/keycard/connect/ui/MainActivity.kt @@ -17,6 +17,7 @@ import kotlin.reflect.KClass import androidx.core.app.ComponentActivity.ExtraData import androidx.core.content.ContextCompat.getSystemService import com.google.zxing.client.android.Intents +import im.status.keycard.connect.data.REQ_WALLETCONNECT class MainActivity : AppCompatActivity(), ScriptListener { private lateinit var viewSwitcher: ViewSwitcher @@ -49,6 +50,7 @@ class MainActivity : AppCompatActivity(), ScriptListener { when (requestCode) { REQ_INTERACTIVE_SCRIPT -> Registry.scriptExecutor.onUserInteractionReturned(resultCode, data) + REQ_WALLETCONNECT -> Registry.walletConnect.onUserInteractionReturned(resultCode, data) IntentIntegrator.REQUEST_CODE -> qrCodeScanned(resultCode, data) } } diff --git a/app/src/main/java/im/status/keycard/connect/ui/SignMessageActivity.kt b/app/src/main/java/im/status/keycard/connect/ui/SignMessageActivity.kt new file mode 100644 index 0000000..2ddf8c3 --- /dev/null +++ b/app/src/main/java/im/status/keycard/connect/ui/SignMessageActivity.kt @@ -0,0 +1,29 @@ +package im.status.keycard.connect.ui + +import android.app.Activity +import androidx.appcompat.app.AppCompatActivity +import android.os.Bundle +import android.view.View +import android.widget.TextView +import im.status.keycard.connect.R +import im.status.keycard.connect.data.SIGN_TEXT_MESSAGE + +class SignMessageActivity : AppCompatActivity() { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_sign_message) + val signText = findViewById(R.id.signText) + signText.text = intent.getStringExtra(SIGN_TEXT_MESSAGE) + } + + fun sign(@Suppress("UNUSED_PARAMETER") view: View) { + setResult(Activity.RESULT_OK) + finish() + } + + fun reject(@Suppress("UNUSED_PARAMETER") view: View) { + setResult(Activity.RESULT_CANCELED) + finish() + } +} diff --git a/app/src/main/java/im/status/keycard/connect/walletconnect/WalletConnect.kt b/app/src/main/java/im/status/keycard/connect/walletconnect/WalletConnect.kt index 5ddcff4..8f2cbdc 100644 --- a/app/src/main/java/im/status/keycard/connect/walletconnect/WalletConnect.kt +++ b/app/src/main/java/im/status/keycard/connect/walletconnect/WalletConnect.kt @@ -1,5 +1,7 @@ package im.status.keycard.connect.walletconnect +import android.app.Activity +import android.content.Intent import com.squareup.moshi.Moshi import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory import im.status.keycard.applet.BIP32KeyPair @@ -8,6 +10,9 @@ import im.status.keycard.connect.Registry import im.status.keycard.connect.card.ExportKeyCommand import im.status.keycard.connect.card.SignCommand import im.status.keycard.connect.card.scriptWithAuthentication +import im.status.keycard.connect.data.REQ_WALLETCONNECT +import im.status.keycard.connect.data.SIGN_TEXT_MESSAGE +import im.status.keycard.connect.ui.SignMessageActivity import kotlinx.coroutines.MainScope import kotlinx.coroutines.launch import okhttp3.OkHttpClient @@ -30,6 +35,7 @@ class WalletConnect : ExportKeyCommand.Listener, SignCommand.Listener { private val sessionStore = FileWCSessionStore(File(Registry.mainActivity.filesDir, "wcSessions.json").apply { createNewFile() }, moshi) private var session: WCSession? = null private var requestId: Long = 0 + private var action: (data: Intent?) -> Unit = this::nop private val sessionCB = object : Session.Callback { override fun onStatus(status: Session.Status) { @@ -69,6 +75,10 @@ class WalletConnect : ExportKeyCommand.Listener, SignCommand.Listener { session?.rejectRequest(call.id, 1L, "Not implemented yet") } + "eth_signTransaction" -> { + session?.rejectRequest(call.id, 1L, "Not implemented yet") + } + "eth_sendRawTransaction" -> { session?.rejectRequest(call.id, 1L, "Not implemented yet") } @@ -79,14 +89,36 @@ class WalletConnect : ExportKeyCommand.Listener, SignCommand.Listener { } private fun signText(id: Long, message: String) { - requestId = id val msg = Hex.decode(if (message.startsWith("0x", true)) message.drop(2) else message) - val keccak256 = Keccak.Digest256() - val hash = keccak256.digest(byteArrayOf(0x19) + "Ethereum Signed Message:\n${msg.size}".toByteArray() + msg) - Registry.scriptExecutor.runScript(scriptWithAuthentication().plus(SignCommand(Registry.walletConnect, hash))) + val text = String(msg) + + requestId = id + action = { + val keccak256 = Keccak.Digest256() + val hash = keccak256.digest(byteArrayOf(0x19) + "Ethereum Signed Message:\n${msg.size}".toByteArray() + msg) + Registry.scriptExecutor.runScript(scriptWithAuthentication().plus(SignCommand(Registry.walletConnect, hash))) + } + + val intent = Intent(Registry.mainActivity, SignMessageActivity::class.java).apply { + putExtra(SIGN_TEXT_MESSAGE, text) + } + + Registry.mainActivity.startActivityForResult(intent, REQ_WALLETCONNECT) } } + private fun nop(@Suppress("UNUSED_PARAMETER") data: Intent?) { } + + fun onUserInteractionReturned(resultCode: Int, data: Intent?) { + if (resultCode == Activity.RESULT_OK) { + action.invoke(data) + } else { + session?.rejectRequest(requestId, -1, "Rejected by user") + } + + action = this::nop + } + fun connect(uri: String) { scope.launch { session?.kill() @@ -114,7 +146,6 @@ class WalletConnect : ExportKeyCommand.Listener, SignCommand.Listener { override fun onResponse(signature: RecoverableSignature) { scope.launch { session?.approveRequest(requestId, "0x${toHexString(signature.r)}${toHexString(signature.s)}${toHexString(byteArrayOf(signature.recId.toByte()))}") - //session?.rejectRequest(requestId, -1, "Rejected by user") } } } \ No newline at end of file diff --git a/app/src/main/res/layout/activity_sign_message.xml b/app/src/main/res/layout/activity_sign_message.xml new file mode 100644 index 0000000..1749272 --- /dev/null +++ b/app/src/main/res/layout/activity_sign_message.xml @@ -0,0 +1,51 @@ + + + + + +