From d4379a47791ea0002eda9821f35c632f1e224962 Mon Sep 17 00:00:00 2001 From: Harsh Shandilya Date: Thu, 16 Jul 2020 12:18:38 +0530 Subject: Remove manual key selection and start actually using `.gpg-id` (#916) Co-authored-by: Aditya Wasan Co-authored-by: Fabian Henneke --- app/src/main/AndroidManifest.xml | 5 - .../main/java/com/zeapo/pwdstore/PasswordStore.kt | 22 ---- .../main/java/com/zeapo/pwdstore/UserPreference.kt | 37 ------- .../autofill/oreo/ui/AutofillDecryptActivity.kt | 2 +- .../com/zeapo/pwdstore/crypto/BasePgpActivity.kt | 31 ++---- .../com/zeapo/pwdstore/crypto/DecryptActivity.kt | 9 +- .../com/zeapo/pwdstore/crypto/GetKeyIdsActivity.kt | 90 ----------------- .../pwdstore/crypto/PasswordCreationActivity.kt | 111 +++++++++++++++++++-- .../java/com/zeapo/pwdstore/utils/Extensions.kt | 2 + app/src/main/res/values-ar/strings.xml | 6 -- app/src/main/res/values-cs/strings.xml | 9 -- app/src/main/res/values-de/strings.xml | 8 -- app/src/main/res/values-es/strings.xml | 12 --- app/src/main/res/values-fr/strings.xml | 12 --- app/src/main/res/values-ja/strings.xml | 6 -- app/src/main/res/values-ru/strings.xml | 13 --- app/src/main/res/values-zh-rCN/strings.xml | 6 -- app/src/main/res/values-zh-rTW/strings.xml | 6 -- app/src/main/res/values/strings.xml | 20 +--- app/src/main/res/xml/preference.xml | 9 -- 20 files changed, 114 insertions(+), 302 deletions(-) delete mode 100644 app/src/main/java/com/zeapo/pwdstore/crypto/GetKeyIdsActivity.kt (limited to 'app') diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 5fcbe706..1fea64ba 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -83,11 +83,6 @@ android:parentActivityName=".PasswordStore" android:windowSoftInputMode="adjustResize" /> - - - val intent = Intent(activity, UserPreference::class.java) - repositoryInitAction.launch(intent) - } - .setNegativeButton(resources.getString(R.string.dialog_negative), null) - .show() - } createRepository() } @@ -580,17 +569,6 @@ class PasswordStore : AppCompatActivity(R.layout.activity_pwdstore) { .show() return false } - if (settings.getStringSet(PreferenceKeys.OPENPGP_KEY_IDS_SET, HashSet()).isNullOrEmpty()) { - MaterialAlertDialogBuilder(this) - .setTitle(resources.getString(R.string.no_key_selected_dialog_title)) - .setMessage(resources.getString(R.string.no_key_selected_dialog_text)) - .setPositiveButton(resources.getString(R.string.dialog_ok)) { _, _ -> - val intent = Intent(activity, UserPreference::class.java) - startActivity(intent) - } - .show() - return false - } return true } diff --git a/app/src/main/java/com/zeapo/pwdstore/UserPreference.kt b/app/src/main/java/com/zeapo/pwdstore/UserPreference.kt index f713ad26..98873fad 100644 --- a/app/src/main/java/com/zeapo/pwdstore/UserPreference.kt +++ b/app/src/main/java/com/zeapo/pwdstore/UserPreference.kt @@ -39,12 +39,10 @@ import com.github.ajalt.timberkt.Timber.tag import com.github.ajalt.timberkt.d import com.github.ajalt.timberkt.w import com.google.android.material.dialog.MaterialAlertDialogBuilder -import com.google.android.material.snackbar.Snackbar import com.zeapo.pwdstore.autofill.AutofillPreferenceActivity import com.zeapo.pwdstore.autofill.oreo.BrowserAutofillSupportLevel import com.zeapo.pwdstore.autofill.oreo.getInstalledBrowsersWithAutofillSupportLevel import com.zeapo.pwdstore.crypto.BasePgpActivity -import com.zeapo.pwdstore.crypto.GetKeyIdsActivity import com.zeapo.pwdstore.git.GitConfigActivity import com.zeapo.pwdstore.git.GitServerConfigActivity import com.zeapo.pwdstore.pwgenxkpwd.XkpwdDictionary @@ -57,8 +55,6 @@ import com.zeapo.pwdstore.utils.autofillManager import com.zeapo.pwdstore.utils.getEncryptedPrefs import java.io.File import java.io.IOException -import java.util.HashSet -import me.msfjarvis.openpgpktx.util.OpenPgpUtils typealias ClickListener = Preference.OnPreferenceClickListener typealias ChangeListener = Preference.OnPreferenceChangeListener @@ -106,9 +102,6 @@ class UserPreference : AppCompatActivity() { } } - // Crypto preferences - val keyPreference = findPreference(PreferenceKeys.OPENPGP_KEY_ID_PREF) - // General preferences val showTimePreference = findPreference(PreferenceKeys.GENERAL_SHOW_TIME) val clearClipboard20xPreference = findPreference(PreferenceKeys.CLEAR_CLIPBOARD_20X) @@ -155,24 +148,6 @@ class UserPreference : AppCompatActivity() { appVersionPreference?.summary = "Version: ${BuildConfig.VERSION_NAME}" - keyPreference?.let { pref -> - updateKeyIDsSummary(pref) - pref.onPreferenceClickListener = ClickListener { - val providerPackageName = requireNotNull(sharedPreferences.getString(PreferenceKeys.OPENPGP_PROVIDER_LIST, "")) - if (providerPackageName.isEmpty()) { - Snackbar.make(requireView(), resources.getString(R.string.provider_toast_text), Snackbar.LENGTH_LONG).show() - false - } else { - val intent = Intent(callingActivity, GetKeyIdsActivity::class.java) - val keySelectResult = registerForActivityResult(StartActivityForResult()) { - updateKeyIDsSummary(pref) - } - keySelectResult.launch(intent) - true - } - } - } - sshKeyPreference?.onPreferenceClickListener = ClickListener { callingActivity.getSshKey() true @@ -369,18 +344,6 @@ class UserPreference : AppCompatActivity() { } } - private fun updateKeyIDsSummary(preference: Preference) { - val selectedKeys = (sharedPreferences.getStringSet(PreferenceKeys.OPENPGP_KEY_IDS_SET, null) - ?: HashSet()).toTypedArray() - preference.summary = if (selectedKeys.isEmpty()) { - resources.getString(R.string.pref_no_key_selected) - } else { - selectedKeys.joinToString(separator = ";") { s -> - OpenPgpUtils.convertKeyIdToHex(s.toLong()) - } - } - } - private fun updateXkPasswdPrefsVisibility(newValue: Any?, prefIsCustomDict: CheckBoxPreference?, prefCustomDictPicker: Preference?) { when (newValue as String) { BasePgpActivity.KEY_PWGEN_TYPE_CLASSIC -> { diff --git a/app/src/main/java/com/zeapo/pwdstore/autofill/oreo/ui/AutofillDecryptActivity.kt b/app/src/main/java/com/zeapo/pwdstore/autofill/oreo/ui/AutofillDecryptActivity.kt index eabd24c0..3656bc7e 100644 --- a/app/src/main/java/com/zeapo/pwdstore/autofill/oreo/ui/AutofillDecryptActivity.kt +++ b/app/src/main/java/com/zeapo/pwdstore/autofill/oreo/ui/AutofillDecryptActivity.kt @@ -24,6 +24,7 @@ import com.zeapo.pwdstore.autofill.oreo.Credentials import com.zeapo.pwdstore.autofill.oreo.DirectoryStructure import com.zeapo.pwdstore.autofill.oreo.FillableForm import com.zeapo.pwdstore.model.PasswordEntry +import com.zeapo.pwdstore.utils.OPENPGP_PROVIDER import java.io.ByteArrayOutputStream import java.io.File import java.io.FileNotFoundException @@ -53,7 +54,6 @@ class AutofillDecryptActivity : AppCompatActivity(), CoroutineScope { private const val EXTRA_FILE_PATH = "com.zeapo.pwdstore.autofill.oreo.EXTRA_FILE_PATH" private const val EXTRA_SEARCH_ACTION = "com.zeapo.pwdstore.autofill.oreo.EXTRA_SEARCH_ACTION" - private const val OPENPGP_PROVIDER = "org.sufficientlysecure.keychain" private var decryptFileRequestCode = 1 diff --git a/app/src/main/java/com/zeapo/pwdstore/crypto/BasePgpActivity.kt b/app/src/main/java/com/zeapo/pwdstore/crypto/BasePgpActivity.kt index 39164e8f..ec8e7f9b 100644 --- a/app/src/main/java/com/zeapo/pwdstore/crypto/BasePgpActivity.kt +++ b/app/src/main/java/com/zeapo/pwdstore/crypto/BasePgpActivity.kt @@ -14,8 +14,6 @@ import android.os.Build import android.os.Bundle import android.text.format.DateUtils import android.view.WindowManager -import android.widget.Toast -import androidx.activity.result.ActivityResultLauncher import androidx.annotation.CallSuper import androidx.annotation.StringRes import androidx.appcompat.app.AppCompatActivity @@ -26,7 +24,7 @@ import com.github.ajalt.timberkt.i import com.google.android.material.snackbar.Snackbar import com.zeapo.pwdstore.ClipboardService import com.zeapo.pwdstore.R -import com.zeapo.pwdstore.UserPreference +import com.zeapo.pwdstore.utils.OPENPGP_PROVIDER import com.zeapo.pwdstore.utils.PreferenceKeys import com.zeapo.pwdstore.utils.clipboard import com.zeapo.pwdstore.utils.snackbar @@ -73,12 +71,6 @@ open class BasePgpActivity : AppCompatActivity(), OpenPgpServiceConnection.OnBou */ val settings: SharedPreferences by lazy { PreferenceManager.getDefaultSharedPreferences(this) } - /** - * Read-only field for getting the list of OpenPGP key IDs that we have access to. - */ - var keyIDs = emptySet() - private set - /** * Handle to the [OpenPgpApi] instance that is used by subclasses to interface with OpenKeychain. */ @@ -87,15 +79,13 @@ open class BasePgpActivity : AppCompatActivity(), OpenPgpServiceConnection.OnBou /** * [onCreate] sets the window up with the right flags to prevent auth leaks through screenshots - * or recent apps screen and fills in [keyIDs] from [settings] + * or recent apps screen. */ @CallSuper override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) window.setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE) tag(TAG) - - keyIDs = settings.getStringSet(PreferenceKeys.OPENPGP_KEY_IDS_SET, null) ?: emptySet() } /** @@ -128,20 +118,11 @@ open class BasePgpActivity : AppCompatActivity(), OpenPgpServiceConnection.OnBou } /** - * Method for subclasses to initiate binding with [OpenPgpServiceConnection]. The design choices - * here are a bit dubious at first glance. We require passing a [ActivityResultLauncher] because - * it lets us react to having a OpenPgp provider selected without relying on the now deprecated - * [startActivityForResult]. + * Method for subclasses to initiate binding with [OpenPgpServiceConnection]. */ - fun bindToOpenKeychain(onBoundListener: OpenPgpServiceConnection.OnBound, activityResult: ActivityResultLauncher) { - val providerPackageName = settings.getString(PreferenceKeys.OPENPGP_PROVIDER_LIST, "") - if (providerPackageName.isNullOrEmpty()) { - Toast.makeText(this, resources.getString(R.string.provider_toast_text), Toast.LENGTH_LONG).show() - activityResult.launch(Intent(this, UserPreference::class.java)) - } else { - serviceConnection = OpenPgpServiceConnection(this, providerPackageName, onBoundListener) - serviceConnection?.bindToService() - } + fun bindToOpenKeychain(onBoundListener: OpenPgpServiceConnection.OnBound) { + serviceConnection = OpenPgpServiceConnection(this, OPENPGP_PROVIDER, onBoundListener) + serviceConnection?.bindToService() } /** diff --git a/app/src/main/java/com/zeapo/pwdstore/crypto/DecryptActivity.kt b/app/src/main/java/com/zeapo/pwdstore/crypto/DecryptActivity.kt index 3425a346..cc70dcc1 100644 --- a/app/src/main/java/com/zeapo/pwdstore/crypto/DecryptActivity.kt +++ b/app/src/main/java/com/zeapo/pwdstore/crypto/DecryptActivity.kt @@ -13,7 +13,6 @@ import android.view.Menu import android.view.MenuItem import android.view.View import androidx.activity.result.IntentSenderRequest -import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult import androidx.activity.result.contract.ActivityResultContracts.StartIntentSenderForResult import androidx.lifecycle.lifecycleScope import com.github.ajalt.timberkt.e @@ -57,13 +56,9 @@ class DecryptActivity : BasePgpActivity(), OpenPgpServiceConnection.OnBound { } } - private val openKeychainResult = registerForActivityResult(StartActivityForResult()) { - decryptAndVerify() - } - override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - bindToOpenKeychain(this, openKeychainResult) + bindToOpenKeychain(this) title = name with(binding) { setContentView(root) @@ -134,7 +129,7 @@ class DecryptActivity : BasePgpActivity(), OpenPgpServiceConnection.OnBound { @OptIn(ExperimentalTime::class) private fun decryptAndVerify(receivedIntent: Intent? = null) { if (api == null) { - bindToOpenKeychain(this, openKeychainResult) + bindToOpenKeychain(this) return } val data = receivedIntent ?: Intent() diff --git a/app/src/main/java/com/zeapo/pwdstore/crypto/GetKeyIdsActivity.kt b/app/src/main/java/com/zeapo/pwdstore/crypto/GetKeyIdsActivity.kt deleted file mode 100644 index 97f6bab2..00000000 --- a/app/src/main/java/com/zeapo/pwdstore/crypto/GetKeyIdsActivity.kt +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright © 2014-2020 The Android Password Store Authors. All Rights Reserved. - * SPDX-License-Identifier: GPL-3.0-only - */ - -package com.zeapo.pwdstore.crypto - -import android.content.Intent -import android.os.Bundle -import androidx.activity.result.IntentSenderRequest -import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult -import androidx.activity.result.contract.ActivityResultContracts.StartIntentSenderForResult -import androidx.core.content.edit -import androidx.lifecycle.lifecycleScope -import com.github.ajalt.timberkt.Timber -import com.github.ajalt.timberkt.e -import com.zeapo.pwdstore.utils.PreferenceKeys -import com.zeapo.pwdstore.utils.snackbar -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import me.msfjarvis.openpgpktx.util.OpenPgpApi -import org.openintents.openpgp.IOpenPgpService2 - -class GetKeyIdsActivity : BasePgpActivity() { - - private val getKeyIds = registerForActivityResult(StartActivityForResult()) { getKeyIds() } - - private val userInteractionRequiredResult = registerForActivityResult(StartIntentSenderForResult()) { result -> - if (result.data == null) { - setResult(RESULT_CANCELED, null) - finish() - return@registerForActivityResult - } - - when (result.resultCode) { - RESULT_OK -> getKeyIds(result.data) - RESULT_CANCELED -> { - setResult(RESULT_CANCELED, result.data) - finish() - } - } - } - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - bindToOpenKeychain(this, getKeyIds) - } - - override fun onBound(service: IOpenPgpService2) { - super.onBound(service) - getKeyIds() - } - - override fun onError(e: Exception) { - e(e) - } - - /** - * Get the Key ids from OpenKeychain - */ - private fun getKeyIds(receivedIntent: Intent? = null) { - val data = receivedIntent ?: Intent() - data.action = OpenPgpApi.ACTION_GET_KEY_IDS - lifecycleScope.launch(Dispatchers.IO) { - api?.executeApiAsync(data, null, null) { result -> - when (result?.getIntExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR)) { - OpenPgpApi.RESULT_CODE_SUCCESS -> { - try { - val ids = result.getLongArrayExtra(OpenPgpApi.RESULT_KEY_IDS) - ?: LongArray(0) - val keys = ids.map { it.toString() }.toSet() - // use Long - settings.edit { putStringSet(PreferenceKeys.OPENPGP_KEY_IDS_SET, keys) } - snackbar(message = "PGP keys selected") - setResult(RESULT_OK) - finish() - } catch (e: Exception) { - Timber.e(e) { "An Exception occurred" } - } - } - OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED -> { - val sender = getUserInteractionRequestIntent(result) - userInteractionRequiredResult.launch(IntentSenderRequest.Builder(sender).build()) - } - OpenPgpApi.RESULT_CODE_ERROR -> handleError(result) - } - } - } - } -} diff --git a/app/src/main/java/com/zeapo/pwdstore/crypto/PasswordCreationActivity.kt b/app/src/main/java/com/zeapo/pwdstore/crypto/PasswordCreationActivity.kt index 286f2951..6cacf4b9 100644 --- a/app/src/main/java/com/zeapo/pwdstore/crypto/PasswordCreationActivity.kt +++ b/app/src/main/java/com/zeapo/pwdstore/crypto/PasswordCreationActivity.kt @@ -11,7 +11,10 @@ import android.text.InputType import android.view.Menu import android.view.MenuItem import android.view.View +import androidx.activity.result.ActivityResultLauncher +import androidx.activity.result.IntentSenderRequest import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult +import androidx.activity.result.contract.ActivityResultContracts.StartIntentSenderForResult import androidx.core.view.isVisible import androidx.core.widget.doOnTextChanged import androidx.lifecycle.lifecycleScope @@ -40,6 +43,7 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import me.msfjarvis.openpgpktx.util.OpenPgpApi import me.msfjarvis.openpgpktx.util.OpenPgpServiceConnection +import me.msfjarvis.openpgpktx.util.OpenPgpUtils import org.eclipse.jgit.api.Git class PasswordCreationActivity : BasePgpActivity(), OpenPgpServiceConnection.OnBound { @@ -51,13 +55,45 @@ class PasswordCreationActivity : BasePgpActivity(), OpenPgpServiceConnection.OnB private val suggestedExtra by lazy { intent.getStringExtra(EXTRA_EXTRA_CONTENT) } private val shouldGeneratePassword by lazy { intent.getBooleanExtra(EXTRA_GENERATE_PASSWORD, false) } private val editing by lazy { intent.getBooleanExtra(EXTRA_EDITING, false) } - private val doNothing = registerForActivityResult(StartActivityForResult()) {} - private var oldCategory: String? = null private val oldFileName by lazy { intent.getStringExtra(EXTRA_FILE_NAME) } + private var oldCategory: String? = null + private var copy: Boolean = false + + private val userInteractionRequiredResult: ActivityResultLauncher = registerForActivityResult(StartIntentSenderForResult()) { result -> + if (result.data == null) { + setResult(RESULT_CANCELED, null) + finish() + return@registerForActivityResult + } + + when (result.resultCode) { + RESULT_OK -> encrypt(result.data) + RESULT_CANCELED -> { + setResult(RESULT_CANCELED, result.data) + finish() + } + } + } + + private fun File.findTillRoot(fileName: String, rootPath: File): File? { + val gpgFile = File(this, fileName) + if (gpgFile.exists()) return gpgFile + + if (this.absolutePath == rootPath.absolutePath) { + return null + } + + val parent = parentFile + return if (parent != null && parent.exists()) { + parent.findTillRoot(fileName, rootPath) + } else { + null + } + } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - bindToOpenKeychain(this, doNothing) + bindToOpenKeychain(this) title = if (editing) getString(R.string.edit_password) else @@ -172,8 +208,14 @@ class PasswordCreationActivity : BasePgpActivity(), OpenPgpServiceConnection.OnB setResult(RESULT_CANCELED) finish() } - R.id.save_password -> encrypt() - R.id.save_and_copy_password -> encrypt(copy = true) + R.id.save_password -> { + copy = false + encrypt() + } + R.id.save_and_copy_password -> { + copy = true + encrypt() + } else -> return super.onOptionsItemSelected(item) } return true @@ -202,10 +244,42 @@ class PasswordCreationActivity : BasePgpActivity(), OpenPgpServiceConnection.OnB otpImportButton.isVisible = !entry.hasTotp() } + private sealed class GpgIdentifier { + data class KeyId(val id: Long) : GpgIdentifier() + data class UserId(val email: String) : GpgIdentifier() + } + + @OptIn(ExperimentalUnsignedTypes::class) + private fun parseGpgIdentifier(identifier: String) : GpgIdentifier? { + // Match long key IDs: + // FF22334455667788 or 0xFF22334455667788 + val maybeLongKeyId = identifier.removePrefix("0x").takeIf { + it.matches("[a-fA-F0-9]{16}".toRegex()) + } + if (maybeLongKeyId != null) { + val keyId = maybeLongKeyId.toULong() + return GpgIdentifier.KeyId(maybeLongKeyId.toLong()) + } + + // Match fingerprints: + // FF223344556677889900112233445566778899 or 0xFF223344556677889900112233445566778899 + val maybeFingerprint = identifier.removePrefix("0x").takeIf { + it.matches("[a-fA-F0-9]{40}".toRegex()) + } + if (maybeFingerprint != null) { + // Truncating to the long key ID is not a security issue since OpenKeychain only accepts + // non-ambiguous key IDs. + val keyId = maybeFingerprint.takeLast(16).toULong(16) + return GpgIdentifier.KeyId(keyId.toLong()) + } + + return OpenPgpUtils.splitUserId(identifier).email?.let { GpgIdentifier.UserId(it) } + } + /** * Encrypts the password and the extra content */ - private fun encrypt(copy: Boolean = false) = with(binding) { + private fun encrypt(receivedIntent: Intent? = null) = with(binding) { val editName = filename.text.toString().trim() val editPass = password.text.toString() val editExtra = extraContent.text.toString() @@ -227,12 +301,25 @@ class PasswordCreationActivity : BasePgpActivity(), OpenPgpServiceConnection.OnB copyPasswordToClipboard(editPass) } - val data = Intent() + val data = receivedIntent ?: Intent() data.action = OpenPgpApi.ACTION_ENCRYPT - // EXTRA_KEY_IDS requires long[] - val longKeys = keyIDs.map { it.toLong() } - data.putExtra(OpenPgpApi.EXTRA_KEY_IDS, longKeys.toLongArray()) + // pass enters the key ID into `.gpg-id`. + val repoRoot = PasswordRepository.getRepositoryDirectory(applicationContext) + val gpgIdentifierFile = File(repoRoot, directory.text.toString()).findTillRoot(".gpg-id", repoRoot) + if (gpgIdentifierFile == null) { + snackbar(message = resources.getString(R.string.failed_to_find_key_id)) + return@with + } + val gpgIdentifierFileContent = gpgIdentifierFile.useLines { it.firstOrNull() } ?: "" + when (val identifier = parseGpgIdentifier(gpgIdentifierFileContent)) { + is GpgIdentifier.KeyId -> data.putExtra(OpenPgpApi.EXTRA_KEY_IDS, arrayOf(identifier.id)) + is GpgIdentifier.UserId -> data.putExtra(OpenPgpApi.EXTRA_USER_IDS, arrayOf(identifier.email)) + null -> { + snackbar(message = resources.getString(R.string.invalid_gpg_id)) + return@with + } + } data.putExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true) val content = "$editPass\n$editExtra" @@ -347,6 +434,10 @@ class PasswordCreationActivity : BasePgpActivity(), OpenPgpServiceConnection.OnB e(e) { "An Exception occurred" } } } + OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED -> { + val sender = getUserInteractionRequestIntent(result) + userInteractionRequiredResult.launch(IntentSenderRequest.Builder(sender).build()) + } OpenPgpApi.RESULT_CODE_ERROR -> handleError(result) } } diff --git a/app/src/main/java/com/zeapo/pwdstore/utils/Extensions.kt b/app/src/main/java/com/zeapo/pwdstore/utils/Extensions.kt index 19b651b7..b274b47d 100644 --- a/app/src/main/java/com/zeapo/pwdstore/utils/Extensions.kt +++ b/app/src/main/java/com/zeapo/pwdstore/utils/Extensions.kt @@ -29,6 +29,8 @@ import com.zeapo.pwdstore.utils.PasswordRepository.Companion.getRepositoryDirect import java.io.File import org.eclipse.jgit.api.Git +const val OPENPGP_PROVIDER = "org.sufficientlysecure.keychain" + fun Int.clearFlag(flag: Int): Int { return this and flag.inv() } diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index 8b87028d..300e03e3 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -14,7 +14,6 @@ تعديل حذف - لم يتم إختيار مزود الأوبن بي جي بي بعد ! الرجاء إدخال إسم ملف جاري تنفيذ الأمر ... @@ -54,7 +53,6 @@ إسم المستخدم : تعديل كلمة السر نسخ كلمة السر - نسخ إسم المستخدم شارك كنص مجرد آخِر تعديل %s @@ -64,8 +62,6 @@ إظهار مفتاح الـ SSH العمومي الذي تم توليده حذف المستودع تنحية المستودع - التشفير - إختيار مزود الأوبن بي جي بي OpenPGP الإعدادات العامة نسخ كلمة السر تلقائيًا تم استيراد مفتاح الـ SSH @@ -108,8 +104,6 @@ إظهار المزيد من المحتوى توليد تحديث القائمة - إظهار كلمة السر - إظهار المزيد من المحتوى أيقونة التطبيق أيقونة المجلد diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index e6c69ab3..fdb0aca3 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -19,8 +19,6 @@ Změnit Použít Tento adresář je již vybrán - OpenPGP klíč nebyl zvolen - Přesměrujeme Vás na nastavení. Prosím, zvolte si Váš OpenPGP klíč. Heslo již existuje! Toto přepíše%1$s %2$s . @@ -29,7 +27,6 @@ Upravit heslo %1$s s použítím Android Password Store. Odstranit %1$s ze store. - Nebyl vybrán poskytovatel OpenPGP! Heslo zkopírováno do schránky, máte %d sekund na jeho zkopírování. Heslo zkopírováno do schránky Zadejte prosím jméno souboru @@ -89,7 +86,6 @@ Jméno: Editovat heslo Kopírovat heslo - Kopírovat jméno Sdílet v nešifrované podobě Naposled změněno %s @@ -99,9 +95,6 @@ Zobrazit vygenerovaný veřejný SSH klíč Smazat repozitář Vyčistit repozitář - Šifrování - Vybrat poskytovatele OpenPGP - Vybrat ID OpenPGP klíče Všeobecné Automaticky kopírovat heslo Automatické kopírování hesla do schránky po úspěšném dešifrování. @@ -159,7 +152,6 @@ Obnovit seznam Nebyl vybrát externí repozitář Odeslat heslo jako plaintext za použití… - Pokaż hasło Automaticky vyplňuje pole hesel v aplikacích. Funguje pouze pro verzi Androidu 4.3 a vyšší. Není závislé na schránce pro Android verze 5.0 a vyšší. Použít výchozí nastavení @@ -168,5 +160,4 @@ Spárovat s Nikdy nepárovat Smazat - Failed to get last changed date diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 257d45ca..7f1aae8b 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -17,7 +17,6 @@ Bearbeiten Löschen - Kein OpenPGP-Provider ausgewählt! Passwort ist in der Zwischenablage, du hast %d Sekunden, um es einzufügen. Bitte setze einen Pfad Du kannst kein leeres Passwort setzen oder leere Extra-Angaben @@ -66,7 +65,6 @@ Benutzername: Passwort bearbeiten Passwort kopieren - Benutzername kopieren Als Klartext teilen Zuletzt geändert %s @@ -77,9 +75,6 @@ Zeige erstellten öffentlichen SSH-Key Repository löschen Repository löschen - Kryptografie - Wähle OpenPGP-Provider - Wähle OpenPGP-Key ID Allgemein Kopiere Passwort automatisch Kopiert das Passwort in die Zwischenablage, wenn der Eintrag entschlüsselt wurde. @@ -139,8 +134,6 @@ Aktualisieren Kein externes Repository ausgewählt Passwort senden als Nur-Text mit behilfe von… - Password wiedergeben - Zeige weiteren Inhalt App Icon Verzeichnis Icon @@ -160,5 +153,4 @@ Bildschirmfoto Accessibility Services Bildschirmfoto des Schalters in Accessibility Services Bildschirmfoto von Autofill in Aktion - Das Abrufen des letzten Änderungsdatums ist fehlgeschlagen. diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 4eecf660..a1fd8725 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -16,8 +16,6 @@ Mover Editar Eliminar - No se ha seleccionado una llave OpenPGP - Serás redirigido a los ajustes. Por favor selecciona tu llave OpenPGP. "Contraseña para %1$s agregada usando Android Password Store." "%1$s editada usando Android Password Store." @@ -25,7 +23,6 @@ "Renombrado %1$s a %2$s usando Android Password Store.." - ¡No se ha seleccionado ningún proveedor OpenGPG! Contraseña copiada al portapapeles, tienes %d segundos para pegarla. Contraseña copiada al portapapeles Por favor selecciona un nombre de archivo @@ -82,7 +79,6 @@ Nombre de usuario: Editar contraseña Copiar contraseña - Copiar nombre de usuario Compartir como texto plano Última modificación %s @@ -94,10 +90,6 @@ Ver llave pública SSH generada Eliminar repositorio Limpiar repositorio - Cifrado - Selecciona un proveedor OpenPGP - Selecciona la llave OpenPGP - Ninguna llave seleccionada General Copiar contraseña automáticamente Automáticamente copia la contraseña al portapapeles si el descifrado fue exitoso. @@ -167,8 +159,6 @@ Actualizar lista Ningún repositorio externo seleccionado Enviar contraseña en texto plano usando… - Mostrar contraseña - Mostrar contenido extra Ícono de app Ícono de directorio @@ -187,7 +177,6 @@ Selecciona un campo editable para pegar el nombre de usuario.\nNombre de usuario disponible por %d segundos. Imposible abrir la llave privada SSH. Por favor verifica que el archivo exista Nueva contraseña - Editando Pantalla de Servicios de Accesibilidad Pantalla de activación en Servicios de Accesibilidad Pantalla de servicio de autollenado en acción @@ -198,5 +187,4 @@ Hackish tools Abortar rebase Hash del commit - Error al obtener la fecha de último cambio diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index c4c75b55..f9ac6d51 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -20,8 +20,6 @@ Utiliser Répertoire déjà sélectionné Voulez-vous utiliser \"%1$s\"? - Clé OpenPGP non sélectionnée - Nous allons vous rediriger vers les paramètres. Veuillez sélectionner votre clé OpenPGP. Le mot de passe existe! Cela écrasera %1$s avec %2$s. @@ -32,7 +30,6 @@ Renommer %1$sà %2$s. - Aucun prestataire OpenPGP sélectionné ! Mot de passe copié dans le presse papier, vous avez %d secondes pour coller celui-ci. Renseignez un nom de fichier Vous ne pouvez pas utiliser un mot de passe vide ou des données supplémentaires vide @@ -89,7 +86,6 @@ Nom d\'utilisateur Éditer le mot de passe Copier le mot de passe - Copier le nom d\'utilisateur Partager en clair Dernière modification le %s @@ -101,10 +97,6 @@ Voir la clef publique SSH générée Supprimer le dépôt Effacer le dépôt - Chiffrement - Sélection du prestataire OpenPGP - Sélection de votre identifiant OpenPGP - Aucune clé sélectionnée Général Copie automatique du mot de passe Copie automatiquement le mot de passe vers le presse-papier si le déchiffrement a réussi. @@ -167,8 +159,6 @@ Rafraichir la liste Pas de dépôt externe séléctionné Envoyer le mot de passe en clair via… - Montrer le mot de passe - Afficher le contenu supplémentaire Icône de l\'application Icône du dossier @@ -186,7 +176,6 @@ Coller le nom d\'utilisateur?\n\n%s Impossible d\'ouvrir la clef ssh, merci de vérifier que le ficher existe Nouveau mot de passe - Montage Capture des services d\'accessibilité Capture de bascule dans les services d\'accessibilité Capture du service de remplissage automatique en action @@ -197,5 +186,4 @@ Se rappeler de la phrase secrète dans la configuration de l\'application (peu sûr) Outils de hack Commettre la clé - Failed to get last changed date diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 02dd3219..d65de8a5 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -18,7 +18,6 @@ 追加 %1$s ストアから。 編集 %1$s ストアから。 - OpenPGP プロバイダが選択されていません! パスワードをクリップボードにコピーしました %d 秒以内に貼り付けしてください。 ファイル名を入力してください 空のパスワードを使用したり、追加のコンテンツを空にすることはできません @@ -64,9 +63,6 @@ 生成した公開 SSH 鍵を表示 リポジトリを削除 リポジトリをクリア - 暗号化 - OpenPGP プロバイダーを選択 - OpenPGP 鍵 ID を選択 全般 自動的にパスワードをコピー 復号化が成功した後、自動的にパスワードをクリップボードにコピーします。 @@ -120,7 +116,6 @@ リストを更新 外部リポジトリが選択されていません パスワードをプレーンテキストとして送信… - パスワードを表示 アプリのパスワードフィールドを自動入力します。 Android バージョン 4.3 以降でのみ動作します。 Android 5.0 以降のクリップボードには依存しません。 デフォルト設定を使用する @@ -129,5 +124,4 @@ 一致 一致しない 削除 - 最終変更日の取得に失敗しました diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index ff36585b..3b41758f 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -20,8 +20,6 @@ Использовать Директория уже выбрана Вы хотите использовать \"%1$s\"? - Ключ OpenPGP не выбран - Мы перенаправим вас в настройки. Пожалуйста, выберите ваш OpenGPG ключ. Пароль уже существует! Это перезапишет %1$sна%2$s @@ -32,7 +30,6 @@ Переименовать %1$sв%2$s. - Не выбран провайдер OpenPGP! Пароль скопирован в буфер обмена, у вас есть %d секунд чтобы вставить его. Пароль скопирован в буфер обмена Пожалуйста, укажите имя файла @@ -94,7 +91,6 @@ Имя пользователя: Редактировать пароль Скопировать пароль - Скопировать имя пользователя Поделиться в открытом виде Последние изменение %s @@ -106,10 +102,6 @@ Просмотреть публичный SSH ключ Удалить репозиторий Очистить репозиторий - Шифрование - Выберите провайдера OpenPGP - Выберите ключ OpenPGP - Ключи не выбраны Общие Автоматически копировать пароль Автоматически копировать пароль в буфер обмена после успешного расшифрования @@ -199,9 +191,6 @@ Обновить список Внешний репозиторий не выбран Поделиться паролем в открытом виде с помощью - Показать пароль - Показать дополнительную информацию - Скрыть расширенный контекст Иконка приложения Иконка папки @@ -244,7 +233,6 @@ Выберите поле ввода для вставки имени пользователя.\nИмя пользователя можно вставить в течение %d секунд. Невозможно открыть приватный ключ ssh, пожалуйста проверьте, что файл существует Новый пароль - Редактирование Снимок экрана сервисов доступности Снимок экрана переключателя в сервисах доступности Снимок экрана сервиса автозаполнения в действии @@ -258,7 +246,6 @@ Прервать перебазирование и записать изменения в новую ветку Полный сброс до состояния удаленной ветки Хэш-сумма изменений - Failed to get last changed date Ошибка при подключении к сервису OpenKeychain SSH API Не найдено SSH API провайдеров. OpenKeychain установлен? Ожидаемое намерение SSH API не удалось diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 34ef46a1..8a57de7b 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -18,7 +18,6 @@ 使用Android Password Store来添加 %1$s 使用Android Password Store来修改 %1$s - 未选择提供OpenPGP的应用 密码已复制到剪贴板, 你有 %d 秒的时间将其粘贴到其他地方. 请提供一个文件名 无法使用空白密码或者空白的额外内容 @@ -64,9 +63,6 @@ 查看生成的 SSH 公钥 删除 Repo 清空 Repo - 加密 - 选择 OpenPGP 应用 - 选择 OpenPGP Key Id 通用 自动复制密码 解密成功后自动将密码复制到剪贴板 @@ -117,7 +113,6 @@ 刷新列表 未选择外部 Repo 将密码以纯文本发送… - 显示密码 在app中自动输入密码. 此功能只在 Andorid 4.3 及以上版本中可用. 在 Andorid 5.0 及以上版本中不依赖剪贴板 使用默认设置 @@ -126,5 +121,4 @@ 匹配 从不匹配 删除 - 获取上次修改日期失败 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index b38380b4..6b120faf 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -15,7 +15,6 @@ 在嘗試新增密碼或任何同步操作之前請在下方 clone 或新增一個新的 Repo 刪除 - 未選擇提供 OpenPGP 的 app 密碼已複製到剪貼簿, 你有 %d 秒的時間將其貼上到其他地方. 請填寫文件名稱 不能使用空白密碼或者空白的備註 @@ -61,9 +60,6 @@ 顯示生成的 SSH 公鑰 刪除 Repo 清空 Repo - 加密 - 選擇 OpenPGP app - 選擇 OpenPGP Key Id 一般 自動複製密碼 解密成功後自動將密碼複製到剪貼簿 @@ -114,7 +110,6 @@ 重新整理 未選擇外部 Repo 將密碼以純文字傳送… - 顯示密碼 在app中自動填入密碼. 此功能只能在 Andorid 4.3 及以上版本中使用. 在 Andorid 5.0 及以上版本中不需要剪貼簿 使用預設值 @@ -123,5 +118,4 @@ 自動填入 手動 刪除 - Failed to get last changed date diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index a616896f..0bf7f413 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -23,7 +23,6 @@ Please clone or create a new repository below before trying to add a password or running any synchronization operation. - A valid PGP key must be selected in Settings before initializing the repository Are you sure you want to delete the password? Are you sure you want to delete %d passwords? @@ -35,8 +34,6 @@ Use Directory already selected Do you want to use \"%1$s\"? - OpenPGP key not selected - We will redirect you to settings. Please select your OpenPGP Key. Password already exists! This will overwrite %1$s with %2$s. Error while moving passwords @@ -50,7 +47,6 @@ Move multiple passwords to %1$s. - No OpenPGP provider selected! Password copied to clipboard, you have %d seconds to paste it somewhere. Password copied to clipboard Copied to clipboard @@ -117,10 +113,8 @@ Username: Edit password Copy password - Copy username Share as plaintext Last changed %s - View OTP Repository @@ -131,10 +125,6 @@ View generated public SSH key Delete repository Clear repository - Crypto - Select OpenPGP provider - Select OpenPGP key ID - No key selected General Passwords Password copy timeout @@ -237,9 +227,6 @@ Refresh list No external repository selected Send password as plaintext using… - Show password - Show extra content - Hide extra content App icon Folder icon @@ -291,7 +278,6 @@ Select an editable field to paste the username.\nUsername is available for %d seconds. Unable to open the ssh private key, please check that the file exists New password - Editing Screenshot of accessibility services Screenshot of toggle in accessibility services Screenshot of autofill service in action @@ -307,7 +293,6 @@ Abort rebase and push new branch Hard reset to remote branch Commit hash - Failed to get last changed date Failed to connect to OpenKeychain SSH API service. No SSH API provider found. Is OpenKeychain installed? SSH API pending intent failed @@ -349,15 +334,12 @@ SSH key Password OpenKeychain - None Successfully saved configuration Configuration error: %s empty hostname please verify your settings and try again port must be numeric path must be absolute (start with \'/\') when using a custom port - Unable to open the ssh-key - Please check that it was imported. Wrong passphrase Wrong password Create new folder @@ -390,6 +372,8 @@ Failed to import TOTP configuration Improve reliability in Chrome Exporting passwords… + Failed to locate .gpg-id, is your store set up correctly? + Found .gpg-id, but it did not contain a key ID, fingerprint or user ID File name must not contain \'/\', set directory above Directory diff --git a/app/src/main/res/xml/preference.xml b/app/src/main/res/xml/preference.xml index 3c39bfad..318b8431 100644 --- a/app/src/main/res/xml/preference.xml +++ b/app/src/main/res/xml/preference.xml @@ -78,15 +78,6 @@ app:title="@string/pref_select_external_repository" /> - - - - -