To protect against unauthorized access to my Nexus 4, I use a standard screen lock with a password. But you have to constantly enter the password manually, and this is a bit annoying. The lock with the pattern key did not impress me, as did the PIN (too few possible combinations). I wanted a strong defense, while maintaining the unlock speed. It is for this reason that I decided to look at NFC technology.
Turnkey solutions
The only ready-made solution I found to implement unlocking the device using a tag is the NFCSecure program. It is paid, but there is no free version. After watching the video on his page on Google Play, I immediately decided for myself that IT was not worth the money. Everything is implemented in the simplest way:
The user turns on the device screen and sees the standard screen blocker.
He unlocks it.
An NFCSecure Activity appears, which pretends to securely block access to the device (for some reason, when you click on the unlock icon, the page blinks, which does not inspire confidence).
We attach the label and the window closes.
Even if we assume that this window blocks any attempts to physically get to the standard launcher (touch buttons, physical buttons, a gesture on the status line), it in no way implements all the protection provided by the standard lock screen. Standard locking is much more functional and even blocks access to the device as a drive, i.e. until you unlock the screen - you will not get access to the files.
In general, this application is quite leaky and does not provide protection comparable to the standard lock screen.
We will make our implementation
The most ideal option for me was integration with a standard lock screen. I wanted to be able to scan tags directly from it and log in, and if there are no tags, then you could use the password as a backup option.
Before starting to do my implementation, I identified two reasons why the author of NFCSecure made his application exactly as it works now, and not as I intended. We describe these problems and their solutions in the application developed by me.
Tag scanner does not always work
Or rather, it does not work in at least two cases that interest us:
When the screen is off.
When we are on the lock screen.
I assume that in these cases the scanner does not work for security reasons. After scanning the tags, the most suitable application is launched, and it is not known what this application will want to do. For example, Google Wallet (judging by the video) requires a pin code and card selection before attaching the device to the terminal.
')
The rules of the scanner are in the system application NfcNci.apk. There is a constant that determines the state of the device for the scan to work (you can read it here ). Naturally this constant needs to be changed. Many developers upload already prepared modified NfcNci.apk files to the xda-developers for the device you need, so I just took the finished file and replaced it with an application on my device.
A constant can be set to at least one of two values that will allow the scanner to read marks when the screen is locked:
The scanner works when the screen is off.
The scanner works when the screen is on and even with active blocking.
The first decision according to the members of the forum is eating about 35% of the battery in 3 hours, despite the fact that the phone was just lying idle. Therefore, it is better to choose the second option, since it does not spend the charge at all + will prevent accidental unlocking and turning on the screen if the label is very close.
Of course, this solution dramatically reduces the threshold for the entry of regular users, since now a rooted device and some gestures will be needed to replace the original application. But since the application is not focused on large masses, then you can put up with it.
No easy unlock
Again, for security reasons, the application on the device cannot simply take and unlock the screen protected by any method (password, pin, pattern, etc.). At the moment there are 2 standard solutions that allow you to unlock the screen:
This class contains 2 methods: disableKeyguard () and reenableKeyguard (). The first method only unlocks the unprotected screen. If the screen is protected by any method, then the call will be ignored. The reenableKeyguard () method must be called to relock the screen, otherwise the blocker will not start after it is turned off.
The disadvantages of this solution are: you cannot unlock a screen that is protected, say, with a password, and you also need to restart the lock screen on some event. In addition, this class is obsolete since API 13, so you should not hope for it.
Window flags
Flags need to be installed on the parent Activity window. FLAG_DISMISS_KEYGUARD only unlocks the screen if it is not protected. After closing the window, the blocker will not recover until the screen turns off. FLAG_SHOW_WHEN_LOCKED will only hide the blocker (even the protected one) and it will immediately come to the fore after the window is closed.
That is, again, these flags will not be able to unlock the protected screen. The maximum that can be done is to show your window on top of it.
In this case, the less opportunities are given to the developer, the more the security of the OS itself increases. The capabilities of the flags, especially FLAG_SHOW_WHEN_LOCKED, allow you to display your application on top of the blocker without compromising the security of the system. But, unfortunately, it does not suit us.
We write workarounds
Since the Android API does not provide us with beautiful solutions to unlock, you have to write crutches workarounds.
As a result, it was written a basic application that implements 3 methods of unlocking. I decided to call it NFC Unlocker (links to Google Play and the source at the end of the post). Implemented workarounds may not be stable, but this is understandable based on their name. All these methods require the user to enter a password in the application settings, and not in the system. This is done so that we can recover / enter (depending on the method) the password instead of the user.
After reading the label, the OS should start the most appropriate Activity. Therefore, using BroadcastReceiver will not work. Next, I will describe these methods.
Setting the flag for the Activity window
Still, the flag can help us in the implementation of our plans. This solution is the cleanest, since it does not require root and uses window flags, which are quite allowed for themselves. In order for the flags to work, you will have to clear the password using the DevicePolicyManager.resetPassword () method. To do this, we will need administrator rights that the application requests from the user on the settings page.
The unlock algorithm is as follows:
The user is scanning the tag, our Activity is launched.
Finish the Activity in the onAttachedToWindow method, since it is in it that our flag is already applied to the window.
In the onDestroy method, we reset the user's password.
Using KeyguardLock
The following method uses the outdated API, but nevertheless successfully performs its task on Android 4.3. As in the previous method, we will have to clear the password for the unlocking to work.
Here the algorithm is more complicated and, at first glance, not stable enough (in practice, everything is much better):
The user is scanning the tag, our Activity is launched.
We start the service, which in the background will create a BroadcastReceiver, which will receive a screen-off event:
ScreenReceiver screenReceiver = new ScreenReceiver();
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
registerReceiver(mReceiver, filter);
As soon as an event is received informing you that the screen is turned off, we turn on the lock and reset the password.
This method works quite stably, but uses an obsolete API.
Entering the password through the shell
I came up with this method first because it is quite simple, but requires root. In Android with a shell, you can call the "input" command, which allows you to enter text and emulate keystrokes. To enter text, use the following syntax:
input text "type your text here"
Keystroke emulation is performed using the following command:
The unlock algorithm for this method is very simple:
The user is scanning the tag, our Activity is launched.
Enter the password using the “input” shell command, and with its help send the Enter key code.
A little about the tags themselves
You can read about the algorithm for selecting an Activity when scanning a tag here . In short, we can say that the OS selects an Activity based on the contents of the tag. To guarantee the launch of our Activity, you need to use AAR (Android Application Records), which simply means writing the name of the application package to the label. With this method, it would be possible to launch an unlock, guaranteed, but I did not have handy tags that support the NDEF standard. Therefore, I identify them by a unique identifier .
Total
And now let's summarize the pros and cons of integration with the native blocker.
Pros:
Do not violate OS protection.
Unlock the device by simply attaching a label to the device.
If the tags are not nearby, then you can enter the password manually.
Minuses:
High entry threshold for users. Need root and modified NfcNci.apk.
Unlock methods may not work stably. You need to choose the right one.
The link to Github has links to modified NfcNci.apk files for some popular smartphones.
To demonstrate the settings and operation of the application, I recorded a video: