Added encryption to notifications

This commit is contained in:
Juan Miguel Boyero Corral 2012-12-01 22:07:45 +01:00
parent a8be09643e
commit 15e4a004a8
10 changed files with 215 additions and 61 deletions

View File

@ -36,7 +36,7 @@ public class Global {
/**
* SWAD application key
*/
private static final String AppKey = ""; //DELETE BEFORE COMMIT!!!
private static final String AppKey = ""; //DELETE THE KEY BEFORE COMMIT!!!
/**
* Server URL
*/

View File

@ -36,6 +36,7 @@ import android.preference.PreferenceActivity;
import android.preference.PreferenceManager;
import es.ugr.swad.swadroid.modules.Courses;
import es.ugr.swad.swadroid.modules.notifications.Notifications;
import es.ugr.swad.swadroid.utils.Base64;
/**
* Preferences window of application.

View File

@ -43,6 +43,8 @@ import android.widget.SimpleCursorAdapter;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import es.ugr.swad.swadroid.gui.ImageExpandableListAdapter;
import es.ugr.swad.swadroid.gui.MenuExpandableListActivity;
import es.ugr.swad.swadroid.model.Course;
import es.ugr.swad.swadroid.model.DataBaseHelper;
import es.ugr.swad.swadroid.model.Model;
@ -316,6 +318,7 @@ public class SWADMain extends MenuExpandableListActivity {
} else if(lastVersion < currentVersion) {
//showUpgradeDialog();
dbHelper.upgradeDB(this);
dbHelper.encryptNotifications();
//prefs.upgradeCredentials();
//Configure automatic synchronization

View File

@ -44,6 +44,8 @@ import com.android.dataframework.Entity;
import es.ugr.swad.swadroid.Global;
//import es.ugr.swad.swadroid.Preferences;
import es.ugr.swad.swadroid.Preferences;
import es.ugr.swad.swadroid.utils.Crypto;
/**
* @author Juan Miguel Boyero Corral <juanmi1982@gmail.com>
@ -62,19 +64,19 @@ public class DataBaseHelper {
/**
* Application preferences
*/
//private Preferences prefs = new Preferences();
private Preferences prefs = new Preferences();
/**
* Database name
*/
//private String DBName = "swadroid_db";
//private String DBName = "swadroid_db_crypt";
/**
* Database passphrase
*/
//private String DBKey;
private String DBKey;
/**
* Database passphrase length
*/
//private int DB_KEY_LENGTH = 128;
private int DB_KEY_LENGTH = 128;
/**
* Constructor
@ -82,24 +84,13 @@ public class DataBaseHelper {
*/
public DataBaseHelper(Context ctx) {
mCtx = ctx;
//prefs.getPreferences(mCtx);
//DBKey = prefs.getDBKey();
prefs.getPreferences(mCtx);
DBKey = prefs.getDBKey();
db = DataFramework.getInstance();
//Initialize SQLCipher libraries
//SQLiteDatabase.loadLibs(mCtx);
//If the passphrase is empty, generate a random passphrase and recreate database
/*if(DBKey.equals("")) {
DBKey = Global.randomString(DB_KEY_LENGTH);
prefs.setDBKey(DBKey);
mCtx.deleteDatabase(DBName);
SQLiteDatabase database = SQLiteDatabase.openOrCreateDatabase(mCtx.getDatabasePath("swadroid_db_crypt"), DBKey, null);
database.close();
}
Log.d("DataBaseHelper", "DBKey=" + DBKey);*/
try {
//db.open(mCtx, mCtx.getPackageName(), DBKey);
db.open(mCtx, mCtx.getPackageName());
@ -108,6 +99,18 @@ public class DataBaseHelper {
} catch (IOException e) {
e.printStackTrace();
}
//If the passphrase is empty, generate a random passphrase and recreate database
if(DBKey.equals("")) {
DBKey = Global.randomString(DB_KEY_LENGTH);
prefs.setDBKey(DBKey);
/*mCtx.deleteDatabase(DBName);
SQLiteDatabase database = SQLiteDatabase.openOrCreateDatabase(mCtx.getDatabasePath("swadroid_db_crypt"), DBKey, null);
database.close();*/
}
//Log.d("DataBaseHelper", "DBKey=" + DBKey);
}
/**
@ -207,16 +210,16 @@ public class DataBaseHelper {
ent.getInt(params.getSecond()));
} else if(table.equals(Global.DB_TABLE_NOTIFICATIONS)) {
o = new SWADNotification(ent.getInt("id"),
ent.getString("eventType"),
Crypto.decrypt(DBKey, ent.getString("eventType")),
ent.getLong("eventTime"),
ent.getString("userSurname1"),
ent.getString("userSurname2"),
ent.getString("userFirstname"),
ent.getString("userPhoto"),
ent.getString("location"),
ent.getString("summary"),
Crypto.decrypt(DBKey, ent.getString("userSurname1")),
Crypto.decrypt(DBKey, ent.getString("userSurname2")),
Crypto.decrypt(DBKey, ent.getString("userFirstname")),
Crypto.decrypt(DBKey, ent.getString("userPhoto")),
Crypto.decrypt(DBKey, ent.getString("location")),
Crypto.decrypt(DBKey, ent.getString("summary")),
ent.getInt("status"),
ent.getString("content"));
Crypto.decrypt(DBKey, ent.getString("content")));
} else if(table.equals(Global.DB_TABLE_TEST_QUESTIONS)) {
id = ent.getInt("id");
PairTable q = (PairTable)getRow(Global.DB_TABLE_TEST_QUESTIONS_COURSE, "qstCod", Long.toString(id));
@ -709,16 +712,16 @@ public class DataBaseHelper {
String status = String.valueOf(n.getStatus());
ent.setValue("id", n.getId());
ent.setValue("eventType", n.getEventType());
ent.setValue("eventType", Crypto.encrypt(DBKey, n.getEventType()));
ent.setValue("eventTime", eventTime);
ent.setValue("userSurname1", n.getUserSurname1());
ent.setValue("userSurname2", n.getUserSurname2());
ent.setValue("userFirstname", n.getUserFirstName());
ent.setValue("userPhoto", n.getUserPhoto());
ent.setValue("location", n.getLocation());
ent.setValue("summary", n.getSummary());
ent.setValue("userSurname1", Crypto.encrypt(DBKey, n.getUserSurname1()));
ent.setValue("userSurname2", Crypto.encrypt(DBKey, n.getUserSurname2()));
ent.setValue("userFirstname", Crypto.encrypt(DBKey, n.getUserFirstName()));
ent.setValue("userPhoto", Crypto.encrypt(DBKey, n.getUserPhoto()));
ent.setValue("location", Crypto.encrypt(DBKey, n.getLocation()));
ent.setValue("summary", Crypto.encrypt(DBKey, n.getSummary()));
ent.setValue("status", status);
ent.setValue("content", n.getContent());
ent.setValue("content", Crypto.encrypt(DBKey, n.getContent()));
ent.save();
}
@ -1664,6 +1667,27 @@ public class DataBaseHelper {
rows.get(i).delete();
}
}
/**
* Encrypts the notifications data
*/
public void encryptNotifications() {
List<Entity> rows = db.getEntityList(Global.DB_TABLE_NOTIFICATIONS);
Iterator<Entity> iter = rows.iterator();
while (iter.hasNext()) {
Entity ent = iter.next();
ent.setValue("eventType", Crypto.encrypt(DBKey, ent.getString("eventType")));
ent.setValue("userSurname1", Crypto.encrypt(DBKey, ent.getString("userSurname1")));
ent.setValue("userSurname2", Crypto.encrypt(DBKey, ent.getString("userSurname2")));
ent.setValue("userFirstname", Crypto.encrypt(DBKey, ent.getString("userSurname2")));
ent.setValue("userPhoto", Crypto.encrypt(DBKey, ent.getString("userPhoto")));
ent.setValue("location", Crypto.encrypt(DBKey, ent.getString("location")));
ent.setValue("summary", Crypto.encrypt(DBKey, ent.getString("summary")));
ent.setValue("content", Crypto.encrypt(DBKey, ent.getString("content")));
ent.save();
}
}
/**
* Empty table from database

View File

@ -316,11 +316,11 @@ public class Test extends Model {
s = buff.toString().trim();
//Remove accents
s = s.replace('', 'a');
s = s.replace('Ž', 'e');
s = s.replace('', 'i');
s = s.replace('', 'o');
s = s.replace('œ', 'u');
s = s.replace('á', 'a');
s = s.replace('é', 'e');
s = s.replace('í', 'i');
s = s.replace('ó', 'o');
s = s.replace('ú', 'u');
return s;
}

View File

@ -18,11 +18,11 @@
*/
package es.ugr.swad.swadroid.modules.notifications;
import es.ugr.swad.swadroid.DownloadImageTask;
import es.ugr.swad.swadroid.Global;
import es.ugr.swad.swadroid.MenuActivity;
import es.ugr.swad.swadroid.R;
import es.ugr.swad.swadroid.gui.MenuActivity;
import es.ugr.swad.swadroid.modules.Messages;
import es.ugr.swad.swadroid.utils.DownloadImageTask;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;

View File

@ -50,7 +50,6 @@ import android.widget.Toast;
import es.ugr.swad.swadroid.Global;
import es.ugr.swad.swadroid.R;
import es.ugr.swad.swadroid.model.DataBaseHelper;
import es.ugr.swad.swadroid.model.SWADNotification;
import es.ugr.swad.swadroid.modules.Module;
@ -169,8 +168,7 @@ public class Notifications extends Module {
setContentView(R.layout.list_items);
this.findViewById(R.id.courseSelectedText).setVisibility(View.GONE);
this.findViewById(R.id.groupSpinner).setVisibility(View.GONE);
this.findViewById(R.id.groupSpinner).setVisibility(View.GONE);
image = (ImageView)this.findViewById(R.id.moduleIcon);
image.setBackgroundResource(R.drawable.notif);
@ -187,6 +185,7 @@ public class Notifications extends Module {
dbCursor = dbHelper.getDb().getCursor(Global.DB_TABLE_NOTIFICATIONS, selection, orderby);
startManagingCursor(dbCursor);
adapter = new NotificationsCursorAdapter(this, dbCursor);
adapter.setDBKey(prefs.getDBKey());
list = (ListView)this.findViewById(R.id.listItems);
list.setAdapter(adapter);

View File

@ -22,14 +22,12 @@ import java.util.Date;
import es.ugr.swad.swadroid.Global;
import es.ugr.swad.swadroid.R;
import es.ugr.swad.swadroid.modules.Messages;
import es.ugr.swad.swadroid.utils.Crypto;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.text.Html;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.CursorAdapter;
import android.widget.ImageView;
@ -41,8 +39,9 @@ import android.widget.TextView;
*
*/
public class NotificationsCursorAdapter extends CursorAdapter {
protected Context ctx;
private boolean [] contentVisible;
Context ctx;
private String DBKey;
/**
* Constructor
@ -75,7 +74,6 @@ public class NotificationsCursorAdapter extends CursorAdapter {
@Override
public void bindView(View view, Context context, Cursor cursor) {
final Context ctx = context;
final Long notificationCode = cursor.getLong(cursor.getColumnIndex("id"));
final String userPhoto = cursor.getString(cursor.getColumnIndex("userPhoto"));
long unixTime;
@ -86,7 +84,7 @@ public class NotificationsCursorAdapter extends CursorAdapter {
java.text.DateFormat dateShortFormat = android.text.format.DateFormat.getDateFormat(context);
java.text.DateFormat timeFormat = android.text.format.DateFormat.getTimeFormat(context);
int numRows = cursor.getCount();
if(contentVisible.length == 0) {
contentVisible = new boolean[numRows];
}
@ -107,17 +105,17 @@ public class NotificationsCursorAdapter extends CursorAdapter {
/*
OnClickListener replyMessageListener = new OnClickListener() {
public void onClick(View v) {
Intent activity = new Intent(ctx.getApplicationContext(), Messages.class);
Intent activity = new Intent(context.getApplicationContext(), Messages.class);
activity.putExtra("notificationCode", notificationCode);
activity.putExtra("summary", summary.getText().toString());
ctx.startActivity(activity);
context.startActivity(activity);
}
};*/
if(eventType != null) {
eventCode.setText(notificationCode.toString());
eventUserPhoto.setText(userPhoto);
type = cursor.getString(cursor.getColumnIndex("eventType"));
eventUserPhoto.setText(Crypto.decrypt(DBKey, userPhoto));
type = Crypto.decrypt(DBKey, cursor.getString(cursor.getColumnIndex("eventType")));
//messageReplyButton.setVisibility(View.GONE);
if(type.equals("examAnnouncement"))
@ -165,9 +163,9 @@ public class NotificationsCursorAdapter extends CursorAdapter {
}
if(eventSender != null){
sender = "";
senderFirstname = cursor.getString(cursor.getColumnIndex("userFirstname"));
senderSurname1 = cursor.getString(cursor.getColumnIndex("userSurname1"));
senderSurname2 = cursor.getString(cursor.getColumnIndex("userSurname2"));
senderFirstname = Crypto.decrypt(DBKey, cursor.getString(cursor.getColumnIndex("userFirstname")));
senderSurname1 = Crypto.decrypt(DBKey, cursor.getString(cursor.getColumnIndex("userSurname1")));
senderSurname2 = Crypto.decrypt(DBKey, cursor.getString(cursor.getColumnIndex("userSurname2")));
//Empty fields checking
if(senderFirstname.compareTo(Global.NULL_VALUE)!=0)
@ -180,10 +178,10 @@ public class NotificationsCursorAdapter extends CursorAdapter {
eventSender.setText(sender);
}
if(location != null) {
location.setText(Html.fromHtml(cursor.getString(cursor.getColumnIndex("location"))));
location.setText(Html.fromHtml(Crypto.decrypt(DBKey, cursor.getString(cursor.getColumnIndex("location")))));
}
if(summary != null){
summaryText = cursor.getString(cursor.getColumnIndex("summary"));
summaryText = Crypto.decrypt(DBKey, cursor.getString(cursor.getColumnIndex("summary")));
//Empty field checking
if(summaryText.compareTo(Global.NULL_VALUE)==0)
@ -192,7 +190,7 @@ public class NotificationsCursorAdapter extends CursorAdapter {
summary.setText(Html.fromHtml(summaryText));
}
if((content != null)){
contentText = cursor.getString(cursor.getColumnIndex("content"));
contentText = Crypto.decrypt(DBKey, cursor.getString(cursor.getColumnIndex("content")));
//Empty field checking
if(contentText.compareTo(Global.NULL_VALUE)==0)
@ -249,4 +247,12 @@ public class NotificationsCursorAdapter extends CursorAdapter {
this.notifyDataSetChanged();
}
}*/
/**
* Sets the database key
* @param key
*/
public void setDBKey(String key) {
DBKey = key;
}
}

View File

@ -33,7 +33,6 @@ import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.KeepAliveHttpsTransportSE;
import org.xmlpull.v1.XmlPullParserException;
import es.ugr.swad.swadroid.Base64;
import es.ugr.swad.swadroid.Global;
import es.ugr.swad.swadroid.Preferences;
import es.ugr.swad.swadroid.R;
@ -41,6 +40,7 @@ import es.ugr.swad.swadroid.model.DataBaseHelper;
import es.ugr.swad.swadroid.model.SWADNotification;
import es.ugr.swad.swadroid.model.User;
import es.ugr.swad.swadroid.ssl.SecureConnection;
import es.ugr.swad.swadroid.utils.Base64;
import android.accounts.Account;
import android.accounts.OperationCanceledException;

View File

@ -0,0 +1,121 @@
/*
* This file is part of SWADroid.
*
* Copyright (C) 2010 Juan Miguel Boyero Corral <juanmi1982@gmail.com>
*
* SWADroid is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* SWADroid is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with SWADroid. If not, see <http://www.gnu.org/licenses/>.
*/
package es.ugr.swad.swadroid.utils;
import java.security.MessageDigest;
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
/**
* Cryptographic class for encription purposes.
* @author Juan Miguel Boyero Corral <juanmi1982@gmail.com>
*/
public class Crypto
{
public static String encrypt(String seed, String cleartext)
{
try
{
byte[] rawKey = getRawKey(seed.getBytes());
byte[] result = encrypt(rawKey, cleartext.getBytes());
return Base64.encodeBytes(result);
}
catch(Exception e)
{
e.printStackTrace();
}
return "error";
}
public static String decrypt(String seed, String encrypted)
{
try
{
byte[] rawKey = getRawKey(seed.getBytes());
byte[] enc = Base64.decode(encrypted);
byte[] result = decrypt(rawKey, enc);
return new String(result);
}
catch(Exception e)
{
e.printStackTrace();
}
return "error";
}
private static byte[] getRawKey(byte[] seed) throws Exception
{
KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
sr.setSeed(seed);
kgen.init(128, sr);
SecretKey skey = kgen.generateKey();
byte[] raw = skey.getEncoded();
return raw;
}
private static byte[] encrypt(byte[] raw, byte[] clear) throws Exception
{
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = cipher.doFinal(clear);
return encrypted;
}
private static byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception
{
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
byte[] decrypted = cipher.doFinal(encrypted);
return decrypted;
}
public static final String md5(final String s)
{
try
{
MessageDigest digest = java.security.MessageDigest.getInstance("MD5");
digest.update(s.getBytes());
byte messageDigest[] = digest.digest();
StringBuffer hexString = new StringBuffer();
for(int i=0; i<messageDigest.length; i++)
{
String h = Integer.toHexString(0xFF & messageDigest[i]);
while(h.length()<2)
{
h="0"+h;
}
hexString.append(h);
}
return hexString.toString();
}
catch(Exception e)
{
e.printStackTrace();
}
return "error";
}
}