User password is now stored encrypted

This commit is contained in:
Juan Miguel Boyero Corral 2013-09-12 20:35:29 +02:00
parent eb6a52f097
commit 892712e6cb
6 changed files with 84 additions and 53 deletions

View File

@ -8,5 +8,5 @@
# project structure. # project structure.
# Project target. # Project target.
target=android-17 target=android-18
android.library=false android.library=false

View File

@ -20,8 +20,10 @@
package es.ugr.swad.swadroid; package es.ugr.swad.swadroid;
import android.accounts.Account; import android.accounts.Account;
import android.app.AlertDialog;
import android.content.ContentResolver; import android.content.ContentResolver;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor; import android.content.SharedPreferences.Editor;
@ -35,14 +37,15 @@ import android.preference.Preference.OnPreferenceClickListener;
import android.preference.PreferenceActivity; import android.preference.PreferenceActivity;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.util.Log; import android.util.Log;
import com.bugsense.trace.BugSenseHandler; import com.bugsense.trace.BugSenseHandler;
import es.ugr.swad.swadroid.model.DataBaseHelper; import es.ugr.swad.swadroid.model.DataBaseHelper;
import es.ugr.swad.swadroid.sync.SyncUtils; import es.ugr.swad.swadroid.sync.SyncUtils;
import es.ugr.swad.swadroid.utils.Base64; import es.ugr.swad.swadroid.utils.Crypto;
import es.ugr.swad.swadroid.utils.Utils; import es.ugr.swad.swadroid.utils.Utils;
import es.ugr.swad.swadroid.widget.SeekBarDialogPreference; import es.ugr.swad.swadroid.widget.SeekBarDialogPreference;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
/** /**
@ -51,6 +54,10 @@ import java.security.NoSuchAlgorithmException;
* @author Juan Miguel Boyero Corral <juanmi1982@gmail.com> * @author Juan Miguel Boyero Corral <juanmi1982@gmail.com>
*/ */
public class Preferences extends PreferenceActivity implements OnPreferenceChangeListener { public class Preferences extends PreferenceActivity implements OnPreferenceChangeListener {
/**
* Login tag name for Logcat
*/
public static final String TAG = Constants.APP_TAG + " Preferences";
/** /**
* Application preferences * Application preferences
*/ */
@ -340,20 +347,29 @@ public class Preferences extends PreferenceActivity implements OnPreferenceChang
} }
/** /**
* Encrypts user password with SHA-512 and encodes it to Base64UrlSafe * Shows an error message.
* *
* @param password Password to be encrypted * @param message Error message to show.
* @return Encrypted password
* @throws NoSuchAlgorithmException
*/ */
private String encryptPassword(String password) throws NoSuchAlgorithmException { protected void error(String tag, String message, Exception ex, boolean sendException) {
String p; new AlertDialog.Builder(this)
MessageDigest md = MessageDigest.getInstance("SHA-512"); .setTitle(R.string.title_error_dialog)
md.update(password.getBytes()); .setMessage(message)
p = Base64.encodeBytes(md.digest()); .setNeutralButton(R.string.close_dialog,
p = p.replace('+', '-').replace('/', '_').replace('=', ' ').replaceAll("\\s+", "").trim(); new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
finish();
}
}).setIcon(R.drawable.erroricon).show();
return p; if (ex != null) {
ex.printStackTrace();
// Send exception details to Bugsense
if (sendException) {
BugSenseHandler.sendExceptionMessage(tag, message, ex);
}
}
} }
/** /**
@ -362,16 +378,11 @@ public class Preferences extends PreferenceActivity implements OnPreferenceChang
* @throws NoSuchAlgorithmException * @throws NoSuchAlgorithmException
*/ */
public void upgradeCredentials() throws NoSuchAlgorithmException { public void upgradeCredentials() throws NoSuchAlgorithmException {
String stars = getStarsSequence(STARS_LENGTH);
editor = prefs.edit(); editor = prefs.edit();
userPassword = prefs.getString(USERPASSWORDPREF, ""); userPassword = prefs.getString(USERPASSWORDPREF, "");
userPassword = encryptPassword(userPassword); userPassword = Crypto.encryptPassword(userPassword);
editor.putString(USERPASSWORDPREF, userPassword); editor.putString(USERPASSWORDPREF, userPassword);
editor.commit(); editor.commit();
userIDPref.setSummary(prefs.getString(USERIDPREF, ""));
userPasswordPref.setSummary(stars);
} }
/** /**
@ -513,7 +524,11 @@ public class Preferences extends PreferenceActivity implements OnPreferenceChang
*/ */
public boolean onPreferenceClick(Preference preference) { public boolean onPreferenceClick(Preference preference) {
userPassword = prefs.getString(USERPASSWORDPREF, ""); userPassword = prefs.getString(USERPASSWORDPREF, "");
//userPassword = encryptPassword(userPassword); try {
userPassword = Crypto.encryptPassword(userPassword);
} catch (NoSuchAlgorithmException ex) {
error(TAG, ex.getMessage(), ex, true);
}
editor.putString(USERPASSWORDPREF, userPassword); editor.putString(USERPASSWORDPREF, userPassword);
return true; return true;
} }

View File

@ -247,8 +247,8 @@ public class SWADMain extends MenuExpandableListActivity {
lastVersion = prefs.getLastVersion(); lastVersion = prefs.getLastVersion();
currentVersion = getPackageManager().getPackageInfo(getPackageName(), 0).versionCode; currentVersion = getPackageManager().getPackageInfo(getPackageName(), 0).versionCode;
dbHelper.initializeDB(); dbHelper.initializeDB();
//lastVersion = 45; //lastVersion = 51;
//currentVersion = 46; //currentVersion = 52;
//If this is the first run, show configuration dialog //If this is the first run, show configuration dialog
if (lastVersion == 0) { if (lastVersion == 0) {
@ -273,12 +273,19 @@ public class SWADMain extends MenuExpandableListActivity {
//showUpgradeDialog(); //showUpgradeDialog();
dbHelper.upgradeDB(this); dbHelper.upgradeDB(this);
//If the app is updating from an unencrypted user password version, encrypt user password
if(lastVersion < 52) {
prefs.upgradeCredentials();
}
//If the app is updating from an unencrypted version, encrypt already downloaded notifications //If the app is updating from an unencrypted version, encrypt already downloaded notifications
if (lastVersion < 45) { if (lastVersion < 45) {
dbHelper.encryptNotifications(); dbHelper.encryptNotifications();
//If the app is updating from the bugged encrypted version, /*
//re-encrypt the notifications using the new method * If the app is updating from the bugged encrypted version,
* re-encrypt the notifications using the new method
*/
} else if (lastVersion == 45) { } else if (lastVersion == 45) {
dbHelper.reencryptNotifications(); dbHelper.reencryptNotifications();
} }

View File

@ -20,18 +20,18 @@
package es.ugr.swad.swadroid.modules; package es.ugr.swad.swadroid.modules;
import android.os.Bundle; import android.os.Bundle;
import android.util.Log;
import es.ugr.swad.swadroid.Constants; import es.ugr.swad.swadroid.Constants;
import es.ugr.swad.swadroid.R; import es.ugr.swad.swadroid.R;
import es.ugr.swad.swadroid.model.User; import es.ugr.swad.swadroid.model.User;
import es.ugr.swad.swadroid.modules.rollcall.RollCallUtil; import es.ugr.swad.swadroid.utils.Utils;
import es.ugr.swad.swadroid.utils.Base64;
import org.ksoap2.SoapFault; import org.ksoap2.SoapFault;
import org.ksoap2.serialization.KvmSerializable; import org.ksoap2.serialization.KvmSerializable;
import org.ksoap2.serialization.SoapObject; import org.ksoap2.serialization.SoapObject;
import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException; import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
/** /**
@ -48,7 +48,7 @@ public class Login extends Module {
/** /**
* Digest for user password. * Digest for user password.
*/ */
private MessageDigest md; //private MessageDigest md;
/** /**
* User ID. * User ID.
*/ */
@ -56,7 +56,7 @@ public class Login extends Module {
/** /**
* User password. * User password.
*/ */
private String userPassword; //private String userPassword;
/** /**
* Login tag name for Logcat * Login tag name for Logcat
*/ */
@ -91,16 +91,6 @@ public class Login extends Module {
startConnection(false, progressDescription, progressTitle); startConnection(false, progressDescription, progressTitle);
} }
private static boolean isInteger(String str) {
try {
Integer.parseInt(str);
return true;
} catch (NumberFormatException nfe) {
nfe.printStackTrace();
}
return false;
}
/** /**
* Connects to SWAD and gets user data. * Connects to SWAD and gets user data.
* *
@ -123,27 +113,28 @@ public class Login extends Module {
userID = prefs.getUserID().trim(); userID = prefs.getUserID().trim();
//If the user ID is a DNI //If the user ID is a DNI
if (RollCallUtil.isValidDni(userID)) { if (Utils.isValidDni(userID)) {
//If the DNI has no letter, remove left zeros //If the DNI has no letter, remove left zeros
if (isInteger(userID)) { if (Utils.isInteger(userID)) {
userID = String.valueOf(Integer.parseInt(userID)); userID = String.valueOf(Integer.parseInt(userID));
//If the last position of the DNI is a char, remove it //If the last position of the DNI is a char, remove it
} else if (isInteger(userID.substring(0, userID.length() - 1))) { } else if (Utils.isInteger(userID.substring(0, userID.length() - 1))) {
userID = String.valueOf(Integer.parseInt(userID.substring(0, userID.length() - 1))); userID = String.valueOf(Integer.parseInt(userID.substring(0, userID.length() - 1)));
} }
} }
//Encrypts user password with SHA-512 and encodes it to Base64UrlSafe //Encrypts user password with SHA-512 and encodes it to Base64UrlSafe
md = MessageDigest.getInstance("SHA-512"); /*md = MessageDigest.getInstance("SHA-512");
md.update(prefs.getUserPassword().getBytes()); md.update(prefs.getUserPassword().getBytes());
userPassword = Base64.encodeBytes(md.digest()); userPassword = Base64.encodeBytes(md.digest());
userPassword = userPassword.replace('+', '-').replace('/', '_').replace('=', ' ').replaceAll("\\s+", "").trim(); userPassword = userPassword.replace('+', '-').replace('/', '_').replace('=', ' ').replaceAll("\\s+", "").trim();*/
//Creates webservice request, adds required params and sends request to webservice //Creates webservice request, adds required params and sends request to webservice
createRequest(); createRequest();
addParam("userID", userID); addParam("userID", userID);
addParam("userPassword", userPassword); //addParam("userPassword", userPassword);
addParam("userPassword", prefs.getUserPassword());
addParam("appKey", Constants.SWAD_APP_KEY); addParam("appKey", Constants.SWAD_APP_KEY);
sendRequest(User.class, true); sendRequest(User.class, true);

View File

@ -36,7 +36,6 @@ import es.ugr.swad.swadroid.model.DataBaseHelper;
import es.ugr.swad.swadroid.model.SWADNotification; import es.ugr.swad.swadroid.model.SWADNotification;
import es.ugr.swad.swadroid.model.User; import es.ugr.swad.swadroid.model.User;
import es.ugr.swad.swadroid.ssl.SecureConnection; import es.ugr.swad.swadroid.ssl.SecureConnection;
import es.ugr.swad.swadroid.utils.Base64;
import org.ksoap2.SoapEnvelope; import org.ksoap2.SoapEnvelope;
import org.ksoap2.SoapFault; import org.ksoap2.SoapFault;
import org.ksoap2.serialization.KvmSerializable; import org.ksoap2.serialization.KvmSerializable;
@ -47,7 +46,6 @@ import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException; import java.io.IOException;
import java.security.KeyManagementException; import java.security.KeyManagementException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Vector; import java.util.Vector;
@ -322,14 +320,14 @@ public class NotificationsSyncAdapterService extends Service {
Log.d(TAG, "Not logged"); Log.d(TAG, "Not logged");
METHOD_NAME = "loginByUserPasswordKey"; METHOD_NAME = "loginByUserPasswordKey";
MessageDigest md = MessageDigest.getInstance("SHA-512"); /* MessageDigest md = MessageDigest.getInstance("SHA-512");
md.update(prefs.getUserPassword().getBytes()); md.update(prefs.getUserPassword().getBytes());
String userPassword = Base64.encodeBytes(md.digest()); String userPassword = Base64.encodeBytes(md.digest());
userPassword = userPassword.replace('+', '-').replace('/', '_').replace('=', ' ').replaceAll("\\s+", "").trim(); userPassword = userPassword.replace('+', '-').replace('/', '_').replace('=', ' ').replaceAll("\\s+", "").trim();*/
createRequest(); createRequest();
addParam("userID", prefs.getUserID()); addParam("userID", prefs.getUserID());
addParam("userPassword", userPassword); addParam("userPassword", prefs.getUserPassword());
addParam("appKey", Constants.SWAD_APP_KEY); addParam("appKey", Constants.SWAD_APP_KEY);
sendRequest(true); sendRequest(true);

View File

@ -27,6 +27,9 @@ import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory; import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec; import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec; import javax.crypto.spec.PBEParameterSpec;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.spec.AlgorithmParameterSpec; import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.KeySpec; import java.security.spec.KeySpec;
@ -137,4 +140,21 @@ public class Crypto {
private static void appendHex(StringBuffer sb, byte b) { private static void appendHex(StringBuffer sb, byte b) {
sb.append(HEX.charAt((b >> 4) & 0x0f)).append(HEX.charAt(b & 0x0f)); sb.append(HEX.charAt((b >> 4) & 0x0f)).append(HEX.charAt(b & 0x0f));
} }
/**
* Encrypts user password with SHA-512 and encodes it to Base64UrlSafe
*
* @param password Password to be encrypted
* @return Encrypted password
* @throws NoSuchAlgorithmException
*/
public static String encryptPassword(String password) throws NoSuchAlgorithmException {
String p;
MessageDigest md = MessageDigest.getInstance("SHA-512");
md.update(password.getBytes());
p = Base64.encodeBytes(md.digest());
p = p.replace('+', '-').replace('/', '_').replace('=', ' ').replaceAll("\\s+", "").trim();
return p;
}
} }