Some time ago I've shown you Password Manager application. This post is also related to passwords. I've created a very simple widget that uses InputStick to type my TrueCrypt password for encrypted system partition. The most important fact is that now all it takes to type the password is just a single click.
Here's a quick comparison of steps required to type the password:
Password Manager:
- Run application.
- Type master password.
- Connect to InputStick (although auto connect feature will be added).
- Click on "TrueCrypt" item.
- Select "Password" entry.
- Press "Type" button.
Widget:
- Click on the widget.
In both cases it is assumed that there is only one InputStick paired with the phone, otherwise you have to manually select InputStick device (unless DeviceManager is set to always connect to "Default" device). Also, I assume that Bluetooth radio is already on, if not you will be asked if you want to enable it.
But what about security? Is it safe this way? Well, in this case I think that it is:
- TrueCrypt is used to protect data in case my laptop gets lost or stolen.
- If I loose both my laptop and phone, it is still protected by relatively complex pattern lock.
- Even if phone is unlocked the only (simple) way to get the password is to type it with InputStick, there is no "show plaintext" option.
- Data stored on system partition is not something that can be remotely accessed, unlike, for example: email account.
Here you can see the widget conveniently placed on my homescreen:
![]() |
TrueCrypt Widget placed on homescreen. |
After clicking on it, it hides icon and shows progress bar. When everything is done, it returns to initial state.
![]() |
TrueCrypt Widget at work :) |
And here's a short video showing how this actually works:
Also, if anyone is interested, take a look at the source code. Most part of the widget is based on this tutorial.
Main widget class: MyWidget.java:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.example.mywidget; | |
import android.app.PendingIntent; | |
import android.appwidget.AppWidgetManager; | |
import android.appwidget.AppWidgetProvider; | |
import android.content.ComponentName; | |
import android.content.Context; | |
import android.content.Intent; | |
import android.view.View; | |
import android.widget.RemoteViews; | |
public class MyWidget extends AppWidgetProvider { | |
public static final String BTN_CLICKED = "buttonClick"; | |
public static final String BTN_READY = "buttonReady"; | |
@Override | |
public void onUpdate(Context context, AppWidgetManager appWidgetManager, | |
int[] appWidgetIds) { | |
RemoteViews remoteViews; | |
ComponentName watchWidget; | |
remoteViews = new RemoteViews(context.getPackageName(), | |
R.layout.my_layout); | |
watchWidget = new ComponentName(context, MyWidget.class); | |
Intent intent = new Intent(context, getClass()); | |
intent.setAction(BTN_CLICKED); | |
remoteViews.setOnClickPendingIntent(R.id.button, | |
PendingIntent.getBroadcast(context, 0, intent, 0)); | |
appWidgetManager.updateAppWidget(watchWidget, remoteViews); | |
} | |
@Override | |
public void onReceive(Context context, Intent intent) { | |
// TODO Auto-generated method stub | |
super.onReceive(context, intent); | |
if (BTN_CLICKED.equals(intent.getAction())) { | |
context.startService(new Intent(context, WidgetService.class)); | |
AppWidgetManager appWidgetManager = AppWidgetManager | |
.getInstance(context); | |
RemoteViews remoteViews; | |
ComponentName watchWidget; | |
remoteViews = new RemoteViews(context.getPackageName(), | |
R.layout.my_layout); | |
watchWidget = new ComponentName(context, MyWidget.class); | |
remoteViews.setViewVisibility(R.id.button, View.GONE); | |
remoteViews.setViewVisibility(R.id.progressBar, View.VISIBLE); | |
appWidgetManager.updateAppWidget(watchWidget, remoteViews); | |
} | |
if (BTN_READY.equals(intent.getAction())) { | |
AppWidgetManager appWidgetManager = AppWidgetManager | |
.getInstance(context); | |
RemoteViews remoteViews; | |
ComponentName watchWidget; | |
remoteViews = new RemoteViews(context.getPackageName(), | |
R.layout.my_layout); | |
watchWidget = new ComponentName(context, MyWidget.class); | |
remoteViews.setViewVisibility(R.id.button, View.VISIBLE); | |
remoteViews.setViewVisibility(R.id.progressBar, View.GONE); | |
appWidgetManager.updateAppWidget(watchWidget, remoteViews); | |
} | |
} | |
} |
Background service, which is actually doing all the work: WidgetService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.example.mywidget; | |
import android.app.Service; | |
import android.content.Intent; | |
import android.os.IBinder; | |
import com.example.inputsticklibrary.usb.USBDevice; | |
import com.example.inputsticklibrary.usb.USBDeviceListener; | |
import com.example.inputsticklibrary.usb.devices.USBKeyboard; | |
public class WidgetService extends Service implements USBDeviceListener { | |
private static final USBKeyboard keyb = new USBKeyboard(); | |
private static boolean running; | |
@Override | |
public void onUSBEvent(int code) { | |
// TODO Auto-generated method stub | |
int state = keyb.getState(); | |
if (state == USBDevice.STATE_READY) { | |
if (!running) { | |
running = true; | |
Thread t = new Thread() { | |
@Override | |
public void run() { | |
try { | |
// wait a bit to be sure its 100% ready | |
Thread.sleep(1000); | |
// type password | |
keyb.type("passwordgoeshere"); | |
// press enter | |
keyb.pressAndRelease(USBKeyboard.NONE, | |
USBKeyboard.KEY_ENTER); | |
// wait for long enough to allow USB host read all | |
// characters | |
Thread.sleep(1000); | |
keyb.disconnect(); | |
running = false; | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
} | |
}; | |
t.start(); | |
} else { | |
this.stopSelf(); | |
} | |
} | |
if (state == USBDevice.STATE_NONE) { | |
keyb.unregisterListener(); | |
this.stopSelf(); | |
} | |
} | |
@Override | |
public void onUSBData(int endpoint, byte[] data) { | |
// TODO Auto-generated method stub | |
} | |
@Override | |
public IBinder onBind(Intent arg0) { | |
// TODO Auto-generated method stub | |
return null; | |
} | |
@Override | |
public int onStartCommand(Intent intent, int flags, int startId) { | |
running = false; | |
keyb.setContext(this.getApplicationContext()); | |
keyb.registerListener(this); | |
if (keyb.getState() == USBDevice.STATE_NONE) { | |
keyb.connect(); | |
} else { | |
this.stopSelf(); | |
} | |
return START_STICKY; | |
} | |
@Override | |
public void onDestroy() { | |
Intent i = new Intent(this, MyWidget.class); | |
i.setAction(MyWidget.BTN_READY); | |
this.sendBroadcast(i); | |
super.onDestroy(); | |
} | |
} |
I suppose it's always important to consider what sort of attack is one trying to guard against - a random theft / loss, a targeted attempt to steal / penetrate specific devices / data, a state agency accessing a confiscated device etc., since absolute security is impossible. However, relying on the lock screen for any protection seems to be a rather questionable idea these days, considering extremely simple methods for bypassing lockscreens on various devices are found and published again and again [1]. Any attacker with a minimal interest in accessing the phone would probably be aware of these, I remember reading about 4-5 different ones just in the last few months. Of course, if one expects the attacker to take the time to reflash the phone on CWM level (without wiping the data), it's a whole different situation...
ReplyDeletePS - regarding lockscrens, I always had a lock code on my previous Symbian S60 phone too. Now imagine my horror when I moved my SIM card to the new phone and the old one started merrily booting _without_ asking for the lock code at all. All it took was removing the SIM, yet I never knew that bug was there...
[1] http://www.csoonline.com/article/735866/android-lock-screen-bypass-highlights-mobile-risk
As for lockscreens I think that in case of Android OS it is actually quite secure, under conditions that the phone is not rooted.
DeleteAnyway, I'm aware that storing unencrypted password on the phone is not the greatest idea, but still, this solution is better that no password at all or using yellow post-it notes. And it could prevent situations like:
http://www.informationweek.com/security/attacks/stolen-nasa-laptop-had-unencrypted-emplo/240142160
or:
http://www.dailymail.co.uk/news/article-2337301/Council-fined-150-000-loss-76-unencrypted-laptops-containing-personal-data-bank-accounts-20-000-people.html
Many people tends to avoid using passwords at all cost, whenever possible. I think that one of reasons for that they simply don't want to type passwords. In such case, this one-click widget may add at least some basic security.