Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Encrypt some preferences #576

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open

Encrypt some preferences #576

wants to merge 8 commits into from

Conversation

oakkitten
Copy link
Collaborator

@oakkitten oakkitten commented Feb 18, 2024

Closes #574. This is based on top of #575. See individual commit messages. Suggest reviewing commit by commit.

TODO: Add include rules for backups. I suppose we only want to backup preferences, custom fonts and themes.

The idea is as such: create a custom version of SharedPreferences that
treats preference keys prefixed with `encrypted` differently, saving them
to an instance of EncryptedSharedPreferences.

To actually use this MultiSharedPreferences in a PreferenceFragmentCompat,
we have to employ a little hack of writing its private field, as for some
reason the fragment does not allow customizing it's shared preferences.
This moves `applicationContext` to the `utils` package.

Additionally, it is mirrored in the tests to allow late initialization.
This will be used in the following commit.

This is highly experimental.
I have no idea what I am doing.
Roboelectric is used to simplify testing with application context and
platform APIs. It provides these things without running on a real device.

We are using JUnit 5. Roboelectric needs JUnit 4; to make this work,
we use org.junit.vintage:junit-vintage-engine.

For in-memory implementation of shared preferences,
we use io.github.ivanshafran:shared-preferences-mock.

Please ignore this:
  testImplementation("androidx.test:runner:1.5.2")
  testImplementation("org.mockito:mockito-core:5.8.0")
I would prefer to only use the `include` rules, but this is quite hard when
it comes to shared preferences. The problem is that the default shared
preferences file name contains the application id. While it is possible to
use application id placeholder in the manifest, it is not currently possible
in the resource files. It is also apparently not possible to use string
resources, it just does not work. We could also use a Gradle plugin that
gives us placeholder replacements, but Android Stem seems to be only parsing
string resources, which is neat but doesn't fit our use. The only feasible
way here would be duplicating the resources for every build variant.

Rules for API ≤ 30 can be tested with the following Bash script,
which is a modified version of the script suitable for > 30 found here:
at https://developer.android.com/guide/topics/data/testingbackup

    #!/bin/bash -eu
    : "${1?"Usage: $0 package name"}"

    adb shell bmgr enable true

    # $ adb shell bmgr list transports
    #     android/com.android.internal.backup.LocalTransport
    #     com.google.android.gms/.backup.BackupTransportService
    adb shell bmgr transport android/com.android.internal.backup.LocalTransport | grep -q "Selected transport" || (echo "Error: error selecting local transport"; exit 1)

    adb shell settings put secure backup_local_transport_parameters 'is_encrypted=true'
    adb shell bmgr backupnow "$1" | grep -F "Package $1 with result: Success" || (echo "Backup failed"; exit 1)

    apk_path_list=$(adb shell pm path "$1")
    OIFS=$IFS
    IFS=$'\n'
    apk_number=0
    for apk_line in $apk_path_list
    do
        (( ++apk_number ))
        apk_path=${apk_line:8:1000}
        # MSYS_NO_PATHCONV=1 allows running this script in Git Bash
        # Copy before pulling to avoid “remote object ... does not exist” errors
        # See this answer josemigallas https://stackoverflow.com/questions/41150038/#43157127
        MSYS_NO_PATHCONV=1 adb shell cp "$apk_path" "/storage/emulated/0/Download/temp_base.apk"
        MSYS_NO_PATHCONV=1 adb pull "/storage/emulated/0/Download/temp_base.apk" "myapk${apk_number}.apk"
    done
    IFS=$OIFS
    adb shell pm uninstall --user 0 "$1"
    apks=$(seq -f 'myapk%.f.apk' 1 $apk_number)

    adb install -t "$apks"

    adb shell bmgr transport com.google.android.gms/.backup.BackupTransportService
    rm $apks

    echo "Done"
@oakkitten oakkitten marked this pull request as ready for review March 8, 2024 18:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Encrypt, don't back up passwords & keys
1 participant