Android - Use Fingerprint scanner and Cipher to encrypt and decrypt multiple strings - android

I need an end to encrypt different strings and related decryptions after user authenticate using fingerprint scanner.
Following this project (https://github.com/StylingAndroid/UserIdentity/tree/Part1) and changed "tryEncrypt" method like below:
private boolean tryEncrypt(Cipher cipher) {
try {
cipher.doFinal(SECRET_BYTES);
String one = "augusto";
String two = "test#gmail.com";
String three = "3333333331";
byte[] oneEnc = cipher.doFinal(one.getBytes());
byte[] twoEnc = cipher.doFinal(one.getBytes());
byte[] threeEnc = cipher.doFinal(one.getBytes());
Log.d("test", "oneEnc: " + Base64.encodeToString(oneEnc,0));
Log.d("test", "twoEnc: " + Base64.encodeToString(twoEnc,0));
Log.d("test", "threeEnc: " + Base64.encodeToString(threeEnc,0));
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
I'm getting this error:
java.lang.IllegalStateException: IV has already been used. Reusing IV in encryption mode violates security best practices.
What is the correct way on how to do it?
Thanks
*******************UPDATE:*****************************
To help others to get solve this problem I used this library and worked like charm:
https://github.com/Mauin/RxFingerprint

You have a problem because your are using a single instance of the Cipher for multiple encryptions (dofinal). You are using a single vector initialization (IV).
Take a look on an option of how to initialize a cipher.
SecureRandom r = new SecureRandom();
byte[] ivBytes = new byte[16];
r.nextBytes(ivBytes);
cipher.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(ivBytes));
As you can see, you need to specify the initialization vector. The initialization vector can not be repeated to guarantee that the encryption works.
In your scenario, you probably gonna need to perform a new initialization.
*Ps: It's also possible to use the Cipher initialization without the IvParameterSpec. In this scenario, the class will generate one for you. However, I believe that you need to perform a initialization per DoFinal to guarantee some randomness.

To help others to get solve this problem I used this library that worked like charm:
https://github.com/Mauin/RxFingerprint

Related

SQLite Context.MODE_PRIVATE

I want to know:
Can we use Context.MODE_PRIVATE in SQLite while Database creating to protect from unwanted Database access.
I am not getting any example on google.
How to use this Context.MODE_PRIVATE in Database.
Please assist me. Provide any link or sample.
IN THIS LINK they are talking about file. so Database is also file.
How can i implement this?
As commonsware mentioned, SQLite databases on internal storage are private by default. But as mentioned by others rooted phone as always access to your file.
Rather you can use any encryption algorithm to save the data in DB which will help you to restrict the readability unless intruder know the encryption algorithm.
You cant set "Context.MODE_PRIVATE" flag in SQLite.
While creating database, following syntax is useful
openOrCreateDatabase(String path, int mode, SQLiteDatabase.CursorFactory factory)
For example,
openOrCreateDatabase("StudentDB",Context.MODE_PRIVATE,null);
See my tutorial on this site.
Option 1: Use SQLcipher.
Option 2: Secure Method Ever No Chance To Hack. It is not perfect, but it is better than nothing.
1) Insert data using this Function:
public static String getEncryptedString(String message) {
String cipherText = null;
try {
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(("YOUR-SECURE-PASSWORD-KEY").getBytes(), "AES"));
byte[] bytes = cipher.doFinal(message.getBytes());
cipherText = Base64.encodeToString(bytes, Base64.DEFAULT);
} catch(Exception ex) {
cipherText = "Error in encryption";
Log.e(TAG , ex.getMessage());
ex.printStackTrace();
}
return cipherText;
}
2) Get data from the database and pass into this function parameter:
//This function returns output string
public static String getDecryptedString(String encoded) {
String decryptString = null;
try {
byte[] bytes = Base64.decode(encoded, Base64.DEFAULT);
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(("YOUR-SECURE-PASSWORD-KEY").getBytes() , "AES"));
decryptString = new String(cipher.doFinal(bytes), "UTF-8");
} catch(Exception ex) {
decryptString = "Error in decryption";
ex.printStackTrace();
}
return decryptString;
}
3) Benefits of these methods:
- Not possible to decrypt without the right Key.
- AES Encryption is a very secure encryption method.
4) Store your AES key in the c++ file.

How to Encrypt Session Values in Android

I'm developing an Android app which based on a web-server. Users, who installed the app, should register on web, so they can login. When someone try to login I verify their information with API.
So I'm curious about persisting and encryption processes. Should I encrypt the values or just put them all to SharedPreferences? If encryption is needed what's the efficient way?
And last but not least, Is SharedPreferences enough in terms of security?
Thanks.
Encryption is easy, but the real question is with what key? If you hardcode the key in the app, or derive it from some known value, anyone with access to the device can easily decrypt those values. What you are achieving is merely obfuscation. Since Android doesn't have a public API to the system keystore, there is not much else you can do if you need to save the actual password. Unless of course you make the user input a password each time they start the app, which kind of defeats the purpose.
If you control both the server and the client, another approach is to use some form of token-based authentication and only save the token. Since tokens can expire and be revoked, the damage by someone getting hold of your token is much less, than exposing an actual password (which may be used on other sites as well).
Of course you should encrypt user settings like login, password or maybe email. I prefer SharedPreferences for storing, and yes it's enough in terms of security.
I've found this two method on StackOverflow, it's fair enough:
protected String encrypt( String value ) {
try {
final byte[] bytes = value!=null ? value.getBytes(UTF8) : new byte[0];
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
SecretKey key = keyFactory.generateSecret(new PBEKeySpec(SEKRIT));
Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");
pbeCipher.init(Cipher.ENCRYPT_MODE, key, new PBEParameterSpec(Settings.Secure.getString(context.getContentResolver(),Settings.System.ANDROID_ID).getBytes(UTF8), 20));
return new String(Base64.encode(pbeCipher.doFinal(bytes), Base64.NO_WRAP),UTF8);
} catch( Exception e ) {
throw new RuntimeException(e);
}
}
protected String decrypt(String value){
try {
final byte[] bytes = value!=null ? Base64.decode(value,Base64.DEFAULT) : new byte[0];
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
SecretKey key = keyFactory.generateSecret(new PBEKeySpec(SEKRIT));
Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");
pbeCipher.init(Cipher.DECRYPT_MODE, key, new PBEParameterSpec(Settings.Secure.getString(context.getContentResolver(),Settings.System.ANDROID_ID).getBytes(UTF8), 20));
return new String(pbeCipher.doFinal(bytes),UTF8);
} catch( Exception e) {
throw new RuntimeException(e);
}
}
Couldn't find link, if I found, I'll edit my answer.
Edit: I found the source, you may have a look at all discussion on here.

Not implemented yet: DSA public key

I'm writing both a server and an Android client application. The Android client sends measurements to the server. In order to ensure the data integrity, a digital signature is appended to each measurement.
Since I need everything to be Gson-compatible, storing the public key itself is not possible. I'm storing the G, P, Q and Y factors instead.
Here's a snippet from the request class:
public PublicKey getPublicKey() {
try {
DSAPublicKeySpec keySpec = new DSAPublicKeySpec(publicKeyY, publicKeyP,
publicKeyQ, publicKeyG);
KeyFactory fact = KeyFactory.getInstance("DSA");
PublicKey pubKey = fact.generatePublic(keySpec); // A
return pubKey;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public void setPublicKey(PublicKey publicKey) {
try {
KeyFactory fact = KeyFactory.getInstance("DSA");
DSAPublicKeySpec pub = fact.getKeySpec(publicKey, DSAPublicKeySpec.class); // B
publicKeyG = pub.getG();
publicKeyP = pub.getP();
publicKeyQ = pub.getQ();
publicKeyY = pub.getY();
} catch (Exception e) {
e.printStackTrace();
}
}
The constructor makes use of the setPublicKey-method. When I create such request on the client side and send it to the server, both result in an exception.
On the client:
java.lang.RuntimeException: not implemented yet DSA Public Key
y: 2f9286201b266f38d682e99814612f7d37c575d3a210de114bdf02092f4a835109f28a590cfc568bb6525d59b8275fe791f3ddf20e85df44fd2e8622289f6dbc27c73d31d1769feae19573df22a9ca8ef80a9f7230b0b4a2671cc03fdb2788b55b4e9a68a7a5a93a214cc5aa39ccb5155a13354870d45a38760a80fd34333073
class java.security.spec.DSAPublicKeySpec
at org.bouncycastle.jce.provider.JDKKeyFactory.engineGetKeySpec(JDKKeyFactory.java:148)
at java.security.KeyFactory.getKeySpec(KeyFactory.java:210)
Next thing in the stack trace points at the rule I marked as B
On the server:
java.lang.NullPointerException
at sun.security.provider.DSAPublicKey.<init>(DSAPublicKey.java:74)
at sun.security.provider.DSAPublicKeyImpl.<init>(DSAPublicKeyImpl.java:46)
at sun.security.provider.DSAKeyFactory.engineGeneratePublic(DSAKeyFactory.java:86)
at java.security.KeyFactory.generatePublic(KeyFactory.java:304)
at sensserve.protocol.StartSessionRequest.getPublicKey(StartSessionRequest.java:66)
Nextly pointing to the rule A.
I absolutely have no clue what I did wrong and what these messages mean. How can I solve these? Anyone who can tell me what I'm doing wrong?
Thanks a lot.
You should be able to store the public key in Base64 encoded from and still get valid JSON. You should be able to use DSAPublicKeySpec directly without calling getKeySpec() which apparently is not implemented in Bouncy Castle (Android's JCE provider). Not sure why you are getting NPE on the server, maybe wrong format. BTW, it will probably be easier if you are dealing with a single provider, so you might want to use Bouncy Castle on the server as well.

sqlite encryption for android

i'm looking very hard for a possibility to encrypt my sqlite database on Android devices, but I was't able to find a satisfying solution.
I need something like a libary to reference, in order to have a "on the fly" encryption/decryption of my database, while using the normal sqlite functions.
I don't want to encrypt data before storing.
I don't want to encrypt the whole databasefile, in order to decrypt it before using.
I know about the following projects:
SEE
wxSQLite
SQLCipher
SQLiteCrypt
Botan
But I can't find any working example for this stuff.
Btw, I'm absolutly willing to purchase a commercial build, but I have to test ist before spending a few hundred dollars.
Did anyone solve this issue for his own?
Try the SQLCipher port to Android instead of the regular SQLCipher.
litereplica supports encryption using the ChaCha cipher, faster than AES on portable devices.
There are bindings for Android.
To create and open an encrypted database we use an URI like this:
"file:/path/to/file.db?cipher=...&key=..."
If anyone is still looking:
Override SQLiteOpenHelper function as below:
void onConfigure(SQLiteDatabase db){
db.execSQL("PRAGMA key = 'secretkey'");
}
private String encrypt(String password) {
try {
SecretKeySpec keySpec = generateKey(password);
Cipher c = Cipher.getInstance("AES");
c.init(Cipher.ENCRYPT_MODE,keySpec);
byte[] encVal = c.doFinal(password.getBytes());
String encryptedValue = Base64.encodeToString(encVal,Base64.DEFAULT);
return encryptedValue;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
private SecretKeySpec generateKey(String password) throws Exception {
final MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] bytes = password.getBytes(StandardCharsets.UTF_8);
digest.update(bytes,0,bytes.length);
byte[] key = digest.digest();
SecretKeySpec secretKeySpec = new SecretKeySpec(key,"AES");
return secretKeySpec;
}
I just used the encrypt function to encrypt the password. Here I used the user's password as a key. Therefore I don't need to keep the key inside the application. When the user wants to log in, simply encrypt the password and try to match with the encrypted password in the database and allow them to log in.

How to Generate HMAC MD5 In Android?

I am new in this Field!I have this Message and Key also i want HMAC MD5 using this two so how it is possible if possible then give some example or sample code of this.The Given link display the overall functionality i want such kind of code.Please help me.
Messgae = POSTuserMon,28Jun201010:18:33GMT7FF4471B-13C0-5A9F-BB7B-7309F1AB7F08
key = d6fc3a4a06ed55d24fecde188aaa9161
Link = http://hash.online-convert.com/md5-generator
Here are working codes.
Generated result is same as Link = http://hash.online-convert.com/md5-generator
public String calcHmac(String src) throws Exception {
String key = "d6fc3a4a06ed55d24fecde188aaa9161";
Mac mac = Mac.getInstance("HmacSHA1");
SecretKeySpec sk = new SecretKeySpec(key.getBytes(),mac.getAlgorithm());
mac.init(sk);
byte[] result = mac.doFinal(src.getBytes());
return Base64.encodeToString(result ,Base64.URL_SAFE);
}
Look at the javax.crypto.Mac class. Try Mac.getInstance("HmacMD5"); and then use the init method with your key and then use the update and doFinal methods just as you would with a MessageDigest object.

Categories

Resources