パスワード入力欄に正しく入力したか直感的に判断できるユーザーインターフェース

ログイン時にIDとパスワードを入力する際、ほとんどのサイトではパスワードが伏字になっているため、自分がどのような文字列を入力しているかを確認できませんが、パスワードの入力文字列がいつも入力しているものと一緒かどうかを判別する方法の一つが HashMask です。

デモサイトでパスワードを入力するとフィールドの右端にグラフが描かれますが、これはパスワードフィールドの入力値が一緒であればその形や色が変わることはありません。このことを利用して、グラフがいつもと一緒の形、色であれば普段と同じ正しいパスワードを入力していることを確認できます。

このプログラムのアルゴリズムはごくシンプルで、

  1. パスワードからハッシュ値を算出する。(sha1ハッシュ関数ライブラリを使用)
  2. グラフの色をハッシュ値を利用して設定
  3. ハッシュ値を数値化する。
  4. 数値によりグラフを描画(sparklineグラフ描画ライブラリを使用)

というアルゴリズムになっており、ハッシュ関数が同一の入力からは同一の出力を返すのを利用して、正常なパスワードを入力している限りいつも同じグラフが描画されるというようなしくみになっています。

さらに噛み砕いて

  1. 長さのわからない入力値から決まったサイズの出力を取得
  2. 出力を数値化してビジュアライズ

という二段階に分けてみると、かなり応用の利く考え方であることがわかります。
特に2の部分にはさまざまな表現方法がありますね。


ここでふと思い立ち、パスワードハッシュから緯度経度を生成し、Google Map から地図を引っ張ってくるっていうのを実装してみました。以下のソースを手元のファイルにコピペしてブラウザで開くと動作すると思います。

<html>
  <head>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
    <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
    <script type="text/javascript" src="http://crypto-js.googlecode.com/files/2.0.0-crypto-sha1.js"></script>
    <script type="text/javascript">
      function generateGMap(){
          var hs = Crypto.SHA1($("#pass_field").val());
          var latArr = hs.substr(0,20).split('');
          var lonArr = hs.substr(20).split('');
          latArr = jQuery.map(latArr, function(n){ return parseInt(String.charCodeAt(n)); }).join('');
          lonArr = jQuery.map(lonArr, function(n){ return parseInt(String.charCodeAt(n)); }).join('');
          var latitude  = (Math.sin(latArr) * 70).toFixed(3);
          var longitude = (Math.sin(lonArr) * 180).toFixed(3);
          var latlng = new google.maps.LatLng(latitude, longitude);
          var myOptions = {
            zoom: 6,
            center: latlng,
            mapTypeId: google.maps.MapTypeId.SATELLITE
          };
          var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
      }
    </script>
  </head>
  <body>
    <form id="test-form">
      <dl>
        <dt>ID:</dt>
        <dd><input type="text" id="id_field" name="id" /></dd>
        <dt>PASS:</dt>
        <dd><input type="password" id="pass_field" name="pass" onChange="generateGMap()"/></dd>
      </dl>
      <div id="map_canvas" style="width:500px; height:250px;"></div>
    </form>
  </body>
</html>

動作イメージは以下のような感じになります。

ちなみにソース中に

Math.sin(latArr) * 70

とあるのは緯度が70度以上になると陸地の割合が極端に少なくなるのでこうしているだけです。
それでも、結構な確率で海ばかりだと思いますけどね。

もし美人時計に時刻を入力とするWebAPIがあったら、正しいパスワードでいつものあの子が表示されるというようなことがしたかったんだけど(笑