diff options
author | Harsh Shandilya <msfjarvis@gmail.com> | 2020-05-28 22:42:13 +0530 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-05-28 22:42:13 +0530 |
commit | e7463ec24c929860f0a7311b558f496919d54d20 (patch) | |
tree | eb460f7e49e1a71acaceaec305e511bb4c0a9d45 /app | |
parent | ffcbabc2f4ef9766271be5335cec1869fe634646 (diff) |
Remove HOTP/TOTP support (#806)
Diffstat (limited to 'app')
-rw-r--r-- | app/build.gradle | 3 | ||||
-rw-r--r-- | app/src/main/java/com/zeapo/pwdstore/PasswordEntry.kt | 104 | ||||
-rw-r--r-- | app/src/main/java/com/zeapo/pwdstore/PasswordStore.kt | 6 | ||||
-rw-r--r-- | app/src/main/java/com/zeapo/pwdstore/UserPreference.kt | 8 | ||||
-rw-r--r-- | app/src/main/java/com/zeapo/pwdstore/crypto/PgpActivity.kt | 158 | ||||
-rw-r--r-- | app/src/main/java/com/zeapo/pwdstore/utils/Otp.java | 63 | ||||
-rw-r--r-- | app/src/main/res/layout/decrypt_layout.xml | 43 | ||||
-rw-r--r-- | app/src/main/res/layout/otp_confirm_layout.xml | 23 | ||||
-rw-r--r-- | app/src/main/res/values-ar/strings.xml | 1 | ||||
-rw-r--r-- | app/src/main/res/values-cs/strings.xml | 2 | ||||
-rw-r--r-- | app/src/main/res/values-es/strings.xml | 10 | ||||
-rw-r--r-- | app/src/main/res/values-fr/strings.xml | 10 | ||||
-rw-r--r-- | app/src/main/res/values-ru/strings.xml | 10 | ||||
-rw-r--r-- | app/src/main/res/values/strings.xml | 11 | ||||
-rw-r--r-- | app/src/main/res/xml/preference.xml | 3 | ||||
-rw-r--r-- | app/src/test/java/com/zeapo/pwdstore/PasswordEntryTest.kt (renamed from app/src/androidTest/java/com/zeapo/pwdstore/PasswordEntryTest.kt) | 41 |
16 files changed, 12 insertions, 484 deletions
diff --git a/app/build.gradle b/app/build.gradle index 2e0671a7..2e203705 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -123,4 +123,7 @@ dependencies { androidTestImplementation deps.testing.androidx.junit androidTestImplementation deps.testing.androidx.espresso_core androidTestImplementation deps.testing.androidx.espresso_intents + + testImplementation deps.testing.junit + testImplementation deps.testing.kotlin_test_junit } diff --git a/app/src/main/java/com/zeapo/pwdstore/PasswordEntry.kt b/app/src/main/java/com/zeapo/pwdstore/PasswordEntry.kt index 32f671be..d9168d39 100644 --- a/app/src/main/java/com/zeapo/pwdstore/PasswordEntry.kt +++ b/app/src/main/java/com/zeapo/pwdstore/PasswordEntry.kt @@ -4,26 +4,18 @@ */ package com.zeapo.pwdstore -import android.net.Uri import java.io.ByteArrayOutputStream import java.io.UnsupportedEncodingException /** * A single entry in password store. */ -class PasswordEntry(private val content: String) { +class PasswordEntry(content: String) { val password: String val username: String? - val digits: String - val totpSecret: String? - val totpPeriod: Long - val totpAlgorithm: String - val hotpSecret: String? - val hotpCounter: Long? var extraContent: String private set - private var isIncremented = false @Throws(UnsupportedEncodingException::class) constructor(os: ByteArrayOutputStream) : this(os.toString("UTF-8")) @@ -31,12 +23,6 @@ class PasswordEntry(private val content: String) { init { val passContent = content.split("\n".toRegex(), 2).toTypedArray() password = passContent[0] - digits = findOtpDigits(content) - totpSecret = findTotpSecret(content) - totpPeriod = findTotpPeriod(content) - totpAlgorithm = findTotpAlgorithm(content) - hotpSecret = findHotpSecret(content) - hotpCounter = findHotpCounter(content) extraContent = findExtraContent(passContent) username = findUsername() } @@ -49,27 +35,6 @@ class PasswordEntry(private val content: String) { return username != null } - fun hasTotp(): Boolean { - return totpSecret != null - } - - fun hasHotp(): Boolean { - return hotpSecret != null && hotpCounter != null - } - - fun hotpIsIncremented(): Boolean { - return isIncremented - } - - fun incrementHotp() { - content.split("\n".toRegex()).forEach { line -> - if (line.startsWith("otpauth://hotp/")) { - extraContent = extraContent.replaceFirst("counter=[0-9]+".toRegex(), "counter=${hotpCounter!! + 1}") - isIncremented = true - } - } - } - val extraContentWithoutUsername by lazy { var usernameFound = false extraContent.splitToSequence("\n").filter { line -> @@ -93,73 +58,8 @@ class PasswordEntry(private val content: String) { return null } - private fun findTotpSecret(decryptedContent: String): String? { - decryptedContent.split("\n".toRegex()).forEach { line -> - if (line.startsWith("otpauth://totp/")) { - return Uri.parse(line).getQueryParameter("secret") - } - if (line.startsWith("totp:", ignoreCase = true)) { - return line.split(": *".toRegex(), 2).toTypedArray()[1] - } - } - return null - } - - private fun findOtpDigits(decryptedContent: String): String { - decryptedContent.split("\n".toRegex()).forEach { line -> - if ((line.startsWith("otpauth://totp/") || - line.startsWith("otpauth://hotp/")) && - Uri.parse(line).getQueryParameter("digits") != null) { - return Uri.parse(line).getQueryParameter("digits")!! - } - } - return "6" - } - - private fun findTotpPeriod(decryptedContent: String): Long { - decryptedContent.split("\n".toRegex()).forEach { line -> - if (line.startsWith("otpauth://totp/") && - Uri.parse(line).getQueryParameter("period") != null) { - return java.lang.Long.parseLong(Uri.parse(line).getQueryParameter("period")!!) - } - } - return 30 - } - - private fun findTotpAlgorithm(decryptedContent: String): String { - decryptedContent.split("\n".toRegex()).forEach { line -> - if (line.startsWith("otpauth://totp/") && - Uri.parse(line).getQueryParameter("algorithm") != null) { - return Uri.parse(line).getQueryParameter("algorithm")!! - } - } - return "sha1" - } - - private fun findHotpSecret(decryptedContent: String): String? { - decryptedContent.split("\n".toRegex()).forEach { line -> - if (line.startsWith("otpauth://hotp/")) { - return Uri.parse(line).getQueryParameter("secret") - } - } - return null - } - - private fun findHotpCounter(decryptedContent: String): Long? { - decryptedContent.split("\n".toRegex()).forEach { line -> - if (line.startsWith("otpauth://hotp/")) { - return java.lang.Long.parseLong(Uri.parse(line).getQueryParameter("counter")!!) - } - } - return null - } - private fun findExtraContent(passContent: Array<String>): String { - val extraContent = if (passContent.size > 1) passContent[1] else "" - // if there is a HOTP URI, we must return the extra content with the counter incremented - return if (hasHotp()) { - extraContent.replaceFirst("counter=[0-9]+".toRegex(), "counter=" + (hotpCounter!!).toString()) - } else extraContent + return if (passContent.size > 1) passContent[1] else "" } companion object { diff --git a/app/src/main/java/com/zeapo/pwdstore/PasswordStore.kt b/app/src/main/java/com/zeapo/pwdstore/PasswordStore.kt index 5857af74..45269145 100644 --- a/app/src/main/java/com/zeapo/pwdstore/PasswordStore.kt +++ b/app/src/main/java/com/zeapo/pwdstore/PasswordStore.kt @@ -636,16 +636,12 @@ class PasswordStore : AppCompatActivity() { when (requestCode) { // if we get here with a RESULT_OK then it's probably OK :) BaseGitActivity.REQUEST_CLONE -> settings.edit { putBoolean("repository_initialized", true) } - // if went from decrypt->edit and user saved changes or HOTP counter was - // incremented, we need to commitChange + // if went from decrypt->edit and user saved changes, we need to commitChange REQUEST_CODE_DECRYPT_AND_VERIFY -> { if (data != null && data.getBooleanExtra("needCommit", false)) { if (data.getStringExtra("OPERATION") == "EDIT") { commitChange(resources.getString(R.string.git_commit_edit_text, data.extras!!.getString("LONG_NAME"))) - } else { - commitChange(resources.getString(R.string.git_commit_increment_text, - data.extras!!.getString("LONG_NAME"))) } } refreshPasswordList() diff --git a/app/src/main/java/com/zeapo/pwdstore/UserPreference.kt b/app/src/main/java/com/zeapo/pwdstore/UserPreference.kt index 10665e38..41404716 100644 --- a/app/src/main/java/com/zeapo/pwdstore/UserPreference.kt +++ b/app/src/main/java/com/zeapo/pwdstore/UserPreference.kt @@ -91,7 +91,6 @@ class UserPreference : AppCompatActivity() { val sshKeyPreference = findPreference<Preference>("ssh_key") val sshKeygenPreference = findPreference<Preference>("ssh_keygen") clearSavedPassPreference = findPreference("clear_saved_pass") - val clearHotpIncrementPreference = findPreference<Preference>("hotp_remember_clear_choice") val viewSshKeyPreference = findPreference<Preference>("ssh_see_key") val deleteRepoPreference = findPreference<Preference>("git_delete_repo") val externalGitRepositoryPreference = findPreference<Preference>("git_external") @@ -138,7 +137,6 @@ class UserPreference : AppCompatActivity() { selectExternalGitRepositoryPreference?.summary = sharedPreferences.getString("git_external_repo", getString(R.string.no_repo_selected)) viewSshKeyPreference?.isVisible = sharedPreferences.getBoolean("use_generated_key", false) deleteRepoPreference?.isVisible = !sharedPreferences.getBoolean("git_external", false) - clearHotpIncrementPreference?.isVisible = sharedPreferences.getBoolean("hotp_remember_check", false) clearClipboard20xPreference?.isVisible = sharedPreferences.getString("general_show_time", "45")?.toInt() != 0 val selectedKeys = (sharedPreferences.getStringSet("openpgp_key_ids_set", null) ?: HashSet()).toTypedArray() @@ -197,12 +195,6 @@ class UserPreference : AppCompatActivity() { true } - clearHotpIncrementPreference?.onPreferenceClickListener = ClickListener { - sharedPreferences.edit { putBoolean("hotp_remember_check", false) } - it.isVisible = false - true - } - openkeystoreIdPreference?.onPreferenceClickListener = ClickListener { sharedPreferences.edit { putString("ssh_openkeystore_keyid", null) } it.isVisible = false 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 89399031..d9027230 100644 --- a/app/src/main/java/com/zeapo/pwdstore/crypto/PgpActivity.kt +++ b/app/src/main/java/com/zeapo/pwdstore/crypto/PgpActivity.kt @@ -21,14 +21,12 @@ import android.text.InputType import android.text.TextUtils import android.text.format.DateUtils import android.text.method.PasswordTransformationMethod -import android.view.LayoutInflater import android.view.Menu import android.view.MenuItem import android.view.MotionEvent import android.view.View import android.view.WindowManager import android.widget.Button -import android.widget.CheckBox import android.widget.TextView import androidx.appcompat.app.AppCompatActivity import androidx.constraintlayout.widget.ConstraintLayout @@ -41,7 +39,6 @@ import androidx.preference.PreferenceManager import com.github.ajalt.timberkt.Timber.e import com.github.ajalt.timberkt.Timber.i import com.github.ajalt.timberkt.Timber.tag -import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.snackbar.Snackbar import com.zeapo.pwdstore.ClipboardService import com.zeapo.pwdstore.PasswordEntry @@ -51,15 +48,11 @@ import com.zeapo.pwdstore.autofill.oreo.AutofillPreferences import com.zeapo.pwdstore.autofill.oreo.DirectoryStructure import com.zeapo.pwdstore.ui.dialogs.PasswordGeneratorDialogFragment import com.zeapo.pwdstore.ui.dialogs.XkPasswordGeneratorDialogFragment -import com.zeapo.pwdstore.utils.Otp import kotlinx.android.synthetic.main.decrypt_layout.crypto_container_decrypt -import kotlinx.android.synthetic.main.decrypt_layout.crypto_copy_otp import kotlinx.android.synthetic.main.decrypt_layout.crypto_copy_username import kotlinx.android.synthetic.main.decrypt_layout.crypto_extra_show import kotlinx.android.synthetic.main.decrypt_layout.crypto_extra_show_layout import kotlinx.android.synthetic.main.decrypt_layout.crypto_extra_toggle_show -import kotlinx.android.synthetic.main.decrypt_layout.crypto_otp_show -import kotlinx.android.synthetic.main.decrypt_layout.crypto_otp_show_label import kotlinx.android.synthetic.main.decrypt_layout.crypto_password_category_decrypt import kotlinx.android.synthetic.main.decrypt_layout.crypto_password_file import kotlinx.android.synthetic.main.decrypt_layout.crypto_password_last_changed @@ -93,7 +86,6 @@ import java.io.ByteArrayInputStream import java.io.ByteArrayOutputStream import java.io.File import java.nio.charset.Charset -import java.util.Date class PgpActivity : AppCompatActivity(), OpenPgpServiceConnection.OnBound { private val clipboard by lazy { getSystemService<ClipboardManager>() } @@ -284,7 +276,6 @@ class PgpActivity : AppCompatActivity(), OpenPgpServiceConnection.OnBound { } override fun onDestroy() { - checkAndIncrementHotp() super.onDestroy() mServiceConnection?.unbindFromService() } @@ -304,23 +295,12 @@ class PgpActivity : AppCompatActivity(), OpenPgpServiceConnection.OnBound { override fun onOptionsItemSelected(item: MenuItem): Boolean { when (item.itemId) { - android.R.id.home -> { - if (passwordEntry?.hotpIsIncremented() == false) { - setResult(RESULT_CANCELED) - } - finish() - } + R.id.crypto_cancel_add, android.R.id.home -> finish() R.id.copy_password -> copyPasswordToClipBoard() R.id.share_password_as_plaintext -> shareAsPlaintext() R.id.edit_password -> editPassword() R.id.crypto_confirm_add -> encrypt() R.id.crypto_confirm_add_and_copy -> encrypt(true) - R.id.crypto_cancel_add -> { - if (passwordEntry?.hotpIsIncremented() == false) { - setResult(RESULT_CANCELED) - } - finish() - } else -> return super.onOptionsItemSelected(item) } return true @@ -463,84 +443,6 @@ class PgpActivity : AppCompatActivity(), OpenPgpServiceConnection.OnBound { } } - 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 - - 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) - } 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 = - checkLayout.findViewById(R.id.hotp_remember_checkbox) - val dialogBuilder = MaterialAlertDialogBuilder(this@PgpActivity) - dialogBuilder.setView(checkLayout) - dialogBuilder.setMessage(R.string.dialog_update_body) - .setCancelable(false) - .setPositiveButton(R.string.dialog_update_positive) { _, _ -> - run { - calculateAndCommitHotp(entry) - if (rememberCheck.isChecked) { - settings.edit { - putBoolean("hotp_remember_check", true) - putBoolean("hotp_remember_choice", true) - } - } - } - } - .setNegativeButton(R.string.dialog_update_negative) { _, _ -> - run { - calculateHotp(entry) - settings.edit { - putBoolean("hotp_remember_check", true) - putBoolean("hotp_remember_choice", false) - } - } - } - val updateDialog = dialogBuilder.create() - updateDialog.setTitle(R.string.dialog_update_title) - updateDialog.show() - } - } - 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 - } - if (settings.getBoolean("copy_on_decrypt", true)) { copyPasswordToClipBoard() } @@ -559,12 +461,9 @@ class PgpActivity : AppCompatActivity(), OpenPgpServiceConnection.OnBound { * Encrypts the password and the extra content */ private fun encrypt(copy: Boolean = false) { - // if HOTP was incremented, we leave fields as is; they have already been set - if (intent.getStringExtra("OPERATION") != "INCREMENT") { - editName = crypto_password_file_edit.text.toString().trim() - editPass = crypto_password_edit.text.toString() - editExtra = crypto_extra_edit.text.toString() - } + editName = crypto_password_file_edit.text.toString().trim() + editPass = crypto_password_edit.text.toString() + editExtra = crypto_extra_edit.text.toString() if (editName?.isEmpty() == true) { showSnackbar(resources.getString(R.string.file_toast_text)) @@ -688,43 +587,6 @@ class PgpActivity : AppCompatActivity(), OpenPgpServiceConnection.OnBound { } /** - * Writes updated HOTP counter to edit fields and encrypts - */ - private fun checkAndIncrementHotp() { - // we do not want to increment the HOTP counter if the user has edited the entry or has not - // generated an HOTP code - if (intent.getStringExtra("OPERATION") != "EDIT" && passwordEntry?.hotpIsIncremented() == true) { - editName = name.trim() - editPass = passwordEntry?.password - editExtra = passwordEntry?.extraContent - - val data = Intent(this, PgpActivity::class.java) - data.putExtra("OPERATION", "INCREMENT") - data.putExtra("fromDecrypt", true) - intent = data - encrypt() - } - } - - private fun calculateHotp(entry: PasswordEntry) { - copyOtpToClipBoard(Otp.calculateCode(entry.hotpSecret, entry.hotpCounter!! + 1, "sha1", entry.digits)) - crypto_otp_show.text = Otp.calculateCode(entry.hotpSecret, entry.hotpCounter + 1, "sha1", entry.digits) - crypto_extra_show.text = entry.extraContent - } - - private fun calculateAndCommitHotp(entry: PasswordEntry) { - calculateHotp(entry) - entry.incrementHotp() - // we must set the result before encrypt() is called, since in - // some cases it is called during the finish() sequence - val returnIntent = Intent() - returnIntent.putExtra("NAME", name.trim()) - returnIntent.putExtra("OPERATION", "INCREMENT") - returnIntent.putExtra("needCommit", true) - setResult(RESULT_OK, returnIntent) - } - - /** * Get the Key ids from OpenKeychain */ private fun getKeyIds(receivedIntent: Intent? = null) { @@ -861,13 +723,6 @@ class PgpActivity : AppCompatActivity(), OpenPgpServiceConnection.OnBound { showSnackbar(resources.getString(R.string.clipboard_username_toast_text)) } - private fun copyOtpToClipBoard(code: String) { - val clipboard = clipboard ?: return - val clip = ClipData.newPlainText("pgp_handler_result_pm", code) - clipboard.setPrimaryClip(clip) - showSnackbar(resources.getString(R.string.clipboard_otp_toast_text)) - } - private fun shareAsPlaintext() { if (findViewById<View>(R.id.share_password_as_plaintext) == null) return @@ -957,13 +812,8 @@ class PgpActivity : AppCompatActivity(), OpenPgpServiceConnection.OnBound { fun doOnPostExecute() { if (skip) return - checkAndIncrementHotp() if (crypto_password_show != null) { - // clear password; if decrypt changed to encrypt layout via edit button, no need - if (passwordEntry?.hotpIsIncremented() == false) { - setResult(RESULT_CANCELED) - } passwordEntry = null crypto_password_show.text = "" crypto_extra_show.text = "" diff --git a/app/src/main/java/com/zeapo/pwdstore/utils/Otp.java b/app/src/main/java/com/zeapo/pwdstore/utils/Otp.java deleted file mode 100644 index 07f73423..00000000 --- a/app/src/main/java/com/zeapo/pwdstore/utils/Otp.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright © 2014-2020 The Android Password Store Authors. All Rights Reserved. - * SPDX-License-Identifier: GPL-3.0-only - */ -package com.zeapo.pwdstore.utils; - -import org.apache.commons.codec.binary.Base32; - -import java.math.BigInteger; -import java.nio.ByteBuffer; -import java.security.InvalidKeyException; -import java.security.NoSuchAlgorithmException; -import java.util.Arrays; - -import javax.crypto.Mac; -import javax.crypto.spec.SecretKeySpec; - -import timber.log.Timber; - -public class Otp { - - private static final Base32 BASE_32 = new Base32(); - - private Otp() { - } - - public static String calculateCode( - String secret, long counter, String algorithm, String digits) { - String[] steam = { - "2", "3", "4", "5", "6", "7", "8", "9", "B", "C", "D", "F", "G", "H", "J", "K", "M", - "N", "P", "Q", "R", "T", "V", "W", "X", "Y" - }; - String ALGORITHM = "Hmac" + algorithm.toUpperCase(); - SecretKeySpec signingKey = new SecretKeySpec(BASE_32.decode(secret), ALGORITHM); - - Mac mac; - try { - mac = Mac.getInstance(ALGORITHM); - mac.init(signingKey); - } catch (NoSuchAlgorithmException e) { - Timber.tag("TOTP").e(e, "%s unavailable - should never happen", ALGORITHM); - return null; - } catch (InvalidKeyException e) { - Timber.tag("TOTP").e(e, "Key is malformed"); - return null; - } - - byte[] digest = mac.doFinal(ByteBuffer.allocate(8).putLong(counter).array()); - int offset = digest[digest.length - 1] & 0xf; - byte[] code = Arrays.copyOfRange(digest, offset, offset + 4); - code[0] = (byte) (0x7f & code[0]); - String strCode = new BigInteger(code).toString(); - if (digits.equals("s")) { - StringBuilder output = new StringBuilder(); - int bigInt = new BigInteger(code).intValue(); - for (int i = 0; i != 5; i++) { - output.append(steam[bigInt % 26]); - bigInt /= 26; - } - return output.toString(); - } else return strCode.substring(strCode.length() - Integer.parseInt(digits)); - } -} diff --git a/app/src/main/res/layout/decrypt_layout.xml b/app/src/main/res/layout/decrypt_layout.xml index c9f3f922..932eefd6 100644 --- a/app/src/main/res/layout/decrypt_layout.xml +++ b/app/src/main/res/layout/decrypt_layout.xml @@ -160,56 +160,17 @@ app:layout_constraintTop_toBottomOf="@id/crypto_username_show_label" tools:visibility="visible" /> - <androidx.appcompat.widget.AppCompatImageView - android:id="@+id/crypto_copy_otp" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_below="@id/crypto_username_show" - android:layout_alignParentEnd="true" - android:background="?android:attr/windowBackground" - android:contentDescription="@string/copy_otp" - android:src="@drawable/ic_content_copy" - android:visibility="invisible" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintTop_toTopOf="@id/crypto_otp_show_label" - tools:visibility="visible" /> - - <androidx.appcompat.widget.AppCompatTextView - android:id="@+id/crypto_otp_show_label" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_below="@id/crypto_username_show" - android:layout_alignParentStart="true" - android:layout_toStartOf="@id/crypto_copy_otp" - android:text="@string/otp" - android:textColor="?android:attr/textColor" - android:textStyle="bold" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toBottomOf="@id/crypto_username_show" /> - - <androidx.appcompat.widget.AppCompatTextView - android:id="@+id/crypto_otp_show" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_below="@id/crypto_otp_show_label" - android:layout_alignParentStart="true" - android:layout_toStartOf="@id/crypto_copy_otp" - android:textColor="?android:attr/textColor" - android:textIsSelectable="true" - android:typeface="monospace" - app:layout_constraintTop_toBottomOf="@id/crypto_otp_show_label" /> - <androidx.appcompat.widget.AppCompatTextView android:id="@+id/crypto_extra_show_label" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_below="@id/crypto_otp_show" + android:layout_below="@id/crypto_username_show" android:layout_alignParentStart="true" android:text="@string/extra_content" android:textColor="?android:attr/textColor" android:textStyle="bold" app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toBottomOf="@id/crypto_otp_show" /> + app:layout_constraintTop_toBottomOf="@id/crypto_username_show" /> <androidx.appcompat.widget.AppCompatTextView android:id="@+id/crypto_extra_show" diff --git a/app/src/main/res/layout/otp_confirm_layout.xml b/app/src/main/res/layout/otp_confirm_layout.xml deleted file mode 100644 index 7db7b105..00000000 --- a/app/src/main/res/layout/otp_confirm_layout.xml +++ /dev/null @@ -1,23 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?><!-- - ~ Copyright © 2014-2020 The Android Password Store Authors. All Rights Reserved. - ~ SPDX-License-Identifier: GPL-3.0-only - --> - -<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:app="http://schemas.android.com/apk/res-auto" - android:layout_width="match_parent" - android:layout_height="match_parent"> - - <CheckBox - android:id="@+id/hotp_remember_checkbox" - android:layout_width="0dp" - android:layout_height="wrap_content" - android:layout_marginStart="16dp" - android:layout_marginTop="8dp" - android:layout_marginEnd="16dp" - android:text="@string/dialog_update_check" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toTopOf="parent" /> - -</androidx.constraintlayout.widget.ConstraintLayout> diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index 380d58b7..ecb03154 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -63,7 +63,6 @@ <string name="edit_password">تعديل كلمة السر</string> <string name="copy_password">نسخ كلمة السر</string> <string name="copy_username">نسخ إسم المستخدم</string> - <string name="copy_otp">نسخ رمز الـ OTP</string> <string name="share_as_plaintext">شارك كنص مجرد</string> <string name="last_changed">آخِر تعديل %s</string> <!-- Preferences --> diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index 5b75d8d5..420c0ce4 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -34,7 +34,6 @@ <string name="clipboard_password_toast_text">Heslo zkopírováno do schránky, máte %d sekund na jeho zkopírování.</string> <string name="clipboard_password_no_clear_toast_text">Heslo zkopírováno do schránky</string> <string name="clipboard_username_toast_text">Jméno zkopírováno do schránky</string> - <string name="clipboard_otp_toast_text">OTP kód zkopírován do schránky</string> <string name="file_toast_text">Zadejte prosím jméno souboru</string> <string name="path_toast_text">Prosím zadejte cestu k souboru</string> <string name="empty_toast_text">Nelze zadat prázdné heslo nebo další obsah</string> @@ -102,7 +101,6 @@ <string name="edit_password">Editovat heslo</string> <string name="copy_password">Kopírovat heslo</string> <string name="copy_username">Kopírovat jméno</string> - <string name="copy_otp">Kopírovat OTP kód</string> <string name="share_as_plaintext">Sdílet v nešifrované podobě</string> <string name="last_changed">Naposled změněno %s</string> <!-- Preferences --> diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 8922fbdf..975f088f 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -24,14 +24,12 @@ <string name="git_commit_edit_text">"%1$s editada usando Android Password Store."</string> <string name="git_commit_remove_text">"%1$s eliminada del almacén usando Android Password Store."</string> <string name="git_commit_move_text">"Renombrado %1$s a %2$s usando Android Password Store.."</string> - <string name="git_commit_increment_text">"Contador de HOTP incrementado para %1$s."</string> <!-- PGPHandler --> <string name="provider_toast_text">¡No se ha seleccionado ningún proveedor OpenGPG!</string> <string name="clipboard_password_toast_text">Contraseña copiada al portapapeles, tienes %d segundos para pegarla.</string> <string name="clipboard_password_no_clear_toast_text">Contraseña copiada al portapapeles</string> <string name="clipboard_username_toast_text">Nombre de usuario copiado al portapapeles</string> - <string name="clipboard_otp_toast_text">Código OTP copiado al portapapeles</string> <string name="file_toast_text">Por favor selecciona un nombre de archivo</string> <string name="empty_toast_text">No puedes dejar la contraseña y el contenido extra ambos vacíos</string> @@ -95,14 +93,8 @@ <string name="edit_password">Editar contraseña</string> <string name="copy_password">Copiar contraseña</string> <string name="copy_username">Copiar nombre de usuario</string> - <string name="copy_otp">Copiar código OTP</string> <string name="share_as_plaintext">Compartir como texto plano</string> <string name="last_changed">Última modificación %s</string> - <string name="dialog_update_title">Atención</string> - <string name="dialog_update_positive">Actualizar registro</string> - <string name="dialog_update_negative">Dejar sin cambios</string> - <string name="dialog_update_body">El contador HOTP será incrementado. Este cambio será confirmado. Si presionas "Dejar sin cambios", el código HOTP será mostrado, pero el contador no se cambiará.</string> - <string name="dialog_update_check">Recordar elección</string> <!-- Preferences --> <string name="pref_edit_server_info">Editar ajustes del servidor Git</string> @@ -216,12 +208,10 @@ <string name="git_push_nff_error">La subida fue rechazada por el servidor, Ejecuta \'Descargar desde servidor\' antes de subir o pulsa \'Sincronizar con servidor\' para realizar ambas acciones.</string> <string name="git_push_generic_error">El envío fue rechazado por el servidor, la razón:</string> <string name="jgit_error_push_dialog_text">Ocurrió un error durante el envío:</string> - <string name="hotp_remember_clear_choice">Limpiar preferencia para incremento HOTP</string> <string name="remember_the_passphrase">Recordar contraseñagit (inseguro)</string> <string name="hackish_tools">Hackish tools</string> <string name="abort_rebase">Abortar rebase</string> <string name="commit_hash">Hash del commit</string> <string name="crypto_extra_edit_hint">Username: Nombre de usuario\n… o algún contenido extra</string> <string name="get_last_changed_failed">Error al obtener la fecha de último cambio</string> - <string name="hotp_pending">Presiona copiar para calcular el HOTP</string> </resources> diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index ad5ad866..eb52acf9 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -31,13 +31,11 @@ <string name="git_commit_edit_text">Editer %1$s depuis le dépôt.</string> <string name="git_commit_remove_text">Retirer %1$s de la mémoire.</string> <string name="git_commit_move_text">Renommer %1$sà %2$s. </string> - <string name="git_commit_increment_text">Incrémenter le compteur HOTP pour %1$s.</string> <!-- PGPHandler --> <string name="provider_toast_text">Aucun prestataire OpenPGP sélectionné !</string> <string name="clipboard_password_toast_text">Mot de passe copié dans le presse papier, vous avez %d secondes pour coller celui-ci.</string> <string name="clipboard_username_toast_text">Nom d\'utilisateur copié</string> - <string name="clipboard_otp_toast_text">Code OTP copié dans le presse-papier</string> <string name="file_toast_text">Renseignez un nom de fichier</string> <string name="empty_toast_text">Vous ne pouvez pas utiliser un mot de passe vide ou des données supplémentaires vide</string> @@ -103,14 +101,8 @@ <string name="edit_password">Éditer le mot de passe</string> <string name="copy_password">Copier le mot de passe</string> <string name="copy_username">Copier le nom d\'utilisateur</string> - <string name="copy_otp">Copier le code OTP</string> <string name="share_as_plaintext">Partager en clair</string> <string name="last_changed">Dernière modification le %s</string> - <string name="dialog_update_title">Attention</string> - <string name="dialog_update_positive">Mettre à jour l\'entrée</string> - <string name="dialog_update_negative">Laisser inchangé</string> - <string name="dialog_update_body">Le compteur HOTP est sur le point d’être incrémenté. Ce changement sera engagé. Si vous appuyez sur \"Laisser inchangé\", le code HOTP sera affiché mais le compteur ne sera pas modifié</string> - <string name="dialog_update_check">Se souvenir de mon choix</string> <!-- Preferences --> <string name="pref_edit_server_info">Editer les paramètres du serveur Git</string> @@ -217,11 +209,9 @@ <string name="git_push_generic_error">Poussée rejetée par le dépôt distant, raison:</string> <string name="git_push_other_error">Pousser au dépôt distant sans avance rapide rejetée. Vérifiez la variable receive.denyNonFastForwards dans le fichier de configuration du répertoire de destination.</string> <string name="jgit_error_push_dialog_text">Une erreur s\'est produite lors de l\'opération de poussée:</string> - <string name="hotp_remember_clear_choice">Effacer les préférences enregistrées pour l’incrémentation HOTP</string> <string name="remember_the_passphrase">Se rappeler de la phrase secrète dans la configuration de l\'application (peu sûr)</string> <string name="hackish_tools">Outils de hack</string> <string name="commit_hash">Commettre la clé</string> <string name="crypto_extra_edit_hint">nom d\'utilisateur: quelque chose d\'autre contenu supplémentaire</string> <string name="get_last_changed_failed">Failed to get last changed date</string> - <string name="hotp_pending">Appuyez sur copie pour calculer le HOTP</string> </resources> diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index ca7ffaa0..d286bbb4 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -31,14 +31,12 @@ <string name="git_commit_edit_text">Отредактирован %1$s из хранилища.</string> <string name="git_commit_remove_text">Удалить %1$sиз хранилища.</string> <string name="git_commit_move_text">Переименовать %1$sв%2$s.</string> - <string name="git_commit_increment_text">Увеличить значение HOTP счетчика для %1$s</string> <!-- PGPHandler --> <string name="provider_toast_text">Не выбран провайдер OpenPGP!</string> <string name="clipboard_password_toast_text">Пароль скопирован в буфер обмена, у вас есть %d секунд чтобы вставить его.</string> <string name="clipboard_password_no_clear_toast_text">Пароль скопирован в буфер обмена</string> <string name="clipboard_username_toast_text">Имя пользователя скопировано в буфер обмена</string> - <string name="clipboard_otp_toast_text">OTP код скопирован в буфер обмена</string> <string name="file_toast_text">Пожалуйста, укажите имя файла</string> <string name="path_toast_text">Пожалуйста, задайте путь к файлу</string> <string name="empty_toast_text">Вы не можете использовать пустой пароль или пустое поле информации</string> @@ -108,14 +106,8 @@ <string name="edit_password">Редактировать пароль</string> <string name="copy_password">Скопировать пароль</string> <string name="copy_username">Скопировать имя пользователя</string> - <string name="copy_otp">Скопировать OTP код</string> <string name="share_as_plaintext">Поделиться в открытом виде</string> <string name="last_changed">Последние изменение %s</string> - <string name="dialog_update_title">Внимание</string> - <string name="dialog_update_positive">Обновить запись</string> - <string name="dialog_update_negative">Оставить без изменений</string> - <string name="dialog_update_body">HOTP счетчик будет увеличен. Это изменение будет сохранено. Если вы нажмете \"Оставить без изменений\", тогда HOTP код будет показан, но счетчик не изменится.</string> - <string name="dialog_update_check">Запомнить мой выбор</string> <!-- Preferences --> <string name="pref_edit_server_info">Изменить настройки сервера git</string> @@ -278,7 +270,6 @@ <string name="git_push_generic_error">Запись изменений была отклонена удаленным репозиторием, причина:</string> <string name="git_push_other_error">Удаленный репозиторий отклонил запись изменений без быстрой перемотки вперед. Проверьте переменную receive.denyNonFastForwards в файле конфигурации репозитория назначения.</string> <string name="jgit_error_push_dialog_text">В хоте операции записи изменений возникла ошибка:</string> - <string name="hotp_remember_clear_choice">Очистить сохраненные настройки для увеличения HOTP</string> <string name="remember_the_passphrase">Заполнить парольную фразу в конфигурации приложнеия (небезопасно)</string> <string name="hackish_tools">Костыльные инструменты</string> <string name="abort_rebase">Прервать перебазирование и записать изменения в новую ветку</string> @@ -286,7 +277,6 @@ <string name="commit_hash">Хэш-сумма изменений</string> <string name="crypto_extra_edit_hint">имя пользователя: какой-то другой дополнительный контент</string> <string name="get_last_changed_failed">Failed to get last changed date</string> - <string name="hotp_pending">Нажмите скопировать чтобы расчитать HOTP</string> <string name="openkeychain_ssh_api_connect_fail">Ошибка при подключении к сервису OpenKeychain SSH API</string> <string name="no_ssh_api_provider">Не найдено SSH API провайдеров. OpenKeychain установлен?</string> <string name="ssh_api_pending_intent_failed">Ожидаемое намерение SSH API не удалось</string> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 1b2f9c52..9b76e05f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -42,14 +42,12 @@ <string name="git_commit_edit_text">Edit password for %1$s using android password store.</string> <string name="git_commit_remove_text">Remove %1$s from store.</string> <string name="git_commit_move_text">Rename %1$s to %2$s.</string> - <string name="git_commit_increment_text">Increment HOTP counter for %1$s.</string> <!-- PGPHandler --> <string name="provider_toast_text">No OpenPGP provider selected!</string> <string name="clipboard_password_toast_text">Password copied to clipboard, you have %d seconds to paste it somewhere.</string> <string name="clipboard_password_no_clear_toast_text">Password copied to clipboard</string> <string name="clipboard_username_toast_text">Username copied to clipboard</string> - <string name="clipboard_otp_toast_text">OTP code copied to clipboard</string> <string name="file_toast_text">Please provide a file name</string> <string name="path_toast_text">Please provide a file path</string> <string name="empty_toast_text">You cannot use an empty password or empty extra content</string> @@ -121,18 +119,11 @@ <string name="password">Password:</string> <string name="extra_content">Extra content:</string> <string name="username">Username:</string> - <string name="otp" translatable="false">OTP:</string> <string name="edit_password">Edit password</string> <string name="copy_password">Copy password</string> <string name="copy_username">Copy username</string> - <string name="copy_otp">Copy OTP code</string> <string name="share_as_plaintext">Share as plaintext</string> <string name="last_changed">Last changed %s</string> - <string name="dialog_update_title">Attention</string> - <string name="dialog_update_positive">Update entry</string> - <string name="dialog_update_negative">Leave unchanged</string> - <string name="dialog_update_body">The HOTP counter is about to be incremented. This change will be committed. If you press "Leave unchanged", the HOTP code will be shown, but the counter will not be changed.</string> - <string name="dialog_update_check">Remember my choice</string> <!-- Preferences --> <string name="pref_repository_title">Repository</string> @@ -316,7 +307,6 @@ <string name="jgit_error_push_dialog_text">Error occurred during the push operation:</string> <string name="clear_saved_passphrase_ssh">Clear saved passphrase for local SSH key</string> <string name="clear_saved_passphrase_https">Clear saved HTTPS password</string> - <string name="hotp_remember_clear_choice">Clear saved preference for HOTP incrementing</string> <string name="remember_the_passphrase">Remember key passphrase</string> <string name="hackish_tools">Hackish tools</string> <string name="abort_rebase">Abort rebase and push new branch</string> @@ -324,7 +314,6 @@ <string name="commit_hash">Commit hash</string> <string name="crypto_extra_edit_hint">username: something other extra content</string> <string name="get_last_changed_failed">Failed to get last changed date</string> - <string name="hotp_pending">Tap copy to calculate HOTP</string> <string name="openkeychain_ssh_api_connect_fail">Failed to connect to OpenKeychain SSH API service.</string> <string name="no_ssh_api_provider">No SSH API provider found. Is OpenKeychain installed?</string> <string name="ssh_api_pending_intent_failed">SSH API pending intent failed</string> diff --git a/app/src/main/res/xml/preference.xml b/app/src/main/res/xml/preference.xml index c823bc6a..9e56ce8f 100644 --- a/app/src/main/res/xml/preference.xml +++ b/app/src/main/res/xml/preference.xml @@ -55,9 +55,6 @@ app:title="@string/pref_ssh_keygen_title" /> <Preference app:key="clear_saved_pass" /> <Preference - app:key="hotp_remember_clear_choice" - app:title="@string/hotp_remember_clear_choice" /> - <Preference app:key="ssh_openkeystore_clear_keyid" app:title="@string/ssh_openkeystore_clear_keyid" /> <Preference diff --git a/app/src/androidTest/java/com/zeapo/pwdstore/PasswordEntryTest.kt b/app/src/test/java/com/zeapo/pwdstore/PasswordEntryTest.kt index 5feb5aaf..2074f40b 100644 --- a/app/src/androidTest/java/com/zeapo/pwdstore/PasswordEntryTest.kt +++ b/app/src/test/java/com/zeapo/pwdstore/PasswordEntryTest.kt @@ -60,45 +60,4 @@ class PasswordEntryTest { assertFalse(PasswordEntry("\n").hasUsername()) assertFalse(PasswordEntry("").hasUsername()) } - - @Test fun testNoTotpUriPresent() { - val entry = PasswordEntry("secret\nextra\nlogin: username\ncontent") - assertFalse(entry.hasTotp()) - assertNull(entry.totpSecret) - } - - @Test fun testTotpUriInPassword() { - val entry = PasswordEntry("otpauth://totp/test?secret=JBSWY3DPEHPK3PXP") - assertTrue(entry.hasTotp()) - assertEquals("JBSWY3DPEHPK3PXP", entry.totpSecret) - } - - @Test fun testTotpUriInContent() { - val entry = PasswordEntry( - "secret\nusername: test\notpauth://totp/test?secret=JBSWY3DPEHPK3PXP") - assertTrue(entry.hasTotp()) - assertEquals("JBSWY3DPEHPK3PXP", entry.totpSecret) - } - - @Test fun testNoHotpUriPresent() { - val entry = PasswordEntry("secret\nextra\nlogin: username\ncontent") - assertFalse(entry.hasHotp()) - assertNull(entry.hotpSecret) - assertNull(entry.hotpCounter) - } - - @Test fun testHotpUriInPassword() { - val entry = PasswordEntry("otpauth://hotp/test?secret=JBSWY3DPEHPK3PXP&counter=25") - assertTrue(entry.hasHotp()) - assertEquals("JBSWY3DPEHPK3PXP", entry.hotpSecret) - assertEquals(25, entry.hotpCounter) - } - - @Test fun testHotpUriInContent() { - val entry = PasswordEntry( - "secret\nusername: test\notpauth://hotp/test?secret=JBSWY3DPEHPK3PXP&counter=25") - assertTrue(entry.hasHotp()) - assertEquals("JBSWY3DPEHPK3PXP", entry.hotpSecret) - assertEquals(25, entry.hotpCounter) - } } |