NFCを使用したAndroid画面のロック解除

Nexus 4への不正アクセスを防ぐため、パスワード付きの標準画面ロックを使用しています。 しかし、常に手動でパスワードを入力する必要があり、これは少し面倒です。 グラフィックキーでのブロックは、PINコード(可能な組み合わせが少なすぎる)と同様、私を感心させませんでした。 ロック解除の速度を維持しながら、強力な保護が必要でした。 このため、NFCテクノロジーを詳しく調べることにしました。



既製のソリューション



タグを使用してデバイスのロック解除を実装するために私が見つけた唯一の既製のソリューションは、 NFCSecureプログラムです。 有料ですが、無料版はありません。 Google Playの彼のページでビデオを見た後、私はすぐにこれにはお金の価値がないと思いました。 すべてが最も簡単な方法で実装されます。

  1. ユーザーがデバイスの画面をオンにすると、標準の画面ロックが表示されます。
  2. 彼はそれのロックを解除します。
  3. アクティビティNFCSecureが表示されます。これは、デバイスへのアクセスを確実にブロックするふりをします(ロック解除アイコンをクリックすると、何らかの理由でページが点滅します。
  4. ラベルを貼ると、ウィンドウが閉じます。


このウィンドウは、標準のランチャー(タッチボタン、物理ボタン、ステータスバーによるジェスチャ)に物理的に到達する試みをブロックすると想定しても、標準のロック画面が提供するすべての保護を実装することはありません。 標準ロックはより機能的であり、ドライブとしてのデバイスへのアクセスをブロックします。 画面のロックを解除するまで、ファイルにアクセスできません。

一般に、このアプリケーションはかなり穴が多く、標準のロック画面に匹敵する保護を提供しません。



実装してみましょう



私にとって最も理想的なオプションは、標準のロック画面との統合でした。 タグを直接スキャンしてログインできるようにしたかったのですが、タグがなければ、パスワードをバックアップオプションとして使用できました。

実装を開始する前に、NFCSecureの作成者が、意図したとおりではなく、正確に動作するようにアプリケーションを作成した2つの理由を特定しました。 これらの問題と、それらをアプリケーションで解決する方法について説明します。



ラベルスキャナーが常に機能しない


より正確には、私たちにとって興味のある少なくとも2つのケースでは機能しません。

  1. 画面がオフのとき。
  2. ロック画面にいるとき。


これらの場合、スキャナーはセキュリティ上の理由で動作しないと思います。 ラベルをスキャンした後、最適なアプリケーションが起動しますが、このアプリケーションが何をしたいのかわかりません。 たとえば、Googleウォレット(ビデオで判断)では、デバイスを端末に接続する前にピンコードとカードを選択する必要があります。



スキャナーのルールは、システムアプリケーションNfcNci.apkにあります。 スキャンが機能するためにデバイスがどの状態でなければならないかを決定する定数があります( こちらをご覧ください )。 当然、この定数は変更する必要があります。 多くの開発者は、必要なデバイスの既製の変更されたNfcNci.apkファイルをxda-developersにアップロードするため、完成したファイルを取得して、デバイス上のアプリケーションをそれで置き換えました。

画面がロックされているときにスキャナーがラベルを読み取ることができるように、定数を2つの値の少なくとも1つに設定できます。

  1. スキャナーは、画面がオフのときに機能します。
  2. スキャナーは、画面がオンになっているとき、およびアクティブなロックがあっても機能します。


フォーラムのメンバーによると 、最初の決定は、電話がアイドル状態にあったという事実にもかかわらず、3時間でバッテリーの約35%を消費します。 したがって、2番目のオプションを選択することをお勧めします。これは、まったく課金しないため、マークが非常に近い場合に誤ってロックを解除して画面をオンにするのを防ぐためです。

もちろん、このソリューションは、元のアプリケーションを置き換えるためにルート化されたデバイスと身体の動きが必要になるため、一般ユーザーのしきい値を大幅に削減します。 ただし、アプリケーションは大規模なものに焦点を合わせていないため、これに同意することができます。



簡単なロック解除機能はありません


繰り返しますが、セキュリティ上の理由から、デバイス上のアプリケーションは、何らかの方法(パスワード、ピン、パターンなど)で保護された画面を取得してロック解除することはできません。 現時点では、画面のロックを解除できる2つの標準ソリューションがあります。

  1. KeyguardManager.KeyguardLockクラス。
  2. ウィンドウのフラグはFLAG_DISMISS_KEYGUARDおよびFLAG_SHOW_WHEN_LOCKEDです。


KeyguardManager.KeyguardLock


このクラスには、disableKeyguard()およびreenableKeyguard()の2つのメソッドが含まれます。 最初の方法は、保護されていない画面のみをロック解除します。 画面が何らかの方法で保護されている場合、呼び出しは無視されます。 画面を再ロックするには、reenableKeyguard()メソッドを呼び出す必要があります。そうしないと、ブロッカーはオフになった後に起動しません。

このソリューションの短所:パスワードで保護された画面のロックを解除することはできません。また、イベントによってはロック画面を再起動する必要があります。 さらに、このクラスはAPI 13から非推奨になっているため、これに依存しないでください。



ウィンドウフラグ


親のアクティビティウィンドウでフラグを設定する必要があります。 FLAG_DISMISS_KEYGUARDは、保護されていない場合にのみ画面のロックを解除します。 ウィンドウを閉じた後、画面がオフになるまでブロッカーは復元されません。 FLAG_SHOW_WHEN_LOCKEDはブロッカーを非表示にし(保護されていても)、ウィンドウを閉じた後、直ちにフォアグラウンドに移動します。

つまり、これらのフラグは保護された画面のロックを解除できません。 できることは、その上にウィンドウを表示することだけです。



この場合、開発者が提供する機会が少ないほど、OS自体のセキュリティが向上します。 フラグ機能、特にFLAG_SHOW_WHEN_LOCKEDを使用すると、システムのセキュリティを損なうことなく、ブロッカーの上にアプリケーションを表示できます。 しかし、残念ながら、これは私たちには適していません。



回避策を書く



Android APIはロック解除のための美しいソリューションを提供しないため回避策のために松葉杖を作成する必要があります。

その結果、3つのロック解除メソッドを実装する基本的なアプリケーションが作成されました。 NFC Unlocker(投稿の最後にあるGoogle Playとソースへのリンク)と呼ぶことにしました。 実装された回避策は安定していない可能性がありますが、これは名前に基づいて理解できます。 これらすべての方法では、ユーザーがシステムではなくアプリケーション設定でパスワードを入力する必要があります。 これは、ユーザーの代わりにパスワードを(メソッドに応じて)回復/入力できるようにするために行われます。

ラベルを読み取った後、OSは最も適切なアクティビティを起動する必要があります。 したがって、BroadcastReceiverを使用しても機能しません。 次に、これらの方法について説明します。



アクティビティウィンドウにフラグを設定する


それにもかかわらず、このフラグは、計画の実施に役立ちます。 このソリューションは、ルートを必要とせず、ウィンドウフラグを使用するため、最もクリーンです。 フラグが機能するには、DevicePolicyManager.resetPassword()メソッドを使用してパスワードをクリアする必要があります。 これを行うには、管理者権限が必要です。これは、アプリケーションが設定ページでユーザーに要求します。

ロック解除アルゴリズムは次のとおりです。

  1. ユーザーがラベルをスキャンすると、アクティビティが開始されます。
  2. クリアパスワード:

    ((DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE)).resetPassword("", 0);





  3. アクティビティのウィンドウにフラグを設定します。

    getActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);



  4. onAttachedToWindowメソッドでアクティビティを完了します。これは、フラグが既にウィンドウに適用されているためです。
  5. onDestroyメソッドでは、ユーザーパスワードを復元します。


KeyguardLockの使用


次のメソッドは古いAPIを使用していますが、それでもAndroid 4.3でタスクを正常に実行します。 前の方法と同様に、ロック解除を機能させるにはパスワードをクリアする必要があります。

ここでは、アルゴリズムはより複雑であり、一見、十分に安定していません(実際には、すべてがはるかに優れています)。

  1. ユーザーがラベルをスキャンすると、アクティビティが開始されます。
  2. クリアパスワード:

    ((DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE)).resetPassword("", 0).



  3. 画面のロックを解除します。

    KeyguardManager keyguardManager = (KeyguardManager) context.getSystemService(Activity.KEYGUARD_SERVICE);





    KeyguardLock keyguardLock = keyguardManager.newKeyguardLock("nfcunlocker");





    keyguardLock.disableKeyguard();



  4. バックグラウンドでBroadcastReceiverを作成するサービスを開始し、画面オフイベントを受信します。

    ScreenReceiver screenReceiver = new ScreenReceiver();





    IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);





    registerReceiver(mReceiver, filter);



  5. 画面がオフであることを通知するイベントを受信したらすぐに、ロックをオンにしてパスワードを復元します。


このメソッドは非常に安定して動作しますが、古いAPIを使用します。



シェルを介したパスワード入力


この方法は非常に単純ですが、ルートが必要なので最初に思いつきました。 Androidのシェルでは、「input」コマンドを呼び出して、テキストを入力し、キーストロークをエミュレートできます。 テキストを入力するには、次の構文を使用します。

input text "type your text here"





キーストロークのエミュレーションは、次のコマンドを使用して実行されます。

input keyevent KEYCODE





ここでキーコードのリストを見つけることができます

この方法のロック解除アルゴリズムは非常に簡単です。

  1. ユーザーがラベルをスキャンすると、アクティビティが開始されます。
  2. シェルコマンド「input」を使用してパスワードを入力し、Enterキーのコードを送信します。


ラベル自体について少し



タグをスキャンするときにアクティビティを選択するアルゴリズムについては、 こちらをご覧ください 。 つまり、OSはラベルの内容に基づいてアクティビティを選択します。 アクティビティの起動を保証するには、 AAR (Android Application Records)を使用する必要があります。つまり、アプリケーションパッケージの名前をラベルに書き込むだけです。 この方法を使用すると、ロック解除の起動を保証できますが、NDEF標準をサポートするタグは手元にありませんでした。 したがって、一意の識別子でそれらを識別します



まとめ



次に、ネイティブブロッカーとの統合の長所と短所をまとめます。

長所:

  1. OSの保護に違反しないでください。
  2. デバイスにラベルを付けるだけでデバイスのロックを解除します。
  3. ラベルが近くにない場合は、パスワードを手動で入力できます。


短所:

  1. ユーザーの高しきい値。 ルートおよび変更されたNfcNci.apkが必要です。
  2. ロック解除メソッドは安定して動作しない場合があります。 適切なものを選択する必要があります。


Githubへのリンクには、一部の一般的なスマートフォン向けに変更されたNfcNci.apkファイルへのリンクがあります。



アプリケーションの構成と操作を示すために、ビデオを録画しました。





参照:

Google Play

Github



PSコードの品質のためにキックしないでください。 私はJava開発者ではありません。



All Articles