I'm new to android and security.
My app uses an encrypted DB which is encrypted by a private key. I want to find a way to store this private key in a protected place, without adding any additional password/pin code.
From what I've read, Android's keystore is the place to do it, but from my understanding, if I'll use it, it demands that I'll set a pin code for the device (which I don't want to do!).
Any suggestions regarding where to store this key and how? (any keystore related solution is acceptable as long as I don't have to set a pin code)
My direction is using some external open source keystore (any suggestions?) which I'll compile as part of my app (and because android doesn't share information between apps it will be ok to use).
I'm aware that my last assumption isn't correct when using a rooted device, but for my case I use only non-rooted devices.
I've searched a lot (here and else where) and couldn't find what I was looking for...
Any help is highly appreciated!!
10x
One thing you need to keep in mind is that the KeyChain isn't available until API 14. If you intend on targeting earlier API versions you need another option. You could use SpongyCastle to create your own KeyStore.
If you are not going to ask the user for a password you should at the very least obscure the password.
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
KeyStore ks = null;
try {
ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(null,null);
// Add certs or keys
ks.store(new FileOutputStream(new File(getFilesDir(),"out.bks")),"password".toCharArray());
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
static {
Security.insertProviderAt(new org.spongycastle.jce.provider.BouncyCastleProvider(), 1);
}
}
Related
I am getting exception for below code
try {
mkeyStore?.load(null)
val keyspec = mkeyStore?.getKey(KEY_ALIAS, null) as SecretKey
} catch {
try {
mkeyStore?.deleteEntry(KEY_ALIAS);
} catch (ex: java.lang.Exception) {
e.printStackTrace();
}
}
Scenario is as below:
fingerprint is added and user registered using fingerprint in app.
Now go to setting remove pin(this also removes already enrolled fingerprints).
Now in settings add pin and fingerprint.
Open app again. As user is already registered using fingerprint , I am initializing cipher with above code. It throws the exception in try as well as catch block. User can't use fingerprint in app at all here on-wards.
(Android 8 - Samsung J600G)
I'm playing around with the Fingerprint demo for Android, in particular the invalidation scenarios, but need a little help to translate this into production worthy logic.
I've tested the app and get the initCipher to fail due to invalidation after adding a fingerprint, but the app has to be running and the key generated while you change the settings. This is because the demo generates a new key each time the app starts. In reality you wouldn't want to do this, but instead generate the key if doesn't exist and reuse it if it does to enforce proper invalidation whether the app is running or not.
How can you modify the app so that the key isn't generated each time, but instead a check to see if one exists first is performed, then that key loaded subsequently? Can you then remove the key once invalidated so the previous logic and enrolment cycle applies?
Found the answer on my own by looking at the KeyStore class a bit more and modifying initCipher(). Not the best implementation, but good enough to test out stuff:
private boolean initCipher(Cipher cipher, String keyName) {
try {
mKeyStore.load(null);
// ADDED: Check is keystore contains my key name
if(!mKeyStore.containsAlias(DEFAULT_KEY_NAME)) {
// ADDED: Create if it doesn't
createKey(DEFAULT_KEY_NAME, true);
}
SecretKey key = (SecretKey) mKeyStore.getKey(keyName, null);
cipher.init(Cipher.ENCRYPT_MODE, key);
return true;
} catch (KeyPermanentlyInvalidatedException e) {
// ADDED: Remove the key if it is invalidated so
// it can be created fresh next time
try {
mKeyStore.deleteEntry(keyName);
} catch (KeyStoreException e1) {
e1.printStackTrace();
return false;
}
return false;
} catch (KeyStoreException | CertificateException | UnrecoverableKeyException | IOException
| NoSuchAlgorithmException | InvalidKeyException e) {
throw new RuntimeException("Failed to init Cipher", e);
}
}
Also need to remove the createKey() call from onCreate() too obviously.
I learnt a bit about reflection after reading about it in some tpics here. From what I understands, it is used to check the avaibility of a certain class/method/field at runtime. But is it really useful in Android ? Android provide us with the api version at runtime and we can know if a particular class/method or field is available by reading the Android doc (or with error message with Android Studio).
I understand how it can be useful with Java in general, but is there any meaning to use it in Android?
Reflection (in every languages) is very powerful.
In Android most of time reflection is not needed, because you can find Security Exceptions, problems. It depends on what You do.
If you use undocumented classes, libs, you can use it, and it's very useful.
Sometimes, to do particular things, like turn on/off 3g on old device, change device language, you need rooted device to use reflection.
Finally, depends always on what You do.
Sometimes it works , and some times it does't work .
E.T work example :
You can reflect the method to hang off a phone call (there are a lot example codes on Internet so I won't copy the code.).
Doesn't work example:
If you want to switch data connect status , use reflection works on 4.4 but will not work on 5.0 because it's a binder connection, the BN will check Permission the app granted , but this permission only granted to system app . So if your app is a third part app,on 5.0 you can't use reflection to switch data connect status.
Hope that helps
This is a very general question, it really depends on what you're trying to do. Sometimes you have to use reflection, if the APIs are hidden, all depends on your use case, generally you should avoid reflection as it complicates your code more than its needs to be and its potentially unsafe for further versions of android.
In my opinion it's a good to way to do particular things.
For example you can use the methods of PowerProfile class to do a simple power model for your phone.
By the method getAveragePower(POWER_WIFI_SCAN) you can take the average current in mA consumed by the subsystem (in this case: wi-fi during scan).
So to use PowerProfile's methods for get your battery capacity you you could use java reflection in this way:
private Object mPowerProfile_;
private static final String POWER_PROFILE_CLASS = "com.android.internal.os.PowerProfile";
private Double batteryCapacity = Double.valueOf(1);
public Double getBatteryCapacity(Context ctx) {
try {
mPowerProfile_ = Class.forName(POWER_PROFILE_CLASS).getConstructor(Context.class).newInstance(this);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try {
batteryCapacity = (Double) Class.forName(POWER_PROFILE_CLASS).getMethod("getAveragePower", String.class).invoke(mPowerProfile_, "battery.capacity");
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
Hi I am working with android.I had created a library project in which data fetched from my server.Now I need to provide my library project to a third party developer, So How can I encrypt my server URL to others??
Try this way :
String stringThatNeedsToBeEncrpyted = "PutYourURL";
MessageDigest mdEnc = null;
try {
mdEnc = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} // Encryption algorithm
mdEnc.update(stringThatNeedsToBeEncrpyted.getBytes(), 0, stringThatNeedsToBeEncrpyted.length());
String md5 = new BigInteger(1, mdEnc.digest()).toString(16);
System.out.println(md5);
I think even you encrypt your URL with des and then decrypt it to connect to your server,as your source code is provided to others,then can see it clearly because then can debug your code.
I think , SHA-512 OR BCRYPT is the best mechanism for hashing to prevent hacking from hackers.
please follow one of them.
I am developing an App in which I need to lock screen than if user unlocks, it should ask for password...
Help would be really appreciated.
What you basically need is a way to make sure that the user has a password set for their lock screen. There's no clean way of doing this. No formal API. If you're willing to risk a hack, you can try this. I cobbled it together some code I found on this site.
boolean hasPasswordOnLockScreen(){
String sLockPasswordFilename =
android.os.Environment.getDataDirectory().getAbsolutePath() +
"/system/password.key";
try {
// Check if we can read a byte from the file
RandomAccessFile raf = new RandomAccessFile(filename, "r");
raf.readByte();
raf.close();
return true;
} catch (FileNotFoundException fnfe) {
return false;
} catch (IOException ioe) {
return false;
}
}
Note that this is a hack and has the potential to not work in the future is the path and file name of the password file changes.