Giter VIP home page Giter VIP logo

secure-preferences's Introduction

Secure-preferences - Deprecated

  • Please use EncryptedSharedPreferences from androidx.security in preferenced to secure-preference. (There are no active maintainers Secure-preferences)

This is Android Shared preference wrapper that encrypts the values of Shared Preferences using AES 128, CBC, and PKCS5 padding with integrity checking in the form of a SHA 256 hash. Each key is stored as a one way SHA 256 hash. Both keys and values are base64 encoded before storing into prefs xml file. By default the generated key is stored in the backing preferences file and so can be read and extracted by root user. Recommend use the user password generated option as added in v0.1.0.

The sample app is available on playstore

Sample app Screenshot

Release v0.1.0+

The v0.1.0 release was a major refactor of the guts of secure prefs, which is Not backwards compatible yet with older 0.0.1 - 0.0.4 versions. So if you have an existing app using this don't upgrade. I'll be looking to add migration into a later release.

Full list of changes

Usage

Dependency

Maven central is the preferred way:

Note: v0.1.0 was dependent on snapshot of aes-crypto, this is only as I was waiting for the aes-crypto repo owner to upload to maven. I've sorted this for v0.1.1+ which is no longer dependent on Snapshot repo.

dependencies {
    implementation 'com.scottyab:secure-preferences-lib:0.1.7'
}

Download

Or download the release .aar or clone this repo and add the library as a Android library project/module.

ProGuard config

As of v0.1.4 no specific -keep config is needed.

DexGuard

There is specific DexGuard config supplied with DexGuard 7+ located <dexgaurd root>/samples/advanced/SecurePreferences

Examples

This will use the default shared pref file

SharedPreferences prefs = new SecurePreferences(context);     

Custom pref file

You can define a separate file for encrypted preferences.

SharedPreferences prefs = new SecurePreferences(context, null, "my_custom_prefs.xml");

User password - (recommended)

Using a password that the user types in that isn't stored elsewhere in the app passed to the SecurePreferences constructor means the key is generated at runtime and not stored in the backing pref file.

SharedPreferences prefs = new SecurePreferences(context, "userpassword", "my_user_prefs.xml");

Changing Password

SecurePreferences securePrefs = new SecurePreferences(context, "userpassword", "my_user_prefs.xml");
securePrefs.handlePasswordChange("newPassword", context);

What does the data look like?

SharedPreferences keys and values are stored as simple map in an XML file. You could also use a rooted device and an app like cheatdroid

XML using Standard Android SharedPreferences

<map>
    <int name="timeout" value="500" />
    <boolean name="is_logged_in" value="true" />
</map>

XML with SecurePreferences

<map>
    <string name="TuwbBU0IrAyL9znGBJ87uEi7pW0FwYwX8SZiiKnD2VZ7">
        pD2UhS2K2MNjWm8KzpFrag==:MWm7NgaEhvaxAvA9wASUl0HUHCVBWkn3c2T1WoSAE/g=rroijgeWEGRDFSS/hg
    </string>
    <string name="8lqCQqn73Uo84Rj">k73tlfVNYsPshll19ztma7U">
        pD2UhS2K2MNjWm8KzpFrag==:MWm7NgaEhvaxAvA9wASUl0HUHCVBWkn3c2T1WoSAE/g=:jWm8KzUl0HUHCVBWkn3c2T1WoSAE/g=
    </string>
</map>

Disclaimer

By default it's not bullet proof security (in fact it's more like obfuscation of the preferences) but it's a quick win for incrementally making your android app more secure. For instance it'll stop users on rooted devices easily modifying your app's shared prefs. Recommend using the user password based prefs as introduced in v0.1.0.

Contributing

Please do send me pull requests, but also bugs, issues and enhancement requests are welcome please add an issue.

Licence

Much of the original code is from Daniel Abraham article on codeproject. This project was created and shared on Github with his permission.

Apache License, Version 2.0

Copyright (C) 2013, Daniel Abraham, Scott Alexander-Bown

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

The sample app Lock icon for sample app licenced under Creative Commons created by Sam Smith via thenounproject.com

secure-preferences's People

Contributors

aeoris avatar doridori avatar fdonzello avatar jabelpeeps avatar linakis avatar natiginfo avatar richardleggett avatar scottyab avatar serchinastico avatar serv-inc avatar willswinson avatar yelinaung avatar zeeshanasghar avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

secure-preferences's Issues

Updating to 0.1.4 from 0.1.3 return null

I have updated the library to 0.1.4 and now, when I access to any secure preference it returns null and the app closes with a NullException.

Is there something that I need to do after the update? Thanks!

handlePasswordChange(...) also try to decrypt auto-generated key

When already use default constructor not passing password or keys, auto-generated key is saved in default shared preference.

But handlePasswordChange(...) also try to change that auto-generated key. During decrypting for getting plain string before encrypt with new password, error occurred.

java.lang.IllegalArgumentException: Cannot parse iv:ciphertext:mac
at com.tozny.crypto.android.AesCbcWithIntegrity$CipherTextIvMac.<init>(AesCbcWithIntegrity.java:568)
at com.securepreferences.SecurePreferences.decrypt(SecurePreferences.java:328)
at com.securepreferences.SecurePreferences.handlePasswordChange(SecurePreferences.java:509)

There is need to be some flag to check if pass or not. If not, always that call generateAesKeyName to get key of auto-generated key. It will be slow.

putStringSet Throws error

While I use editor.putString it is working well ,
but when I tried to use editor.putStringSet, app crashes giving following error :

 Caused by: java.lang.ClassCastException: java.util.HashMap cannot be cast to java.lang.String.

I am adding Arraylist in set. It works well if I donot try to encrypt the data. Gives error if I use it.

Am I missing something.
THank YOu

Handle prefs migration

Handle changes to key generation.
As similar library does handle the migration of breaking changes with upgrade strategy simple to SQLlitehelper.onUpdate()

Use secure-preferences with Robolectric

I am using secure-preferences to encrypt my local preferences. However, when using Robolectric to run unit tests, the preferences are not correctly filled in, and when trying to check if the key is contained in the file, it is always empty.

My app code for the shared prefs:

public class AppSharedPrefs {
    private ApplicationSharedPreferences(Context context) {
        sSharedPreferences = new SecurePreferences(context, context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE));
        sEditor = sSharedPreferences.edit();
        mContext = context;

        clearSharedPreferences();

    }

    public static ApplicationSharedPreferences getInstance(Context context) {
        if (instance == null) {
            instance = new ApplicationSharedPreferences(context);
        }
        return instance;
    }

    ... then all getter and setter ...
}

Then, my test code:

@RunWith(TestRunner.class)
public class CustomerAPITest extends GlobalTestCase {

    @Test
    public void handleActionTest() throws JSONException {
        final String VALUE = "1";

        AppSharedPreferences asp = AppSharedPreferences.getInstance(getTestContext());
        asp.setMyValue(VALUE);

        new CustomerAPI().handleAction();
        ....
    }
}

and my function in "handleAction()" will read VALUE, with:

AppSharedPreferences asp = AppSharedPreferences.getInstance(context);
asp.getMyValue(VALUE); // always null

but is always null, shared preferences always empty.
If I remove SecurePreferences and use standard Android prefs, everything works.

Any clue how to solve this and if it is a problem of the library?

Question about license and using strong encryption outside of USA

I am working on a Android application that i want to release to be available for customers from both USA and Romania. Does this library require a special license for using strong encryption? The reason why i ask this is because some other libraries like SQLCIpher for Android require special license for this ( according to this blog http://www.informit.com/articles/article.aspx?p=2268753&seqNum=3 )

I was wondering if this is the case for this too. Please let me know. Thank you very much.

NoSuchAlgorithmException: SecretKeyFactory PBKDF2WithHmacSHA1 implementation not found

I'm getting this internal crash in all users with Samsung SCH-I705 (Samsung Tab2 7") with Adnroid 4.1.2, in the line what I'm doing this:
sPrefs = new SecurePreferences(context);

I'm importing the library in gradle file:
compile 'com.scottyab:secure-preferences-lib:0.1.3'

Fatal Exception: java.lang.RuntimeException: Unable to create application com.fieldaware.app.FAApplication: java.lang.IllegalStateException: java.security.NoSuchAlgorithmException: SecretKeyFactory PBKDF2WithHmacSHA1 implementation not found
at android.app.ActivityThread.handleBindApplication(ActivityThread.java)
at android.app.ActivityThread.access$1400(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java)
at android.os.Handler.dispatchMessage(Handler.java)
at android.os.Looper.loop(Looper.java)
at android.app.ActivityThread.main(ActivityThread.java)
at java.lang.reflect.Method.invokeNative(Method.java)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java)
at dalvik.system.NativeStart.main(NativeStart.java)
Caused by java.lang.IllegalStateException: java.security.NoSuchAlgorithmException: SecretKeyFactory PBKDF2WithHmacSHA1 implementation not found
at com.securepreferences.SecurePreferences.(Unknown Source)
at com.securepreferences.SecurePreferences.(Unknown Source)
at com.securepreferences.SecurePreferences.(Unknown Source)
at com.fieldaware.app.utils.Settings.(Unknown Source)
at com.fieldaware.app.FAApplication.onCreate(SourceFile)
at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java)
at android.app.ActivityThread.access$1400(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java)
at android.os.Handler.dispatchMessage(Handler.java)
at android.os.Looper.loop(Looper.java)
at android.app.ActivityThread.main(ActivityThread.java)
at java.lang.reflect.Method.invokeNative(Method.java)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java)
at dalvik.system.NativeStart.main(NativeStart.java)
Caused by java.security.NoSuchAlgorithmException: SecretKeyFactory PBKDF2WithHmacSHA1 implementation not found
at org.apache.harmony.security.fortress.Engine.notFound(Engine.java)
at org.apache.harmony.security.fortress.Engine.getInstance(Engine.java)
at javax.crypto.SecretKeyFactory.getInstance(SecretKeyFactory.java)
at com.tozny.crypto.android.AesCbcWithIntegrity.generateKeyFromPassword(SourceFile)
at com.tozny.crypto.android.AesCbcWithIntegrity.generateKeyFromPassword(SourceFile)
at com.securepreferences.SecurePreferences.generateAesKeyName(SourceFile)
at com.securepreferences.SecurePreferences.(Unknown Source)
at com.securepreferences.SecurePreferences.(Unknown Source)
at com.securepreferences.SecurePreferences.(Unknown Source)
at com.fieldaware.app.utils.Settings.(Unknown Source)
at com.fieldaware.app.FAApplication.onCreate(SourceFile)
at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java)
at android.app.ActivityThread.access$1400(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java)
at android.os.Handler.dispatchMessage(Handler.java)
at android.os.Looper.loop(Looper.java)
at android.app.ActivityThread.main(ActivityThread.java)
at java.lang.reflect.Method.invokeNative(Method.java)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java)
at dalvik.system.NativeStart.main(NativeStart.java)

No issues in others devices. Is there some workaround to avoid this issue?
Thanks

Could not find com.scottyab:aes-crypto:0.0.2-SNAPSHOT

Hi Scott,

I was using your library with this configuration in Graddle.

compile 'com.scottyab:aes-crypto:0.0.2-SNAPSHOT'
compile('com.scottyab:secure-preferences-lib:0.1.0') {
provided 'com.scottyab:aes-crypto:0.0.2-SNAPSHOT'
}

It was working fine until last week. I got an error that aes-crypto:002-SNAPSHOT cannot be found.

Could you please check this.

Kind regards,

G

`SecurePreference.getStringUnencrypted()` misleading naming

I think it would be good to rename this method as its a little misleading - as actually it will return the raw string from the prefs - which will be encrypted. To me a better name would be SecurePreference.getStringUndecrypted() || SecurePreference.getEncryptedString()

clear() also removes auto-generated key

When you call clear() on your SecurePreferences instance, it also removes the encryption key used. This means that if you do the following, you can't read out the values you'd expect:

new SecurePreferences(context, "", "file-name");
.putString("foo", "bar");
.getString("foo")  // returns bar as expected
.clear();
.putString("foo", "bar");

new SecurePreferences(context, "", "file-name");
getString("foo") // returns null since the key was recreated after .clear removed it. 

The problem is that clear() does not also remove the SecureKeys instance, but it does remove the preference that backs it. The following "putString" encrypts with the old SecureKeys instance. Then, when the constructor fires, it can't find the preference and recreates it causing a new SecureKeys instance to be created as well.

Allow to provide own salt instead of deprecated ANDROID_ID

Depend on ANDROID_ID is really not good idea, it is deprecated by Google and it can change on some crap devices for example during Android update and user will lost it's data. It is also not good idea if you want to allows to backup preferences and restore it on the new user device.

I know that I can provide completely own SecretKeys, but it is too much complicated.

Maybe some builder for preferences would be much better than too much constructor parameters.

SecurePreferences.getInt throw java.lang.ClassCastException:null

My app uses the version 0.1.4.
Recently, I met a problem: call SecurePreferences. getInt() method, throw "Java. Lang. ClassCastException: null". I find in source code, and find the decrypt (final String ciphertext) method may return null, so the Integer. ParseInt (null) method would throw this exception. I think SecurePreferences. getInt (String key, int defaultValue) method should take the initiative to throw an exception, life for SecurePreferences. getInt (String key, int defaultValue) method throws a NumberFormatException, so that the caller can try catch this a NumberFormatException exception.

Cannot instantiate SecurePrefs in testing

Hi
I am trying to write unit tests, one of which requires an instance of SecurePreferences. So I am passing a context like this:
mContext = Mockito.mock(Context.class);
securePreferences = new SecurePreferences(mContext);

However, the context isn't mocked, and as a result I cannot use SecurePrefs in testing. Do you have any ideas about this?

Gradle build

I'm using this library in my project and I've ported the library to gradle.
Do you like to have Gradle-compatible build ? If so, I will port sample as well.
Thanks.

First time initialization with an empty string as password is very slow, it typically takes 4 seconds on every device

private SecurePreferences mSecurePrefs;
private SecurePreferences openSharedPrefs(){
if (mSecurePrefs == null) {
mSecurePrefs = new SecurePreferences(context, "", "sec_prefs.xml");
}
return mSecurePrefs;
}

Usage:
PreferenceManager pref = new SharedPreferencesManager(context);
String text = pref.getText();
The first time initialisation of preferences takes lot of time, on average 4 seconds, which is really frustrating for the user. have implemented this library at the first time launch of the app and lot of users are complaining that app never loads because of this issue.

Can you please help to improve the speed of initialization with respect to the above scenario.

Thanks

Proguard compatibility

Today I stumbled upon an issue with Proguard.

The AesCbcWithIntegrity class from aes-crypto lib contains the PrngFixes inner class, which in turn contains LinuxPRNGSecureRandom and LinuxPRNGSecureRandomProvider inner classes. Then the class returned from SecureRandom.getProvider() is compared with simple equals on its simple name with the string "LinuxPRNGSecureRandomProvider" here.

When Proguard changes the names of these inner classes to some non-sense, the comparison won't, of course, work.

My proposed fix is to mention correct Proguard rules in README.md. This works for me:

-keep class com.tozny.crypto.android.AesCbcWithIntegrity$PrngFixes$* { *; }

Usage of the String class for sensitive key material

Consider using a char[] instead of String object for the password parameter in the constructor. Also consider not loading the encryption key in a String object while loading/storing it in the backing preference file. Make a file in the private app directory where you write the key as a byte sequence instead. Zero the char[] or byte[] array when the material is not used anymore.

Updating Password Not Working

While using one static key , it is working as charm, but my situation is bit different,
need to change the key often.
So I tried to use

    SecurePreferences securePrefs = new SecurePreferences(context, "userpassword", "my_user_prefs.xml");
    securePrefs.handlePasswordChange("newPassword", context);

But not working.

How to decrypt shared pref key

When i was trying to use SharedPreferences.getAll(), I am getting the encrypted key = actual value(e.g E9hgkasdjafuyg3X = false)

How to get the actual key also? Thanks.

'getString' returns null in 0.1.4

I have an app using the version 0.1.3, which stores a Base64 encoded String(say with key "a_key") in the secured preference which is encrypted with user provided password. In a later version I have used version 0.1.4 of this library. Now when I updated the app to this later version from the earlier one, getString("a_key", null) is returning null although it had a valid value stored earlier. My test device is a Nexus 5, running on Android 6.1.

Empty SecurePreferences

Anytime the app goes to the background, it looses the SecurePreferences object. And when a new one is created with the same key as was used to create initially, the object becomes available and everything works fine.
But after a while, sometimes, when creating (re-initializing) the SecurePreferences object, the file gets renamed to com.package.name_preferences somehow, and a new file is created. So when a query is made it always returns the default value since the file is empty. So now there'll be 2 files. I monitored with the Android Device Monitor.
A workaround is to check if empty then get the other file instead.

Constructor error with null password

When I try to create an instance of SharedPreferences using the constructor with null as the password as shown in the README:

new SecurePreferences(context,null,"name_of_file.xml");

I get an error:

Cannot resolve constructor 'SecurePreferences(android.content.Context, null, java.lang.String)'

I was able to workaround the issue by passing empty string as the password instead. It looks like the behavior is the same, and the lib will generate a key for me.

SecureException in AesCbcWithIntegrity:installLinuxPRNGSecureRandom

Hi,
last release of library crash on HUAWEI G630 U10 with Android 4.3.

Caused by java.lang.SecurityException
com.tozny.crypto.android.AesCbcWithIntegrity$PrngFixes.installLinuxPRNGSecureRandom (AesCbcWithIntegrity.java:764)
com.tozny.crypto.android.AesCbcWithIntegrity$PrngFixes.apply (AesCbcWithIntegrity.java:684)
com.tozny.crypto.android.AesCbcWithIntegrity.fixPrng (AesCbcWithIntegrity.java:347)
com.tozny.crypto.android.AesCbcWithIntegrity.generateKeyFromPassword (AesCbcWithIntegrity.java:184)
com.tozny.crypto.android.AesCbcWithIntegrity.generateKeyFromPassword (AesCbcWithIntegrity.java:234)
com.tozny.crypto.android.AesCbcWithIntegrity.generateKeyFromPassword (AesCbcWithIntegrity.java:219)
com.securepreferences.SecurePreferences. (SecurePreferences.java:145)
com.securepreferences.SecurePreferences. (SecurePreferences.java:92)

Security scan fail

Hi Scott,

After security scan by our tool this lib get failed because follows threat is found.

Description: This cryptographic object is initialized with the cipher spec 'AES', which uses the known risky ECB cipher mode. Because ECB encrypts each block of plaintext independently, the resulting ciphertext is susceptible to dictionary attacks.
Remediation: Use CBC or CTR mode instead. Consult the cryptographic literature to determine which mode is appropriate for your use case.

Thanks,
Dan

Crash while calling getInt with "null" saved.

  Caused by: java.lang.ClassCastException: Invalid int: "null" 
     at com.securepreferences.SecurePreferences.getInt(SecurePreferences.java:389)

This is a valid (but bad practice) call:

   Integer test = null;
   editor.putInt("key", test);

It results in "null" being set in shared preferences because we .toString the Integer value before saving it off encrypted. Then, when we call editor.getInt("key") we get the crash above.

Expand with iterationCount parameter to cover several use case

Same with description in this link, #48

Hello there,

As mentioned in #18, default constructor of SecurePreference is too slow to create instance. In there, solution is to give parameter at AesCbcWithIntegrity.generateKeyFromPassword(...) like below.

AesCbcWithIntegrity.SecretKeys mykeys = AesCbcWithIntegrity.generateKeyFromPassword(password, salt, iterationCount);
SecurePreferences securePrefs = new SecurePreferences(getContext(), mykeys, "pref-file");

But if already use this library, we need to change password using handlePasswordChange(String newPassword, Context context) to solve the problem too slow to create instance. This method doesn't support not only iteration count to generate key, but also AES key.

If I solve above problem, next is to check is this migrated. Then if password changed with iteration, I make instance of SecurePreference. But also, there is blocker generateAesKeyName in constructor when pass password, not key. generateAesKeyName is default key generator of key, also don't support iteration count to generate key. But this method is private static. I can't override it. So inheritance of SecurePreference can't solve problem.

So What I did :

  1. Expand method constructor, handlePasswordChange, generateAesKeyName with iterationCount
  2. Make public generateAesKeyName for to prepare something to change logic
    (Maybe, protected is enough to cover this issue.)
  3. Add comment
  4. Add test to handlePasswordChange with iteration count
  5. Fix wrong method name. getUnencryptedString -> getEncryptedString
    (Value from sharePreference look like not encrypted, but not using original key, using hashPrefKey in this method)
  6. Fix wrong assignment to sharePrefFilename (Same with #42)

Thanks for reading. If you have any question or request, please let me know.

handlePasswordChange problems (v0.1.4)

Consider the following code snippet

SecurePreferences securedPreferences = new SecurePreferences(myContext, "myPassword", "myfile");
securedPreferences.handlePasswordChange("myNewPassword", myContext);

Using handlePasswordChange leads to a strange behaviour. After method call, secured preferences file myfile.xml is empty and updated preferences are written into default shared preferences file.

Problem seems to come from the following method

private SharedPreferences getSharedPreferenceFile(Context context, String prefFilename) {
        this.sharedPrefFilename = sharedPrefFilename ;

        if(TextUtils.isEmpty(prefFilename)) {
            return PreferenceManager
                    .getDefaultSharedPreferences(context);
        }
        else{
          return context.getSharedPreferences(prefFilename, Context.MODE_PRIVATE);
        }
}

It does not set sharedPrefFilename attribute with parameter prefFilename. So it is null when handlePasswordChange uses it to handle shared preference instance refresh

//refresh the sharedPreferences object ref: I found it was retaining old ref/values
sharedPreferences = null;
sharedPreferences = getSharedPreferenceFile(context, sharedPrefFilename);

Latest tag is missing

I was wondering where is tag 1.0.4. As you have mentioned #31 is fixed in that but I can see in master it is not.

Move away from AESCrypt-Android

AESCrypt-Android is a completly insecured cryptography library!

It uses a simple SHA256 in order derivate a key from a password with no salt. That basically useless.
=> Please consider using at least PBKDF2 with a good salt and sufficient number of iterations.
=> Read https://www.nccgroup.trust/us/about-us/newsroom-and-events/blog/2015/march/enough-with-the-salts-updates-on-secure-password-schemes/

It doesn't provide authenticated encryption and so doesn't provide integrity an authentication checks.
=> Please consider using something like Keyczar
=> Read http://tonyarcieri.com/all-the-crypto-code-youve-ever-written-is-probably-broken

It provides a "convenient" encrypt/decrypt method that uses a fixed salt. That's awful.

Please don't use this library.

how to use AES256 instead of AES 128

Thank you for the great library. I suggested using this library in our project but security team gave me this comment. Please advise.

For local storage of the user passwords use at least AES 256 minimum not 128.
When using PKCS5, verify that the implementation does not allow for Oracle padding attacks in that the responding side does not leak padding validation to the client. See the following
https://www.owasp.org/images/e/eb/Fun_with_Padding_Oracles.pdf

Make sure that the stored credentials are place under the /data/data path on Android and not in user land on the sd card.
On uninstallation of the application, all user data including the stored encrypted credentials should be deleted.

How is the key and key password protected?
Preferably obfuscate the mechanism to create the key and password in native .so files if this is viable.

Do not have the key and key password present in plaintext in the Java source code.

Use a method to generate the key and password and then obfuscate this method with proguard.
Proguard should also be used to hide any inputs into this method.

Ideally use a per user key and password, this can be created based off of the android device id.

How to set `SecurePreferences` as default shared preferences?

I would like the PreferenceManager.getDefaultSharedPreferences(this) method to return my SecurePreferences instance.

So is it possible to set SecurePreferences as default shared preferences and is there maybe some way to have PreferenceFragmentCompat use SecurePreferences?

Slows down my app

Hello,
ever since I upgraded to 0.0.1 from 0.0.4, my app has experienced tremendous slowdown. I mean like 10x slower! Any ideas what the issue could be here?

Thanks,
Igor

Static SharedPreferences field

Due to the SharedPreferences field value in SecurePreferences it is impossible to have multiple secure preference files. This also causes issues when running Robolectric tests. We saw test pollution when we tried to inject a new instance of SecurePreferences for each test example that depended on one.

Encrypt key with Androidkeystore key

Add the option for developers to enable additional security on API:18+ using the Androidkeystore.

Androidkeystore is for RSA (and EC since 4.4) certs so use a newly generated one to encrypt the keys used for the key and value encryption

Add custom ProGuard/DexGuard config

08-02 05:00:41.356 1533-1533/erparchitector.findwork.app.android E/AndroidRuntime﹕ FATAL EXCEPTION: main
java.lang.SecurityException: new SecureRandom() backed by wrong Provider: class com.tozny.crypto.android.AesCbcWithIntegrity$PrngFixes$LinuxPRNGSecureRandomProvider
at com.tozny.crypto.android.AesCbcWithIntegrity$PrngFixes.installLinuxPRNGSecureRandom(Unknown Source)
at com.tozny.crypto.android.AesCbcWithIntegrity$PrngFixes.apply(Unknown Source)
at com.tozny.crypto.android.AesCbcWithIntegrity.fixPrng(Unknown Source)
at com.tozny.crypto.android.AesCbcWithIntegrity.generateKeyFromPassword(Unknown Source)
at com.tozny.crypto.android.AesCbcWithIntegrity.generateKeyFromPassword(Unknown Source)
at com.securepreferences.SecurePreferences.generateAesKeyName(Unknown Source)
at com.securepreferences.SecurePreferences.(Unknown Source)
at com.securepreferences.SecurePreferences.(Unknown Source)
at com.securepreferences.SecurePreferences.(Unknown Source)
at erparchitector.findwork.app.android.utils.Preferences.(Unknown Source)
at erparchitector.findwork.app.android.network.Session.getInstance(Unknown Source)
at erparchitector.findwork.app.android.App.getSession(Unknown Source)
at erparchitector.findwork.app.android.gui.ProfileContainer.onCreate(Unknown Source)
at android.support.v4.app.Fragment.performCreate(Unknown Source)
at android.support.v4.app.FragmentManagerImpl.moveToState(Unknown Source)
at android.support.v4.app.FragmentManagerImpl.moveToState(Unknown Source)
at android.support.v4.app.BackStackRecord.run(Unknown Source)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(Unknown Source)
at android.support.v4.app.FragmentManagerImpl$1.run(Unknown Source)
at android.os.Handler.handleCallback(Handler.java:725)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5041)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
at dalvik.system.NativeStart.main(Native Method)

After proguard obfuscation :(

How to clear sharedPreference without password?

I used the user password mode in my application. So how do I clear the shared preference without asking the user password on logout. Currently, every access to the shared preference in other activities will require password to get the created shared preference instance during login, but this is fine for fetching the information. But when the user logs out, is it possible to clear it without the password? Please advise, thanks!

Exception thrown in SecurePreferences constructor

I'm using Your library version 0.1.0, but looking through the code I think this might be a problem with other versions too. Just noticed this in crash report today in google play console:

java.lang.IllegalArgumentException: bad base-64
at android.util.Base64.decode(Base64.java:161)
at android.util.Base64.decode(Base64.java:136)
at android.util.Base64.decode(Base64.java:118)
at com.tozny.crypto.android.AesCbcWithIntegrity.generateKeyFromPassword(AesCbcWithIntegrity.java:188)
at com.securepreferences.SecurePreferences.(SecurePreferences.java:160)

I'm creating secure prefs object using SecurePreferences(Context context, final String password, final String sharedPrefFilename) constructor and then IllegalArgumentException is thrown. Seems like salt passed to AesCbcWithIntegrity.generateKeyFromPassword(String password, String salt) is not always valid base64 string. The string passed as salt is generated with getDeviceSerialNumber(context) method. I think problem lies here - does this method always returns valid base64 string? Not all devices are affected. I've just noticed this on some LG phones with Android 5.0.

Compatability issue when using android gradle plugin shrinker

SecurePreferences Version: v0.1.4
Target Device: Emulator with Image API 18, Google APIs Intel x86, rev. 5
Gradle Android Plugin Version: v2.2.2

When using the Android Gradle plugin shrinker, a NoSuchAlgorithmException is thrown when trying to instantiate a new SecurePreferences object on the target device specified above. It works fine when run on a device on API 23.

The stack trace:

java.security.NoSuchAlgorithmException: SecureRandom SHA1PRNG implementation not found
     at java.security.SecureRandom.<init>(SecureRandom.java:100)
     at com.tozny.crypto.android.AesCbcWithIntegrity$PrngFixes.installLinuxPRNGSecureRandom(AesCbcWithIntegrity.java:760)
     at com.tozny.crypto.android.AesCbcWithIntegrity$PrngFixes.apply(AesCbcWithIntegrity.java:684)
     at com.tozny.crypto.android.AesCbcWithIntegrity.fixPrng(AesCbcWithIntegrity.java:347)
     at com.tozny.crypto.android.AesCbcWithIntegrity.generateKeyFromPassword(AesCbcWithIntegrity.java:184)
     at com.tozny.crypto.android.AesCbcWithIntegrity.generateKeyFromPassword(AesCbcWithIntegrity.java:167)
     at com.securepreferences.SecurePreferences.generateAesKeyName(SecurePreferences.java:202)
     at com.securepreferences.SecurePreferences.<init>(SecurePreferences.java:118)
     at com.securepreferences.SecurePreferences.<init>(SecurePreferences.java:92)
     at com.whatever.Session.<init>(Session.java:45)

Where line 45 of Session.java is
preferences = new SecurePreferences(context, "", SHARED_PREF_FILENAME);

As far as I've noticed, this only happens when enabling the Gradle plugin shrinker, and happens with and without Instant Run enabled. Using proguard to shrink works fine as well.

So, it looks like the Gradle shrinker is pulling out more than it needs to. Checking out the apks in Classyshark confirms this.

Resolution
Although the readme says no proguard config is necessary for v0.1.4, the resolution is to add -keep class com.tozny.crypto.android.AesCbcWithIntegrity$PrngFixes$* { *; } to the proguard file and the Gradle plugin shrinker will behave.

Perhaps we should add a consumer proguard file with this rule to support the Gradle Android plugin shrinker.

Using PBKDF2WithHmacSHA1 with 10k iterations and 48B output is too slow

I'd very much like to use this library, but the initialization of the key takes 3 seconds on my Nexus 5. Since this is done in Application's onCreate (because I need the settings there), it's not usable.

I understand that you're trying to make it as easy to use and as secure as possible, but would you consider allowing users of the library to provide their own key? Since the encryption is really more of an obfuscation (anyone can decompile the app and generate the same key), it wouldn't be a problem for me to have less security, but 100x faster startup time :)

Also here's some discussion about the slowness: http://stackoverflow.com/questions/24652602/pbkdf2withhmacsha1-key-generation-takes-too-long-on-android

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.