ログイン情報を自動入力するブックマークレットの作り方
Webページの入力情報を読み取る
- 上記ページで以下のAppleScriptを実行すると...
tell application "Safari"
activate
do JavaScript "(function(d, s, r, url_key, inputs, options, i){
url_key=d.location.protocol.replace(/[^A-Za-z]/g,'_')+'__'+d.location.hostname.replace(/[^A-Za-z]/g,'_')+d.location.pathname.replace(/\\W/g,'_');
inputs=d.getElementsByTagName('input');
options=d.getElementsByTagName('option');
for(i=0;i<inputs.length;i++){
if(inputs[i].type!='hidden'&&inputs[i].type!='image'&&inputs[i].type!='button'){
s.push(eval('('+'{type: \"'+inputs[i].type+'\", id: \"'+inputs[i].id+'\", name: \"'+inputs[i].name+'\", value: \"'+inputs[i].value+'\", checked: '+inputs[i].checked+', index: \"'+i+'\"}'+')'));
}
}
for(i=0;i<options.length;i++){
if(options[i].selected){
s.push(eval('('+'{type: \"option\", name: \"'+options[i].name+'\", value: \"'+options[i].value+'\", selected: '+options[i].selected+', index: \"'+i+'\"}'+')'));
}
}
r[url_key]=s;
return r;
})(document,[],{})" in document 1
end tell
- URLをキーとした、以下のレコードが返ってくる。
{
https___healthcare_mb_softbank_jp_pc_assets_setup_web_explanation_input_php:{
{checked:false, |id|:"telno3", value:"00012345678", type:"text", |name|:"", |index|:"0"},
{checked:false, |id|:"passwd", value:"1234", type:"password", |name|:"passwd", |index|:"1"},
{|index|:"3", value:"4", type:"option", |name|:"undefined", selected:true}
}
}
- URLをキーにして、以下3項目のフォームの情報を配列として保持している。
- 体組成計の電話番号(テキストフィールド)
- ユーザー番号(プルダウンリスト)
- 暗証番号(パスワードフィールド)
自動入力するJavaScript
- 上記AppleScriptレコードは、以下のようなJSONに変換できる。
{ https___healthcare_mb_softbank_jp_pc_assets_setup_web_explanation_input_php:[ {checked:false, id:"telno3", value:"00012345678", type:"text", name:"", index:"0"}, {checked:false, id:"passwd", value:"1234", type:"password", name:"passwd", index:"1"}, {index:"3", value:"4", type:"option", name:"undefined", selected:true} ] }
- そして、上記JSONを利用して、自動入力するJavaScriptコードを考えてみた。
(function(){ var json={ https___healthcare_mb_softbank_jp_pc_assets_setup_web_explanation_input_php:[ {checked:false, id:"telno3", value:"00012345678", type:"text", name:"", index:"0"}, {checked:false, id:"passwd", value:"1234", type:"password", name:"passwd", index:"1"}, {index:"3", value:"4", type:"option", name:"undefined", selected:true} ] }; var url_key=document.location.protocol.replace(/[^A-Za-z]/g,'_')+'__'+document.location.hostname.replace(/[^A-Za-z]/g,'_')+document.location.pathname.replace(/\W/g,'_'); var j=json[url_key]; for(var i=0;i<j.length;i++){ if(j[i].type=='text'||j[i].type=='password'){ if(document.getElementsByName(j[i].name).length > 0){ document.getElementsByName(j[i].name)[0].value=j[i].value }else{ document.getElementById(j[i].id).value=j[i].value } }else if(j[i].type=='radio'||j[i].type=='checkbox'){ document.getElementsByTagName('input')[j[i].index].checked=j[i].checked }else if(j[i].type=='option'){ if(document.getElementsByTagName('option')[j[i].index].value==j[i].value){ document.getElementsByTagName('option')[j[i].index].selected=j[i].selected } } } alert('auto_login works!'); })()
- ブックマークレットとするため...
- Closure Compiler Serviceで圧縮し、
- 改行を削除し、
- コード先頭に"javascript:"を追記してみた。
javascript:(function(){for(var b={https___healthcare_mb_softbank_jp_pc_assets_setup_web_explanation_input_php:[{checked:!1,id:"telno3",value:"00012345678",type:"text",name:"",index:"0"},{checked:!1,id:"passwd",value:"1234",type:"password",name:"passwd",index:"1"},{index:"3",value:"4",type:"option",name:"undefined",selected:!0}]}[document.location.protocol.replace(/[^A-Za-z]/g,"_")+"__"+document.location.hostname.replace(/[^A-Za-z]/g,"_")+document.location.pathname.replace(/\W/g,"_")],a=0;a<b.length;a++)"text"==b[a].type||"password"==b[a].type?0<document.getElementsByName(b[a].name).length?document.getElementsByName(b[a].name)[0].value=b[a].value:document.getElementById(b[a].id).value=b[a].value:"radio"==b[a].type||"checkbox"==b[a].type?document.getElementsByTagName("input")[b[a].index].checked=b[a].checked:"option"==b[a].type&&document.getElementsByTagName("option")[b[a].index].value==b[a].value&&(document.getElementsByTagName("option")[b[a].index].selected=b[a].selected);alert("auto_login works!")})();
- 上記コードをブックマークレットとして保存し、先程の例のページを開いて実行してみると...
- 例:https://healthcare.mb.softbank.jp/pc/assets/setup/web_explanation_input.php
見事!元どおりに入力された!
安全の問題
- 以上が、ブックマークレットを利用して自動入力する基本のコードである。
- AppleScriptで入力情報を収集して、上記のようなJavaScriptコードを自動生成するようにすれば、iPhoneやiPadでも自動入力が可能になる。
- Safariが自動入力してくれないページでも、このブックマークレットなら自動入力してくれる。(可能性大)
- さらに、プルダウンリストやチェックボックス・ラジオボタンの状態も自動入力できるのだ。
しかし、このブックマークレットをこのまま使うのは危険である!
- 見てのとおり、コードの中にパスワードなどの重要な情報がそのまま保存されている。
- もしも、このブックマークレットが何らかの原因で外部に漏洩すると、不正ログインが簡単に実行できてしまう。
- このページはスマート体組成計のページなので大した実害はないが、(体重や脂肪の計測値が見られるだけ)
- 仮に金融機関のページのログイン情報だと、痛い目に遭う可能性大。
重要な情報は暗号化しておかなければならないのだ!
- 暗号化を実現するコマンドとJavaScriptライブラリを探してみた。
opensslコマンドの環境
- OSX 10.9.4に標準インストールされているopensslコマンドのバージョンは、0.9.8y。
$ openssl version
OpenSSL 0.9.8y 5 Feb 2013
- 巷を騒がせたopensslのバグ"Heartbleed"は、openssl 1.0.1〜1.0.1fに含まれる。
- よって、OSX標準インストールされるopnessl 0.9.8yには、バグは存在しない。
- 仮に openssl 1.0.1〜1.0.1fを利用している場合は、1.0.1gへアップデートする。
-
-
- 参考ページ:opensslのバージョン確認とアップデート(Heartbleed対応) - Qiita(感謝です!)
-
opensslコマンドで暗号化する
- 例:文字列"hello world!!"を"1234"というパスワードで暗号化するしてみる。
$ echo 'hello world!!' | openssl enc -e -a -salt -aes-256-cbc -pass pass:1234
U2FsdGVkX1/ViT/1pTYv4dZsujl2feiy8Wuq72NlWCI=
enc | 共通鍵による暗号化 |
---|---|
-e | エンコードする(暗号化する) |
-d | デコードする(復号化する) |
-a(-base64) | base64エンコード・デコードを有効にする |
-salt | 鍵生成ルーチンでソルトを利用する。特に理由(0.9.5以前との互換性を維持する等)がない限り、-saltは必ず指定しておくべき。 |
-aes-256-cbc | 特に理由(暗号化・復号化の処理スピードの問題など)がない限り、鍵長が最も長い-aes-256-cbcを選択しておいた方が良さそう。 |
-
-
- 参考ページ:OpenSSL Manual Translation - enc(1)(感謝です!)
-
- 今度は、暗号化された”U2FsdGVkX1/ViT/1pTYv4dZsujl2feiy8Wuq72NlWCI=”を復元してみる。
$ echo U2FsdGVkX1/ViT/1pTYv4dZsujl2feiy8Wuq72NlWCI= | openssl enc -d -a -salt -aes-256-cbc -pass pass:1234 hello world!!
元の文字列"hello world!!"が復元できた!
JavaScriptで復号化する
暗号文をブックマークレットに含める場合、それを復号するためのJavaScriptが必要になる。当初、二つのAES JavaScriptライブラリを見つけた。
JavaScript Implementation of AES Advanced Encryption Standard in Counter Mode | Movable Type Scripts
- このライブラリは、AES-CTR(CounTeR:カウンタ)モードの暗号化・復号化を行う。
- ライセンスは、クリエイティブ・コモンズ・ライセンス(CCライセンス)。
- サンプル:
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <title>aes-256-ctrサンプル</title> </head> <body> <p>原文 : hello world!!</p> <p id="encrypted_text">0</p> <p id="decrypted_text">0</p> </body> <!-- AES implementation in JavaScript(c) Chris Veness 2005-2014 --> <script src="http://www.movable-type.co.uk/scripts/js/crypto/aes.js">/* AES JavaScript implementation */</script> <script src="http://www.movable-type.co.uk/scripts/js/crypto/aes-ctr.js">/* AES Counter Mode implementation */</script> <script type="text/javascript"> var encrypted = Aes.Ctr.encrypt("hello world!!", "1234", 256); document.getElementById('encrypted_text').innerText = "暗号化: " + encrypted; var decrypted = Aes.Ctr.decrypt(encrypted, "1234", 256); document.getElementById('decrypted_text').innerText = "復号化: " + decrypted; </script> </html>
- 上記コードをファイル名"aes_ctr.html"で保存して、開いてみると...
原文 : hello world!! 暗号化: xwHwoweU3FMNRuMVxVY1bVG3qJNP 復号化: hello world!!
- opensslコマンドとの互換性
- OSX 10.9.4に標準インストールされるOpenSSL 0.9.8yは、aes-ctrに対応していない。
- 一方、HomebrewでインストールしたOpenSSL 1.0.1hでは、aes-ctrに対応している。
- しかし、同じaes-ctrでありながら、このJavaScriptライブラリとopensslコマンド相互の暗号化・復号化ができない。
- 例:opensslコマンドで暗号化したものを、このJavaScriptライブラリで複合化できなかった...。(なぜだろう?Saltの扱いの違い?)
- たとえ互換性がなくても、このJavaScriptライブラリで暗号化すれば問題なく復号化できるので、躊躇する必要はない。
crypto-js - JavaScript implementations of standard and secure cryptographic algorithms - Google Project Hosting
- このライブラリは、AES-256-CBC(Cipher Block Chaining:暗号ブロック連鎖)モードの暗号化・復号化を行う。
- 読み込むライブラリ(ファイル)によって、AES-256-CBC以外にも様々な暗号化に対応しているようだ。
- サンプル:
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <title>aes-256-cbcサンプル</title> </head> <body> <p>原文 : hello world!!</p> <p id="encrypted_text">0</p> <p id="decrypted_text_bin">0</p> <p id="decrypted_text_utf8">0</p> </body> <script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/aes.js"></script> <script type="text/javascript"> var encrypted = CryptoJS.AES.encrypt("hello world!!", "1234"); document.getElementById('encrypted_text').innerText = "暗号化 : " + encrypted; var decrypted_bin = CryptoJS.AES.decrypt(encrypted, "1234"); document.getElementById('decrypted_text_bin').innerText = "復号 文字コード: " + decrypted_bin; var decrypted_utf8 = decrypted_bin.toString(CryptoJS.enc.Utf8); document.getElementById('decrypted_text_utf8').innerText = "復号 UTF8 : " + decrypted_utf8; </script> </html>
- 上記コードをファイル名"aes_cbc.html"で保存して、開いてみると...
原文 : hello world!! 暗号化 : U2FsdGVkX1/jmFp4MNDcqnb8zmD/3GB+xSEWuEs+qnI= 復号 文字コード: 68656c6c6f20776f726c642121 復号 UTF8 : hello world!!
- opensslコマンドとの互換性
- OSX 10.9.4に標準インストールされるOpenSSL 0.9.8yと、完全な互換性がある。
- 試しに、上記で暗号化したものをopensslコマンドで復号化してみると...
$ echo U2FsdGVkX1/jmFp4MNDcqnb8zmD/3GB+xSEWuEs+qnI= | openssl enc -d -a -salt -aes-256-cbc -pass pass:1234 hello world!!
- その逆も然り...
$ echo 'hello world!!' | openssl enc -e -a -salt -aes-256-cbc -pass pass:1234 U2FsdGVkX1/ZwwQ3vwuYHqYvPDhfAKria033cuKWHEs=
原文 : hello world!! 暗号化 : U2FsdGVkX1/ZwwQ3vwuYHqYvPDhfAKria033cuKWHEs= 復号 文字コード: 68656c6c6f20776f726c6421210a 復号 UTF8 : hello world!!
どちらも、ちゃんと復号化できた!
ログイン情報を暗号化する
- 以上の暗号化ツールを活用して、ログイン情報を暗号化してみる。
- opensslコマンドでログイン情報を暗号化してブックマークレットコードに組み込み、
- crypto-jsJavaScriptライブラリでブックマークレット実行時に復号するのだ。
- 余分な改行を削除したログイン情報のテキスト。
'{https___healthcare_mb_softbank_jp_pc_assets_setup_web_explanation_input_php:[{checked:false, id:"telno3", value:"00012345678", type:"text", name:"", index:"0"}, {checked:false, id:"passwd", value:"1234", type:"password", name:"passwd", index:"1"}, {index:"3", value:"4", type:"option", name:"undefined", selected:true}]}'
$ echo -n '{https___healthcare_mb_softbank_jp_pc_assets_setup_web_explanation_input_php:[{checked:false, id:"telno3", value:"00012345678", type:"text", name:"", index:"0"}, {checked:false, id:"passwd", value:"1234", type:"password", name:"passwd", index:"1"}, {index:"3", value:"4", type:"option", name:"undefined", selected:true}]}' | openssl enc -e -salt -aes-256-cbc -pass pass:MSTER_PASS | base64
U2FsdGVkX1/uT2sjZl3uT43ciqzmXYZpB8mwYxMpyGk0EN/Gz0hzixJ4+Js2mU68qOWohJmpPGgr5g1+eaxL8aeLh+ooMgxXYLZozYUhWaJ99+0+tKV9GDarpbOMrfA6zE8hvCy62XChqZZINsPOA7G3KuFs54+BKNXFqKbsyA2f0MciDxQcmZgeTC8ci+rS1WZHyTMK5EPh6GhPK/QpoejG1JdXpcGdV94pN7R8flpT4iyMdGdbCfSeL7xjnmZs3BMvc5S50VZEtIdsD9BCeixQFf7GCZvuTJH4zxQHoPZMLc1T85ReBliiya9PvHcD6VfxTk4iuvodqIAC3J/pF5IP5fEhR/24XOZ/5gcEa92u8HulCp0LgfAeUxrgABo0a+ELvpysYBKQmwuTNU9ssFh9QA841RXvLh/JUnQAE8YTksS27PF50nhZap6C1OC5rOIRvIdrTgSgImjQ6TxhiA==
- 暗号化されたログイン情報を利用したブックマークレットに修正してみた。
- JavaScriptライブラリをロードする時間を考慮して、setTimeoutで0.5秒待機してから実行している。
- ネットワーク環境やブラウザの性能によって、より多くの待機時間が必要になるかもしれない。
(function(){ //JavaScriptライブラリをロード var e=document.createElement('script'); e.src='//crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/aes.js'; document.body.appendChild(e); setTimeout(function(){ //暗号化ログイン情報を復号する var passwd_raw=prompt('auto_login Password',''); var json_text_cipher='U2FsdGVkX1/uT2sjZl3uT43ciqzmXYZpB8mwYxMpyGk0EN/Gz0hzixJ4+Js2mU68qOWohJmpPGgr5g1+eaxL8aeLh+ooMgxXYLZozYUhWaJ99+0+tKV9GDarpbOMrfA6zE8hvCy62XChqZZINsPOA7G3KuFs54+BKNXFqKbsyA2f0MciDxQcmZgeTC8ci+rS1WZHyTMK5EPh6GhPK/QpoejG1JdXpcGdV94pN7R8flpT4iyMdGdbCfSeL7xjnmZs3BMvc5S50VZEtIdsD9BCeixQFf7GCZvuTJH4zxQHoPZMLc1T85ReBliiya9PvHcD6VfxTk4iuvodqIAC3J/pF5IP5fEhR/24XOZ/5gcEa92u8HulCp0LgfAeUxrgABo0a+ELvpysYBKQmwuTNU9ssFh9QA841RXvLh/JUnQAE8YTksS27PF50nhZap6C1OC5rOIRvIdrTgSgImjQ6TxhiA=='; var json_text=CryptoJS.AES.decrypt(json_text_cipher, passwd_raw).toString(CryptoJS.enc.Utf8); var json=eval('('+json_text+')'); //URLに対応したログイン情報を取り出す var url_key=document.location.protocol.replace(/[^A-Za-z]/g,'_')+'__'+document.location.hostname.replace(/[^A-Za-z]/g,'_')+document.location.pathname.replace(/\W/g,'_'); var j=json[url_key]; //自動入力する for(var i=0;i<j.length;i++){ if(j[i].type=='text'||j[i].type=='password'){ if(document.getElementsByName(j[i].name).length > 0){ document.getElementsByName(j[i].name)[0].value=j[i].value }else{ document.getElementById(j[i].id).value=j[i].value } }else if(j[i].type=='radio'||j[i].type=='checkbox'){ document.getElementsByTagName('input')[j[i].index].checked=j[i].checked }else if(j[i].type=='option'){ if(document.getElementsByTagName('option')[j[i].index].value==j[i].value){ document.getElementsByTagName('option')[j[i].index].selected=j[i].selected } } } alert('auto_login works!'); }, 500);//setTimeout })()
- ブックマークレット中に含まれるのは暗号化されたログイン情報である。
- ログイン情報を復号するためのマスターパスワードの入力が、毎回必要になるが、
- たとえ漏洩したとしても、パスワードを知らない限り、不正利用はできないのだ。
これでログイン情報は暗号化され、安全になった!
マスターパスワードの照合
- これでブックマークレットは安全になったが、一つ問題が発生した。
- マスターパスワードが正しければ正常に自動入力されるのだけど、
- マスターパスワードが間違っていると、何のリアクションもない。
- 仮にパスワードが違っていた場合は「パスワードが違います」くらいの出力をしたいものだ。
- 照合するためには、正しいマスターパスワードをどこかに保存しておく必要がある。
- ところが、どこかに保存すると、それが漏洩したときの危険性が気になる。
- できることなら、マスターパスワードはどこにも保存せずに、照合するのがベスト。
- では、正しいマスターパスワードを知らずして、正誤判定する方法なんてあるのか?
ハッシュ値を使うと、それができる!
ハッシュ値の特性
- 原文が同じ内容なら、必ず同一のハッシュ値になる。
- 1文字でも違っていると、その値は大きく変化する。
- 上記の特性を利用するとこで、パスワードの照合を安全に行うことができる。
- 仮にハッシュ値が漏洩しても、パスワード原文は推測できないので安全なのだ。
- 一方、パスワード原文を保存していた場合は、それが漏洩した時に大問題になる。
opensslコマンドでsha256ハッシュ値を取得する
$ echo -n 1234 | openssl dgst -sha256
03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4
JavaScriptでsha256ハッシュ値を取得する
sha256ハッシュを計算するJavaScriptライブラリでも試してみた。
user1.matsumoto.ne.jp/~goma/js/sha1.js
- サンプルコード
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <title>SHA-256サンプル</title> </head> <body> <p>原文 : 1234</p> <p id="encrypted_text">0</p> </body> <script src="http://user1.matsumoto.ne.jp/~goma/js/sha256.js"></script> <script type="text/javascript"> var encrypted = sha256.hex("1234"); document.getElementById('encrypted_text').innerText = "sha256 : " + encrypted; </script> </html>
- 上記サンプルコードをSafariで開いてみると...
原文 : 1234 sha256 : 03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4
crypto-js - JavaScript implementations of standard and secure cryptographic algorithms - Google Project Hosting
- サンプルコード
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <title>sha256サンプル</title> </head> <body> <p>原文 : 1234</p> <p id="encrypted_text">0</p> </body> <script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/sha256.js"></script> <script type="text/javascript"> var encrypted = CryptoJS.SHA256("1234"); document.getElementById('encrypted_text').innerText = "sha256 : " + encrypted; </script> </html>
- 上記サンプルコードをSafariで開いてみると...
原文 : 1234 sha256 : 03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4
opensslコマンド・Javascriptライブラリ、いずれのハッシュ値も同一の値だ!
sha256でマスターパスワードを照合
- 以上のハッシュ関数を活用して、マスターパスワードを照合してみる。
- opensslコマンドとcrypto-jsJavaScriptライブラリを使ってみた。
- まずはMASTER_PASSのsha256ハッシュ値を求めた。
$ echo -n MASTER_PASS | openssl dgst -sha256
3b70f81b4a16b6546ea8114e43be495ce154c3a1e92056a59d7af3db6a9914fd
- 上記ハッシュ値を利用して、パスワードを照合するコードを追加してみた。
(function(){ //JavaScriptライブラリをロード (function(e){ e=document.createElement('script'); e.src='//crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/aes.js'; document.body.appendChild(e); e=document.createElement('script'); e.src='//crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/sha256.js'; document.body.appendChild(e); })() setTimeout(function(){ //マスターパスワードを照合する var passwd_sha256='3b70f81b4a16b6546ea8114e43be495ce154c3a1e92056a59d7af3db6a9914fd'; var passwd_raw=prompt('auto_login Password',''); if(CryptoJS.SHA256(passwd_raw) != passwd_sha256){ if(passwd_raw != ''){alert('Password is NG.');}return; } //暗号化ログイン情報を復号する var json_text_cipher='U2FsdGVkX1/uT2sjZl3uT43ciqzmXYZpB8mwYxMpyGk0EN/Gz0hzixJ4+Js2mU68qOWohJmpPGgr5g1+eaxL8aeLh+ooMgxXYLZozYUhWaJ99+0+tKV9GDarpbOMrfA6zE8hvCy62XChqZZINsPOA7G3KuFs54+BKNXFqKbsyA2f0MciDxQcmZgeTC8ci+rS1WZHyTMK5EPh6GhPK/QpoejG1JdXpcGdV94pN7R8flpT4iyMdGdbCfSeL7xjnmZs3BMvc5S50VZEtIdsD9BCeixQFf7GCZvuTJH4zxQHoPZMLc1T85ReBliiya9PvHcD6VfxTk4iuvodqIAC3J/pF5IP5fEhR/24XOZ/5gcEa92u8HulCp0LgfAeUxrgABo0a+ELvpysYBKQmwuTNU9ssFh9QA841RXvLh/JUnQAE8YTksS27PF50nhZap6C1OC5rOIRvIdrTgSgImjQ6TxhiA=='; var json_text=CryptoJS.AES.decrypt(json_text_cipher, passwd_raw).toString(CryptoJS.enc.Utf8); var json=eval('('+json_text+')'); //URLに対応したログイン情報を取り出す var url_key=document.location.protocol.replace(/[^A-Za-z]/g,'_')+'__'+document.location.hostname.replace(/[^A-Za-z]/g,'_')+document.location.pathname.replace(/\W/g,'_'); var j=json[url_key]; if(j==null){ alert('No auto_login info.');return; } //自動入力する for(var i=0;i<j.length;i++){ if(j[i].type=='text'||j[i].type=='password'){ if(document.getElementsByName(j[i].name).length > 0){ document.getElementsByName(j[i].name)[0].value=j[i].value }else{ document.getElementById(j[i].id).value=j[i].value } }else if(j[i].type=='radio'||j[i].type=='checkbox'){ document.getElementsByTagName('input')[j[i].index].checked=j[i].checked }else if(j[i].type=='option'){ if(document.getElementsByTagName('option')[j[i].index].value==j[i].value){ document.getElementsByTagName('option')[j[i].index].selected=j[i].selected } } } alert('auto_login works!'); }, 500);//setTimeout })()
これでマスターパスワードの照合もできるようになった!
- 状況に応じて、以下のメッセージを出力するのだ。
- マスターパスワードが違っていたら、'Password is NG.'
- ログイン情報が見つからなかったら、'No auto_login info.'
- 正常に自動入力できた場合は、'auto_login works!'
auto_loginプロジェクト
以上の仕組みを利用して、auto_loginプロジェクトはログイン情報を保全している。
-
-
- 果たして、ちゃんと安全を確保できているのだろうか?
-
関連ページ
- Safariであらゆるページに自動ログインする方法 - ザリガニが見ていた...。
- auto_login AppleScriptコード - ザリガニが見ていた...。
- iPhone・iPadのSafariでもあらゆるページで自動入力したい - ザリガニが見ていた...。
- auto_loginスクリプトのSafari7対応 - ザリガニが見ていた...。
- ブックマークレットの書き方の段階的な発展の仕方 - ザリガニが見ていた...。
onloadすればsetTimeoutが不要
- JavaScriptライブラリをロードする時間を考慮して、setTimeoutで大雑把に0.5秒待機する、という運を天に任せる的なコードは、常々どうにかしたいと思っていた。
- 0.5秒も待つ必要ないかもしれないし、あるいはもっと待つ必要があるかもしれない。
- 理想は、JavaScriptライブラリのロードが完了したタイミングで、本体のブックマークレットを実行するべき。
ロードが完了したタイミング=onloadイベントハンドラを使えばいいのだ!
- scriptタグを追加する時に、onload属性を追加して、ブックマークレット本体の関数を呼び出すように変更してみた。
(function(f,e){ //JavaScriptライブラリをロード e=document.createElement('script'); e.src='//crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/aes.js'; document.body.appendChild(e); e=document.createElement('script'); e.src='//crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/sha256.js'; e.onload=function(){f()}; document.body.appendChild(e); })(function(){ //マスターパスワードを照合する var passwd_sha256='3b70f81b4a16b6546ea8114e43be495ce154c3a1e92056a59d7af3db6a9914fd'; var passwd_raw=prompt('auto_login Password',''); if(CryptoJS.SHA256(passwd_raw) != passwd_sha256){ if(passwd_raw != ''){alert('Password is NG.');}return; } //暗号化ログイン情報を復号する var json_text_cipher='U2FsdGVkX1/uT2sjZl3uT43ciqzmXYZpB8mwYxMpyGk0EN/Gz0hzixJ4+Js2mU68qOWohJmpPGgr5g1+eaxL8aeLh+ooMgxXYLZozYUhWaJ99+0+tKV9GDarpbOMrfA6zE8hvCy62XChqZZINsPOA7G3KuFs54+BKNXFqKbsyA2f0MciDxQcmZgeTC8ci+rS1WZHyTMK5EPh6GhPK/QpoejG1JdXpcGdV94pN7R8flpT4iyMdGdbCfSeL7xjnmZs3BMvc5S50VZEtIdsD9BCeixQFf7GCZvuTJH4zxQHoPZMLc1T85ReBliiya9PvHcD6VfxTk4iuvodqIAC3J/pF5IP5fEhR/24XOZ/5gcEa92u8HulCp0LgfAeUxrgABo0a+ELvpysYBKQmwuTNU9ssFh9QA841RXvLh/JUnQAE8YTksS27PF50nhZap6C1OC5rOIRvIdrTgSgImjQ6TxhiA=='; var json_text=CryptoJS.AES.decrypt(json_text_cipher, passwd_raw).toString(CryptoJS.enc.Utf8); var json=eval('('+json_text+')'); //URLに対応したログイン情報を取り出す var url_key=document.location.protocol.replace(/[^A-Za-z]/g,'_')+'__'+document.location.hostname.replace(/[^A-Za-z]/g,'_')+document.location.pathname.replace(/\W/g,'_'); var j=json[url_key]; if(typeof j==='undefined'){ alert('No auto_login info.');return; } //自動入力する for(var i=0;i<j.length;i++){ if(j[i].type=='text'||j[i].type=='password'){ if(document.getElementsByName(j[i].name).length > 0){ document.getElementsByName(j[i].name)[0].value=j[i].value }else{ document.getElementById(j[i].id).value=j[i].value } }else if(j[i].type=='radio'||j[i].type=='checkbox'){ document.getElementsByTagName('input')[j[i].index].checked=j[i].checked }else if(j[i].type=='option'){ if(document.getElementsByTagName('option')[j[i].index].value==j[i].value){ document.getElementsByTagName('option')[j[i].index].selected=j[i].selected } } } alert('auto_login works!'); })