Asked  7 Months ago    Answers:  5   Viewed   53 times

I am creating an application which connects to the server using username/password and I would like to enable the option "Save password" so the user wouldn't have to type the password each time the application starts.

I was trying to do it with Shared Preferences but am not sure if this is the best solution.

I would appreciate any suggestion on how to store user values/settings in Android application.

 Answers

30

In general SharedPreferences are your best bet for storing preferences, so in general I'd recommend that approach for saving application and user settings.

The only area of concern here is what you're saving. Passwords are always a tricky thing to store, and I'd be particularly wary of storing them as clear text. The Android architecture is such that your application's SharedPreferences are sandboxed to prevent other applications from being able to access the values so there's some security there, but physical access to a phone could potentially allow access to the values.

If possible I'd consider modifying the server to use a negotiated token for providing access, something like OAuth. Alternatively you may need to construct some sort of cryptographic store, though that's non-trivial. At the very least, make sure you're encrypting the password before writing it to disk.

Tuesday, June 1, 2021
 
ammezie
answered 7 Months ago
66

Your original solution saves 10000 objects in 10000 transactions and creates 10000 objects for it, so that's pretty much the worst possible approach.


Technically the right way should be this:

public void storeBookings(final List<Booking> bookings) {
    mRealm.executeTransaction(new Realm.Transaction() {
        @Override
        public void execute(Realm realm) {
            realm.insertOrUpdate(bookings);
        }
    });
}

In most cases when the saved object is not the same as the original object, what I do is this:

public void storeBookings(final List<Booking> bookings) {
    mRealm.executeTransaction(new Realm.Transaction() {
        @Override
        public void execute(Realm realm) {
            RealmBook realmBook = new RealmBook();
            for(Booking booking : bookings) {
                realmBook = mapper.toRealm(booking, realmBook); // does not create new instance
                realm.insertOrUpdate(realmBook);
            }
        }
    });
}

This solution uses 1 detached object to map the content of the list.

Thursday, July 29, 2021
 
Pegues
answered 5 Months ago
23

The IV should not be generated from the password alone.

The point of the IV that even with the same key and plaintext is re-used, a different ciphertext will be produced. If the IV is deterministically produced from the password only, you'd get the same ciphertext every time. In the cited example, a salt is randomly chosen, so a new key is generated even with the same password.

Just use a random number generator to choose an IV. That's what the cipher is doing internally.


I want to stress that you have to store either the IV (if you use the first method) or a salt (if you use the second method) together with the ciphertext. You won't have good security if everything is derived from the password; you need some randomness in every message.

Sunday, August 1, 2021
 
PiyaModi
answered 4 Months ago
73

You are misusing a pseudo random number generator and it's seed as a key derivation function - this is really really bad style. The pseudo random number generator "SHA1PRNG" is not a standard like AES - therefore you never know what implementation you get. See also Is there a SHA1PRNG standard?

It makes me no wonder that you get different results. Getting a deterministic result based on a given seed is not a property you can expect from a pseudo random number functions.

If you want to derive a cryptographic key from a password please use a Key Derivation Function like PKCS #5 / PBKDF2. An implementation of PBKDF2 is AFAIR included in Bouncy Castle.

Monday, August 9, 2021
 
tadman
answered 4 Months ago
16

The preferred way is to separate them:

foo = bar();
if (foo < 0)
    error(); 

Edit: This is better way for both readability and avoiding bugs, such as in your first case:

if (foo = bar() && foo < 0)
    error();

That should probably be:

if ((foo = bar()) && foo < 0)
    error();
Tuesday, August 24, 2021
 
Byron Whitlock
answered 4 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :  
Share