Implemented Crypto
for better (not the best) password saving
This commit is contained in:
parent
e2421ae720
commit
974ffcdd7b
3 changed files with 109 additions and 26 deletions
|
@ -1,11 +1,22 @@
|
|||
package info.nerull7.mysqlbrowser;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Base64;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.nio.charset.Charset;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.Key;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.spec.KeySpec;
|
||||
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.Cipher;
|
||||
|
@ -13,57 +24,83 @@ import javax.crypto.IllegalBlockSizeException;
|
|||
import javax.crypto.KeyGenerator;
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.PBEKeySpec;
|
||||
|
||||
/**
|
||||
* Created by nerull7 on 28.07.14.
|
||||
*/
|
||||
public class Crypto {
|
||||
private static final String KEY_FILE = "null_file"; // to trick h4x0r5
|
||||
// private static final String ENCRYPTION_ALGORITHM = "AES/CBC/PKCS5Padding"; // doesn't work TODO: Maybe fix?
|
||||
private static final String ENCRYPTION_ALGORITHM = "AES";
|
||||
private static final String KEY_ALGORITHM = "AES";
|
||||
private static final int OUTPUT_KEY_LENGTH = 256;
|
||||
|
||||
private static SecretKey secretKey;
|
||||
private SecretKey secretKey;
|
||||
private Context context;
|
||||
|
||||
private static SecretKey generateKey() throws NoSuchAlgorithmException {
|
||||
public Crypto(Context context){
|
||||
this.context = context;
|
||||
|
||||
try {
|
||||
getSecretKey();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private SecretKey generateKey() throws NoSuchAlgorithmException {
|
||||
SecureRandom secureRandom = new SecureRandom();
|
||||
|
||||
KeyGenerator keyGenerator = KeyGenerator.getInstance(ENCRYPTION_ALGORITHM);
|
||||
KeyGenerator keyGenerator = KeyGenerator.getInstance(KEY_ALGORITHM);
|
||||
keyGenerator.init(OUTPUT_KEY_LENGTH, secureRandom);
|
||||
SecretKey secretKey = keyGenerator.generateKey();
|
||||
|
||||
return secretKey;
|
||||
}
|
||||
|
||||
private static SecretKey getSecretKey() throws NoSuchAlgorithmException {
|
||||
if(secretKey==null)
|
||||
secretKey = generateKey();
|
||||
private void getSecretKey() throws NoSuchAlgorithmException, IOException, ClassNotFoundException {
|
||||
String key;
|
||||
|
||||
Log.d("SecureKEY", "Hash:" + secretKey.hashCode());
|
||||
return secretKey;
|
||||
// First try to open file
|
||||
File keyFile = new File(context.getFilesDir(), KEY_FILE);
|
||||
if(!keyFile.exists()) { // new key
|
||||
secretKey = generateKey();
|
||||
FileOutputStream fileOutputStream = new FileOutputStream(keyFile);
|
||||
ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
|
||||
objectOutputStream.writeObject(secretKey);
|
||||
objectOutputStream.close();
|
||||
fileOutputStream.close();
|
||||
} else { // read existing key from file
|
||||
FileInputStream fileInputStream = new FileInputStream(keyFile);
|
||||
ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
|
||||
secretKey = (SecretKey) objectInputStream.readObject();
|
||||
objectInputStream.close();
|
||||
fileInputStream.close();
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] encrypt(String input) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
|
||||
public byte[] encrypt(String input) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
|
||||
byte[] output;
|
||||
Cipher cipher = Cipher.getInstance(ENCRYPTION_ALGORITHM);
|
||||
cipher.init(Cipher.ENCRYPT_MODE, getSecretKey());
|
||||
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
|
||||
output = cipher.doFinal(input.getBytes(Charset.defaultCharset()));
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
public static String decrypt(byte[] input) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
|
||||
public String decrypt(byte[] input) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
|
||||
String output;
|
||||
byte [] tmp; // TODO: REMOVE
|
||||
|
||||
Cipher cipher = Cipher.getInstance(ENCRYPTION_ALGORITHM);
|
||||
cipher.init(Cipher.DECRYPT_MODE, getSecretKey());
|
||||
// output = String.valueOf(cipher.doFinal(input));
|
||||
tmp = cipher.doFinal(input);
|
||||
|
||||
// output = tmp.toString();
|
||||
output = new String(input, Charset.defaultCharset());
|
||||
cipher.init(Cipher.DECRYPT_MODE, secretKey);
|
||||
output = new String(cipher.doFinal(input), Charset.defaultCharset());
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
public String decryptBase64(String encodedString) throws IllegalBlockSizeException, InvalidKeyException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException {
|
||||
byte [] encryptedString = Base64.decode(encodedString, Base64.DEFAULT);
|
||||
String decrypted = decrypt(encryptedString);
|
||||
return decrypted;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,8 +63,14 @@ public class LoginFragment extends Fragment implements View.OnClickListener, Asy
|
|||
if(sharedPreferences.getBoolean(SettingsFragment.SAVE_SERVER_CREDENTIALS, false)){
|
||||
urlTextbox.setText(sharedPreferences.getString(SettingsFragment.URL_CREDENTIALS, null));
|
||||
loginTextbox.setText(sharedPreferences.getString(SettingsFragment.LOGIN_CREDENTIALS, null));
|
||||
passwordTextbox.setText(sharedPreferences.getString(SettingsFragment.PASSWORD_CREDENTIALS, null));
|
||||
test(urlTextbox.getText().toString());
|
||||
Crypto crypto = new Crypto(getActivity());
|
||||
String password = sharedPreferences.getString(SettingsFragment.PASSWORD_CREDENTIALS, null);
|
||||
if(password!=null) {
|
||||
try {
|
||||
passwordTextbox.setText(crypto.decryptBase64(password));
|
||||
} catch (Exception e) { e.printStackTrace(); }
|
||||
}
|
||||
// test(urlTextbox.getText().toString());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -72,10 +78,9 @@ public class LoginFragment extends Fragment implements View.OnClickListener, Asy
|
|||
String tmp;
|
||||
byte [] tmp_byte;
|
||||
try {
|
||||
tmp_byte = Crypto.encrypt(text);
|
||||
Log.d("Crypto", "encrypted: " + tmp_byte);
|
||||
tmp = Crypto.decrypt(tmp_byte);
|
||||
Log.d("Crypto", "decrypted: " + tmp);
|
||||
Crypto crypto = new Crypto(getActivity());
|
||||
tmp_byte = crypto.encrypt(text);
|
||||
crypto.decrypt(tmp_byte);
|
||||
} catch (Exception e) { e.printStackTrace(); }
|
||||
}
|
||||
|
||||
|
|
|
@ -7,11 +7,19 @@ import android.preference.EditTextPreference;
|
|||
import android.preference.Preference;
|
||||
import android.preference.PreferenceFragment;
|
||||
import android.preference.PreferenceScreen;
|
||||
import android.util.Base64;
|
||||
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
|
||||
/**
|
||||
* Created by nerull7 on 18.07.14.
|
||||
*/
|
||||
public class SettingsFragment extends PreferenceFragment implements NumberPickerDialog.OnNumberSetListener, Preference.OnPreferenceClickListener {
|
||||
public class SettingsFragment extends PreferenceFragment implements NumberPickerDialog.OnNumberSetListener, Preference.OnPreferenceClickListener, Preference.OnPreferenceChangeListener {
|
||||
public static final String ENTRIES_PAGE_LIMIT = "entries_limit";
|
||||
public static final String SAVE_SERVER_CREDENTIALS = "save_credentials_enabled";
|
||||
public static final String URL_CREDENTIALS = "url";
|
||||
|
@ -29,10 +37,13 @@ public class SettingsFragment extends PreferenceFragment implements NumberPicker
|
|||
private EditTextPreference loginCredentials;
|
||||
private EditTextPreference passwordCredentials;
|
||||
|
||||
private Crypto crypto;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState){
|
||||
super.onCreate(savedInstanceState);
|
||||
preferences = getPreferenceManager().getDefaultSharedPreferences(getActivity());
|
||||
crypto = new Crypto(getActivity());
|
||||
|
||||
loadPrefs();
|
||||
}
|
||||
|
@ -49,9 +60,11 @@ public class SettingsFragment extends PreferenceFragment implements NumberPicker
|
|||
|
||||
// Settings fields
|
||||
setEntriesPageLimitSummary();
|
||||
setPasswordCredentials();
|
||||
|
||||
// Settings Listener
|
||||
saveCredentials.setOnPreferenceClickListener(this);
|
||||
passwordCredentials.setOnPreferenceChangeListener(this);
|
||||
}
|
||||
|
||||
private void setSaveServerCredentials(boolean isEnabled){
|
||||
|
@ -85,6 +98,26 @@ public class SettingsFragment extends PreferenceFragment implements NumberPicker
|
|||
mEntriesLimit.setSummary(getString(R.string.entries_summary, getEntriesPageLimit()));
|
||||
}
|
||||
|
||||
private void setPasswordCredentials(){
|
||||
String password;
|
||||
password = preferences.getString(PASSWORD_CREDENTIALS, null);
|
||||
if(password != null)
|
||||
try {
|
||||
passwordCredentials.setText(crypto.decryptBase64(password));
|
||||
} catch (Exception e) { e.printStackTrace(); } // TODO: Something useful
|
||||
}
|
||||
|
||||
private void savePassword(String password){
|
||||
try {
|
||||
SharedPreferences.Editor editor = preferences.edit();
|
||||
byte [] encryptedPassword;
|
||||
encryptedPassword = crypto.encrypt(password);
|
||||
String passwordBase64 = Base64.encodeToString(encryptedPassword, Base64.DEFAULT);
|
||||
editor.putString(PASSWORD_CREDENTIALS, passwordBase64);
|
||||
editor.apply();
|
||||
} catch (Exception e) { e.printStackTrace(); } // TODO: Something useful
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
|
||||
if(preference == mEntriesLimit){
|
||||
|
@ -112,4 +145,12 @@ public class SettingsFragment extends PreferenceFragment implements NumberPicker
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
if(preference == passwordCredentials){
|
||||
savePassword((String) newValue);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue