aboutsummaryrefslogtreecommitdiffstats
path: root/app/src/test/java
AgeCommit message (Collapse)AuthorFilesLines
75 min.feat(app): drop two sort orders, fix the proxy user nameDanilo M.4-0/+168
The Compose list shows folders and entries in separate groups, so the files first and type independent sort orders did nothing visible. They are removed; a stored one migrates to folders first, and any unknown value reads as folders first instead of throwing. The OpenKeychain SSH key ID, which nothing reads any more, is removed once. GitSettings wrote the proxy user name to the proxy preferences but read it from the main settings, so ProxyUtils never authenticated. Adds the pure parts of the settings port: proxy port parsing, HEAD status and the commit log. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
5 hoursfix(app): address the step 5 review and emulator findingsDanilo M.1-0/+10
- A store a cancelled attempt already made for the chosen key (its .gpg-id names exactly that key) no longer counts as occupied: choosing the key again commits and moves on instead of refusing. - SSH key import reads at most 100 kB whatever the provider reports, like the PGP import, instead of reading the stream whole. - PGPKeyManager replaces a key through a temporary file moved over it atomically, so a failed write keeps the old key; listings only read .key files, so a stray temporary file is never taken for a key. - "View generated public SSH key" goes through the settings result launcher, so the preference visibility refreshes afterwards. - A plain start from LaunchActivity replaces the task: an open MainActivity (e.g. one whose store vanished) is no longer left below the new one, and one back leaves the app. - The PGP keys screen's import FAB carries its content description itself; M3 cleared the icon's. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6 hoursfix(app): harden the setup key importsDanilo M.1-0/+19
- PGP key import reads at most 1 MiB (bounded read, buffer zeroed) and refuses larger files with a new message. - SshKeyViewModel catches any Exception from import and generation (CancellationException rethrown) instead of a short list, so an unexpected provider or sshj error no longer crashes the app. - Pending PGP key bytes are zeroed in a finally block, also on cancellation during addKey after a replace, and an earlier pending pick is zeroed before a new one takes its place. - PGPKeyManager never replaces a stored secret key with a public-only key of the same ID, with or without replace (KeyDowngradeException); the setup ViewModel shows a localized message for it. Unit test added. - storeRecipients strips '#' comments and a trailing '!' as pass reads .gpg-id; tests added. - GitServerViewModel.clearStore returns the failure when the store folder cannot be emptied, so the clone does not start; the plan's Task 3 call site reports it. - readGpgId opens the file with NOFOLLOW_LINKS and reads at most 64 KiB + 1 bytes, refusing more. - SshKey.import writes the new private key to a temp file and moves it over atomically before dropping the old key's Keystore entry, public key and passphrase, so an I/O error keeps the old key. - KeyUtils.isSecretKey notes (ponytail) that GnuPG stub and smartcard keyrings count as secret. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6 hoursfeat(app): add the setup model and stricter key checksDanilo M.2-0/+154
URL checks and fixes, authentication modes per URL, the clone target, the store's recipients, a size- and symlink-checked .gpg-id read and the .gpg-id text for a new store (uppercase long key IDs), as pure functions for the Compose setup screens. The SSH key import now also requires a format sshj recognizes (an OpenPGP private key block matched the old marker check and was imported as the SSH key) and no longer crashes on an empty size cursor. KeyUtils tells secret keys apart and no longer throws on a key without user ID. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
10 hoursfix(git): get sshj's Ed25519 keys from Bouncy CastleDanilo M.1-0/+14
Recent Conscrypt (Android 14 mainline updates) registers a KeyFactory for Ed25519. With sshj leaving provider selection to the JCA, its Ed25519KeyFactory now gets Conscrypt's key class, whose algorithm name sshj does not map to ssh-ed25519: KeyType.fromKey returns UNKNOWN and every Ed25519 host key fails with "Don't know how to encode key", so clone and sync over SSH break. 0.1.4 is affected since the sshj 0.41.2 update. Register a provider at position 1 that serves only KeyFactory.Ed25519 from Bouncy Castle (kept by the existing R8 rule). Everything else, including signatures with Android Keystore keys, still goes through normal JCA provider selection. Verified on an Android 14 tablet: clone over SSH failed before and works with the fix. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> (cherry picked from commit ad3c63f665e6264ed1db42d6ae2dfc0947e33393)
11 hoursfix(app): harden the editor save path and the pickerDanilo M.1-0/+4
- Run the save's write, original delete, autofill and history updates under NonCancellable so a recreated activity cannot leave a half done rename. - fsync the temporary file before the atomic move. - Move dialog: refuse targets outside the store (symlinks) and moving a folder into itself or a descendant, with a toast. - Folder picker: do not navigate into a new folder whose mkdirs failed; show a toast (new string, en and it). - Normalize entryFile so "./" and "a/../b" give the same keys as the list; covered in EditorModelTest. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
11 hoursfeat(app): add the editor model and the picker's folder listingDanilo M.2-0/+164
Pure functions for the Compose editor: the form and the pass file it writes, validation, the target file, the overwrite check, an atomic write, OTP URI building and the random generator's options. The folder picker lists subfolders with the list's hidden filter. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
20 hoursfeat(app): add the entry view model and the OTP periodDanilo M.1-0/+57
Totp now carries its period, so the entry view can draw how much of the code's lifetime is left. EntryFields groups a decrypted entry the way the spec lays it out. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
22 hoursfix(app): harden store delete, move and renameDanilo M.1-0/+29
- renameFolder stops when the move fails instead of recording and committing - delete runs its file work on the IO dispatcher - folder delete no longer follows directory symlinks (new test) - overwrite dialog is dismissed when its coroutine is cancelled Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
22 hoursfeat(app): add the list rows and folder navigation modelDanilo M.1-0/+93
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
24 hoursbuild(deps): update sshj to 0.41.2 and drop eddsaDanilo M.2-0/+75
sshj 0.40 replaced the unmaintained net.i2p.crypto:eddsa 0.3.0 (last release 2019) with Bouncy Castle's Ed25519. 0.41.2 still targets Java 8. The app used eddsa directly for wrapped Ed25519 SSH keys. Generate the 32-byte seed with SecureRandom and build the key pair with sshj's Ed25519KeyFactory and Bouncy Castle's public key derivation. The wrapped format is still the raw RFC 8032 seed, so keys generated by 0.1.3 keep working; Ed25519KeyPairTest pins this with the RFC 8032 test vector. sshj 0.40 also changed setSecurityProvider(null) to reset the registerBouncyCastle flag, which undid the earlier setRegisterBouncyCastle(false): sshj then forced every operation through Bouncy Castle, which cannot sign with Android Keystore keys ("no encoding for EC private key"), and hardware-backed SSH keys failed to authenticate. Call the two in the opposite order; SshjConfigTest checks that sshj leaves provider selection to the JCA. Verified with the R8 release build on the emulator against the e2e server: a hardware ECDSA key, a newly generated wrapped Ed25519 key and an imported OpenSSH Ed25519 key all authenticated and synced. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
25 hoursfeat(crypto): replace androidx security-crypto with Keystore AES-GCMDanilo M.1-0/+87
security-crypto is deprecated in 1.1.0 and the app was stuck on 1.1.0-alpha06, since the stable release fails the warnings-as-errors build. It also pulled in Tink for what is a single AES-GCM operation. KeystorePreferences is a SharedPreferences whose values are AES-GCM sealed under an Android Keystore key (random IV, entry name as AAD so values cannot be swapped between entries); a value that fails to decrypt reads as absent. It backs the Git credentials (git_secrets), the proxy credentials (proxy_secrets) and the PGP passphrase cache, whose key needs the screen lock or a strong biometric within 60s and is recreated if a new biometric enrollment invalidates it. Wrapped Ed25519 SSH keys are sealed the same way into the private key file. Password generator settings are not secret and move to plain preferences. Nothing is migrated: removeSecurityCryptoData deletes the old encrypted preference files, Tink keysets, their Keystore master keys and a security-crypto wrapped Ed25519 key once on upgrade. Only 0.1.x installs from the last few hours have such data. Hardware SSH keys and imported keys are untouched. Tests: KeystorePreferencesTest (round trip, defaults, no plaintext, random IVs, AAD binding, tamper rejection, remove/clear) with a software AES key. Verified on the emulator by upgrading a 0.1.2 debug build that held a wrapped Ed25519 key, Tink keysets and a cached passphrase: the old data was deleted, a new Ed25519 key authenticated over SSH after a fingerprint unlock, and a passphrase cached on first decrypt was reused on the second with only the fingerprint. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
25 hoursfix(crypto): refuse to encrypt when a .gpg-id recipient key is missingDanilo M.1-0/+84
CryptoRepository.encrypt looked up every .gpg-id recipient and dropped the ones it could not find, so an entry saved on a device that lacked one recipient's key was encrypted to the others only. With a store shared between a phone key and a smartcard key, entries created on the phone could no longer be decrypted with the smartcard alone. Fail with the lookup error instead (KeyNotFoundException names the key), so the user imports the missing public key and saves again. PasswordCreationActivity also ignored the Result of encrypt and wrote the output buffer regardless: on any encryption failure it wrote an empty .gpg file, overwriting the entry when editing, and committed it. Show the error and leave the file untouched. CryptoRepositoryTest covers both the missing-recipient failure and the all-present success path, with keys generated by PGPainless (added as an app test dependency). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
31 hoursbuild(deps): update JGit from 4.5.7 to 5.13.5Danilo M.1-1/+27
JGit 4.5.7 dates from 2019. 5.13 is the last line that needs only Java 8 APIs, so it works with Android's desugaring; it also fixes GHSA-3p86-9955-h393 (arbitrary file overwrite on checkout). GHSA-vrpq-qp53-qv56 (XXE in repo manifest parsing) has no 5.x fix but the app never parses repo manifests. API changes: - SshSessionFactory now requires getType(). - CheckoutCommand.setForce is deprecated; setForceRefUpdate is its documented replacement with the same meaning. JGit 5 references java.lang.management and javax.management, which Android lacks; R8 flagged them. Both paths are made unreachable rather than only silenced: - WindowCache registers JMX statistics by default; Application.onCreate now installs a WindowCacheConfig with exposeStatsViaJmx = false. - GC.gc() takes a PID lock that queries ManagementFactory and would throw NoClassDefFoundError on a device. GcOperation now runs the GC steps (packRefs, repack, prune) directly; the lock only guards against concurrent gc processes, which cannot happen in the app. Aggressive packing is dropped. The R8 -dontwarn rules and the lint baseline entries are added only for those two now-unreachable references. JGitBehaviourTest covers the operations' command chains plus the GC steps and passes on 5.13.5. It now ignores the developer's global git config, which JGit 5 reads (commit.gpgsign made test commits try to sign). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
31 hourstest(git): pin down the JGit behaviour the git operations rely onDanilo M.1-0/+158
Run the command chains of SyncOperation, PushOperation, BreakOutOfDetached and ResetToRemoteOperation against a local bare repository and assert the results GitCommandExecutor branches on: rebase success, push OK / UP_TO_DATE / REJECTED_NONFASTFORWARD, a stopped rebase with its branch recoverable, abort and push to a conflict branch, and hard reset to the remote. Passes on JGit 4.5.7; it is the safety net for the JGit upgrade. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
32 hoursfix(git): keep the branch name when breaking out of a failed rebaseDanilo M.1-0/+28
When a pull with rebase stops on a conflict, HEAD is detached and getCurrentBranch() returned null. "Abort rebase and push new branch" then pushed the local commits to "conflicting-null-<time>" and failed to switch back with "Branch name <null> is not allowed", leaving the repository on the conflict branch. Fall back to the branch JGit records in rebase-merge/head-name (or rebase-apply/head-name) while a rebase is in progress. Found while driving the conflict flow on an emulator against the e2e test server; verified there: the edit is pushed to conflicting-master-<time> and the operation completes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
34 hoursfix: stop exporting DecryptActivity and validate decrypt pathsDanilo M.1-0/+45
DecryptActivity was exported without an intent filter, so any installed app could start it with arbitrary FILE_PATH/REPO_PATH extras (and crash it by omitting them). Nothing outside the app needs to launch it: shortcuts and the decrypt action go through LaunchActivity. LaunchActivity stays exported, so it now treats FILE_PATH as untrusted: the path is forwarded only when it canonically resolves to a regular file inside the password store, and REPO_PATH is always the real store directory instead of the caller-supplied value. Anything else falls back to the main screen. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2024-08-14chore: add missing copyright headers and update existing onesHarsh Shandilya2-2/+2
2024-05-28chore: reformat with trailing commas changesHarsh Shandilya1-9/+9
2022-10-25refactor: move UriTotpFinderTest to `format-common-impl`Harsh Shandilya1-60/+0
2022-07-15Remove OpenKeychain code and leave TODOs for missing functionalityHarsh Shandilya1-41/+0
2022-07-15all: re-do package structure yet againHarsh Shandilya4-5/+5
2022-05-02Misc cleanups (#1891)Harsh Shandilya1-4/+4
2022-04-21Remove support for external storage and raise target SDK to 31 (#1863)Harsh Shandilya1-19/+20
2021-12-21app: migrate XkPasswd users to DicewareHarsh Shandilya1-0/+28
2021-12-02Cleanup dependency declarations and upgrade to Kotlin 1.6.0 (#1565)Harsh Shandilya3-8/+8
2021-07-17Refactor TOTP implementation and expand SteamGuard hacks (#1460)Harsh Shandilya1-0/+6
* UriTotpFinder: commonize query parameter handling * gitignore: add more IDEA files * TotpFinder: add `findIssuer` * PasswordEntry: don't eagerly fetch TOTP related fields * format-common: expand SteamGuard workaround * CHANGELOG: add SteamGuard workaround
2021-05-22Tweak documentation and drop unused importHarsh Shandilya1-1/+0
Signed-off-by: Harsh Shandilya <me@msfjarvis.dev>
2021-05-22test: remove context parameterAditya Wasan1-2/+2
Signed-off-by: Aditya Wasan <adityawasan55@gmail.com>
2021-05-22spotless: fix formattingAditya Wasan1-9/+30
Signed-off-by: Aditya Wasan <adityawasan55@gmail.com>
2021-05-22test: update MigrationsTest to run on JVMAditya Wasan1-31/+45
Signed-off-by: Aditya Wasan <adityawasan55@gmail.com>
2021-05-22chore(format): format code using spotlessSphericalKat1-1/+0
Signed-off-by: SphericalKat <amolele@gmail.com>
2021-05-17fix(tests): return null/default values from faked android sdkSphericalKat1-0/+125
fixes behaviour of getFilesDir Signed-off-by: SphericalKat <amolele@gmail.com>
2021-05-02app: update GpgIdentifier testsHarsh Shandilya1-5/+3
Signed-off-by: Harsh Shandilya <me@msfjarvis.dev>
2021-04-19Migrate some tests to Robolectric (#1389)Harsh Shandilya2-0/+114
Signed-off-by: Harsh Shandilya <me@msfjarvis.dev>
2021-04-18app: switch to format-common's PasswordEntryHarsh Shandilya2-268/+0
Signed-off-by: Harsh Shandilya <me@msfjarvis.dev>
2021-03-18all: reformat with ktfmtHarsh Shandilya3-224/+251
Signed-off-by: Harsh Shandilya <me@msfjarvis.dev>
2021-03-18all: update copyrightsHarsh Shandilya3-2/+7
Signed-off-by: Harsh Shandilya <me@msfjarvis.dev>
2021-02-19Parse extra content into key value pairs (#1321)Aditya Wasan1-1/+33
* ui: add skeleton recyclerview to parse extra content Signed-off-by: Aditya Wasan <adityawasan55@gmail.com> * ui: add recyclerview and update PasswordEntry to create map of key-value pairs Signed-off-by: Aditya Wasan <adityawasan55@gmail.com> * password-entry: When key-value pair is not correctly formed, display it as Extra Content Signed-off-by: Aditya Wasan <adityawasan55@gmail.com> * Fix formatting Signed-off-by: Aditya Wasan <adityawasan55@gmail.com> * bug: update otp code on main thread Signed-off-by: Aditya Wasan <adityawasan55@gmail.com> * Add complete string if key-value pair cannot be formed Signed-off-by: Aditya Wasan <adityawasan55@gmail.com> * test: add a few tests for key-value parsing logic Signed-off-by: Aditya Wasan <adityawasan55@gmail.com> * prefs: remove SHOW_EXTRA_CONTENT from shared preferences Signed-off-by: Aditya Wasan <adityawasan55@gmail.com> * Update CHANGELOG.md * Cleanup and refactor Signed-off-by: Harsh Shandilya <me@msfjarvis.dev> * PasswordEntryTest: silence nullability warning Signed-off-by: Harsh Shandilya <me@msfjarvis.dev> * PasswordEntry: simplify constructor Signed-off-by: Harsh Shandilya <me@msfjarvis.dev> * PasswordEntry: annotate test-enablement visibility Signed-off-by: Harsh Shandilya <me@msfjarvis.dev> * Reintroduce the catch-all field Signed-off-by: Harsh Shandilya <me@msfjarvis.dev> * update parsing logic Signed-off-by: Aditya Wasan <adityawasan55@gmail.com> * add one more test case Signed-off-by: Aditya Wasan <adityawasan55@gmail.com> * Add missing newlines Signed-off-by: Harsh Shandilya <me@msfjarvis.dev> * Remove unnecessary scrollview Signed-off-by: Harsh Shandilya <me@msfjarvis.dev> * rv: do not return if hasExtraContent is false Signed-off-by: Aditya Wasan <adityawasan55@gmail.com> * Don't anchor RV to bottom Signed-off-by: Harsh Shandilya <me@msfjarvis.dev> Co-authored-by: Harsh Shandilya <me@msfjarvis.dev>
2021-02-15Add tests for GPG identifier parsing (#1319)Harsh Shandilya1-0/+38
2020-12-05Refactor package structure (#1233)Harsh Shandilya2-4/+4
* idea: default test runner to Gradle * Kick off package structure revamp * Reparent all classes under dev.msfjarvis.aps Signed-off-by: Harsh Shandilya <me@msfjarvis.dev>
2020-11-06Fix extra content for multiple username fields (#1192)Harsh Shandilya1-0/+11
Fixes #1190 Signed-off-by: Harsh Shandilya <me@msfjarvis.dev>
2020-10-23Minimal support for MIME secret encoding (#1170)Joris Minjat1-0/+9
Co-authored-by: Fabian Henneke <FabianHenneke@users.noreply.github.com>
2020-09-05Otp: use runCatching to replace exception handlingHarsh Shandilya2-17/+19
Signed-off-by: Harsh Shandilya <me@msfjarvis.dev>
2020-07-25Properly handle files without passwords (#969)Harsh Shandilya1-0/+23
* Properly handle files without passwords Fixes #967 Signed-off-by: Harsh Shandilya <me@msfjarvis.dev> * Fix tests Signed-off-by: Harsh Shandilya <me@msfjarvis.dev> * Only look for TOTP URI Signed-off-by: Harsh Shandilya <me@msfjarvis.dev>
2020-07-14Fix navigation bar theming and reformat (#930)Harsh Shandilya2-2/+9
2020-06-29Reintroduce TOTP support (#890)Harsh Shandilya3-63/+157
Co-authored-by: Fabian Henneke <fabian@henneke.me>
2020-05-28Remove HOTP/TOTP support (#806)Harsh Shandilya1-0/+63