diff options
-rw-r--r-- | app/src/main/java/com/zeapo/pwdstore/autofill/AutofillService.kt | 6 | ||||
-rw-r--r-- | app/src/main/java/com/zeapo/pwdstore/crypto/PgpActivity.kt | 331 | ||||
-rw-r--r-- | dependencies.gradle | 2 |
3 files changed, 174 insertions, 165 deletions
diff --git a/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillService.kt b/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillService.kt index 1461746d..3086e297 100644 --- a/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillService.kt +++ b/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillService.kt @@ -567,12 +567,12 @@ class AutofillService : AccessibilityService() { } private inner class OnBoundListener : OpenPgpServiceConnection.OnBound { - override fun onBound(service: IOpenPgpService2?) { + override fun onBound(service: IOpenPgpService2) { decryptAndVerify() } - override fun onError(e: Exception?) { - e?.printStackTrace() + override fun onError(e: Exception) { + e.printStackTrace() } } diff --git a/app/src/main/java/com/zeapo/pwdstore/crypto/PgpActivity.kt b/app/src/main/java/com/zeapo/pwdstore/crypto/PgpActivity.kt index 92c78d35..b0fc8684 100644 --- a/app/src/main/java/com/zeapo/pwdstore/crypto/PgpActivity.kt +++ b/app/src/main/java/com/zeapo/pwdstore/crypto/PgpActivity.kt @@ -51,6 +51,9 @@ import kotlinx.android.synthetic.main.encrypt_layout.crypto_password_category import kotlinx.android.synthetic.main.encrypt_layout.crypto_password_edit import kotlinx.android.synthetic.main.encrypt_layout.crypto_password_file_edit import kotlinx.android.synthetic.main.encrypt_layout.generate_password +import kotlinx.coroutines.Dispatchers.IO +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch import me.msfjarvis.openpgpktx.OpenPgpError import me.msfjarvis.openpgpktx.util.OpenPgpApi import me.msfjarvis.openpgpktx.util.OpenPgpApi.Companion.ACTION_DECRYPT_VERIFY @@ -243,128 +246,129 @@ class PgpActivity : AppCompatActivity(), OpenPgpServiceConnection.OnBound { val iStream = FileUtils.openInputStream(File(fullPath)) val oStream = ByteArrayOutputStream() - api?.executeApiAsync(data, iStream, oStream, object : OpenPgpApi.IOpenPgpCallback { - override fun onReturn(result: Intent?) { - when (result?.getIntExtra(RESULT_CODE, RESULT_CODE_ERROR)) { - RESULT_CODE_SUCCESS -> { - try { - val showPassword = settings.getBoolean("show_password", true) - val showExtraContent = settings.getBoolean("show_extra_content", true) + GlobalScope.launch(IO) { + api?.executeApiAsync(data, iStream, oStream, object : OpenPgpApi.IOpenPgpCallback { + override fun onReturn(result: Intent?) { + when (result?.getIntExtra(RESULT_CODE, RESULT_CODE_ERROR)) { + RESULT_CODE_SUCCESS -> { + try { + val showPassword = settings.getBoolean("show_password", true) + val showExtraContent = settings.getBoolean("show_extra_content", true) - crypto_container_decrypt.visibility = View.VISIBLE + crypto_container_decrypt.visibility = View.VISIBLE - val monoTypeface = Typeface.createFromAsset(assets, "fonts/sourcecodepro.ttf") - val entry = PasswordEntry(oStream) + val monoTypeface = Typeface.createFromAsset(assets, "fonts/sourcecodepro.ttf") + val entry = PasswordEntry(oStream) - passwordEntry = entry + passwordEntry = entry - if (intent.getStringExtra("OPERATION") == "EDIT") { - editPassword() - return - } + if (intent.getStringExtra("OPERATION") == "EDIT") { + editPassword() + return + } - if (entry.password.isEmpty()) { - crypto_password_show.visibility = View.GONE - crypto_password_show_label.visibility = View.GONE - } else { - crypto_password_show.visibility = View.VISIBLE - crypto_password_show_label.visibility = View.VISIBLE + if (entry.password.isEmpty()) { + crypto_password_show.visibility = View.GONE + crypto_password_show_label.visibility = View.GONE + } else { + crypto_password_show.visibility = View.VISIBLE + crypto_password_show_label.visibility = View.VISIBLE + crypto_password_show.typeface = monoTypeface + crypto_password_show.text = entry.password + } crypto_password_show.typeface = monoTypeface crypto_password_show.text = entry.password - } - crypto_password_show.typeface = monoTypeface - crypto_password_show.text = entry.password - - crypto_password_toggle_show.visibility = if (showPassword) View.GONE else View.VISIBLE - crypto_password_show.transformationMethod = if (showPassword) { - null - } else { - HoldToShowPasswordTransformation( + + crypto_password_toggle_show.visibility = if (showPassword) View.GONE else View.VISIBLE + crypto_password_show.transformationMethod = if (showPassword) { + null + } else { + HoldToShowPasswordTransformation( crypto_password_toggle_show, Runnable { crypto_password_show.text = entry.password } - ) - } - - if (entry.hasExtraContent()) { - crypto_extra_show.typeface = monoTypeface - crypto_extra_show.text = entry.extraContent + ) + } - if (showExtraContent) { - crypto_extra_show_layout.visibility = View.VISIBLE - crypto_extra_toggle_show.visibility = View.GONE - crypto_extra_show.transformationMethod = null - } else { - crypto_extra_show_layout.visibility = View.GONE - crypto_extra_toggle_show.visibility = View.VISIBLE - crypto_extra_toggle_show.setOnCheckedChangeListener { _, _ -> - crypto_extra_show.text = entry.extraContent - } + if (entry.hasExtraContent()) { + crypto_extra_show.typeface = monoTypeface + crypto_extra_show.text = entry.extraContent + + if (showExtraContent) { + crypto_extra_show_layout.visibility = View.VISIBLE + crypto_extra_toggle_show.visibility = View.GONE + crypto_extra_show.transformationMethod = null + } else { + crypto_extra_show_layout.visibility = View.GONE + crypto_extra_toggle_show.visibility = View.VISIBLE + crypto_extra_toggle_show.setOnCheckedChangeListener { _, _ -> + crypto_extra_show.text = entry.extraContent + } - crypto_extra_show.transformationMethod = object : PasswordTransformationMethod() { - override fun getTransformation(source: CharSequence, view: View): CharSequence { - return if (crypto_extra_toggle_show.isChecked) source else super.getTransformation(source, view) + crypto_extra_show.transformationMethod = object : PasswordTransformationMethod() { + override fun getTransformation(source: CharSequence, view: View): CharSequence { + return if (crypto_extra_toggle_show.isChecked) source else super.getTransformation(source, view) + } } } - } - - if (entry.hasUsername()) { - crypto_username_show.visibility = View.VISIBLE - crypto_username_show_label.visibility = View.VISIBLE - crypto_copy_username.visibility = View.VISIBLE - crypto_copy_username.setOnClickListener { copyUsernameToClipBoard(entry.username!!) } - crypto_username_show.typeface = monoTypeface - crypto_username_show.text = entry.username - } else { - crypto_username_show.visibility = View.GONE - crypto_username_show_label.visibility = View.GONE - crypto_copy_username.visibility = View.GONE + if (entry.hasUsername()) { + crypto_username_show.visibility = View.VISIBLE + crypto_username_show_label.visibility = View.VISIBLE + crypto_copy_username.visibility = View.VISIBLE + + crypto_copy_username.setOnClickListener { copyUsernameToClipBoard(entry.username!!) } + crypto_username_show.typeface = monoTypeface + crypto_username_show.text = entry.username + } else { + crypto_username_show.visibility = View.GONE + crypto_username_show_label.visibility = View.GONE + crypto_copy_username.visibility = View.GONE + } } - } - if (entry.hasTotp() || entry.hasHotp()) { - crypto_extra_show_layout.visibility = View.VISIBLE - crypto_extra_show.typeface = monoTypeface - crypto_extra_show.text = entry.extraContent + if (entry.hasTotp() || entry.hasHotp()) { + crypto_extra_show_layout.visibility = View.VISIBLE + crypto_extra_show.typeface = monoTypeface + crypto_extra_show.text = entry.extraContent - crypto_otp_show.visibility = View.VISIBLE - crypto_otp_show_label.visibility = View.VISIBLE - crypto_copy_otp.visibility = View.VISIBLE + crypto_otp_show.visibility = View.VISIBLE + crypto_otp_show_label.visibility = View.VISIBLE + crypto_copy_otp.visibility = View.VISIBLE - if (entry.hasTotp()) { - crypto_copy_otp.setOnClickListener { - copyOtpToClipBoard( + if (entry.hasTotp()) { + crypto_copy_otp.setOnClickListener { + copyOtpToClipBoard( Otp.calculateCode( - entry.totpSecret, - Date().time / (1000 * entry.totpPeriod), - entry.totpAlgorithm, - entry.digits) - ) - } - crypto_otp_show.text = - Otp.calculateCode( entry.totpSecret, Date().time / (1000 * entry.totpPeriod), entry.totpAlgorithm, entry.digits) - } else { - // we only want to calculate and show HOTP if the user requests it - crypto_copy_otp.setOnClickListener { - if (settings.getBoolean("hotp_remember_check", false)) { - if (settings.getBoolean("hotp_remember_choice", false)) { - calculateAndCommitHotp(entry) + ) + } + crypto_otp_show.text = + Otp.calculateCode( + entry.totpSecret, + Date().time / (1000 * entry.totpPeriod), + entry.totpAlgorithm, + entry.digits) + } else { + // we only want to calculate and show HOTP if the user requests it + crypto_copy_otp.setOnClickListener { + if (settings.getBoolean("hotp_remember_check", false)) { + if (settings.getBoolean("hotp_remember_choice", false)) { + calculateAndCommitHotp(entry) + } else { + calculateHotp(entry) + } } else { - calculateHotp(entry) - } - } else { - // show a dialog asking permission to update the HOTP counter in the entry - val checkInflater = LayoutInflater.from(this@PgpActivity) - val checkLayout = checkInflater.inflate(R.layout.otp_confirm_layout, null) - val rememberCheck: CheckBox = + // show a dialog asking permission to update the HOTP counter in the entry + val checkInflater = LayoutInflater.from(this@PgpActivity) + val checkLayout = checkInflater.inflate(R.layout.otp_confirm_layout, null) + val rememberCheck: CheckBox = checkLayout.findViewById(R.id.hotp_remember_checkbox) - val dialogBuilder = MaterialAlertDialogBuilder(this@PgpActivity) - dialogBuilder.setView(checkLayout) - dialogBuilder.setMessage(R.string.dialog_update_body) + val dialogBuilder = MaterialAlertDialogBuilder(this@PgpActivity) + dialogBuilder.setView(checkLayout) + dialogBuilder.setMessage(R.string.dialog_update_body) .setCancelable(false) .setPositiveButton(R.string.dialog_update_positive) { _, _ -> run { @@ -386,32 +390,33 @@ class PgpActivity : AppCompatActivity(), OpenPgpServiceConnection.OnBound { editor.apply() } } - val updateDialog = dialogBuilder.create() - updateDialog.setTitle(R.string.dialog_update_title) - updateDialog.show() + val updateDialog = dialogBuilder.create() + updateDialog.setTitle(R.string.dialog_update_title) + updateDialog.show() + } } + crypto_otp_show.setText(R.string.hotp_pending) } - crypto_otp_show.setText(R.string.hotp_pending) + crypto_otp_show.typeface = monoTypeface + } else { + crypto_otp_show.visibility = View.GONE + crypto_otp_show_label.visibility = View.GONE + crypto_copy_otp.visibility = View.GONE } - crypto_otp_show.typeface = monoTypeface - } else { - crypto_otp_show.visibility = View.GONE - crypto_otp_show_label.visibility = View.GONE - crypto_copy_otp.visibility = View.GONE - } - if (settings.getBoolean("copy_on_decrypt", true)) { - copyPasswordToClipBoard() + if (settings.getBoolean("copy_on_decrypt", true)) { + copyPasswordToClipBoard() + } + } catch (e: Exception) { + Log.e(TAG, "An Exception occurred", e) } - } catch (e: Exception) { - Log.e(TAG, "An Exception occurred", e) } + RESULT_CODE_USER_INTERACTION_REQUIRED -> handleUserInteractionRequest(result, REQUEST_DECRYPT) + RESULT_CODE_ERROR -> handleError(result) } - RESULT_CODE_USER_INTERACTION_REQUIRED -> handleUserInteractionRequest(result, REQUEST_DECRYPT) - RESULT_CODE_ERROR -> handleError(result) } - } - }) + }) + } } /** @@ -453,36 +458,38 @@ class PgpActivity : AppCompatActivity(), OpenPgpServiceConnection.OnBound { val path = if (intent.getBooleanExtra("fromDecrypt", false)) fullPath else "$fullPath/$editName.gpg" - api?.executeApiAsync(data, iStream, oStream, object : OpenPgpApi.IOpenPgpCallback { - override fun onReturn(result: Intent?) { - when (result?.getIntExtra(RESULT_CODE, RESULT_CODE_ERROR)) { - RESULT_CODE_SUCCESS -> { - try { - // TODO This might fail, we should check that the write is successful - val outputStream = FileUtils.openOutputStream(File(path)) - outputStream.write(oStream.toByteArray()) - outputStream.close() - - val returnIntent = Intent() - returnIntent.putExtra("CREATED_FILE", path) - returnIntent.putExtra("NAME", editName) - returnIntent.putExtra("LONG_NAME", getLongName(fullPath, repoPath, editName!!)) - - // if coming from decrypt screen->edit button - if (intent.getBooleanExtra("fromDecrypt", false)) { - returnIntent.putExtra("OPERATION", "EDIT") - returnIntent.putExtra("needCommit", true) + GlobalScope.launch(IO) { + api?.executeApiAsync(data, iStream, oStream, object : OpenPgpApi.IOpenPgpCallback { + override fun onReturn(result: Intent?) { + when (result?.getIntExtra(RESULT_CODE, RESULT_CODE_ERROR)) { + RESULT_CODE_SUCCESS -> { + try { + // TODO This might fail, we should check that the write is successful + val outputStream = FileUtils.openOutputStream(File(path)) + outputStream.write(oStream.toByteArray()) + outputStream.close() + + val returnIntent = Intent() + returnIntent.putExtra("CREATED_FILE", path) + returnIntent.putExtra("NAME", editName) + returnIntent.putExtra("LONG_NAME", getLongName(fullPath, repoPath, editName!!)) + + // if coming from decrypt screen->edit button + if (intent.getBooleanExtra("fromDecrypt", false)) { + returnIntent.putExtra("OPERATION", "EDIT") + returnIntent.putExtra("needCommit", true) + } + setResult(RESULT_OK, returnIntent) + finish() + } catch (e: Exception) { + Log.e(TAG, "An Exception occurred", e) } - setResult(RESULT_OK, returnIntent) - finish() - } catch (e: Exception) { - Log.e(TAG, "An Exception occurred", e) } + RESULT_CODE_ERROR -> handleError(result) } - RESULT_CODE_ERROR -> handleError(result) } - } - }) + }) + } } /** @@ -559,39 +566,41 @@ class PgpActivity : AppCompatActivity(), OpenPgpServiceConnection.OnBound { private fun getKeyIds(receivedIntent: Intent? = null) { val data = receivedIntent ?: Intent() data.action = OpenPgpApi.ACTION_GET_KEY_IDS - api?.executeApiAsync(data, null, null, object : OpenPgpApi.IOpenPgpCallback { - override fun onReturn(result: Intent?) { - when (result?.getIntExtra(RESULT_CODE, RESULT_CODE_ERROR)) { - RESULT_CODE_SUCCESS -> { - try { - val ids = result.getLongArrayExtra(OpenPgpApi.RESULT_KEY_IDS) + GlobalScope.launch(IO) { + api?.executeApiAsync(data, null, null, object : OpenPgpApi.IOpenPgpCallback { + override fun onReturn(result: Intent?) { + when (result?.getIntExtra(RESULT_CODE, RESULT_CODE_ERROR)) { + RESULT_CODE_SUCCESS -> { + try { + val ids = result.getLongArrayExtra(OpenPgpApi.RESULT_KEY_IDS) ?: LongArray(0) - val keys = ids.map { it.toString() }.toSet() + val keys = ids.map { it.toString() }.toSet() - // use Long - settings.edit().putStringSet("openpgp_key_ids_set", keys).apply() + // use Long + settings.edit().putStringSet("openpgp_key_ids_set", keys).apply() - showSnackbar("PGP keys selected") + showSnackbar("PGP keys selected") - setResult(RESULT_OK) - finish() - } catch (e: Exception) { - Log.e(TAG, "An Exception occurred", e) + setResult(RESULT_OK) + finish() + } catch (e: Exception) { + Log.e(TAG, "An Exception occurred", e) + } } + RESULT_CODE_USER_INTERACTION_REQUIRED -> handleUserInteractionRequest(result, REQUEST_KEY_ID) + RESULT_CODE_ERROR -> handleError(result) } - RESULT_CODE_USER_INTERACTION_REQUIRED -> handleUserInteractionRequest(result, REQUEST_KEY_ID) - RESULT_CODE_ERROR -> handleError(result) } - } - }) + }) + } } - override fun onError(e: Exception?) {} + override fun onError(e: Exception) {} /** * The action to take when the PGP service is bound */ - override fun onBound(service: IOpenPgpService2?) { + override fun onBound(service: IOpenPgpService2) { initOpenPgpApi() when (operation) { "EDIT", "DECRYPT" -> decryptAndVerify() diff --git a/dependencies.gradle b/dependencies.gradle index 43f94708..ed9e13b4 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -40,7 +40,7 @@ ext.deps = [ commons_codec: 'commons-codec:commons-codec:1.13', jsch: 'com.jcraft:jsch:0.1.55', jgit: 'org.eclipse.jgit:org.eclipse.jgit:3.7.1.201504261725-r', - openpgp_ktx: 'com.github.android-password-store:openpgp-ktx:0.1.0', + openpgp_ktx: 'com.github.android-password-store:openpgp-ktx:1.0.0', ssh_auth: 'org.sufficientlysecure:sshauthentication-api:1.0' ], |