aboutsummaryrefslogtreecommitdiffstats
path: root/app/src/test
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/test')
-rw-r--r--app/src/test/java/app/passwordstore/util/crypto/KeystorePreferencesTest.kt87
1 files changed, 87 insertions, 0 deletions
diff --git a/app/src/test/java/app/passwordstore/util/crypto/KeystorePreferencesTest.kt b/app/src/test/java/app/passwordstore/util/crypto/KeystorePreferencesTest.kt
new file mode 100644
index 00000000..86681064
--- /dev/null
+++ b/app/src/test/java/app/passwordstore/util/crypto/KeystorePreferencesTest.kt
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2026 Danilo M. <danix@danix.xyz>
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+package app.passwordstore.util.crypto
+
+import android.content.SharedPreferences
+import androidx.core.content.edit
+import com.github.ivanshafran.sharedpreferencesmock.SPMockBuilder
+import java.util.Base64
+import javax.crypto.KeyGenerator
+import kotlin.test.BeforeTest
+import kotlin.test.Test
+import kotlin.test.assertEquals
+import kotlin.test.assertFalse
+import kotlin.test.assertNotEquals
+import kotlin.test.assertNull
+import kotlin.test.assertTrue
+
+class KeystorePreferencesTest {
+
+ private lateinit var backing: SharedPreferences
+ private lateinit var prefs: SharedPreferences
+ private val key = KeyGenerator.getInstance("AES").apply { init(256) }.generateKey()
+
+ @BeforeTest
+ fun setup() {
+ backing = SPMockBuilder().createSharedPreferences()
+ prefs = KeystorePreferences(backing) { key }
+ }
+
+ @Test
+ fun roundTripsStringsAndInts() {
+ prefs.edit {
+ putString("password", "hunter2")
+ putInt("port", 8080)
+ }
+ assertEquals("hunter2", prefs.getString("password", null))
+ assertEquals(8080, prefs.getInt("port", -1))
+ }
+
+ @Test
+ fun returnsDefaultsWhenAbsent() {
+ assertNull(prefs.getString("password", null))
+ assertEquals(-1, prefs.getInt("port", -1))
+ assertFalse(prefs.contains("password"))
+ }
+
+ @Test
+ fun storesNoPlaintext() {
+ prefs.edit { putString("password", "hunter2") }
+ val stored = backing.getString("password", null)!!
+ assertFalse(stored.contains("hunter2"))
+ prefs.edit { putString("other", "hunter2") }
+ assertNotEquals(stored, backing.getString("other", null), "IVs must be random")
+ }
+
+ @Test
+ fun rejectsValueMovedToAnotherName() {
+ prefs.edit { putString("password", "hunter2") }
+ backing.edit { putString("username", backing.getString("password", null)) }
+ assertNull(prefs.getString("username", null))
+ }
+
+ @Test
+ fun rejectsTamperedValue() {
+ prefs.edit { putString("password", "hunter2") }
+ val bytes = Base64.getDecoder().decode(backing.getString("password", null))
+ bytes[bytes.size - 1] = (bytes.last().toInt() xor 1).toByte()
+ backing.edit { putString("password", Base64.getEncoder().encodeToString(bytes)) }
+ assertNull(prefs.getString("password", null))
+ }
+
+ @Test
+ fun removeAndClear() {
+ prefs.edit {
+ putString("a", "1")
+ putString("b", "2")
+ }
+ prefs.edit { remove("a") }
+ assertFalse(prefs.contains("a"))
+ assertTrue(prefs.contains("b"))
+ prefs.edit { clear() }
+ assertFalse(prefs.contains("b"))
+ }
+}