Upload
jain-zang
View
31
Download
0
Embed Size (px)
Citation preview
Secure-preferenceshttps://github.com/scottyab/secure-preferences
JainNewegg developer
What is SharedPreferences
• Save and retrieve persistent key-value pairs of primitive data types
• Save any primitive data: booleans, floats, ints, longs, and strings
Why use Secure-preferences
• Protect secret data1.password2.token3.setting
Secure mechanism• Encrypts the values using AES 128, CBC, and
PKCS5
• Each key is stored as a one way SHA 256 hash
• Both keys and values are base64 encoded before storing into prefs xml file
Secure data
How to usepublic SharedPreferences getSharedPreferences() { if(mSecurePrefs==null){ mSecurePrefs = new SecurePreferences(this, "", "my_prefs.xml"); SecurePreferences.setLoggingEnabled(true); } return mSecurePrefs;}
public SharedPreferences getSharedPreferences1000() { try { AesCbcWithIntegrity.SecretKeys myKey = AesCbcWithIntegrity.generateKeyFromPassword( Build.SERIAL,AesCbcWithIntegrity.generateSalt(),1000); return new SecurePreferences(this, myKey, "my_prefs_1000.xml"); } catch (GeneralSecurityException e) { Log.e(TAG, "Failed to create custom key for SecurePreferences", e); } return null;}
How to usepublic SharedPreferences getSharedPreferences() { if(mSecurePrefs==null){ mSecurePrefs = new SecurePreferences(this, "", "my_prefs.xml"); SecurePreferences.setLoggingEnabled(true); } return mSecurePrefs;}
How to usepublic SharedPreferences getSharedPreferences() { if(mSecurePrefs==null){ mSecurePrefs = new SecurePreferences(this, "", "my_prefs.xml"); SecurePreferences.setLoggingEnabled(true); } return mSecurePrefs;}
public SharedPreferences getSharedPreferences1000() { try { AesCbcWithIntegrity.SecretKeys myKey = AesCbcWithIntegrity.generateKeyFromPassword( Build.SERIAL,AesCbcWithIntegrity.generateSalt(),1000); return new SecurePreferences(this, myKey, "my_prefs_1000.xml"); } catch (GeneralSecurityException e) { Log.e(TAG, "Failed to create custom key for SecurePreferences", e); } return null;}
public SecurePreferences getUserPinBasedSharedPreferences(String password){ if(mUserPrefs==null) { mUserPrefs = new SecurePreferences(this, password, "user_prefs.xml"); } return mUserPrefs;}
public void onGetButtonClick(View v) {final String value = getSharedPref().getString(MainActivity.KEY, null);
toast(MainActivity.KEY + "'s, value= " + value);}
public void onSetButtonClick(View v) {getSharedPref().edit().putString(MainActivity.KEY, MainActivity.VALUE)
.commit();toast(MainActivity.KEY + " with enc value:" + MainActivity.VALUE
+ ". Saved");}
public void onRemoveButtonClick(View v) {getSharedPref().edit().remove(MainActivity.KEY).commit();
toast("key:" + MainActivity.KEY + " removed from secure prefs");}
public void onClearAllButtonClick(View v) {getSharedPref().edit().clear().commit();updateEncValueDisplay();
toast("All secure prefs cleared");}
Put valueputString(String key, String value)
hashPrefKey(String prefKey)
encrypt(String cleartext)
encrypt(byte[] plaintext, SecretKeys secretKeys)
new CipherTextIvMac(byteCipherText, iv, integrityMac)
toString()public static CipherTextIvMac encrypt(byte[] plaintext, SecretKeys secretKeys) throws GeneralSecurityException { byte[] iv = generateIv(); Cipher aesCipherForEncryption = Cipher.getInstance(CIPHER_TRANSFORMATION); aesCipherForEncryption.init(Cipher.ENCRYPT_MODE, secretKeys.getConfidentialityKey(), new IvParameterSpec(iv)); /* * Now we get back the IV that will actually be used. Some Android * versions do funny stuff w/ the IV, so this is to work around bugs: */ iv = aesCipherForEncryption.getIV(); byte[] byteCipherText = aesCipherForEncryption.doFinal(plaintext); byte[] ivCipherConcat = CipherTextIvMac.ivCipherConcat(iv, byteCipherText); byte[] integrityMac = generateMac(ivCipherConcat, secretKeys.getIntegrityKey()); return new CipherTextIvMac(byteCipherText, iv, integrityMac);}
putString(String key, String value)
hashPrefKey(String prefKey)
encrypt(String cleartext)
encrypt(byte[] plaintext, SecretKeys secretKeys)
new CipherTextIvMac(byteCipherText, iv, integrityMac)
toString()public String toString() { String ivString = Base64.encodeToString(iv, BASE64_FLAGS); String cipherTextString = Base64.encodeToString(cipherText, BASE64_FLAGS); String macString = Base64.encodeToString(mac, BASE64_FLAGS); return String.format(ivString + ":" + macString + ":" + cipherTextString);}
Put value
Get valuegetInt(String key, int defaultValue)
decrypt(final String ciphertext)
new AesCbcWithIntegrity.CipherTextIvMac(ciphertext)
decryptString(cipherTextIvMac, keys)
public static byte[] decrypt(CipherTextIvMac civ, SecretKeys secretKeys) throws GeneralSecurityException { byte[] ivCipherConcat = CipherTextIvMac.ivCipherConcat(civ.getIv(), civ.getCipherText()); byte[] computedMac = generateMac(ivCipherConcat, secretKeys.getIntegrityKey()); if (constantTimeEq(computedMac, civ.getMac())) { Cipher aesCipherForDecryption = Cipher.getInstance(CIPHER_TRANSFORMATION); aesCipherForDecryption.init(Cipher.DECRYPT_MODE, secretKeys.getConfidentialityKey(), new IvParameterSpec(civ.getIv())); return aesCipherForDecryption.doFinal(civ.getCipherText()); } else { throw new GeneralSecurityException("MAC stored in civ does not match computed MAC."); }}
new String(decrypt(civ, secretKeys), encoding)
Q & A