セキュリティ、パスワード、パスワードクラッキングなどに特化したHabrahabrに関する最近の出版物の後 ユーザーのスマートフォン上の特別なアプリケーションによって生成されるワンタイムパスワードを使用した認証のアイデアを思い付きました。 この考え方は、SecureIDデバイスで使用されている考え方と非常によく似ています(最近Habrahabrでも取り上げられました)。 現代のスマートフォンはますます多くの人が利用でき、その機能はそのようなスキームを実装するのに十分です。 この記事では、スマートフォン+ Webサイトバンドルの相互作用、いくつかの実装機能のアイデアを説明し、動作するプロトタイプを示します。
アイデアは簡単です-サイトに登録するとき、ユーザーはオプションで、スマートフォンにインストールされた認証用の特別なアプリケーションを使用してワンタイムパスワードを生成する機会を与えられます。 これを行うには、サーバー側で、ユーザーごとに一意の秘密キーが生成され、スマートフォンに転送する必要があります。 さらに、このキーに基づいて、スマートフォン側のアプリケーションはワンタイムパスワードを生成します。 各パスワードの有効期間は制限されています。 なぜなら 最新のスマートフォンにはすべてカメラが搭載されているため、秘密鍵を転送する最も簡単な方法は、スマートフォンのカメラを使用して秘密鍵を含むQRコードを読み取って認識することです。 もちろん、手動でキーを入力し、SMSで送信し、サーバーが生成したリンクを使用してキーファイルをダウンロードできますが、このようなソリューションは必ずしも便利ではありません。 この方法は、サイトでの承認の主な方法であると主張していませんが、承認のオプションの手段として使用できます。
サイトに登録する際のユーザーアクションのシーケンスは次のとおりです。
- サイトに登録するとき(または登録後)、ユーザーはワンタイムパスワードを使用して追加の認証オプションを選択できます。
- このオプションを選択すると、サーバーは秘密鍵を生成し、データベースに保存してユーザーに関連付けます。
- 秘密鍵を作成した後、ユーザーは秘密鍵を含むQRコードを含む画像を生成します。
- ユーザーは、スマートフォンのカメラを使用して秘密鍵の値を読み取ります。
- スマートフォン上のアプリケーションは秘密鍵を保存し、それをサイトに関連付け、それを使用してワンタイムパスワードを生成します。
QRコードが広く普及しているため、QRコードを使用するだけで非常に大量のデータ(数百および数千文字)を転送できますが、データをエンコードする他の方法の使用を妨げるものはありません。
HOTPアルゴリズムは、ワンタイムパスワードを生成するための基礎として採用されました。 このアルゴリズムはオープンスタンダードであり、自由に利用できます。 彼に対応するRFC 4226もあります。
このアイデアを実装およびテストするために、多数のGoogle App Engine + Androidスマートフォンが選択されました。 このサイトのデモバージョンはhttp://grey-box.appspot.com/にあります。Androidベースのスマートフォン用の小さなデモアプリケーションへのリンクもあります。AndroidOSバージョン1.6以降がサポートされています。 どちらのアプリケーションも非常に単純なので、それらについて詳しく説明することはせず、最も興味深い点にのみ焦点を当てます。
両方のアプリケーションの基礎は、ワンタイムパスワードの計算です。 ユーザーがサイトにログインするたびに、特別なアプリケーションを使用してスマートフォンでワンタイムパスワードを生成します。 パスワードには期限があり、有効期間は限られています。 ユーザーが作成されたパスワードを入力すると、サーバーは同じアクションを実行します-サーバー側でパスワードを生成します。 パスワードが一致すれば、認証は成功します。 同じパスワードを生成するには、サーバーとスマートフォンが同じ初期データに基づいてパスワードを作成する必要があります。 この初期データは、ユーザーの秘密鍵と現在の時刻です。 サーバーが秘密キーを生成するとき、キーが生成された時点で(UNIXタイムスタンプの形式で)保存されます。 秘密鍵と鍵生成時間はQRコードにエンコードされ、スマートフォンに送信されます。 スマートフォンのアプリケーションは、秘密鍵と鍵生成時間を読み取り、サーバー側とスマートフォン側の時間の差を計算します。 将来、この差は時刻を同期するために使用されます。
サーバー側では、3つの主要なアクションを実行する必要があります。
- 秘密鍵の生成
- QRコード生成
- ワンタイムパスワードの生成と検証
以下は、Pythonコードの関連部分です。
# . import time import hmac from hashlib import sha1 ... OTP_TTL = 300 # , # username = request.get(“username”) timestamp = int(time.time()) / OTP_TTL # secret_key = hmac.new(str(timestamp) + username, digestmod=sha1).hexdigest().upper() # ..
QRコードを含む画像を生成するための最も簡単なオプションは、任意のサービスを使用してさまざまなバーコードを生成することです。 このようなサービスは数多くあります。このシステムでは、Google Corporationが提供するサービスであるGoogle Charts Toolsが使用されました。 このサービスを使用すると、さまざまなグラフ、チャート、さまざまなバーコードを生成できます。 同様の方法は、実装を簡単にするためだけに使用されました。実際のシステムでは、サーバー側でバーコードを生成することをお勧めします。
QR_TPL = "https://chart.googleapis.com/chart?chs=100x100&cht=qr&chl=%s&choe=UTF-8" qr_url = QR_TPL % ('%s:%s' % (secret_key, timestamp)) # HTML . ...
ワンタイムパスワード生成。
import time import hmac from hashlib import sha1 … OTP_TTL = 300 # , TRUNCATE_MASK = 0x7FFFFFFF # MOD = 1000000 # # username = request.get("username") password = request.get("password") # st = storage.gql("where user = :1", username).get() secret_key =st.secret_key # timestamp timestamp = int(time.time()) / OTP_TTL # ... one_time_password = str((int(hmac.new(secret_key, str(timestamp), sha1).hexdigest(), 16) & TRUNCATE_MASK) % MOD) # ... if password == one_time_password: # else: #
スマートフォンの側面では、2つの主要なアクションが実行されます。
- QRコードの読み取りと認識とそれに続くデータストレージ
- ワンタイムパスワード生成
バーコードを読み取り、認識するためのライブラリがいくつかあります。おそらく最もアクティブに使用され、普及しているのは、 Zxingオープンライブラリです。 このライブラリは、Google AndroidやApple iOSを含む多くのプラットフォームをサポートしています。 このライブラリに基づいて、オープンアプリケーションのバーコードスキャナーも実装されます。このアプリケーションも非常に一般的で、多くの最新のAndroidスマートフォンにプリインストールされています。 もともとはこのライブラリをアプリケーションに統合することを目的としていましたが、インターネットやドキュメントを長時間検索した結果、これが最速かつ最も簡単な方法ではないことがわかりました。 Androidプラットフォームが提供するインテントコールメカニズムを使用することが決定されました。 このアプローチでは、必要に応じてバーコードスキャナーを追加でインストールする必要がありますが、必要な機能をアプリケーションに統合するのがはるかに簡単です。 これはこのアプローチのマイナス点ですが、プラスもあります-現在および将来のすべての可能なスマートフォンモデルに同行してサポートする必要はありません-これはZxing開発チームのタスクです 。 他のバーコード認識アプリケーションのサポートを実装することもでき、1つのバーコードスキャナーに限定されません。
以下は、 バーコードスキャナーアプリケーションの応答を呼び出して処理するために使用される小さなJavaコードです。
... // Barcode Scanner Intent, Intent intent = new Intent("com.google.zxing.client.android.SCAN"); intent.putExtra("SCAN_MODE", "QR_CODE_MODE"); startActivityForResult(intent, 0); ... // Barcode Scanner public void onActivityResult(int requestCode, int resultCode, Intent intent) { if (requestCode == 0) { if (resultCode == RESULT_OK) { // String contents = intent.getStringExtra("SCAN_RESULT"); // … … } } } ...
ワンタイムパスワード生成。
// import java.math.BigInteger; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; ... // , long OTP_TTL = 300; long TRUNCATE_MASK = 0x7FFFFFFF; long MOD = 1000000; ... // String secret_key = key_storage.getString("secret_key", ""); // long time_delta = key_storage.getLong("time_delta", 0); long local_time = (System.currentTimeMillis()/1000) / TIME_MASK; long server_time = local_time + time_delta; try { SecretKeySpec keySpec = new SecretKeySpec(secret_key.getBytes(), "HmacSHA1"); Mac mac = Mac.getInstance("HmacSHA1"); mac.init(keySpec); byte[] result = mac.doFinal(Long.toString(server_time).getBytes()); password = Long.toString((new BigInteger(1, result).intValue() & TRUNCATE_MASK) % MOD); } catch (NoSuchAlgorithmException e) { ... } catch (InvalidKeyException e) { ... } // ...
スマートフォン用のシンプルなサイトプロトタイプおよびデモアプリケーションは、 http://grey-box.appspot.com/で入手できます 。 AndroidアプリケーションはAuth IDと呼ばれ、動作するために特別な許可やアクセス権は必要ありません。 唯一の要件は、QRコードのスキャンに使用されるバーコードスキャナーアプリケーションの可用性です。 現時点では、 Auth IDアプリケーションの機能は最小限であり、アプリケーションは1人のユーザーとデモサイトのみのキーを保存できます。 別のユーザーの下で登録すると、秘密鍵は既存のものの上に書き換えられます。 将来的には、この認可スキームが配布されていれば、さまざまなサイトおよびユーザーのキーの保存を追加できます。 コメントや提案があれば嬉しいです。
参照:
http://ru.wikipedia.org/wiki/QR-%D0%BA%D0%BE%D0%B4-QRコードとは
http://en.wikipedia.org/wiki/HOTP-HOTPアルゴリズムの説明
http://tools.ietf.org/html/rfc4226-HOTPアルゴリズムのRFC 4226
https://chart.googleapis.com-Google Chart Tools
http://code.google.com/p/zxing/-さまざまなバーコードをスキャンおよび認識するためのZxingライブラリ。
http://grey-box.appspot.com/-アイデアを説明するデモサイトとアプリケーション。
PSソースは、テストの登録とログイン後に利用できます。 コードはテストであり、アイデアの機能を検証するためだけに作成されたもので、実際の使用にはお勧めできません。