はてなキーワード: SHA1とは
JPKIMobile(jp.go.jpki.mobile.utility)と同じ署名を持つグループ
証明書[1]:
所有者: CN=Japan Agency for Local Authority Information Systems, OU=User client application for Android, O=Japan Agency for Local Authority Information Systems, L=Chiyoda-ku, ST=Tokyo, C=JP
発行者: CN=Japan Agency for Local Authority Information Systems, OU=User client application for Android, O=Japan Agency for Local Authority Information Systems, L=Chiyoda-ku, ST=Tokyo, C=JP
有効期間の開始日: Fri Aug 12 14:51:15 GMT+09:00 2016終了日: Sun Aug 11 14:51:15 GMT+09:00 2041
MD5: B5:16:A7:CE:B9:AC:42:70:89:0C:0B:7A:90:93:F8:6B
SHA1: 98:76:11:8F:5D:CD:2E:70:63:C1:1F:E5:48:CB:EB:ED:33:A1:CF:93
SHA256: A9:32:34:5D:B8:E9:E9:B3:FA:FE:FE:84:C0:EE:6E:A2:B8:5D:38:FF:B9:58:24:3E:C7:75:00:1B:E6:6B:4A:67
バージョン: 3
マイナポータルAP(jp.go.cas.mpa)と同じ署名を持つグループ
証明書[1]:
所有者: CN=Android, OU=Android, O=Google Inc., L=Mountain View, ST=California, C=US
発行者: CN=Android, OU=Android, O=Google Inc., L=Mountain View, ST=California, C=US
シリアル番号: 397894eb0dfabe4f486ef8962795f7584d73a6dd
有効期間の開始日: Mon Aug 28 10:11:52 GMT+09:00 2017終了日: Wed Aug 28 10:11:52 GMT+09:00 2047
MD5: D1:54:F3:D6:E0:F1:86:3F:37:DD:46:7A:D8:71:C9:00
SHA1: EC:41:03:27:68:75:7D:31:25:00:ED:19:3D:C1:00:80:C2:14:B3:85
SHA256: AB:57:C0:63:26:50:E1:D8:48:8C:D8:88:6C:19:5D:3E:43:95:8B:C4:0F:4F:0A:B1:6D:CA:26:49:D9:76:A5:14
バージョン: 3
1、何らかの文字列をハッシュ値にしたものをさらしつつ書き込みをする
ff74f78c80ade36037cc1f362276d64d7cfe3660
書き込みしてやんよ
2、自己証明が必要になったら、ハッシュ法と文字列をさらしつつ、別の文字列で作ったハッシュ値をさらす
http://anond.hatelabo.jp/xxxxxxxx に書き込みしたのオレだよオレ
a2656246d49b9f9944ac638d0f99aa2291ad7082
あとはこの繰り返し。トリップの原理も同じだと思うが、ハッシュ値から元の文字列を計算するのは無理に近いので有効のはず。
open /var/mobile/Library/Preferences/com.apple.restrictionspassword.plist
you can find this kinds:
<key>RestrictionsPasswordKey</key> <data> xxxxxxxxxxxxxxxxxxxxxxxxxxx= </data> <key>RestrictionsPasswordSalt</key> <data> XXXXXX== </data>
$ key=```echo "key" | base64 -d | xxd -p``` $ salt=```echo "salt" | base64 -d | xxd -p```
finally try matching hashed 0000~9999(PBKDF2-HMAC-SHA1, salt=salt, iterations=1000) and the given key
more info: http://hashcat.net/forum/archive/index.php?thread-2892.html
「プロテクトかけたアルゴリズムを実装したバージョンに差し替え」たなんて言われると本当に「プロテクト」がかかっているのか確かめてみたくなるのが人情というもの。というわけで、プロテクト強化後のもふったー(v0.9.6b)からconsumer secretが抜けるか試してみた。結論から言うと、あっけなく取り出せた。以下に手順を記す。
動作がよくわかっていないアプリケーションを解析して仕様を明らかにすることをリバースエンジニアリングと呼ぶ。ソフトウェアのリバースエンジニアリングは基本的に対象を逆アセンブルしてひたすら読むことによって行う(その補助に1命令ずつ実行してレジスターやメモリーの様子を観察することもある)。しかし、よっぽど小規模なものでなければオブジェクトコード全体を逆アセンブルして最初から最後まで読むなんてのは不可能だ。人間の読速度には限界があるし、時間も有限だからだ。そして、詳しい動作を知りたい部分というのは全体のごく一部であることが多いので全逆アセンブリを読むのには非常に無駄が多い。
だから、リバースエンジニアリングではいかに詳らかにすべき動作を行っているコードを絞り込むか(=読むべき逆アセンブリを少なくするか)が重要になる。
この場合も同様だ。TwitterのGUIクライアントを頭から読むのは到底無理なので、どうやって解析すべきコードの範囲を狭めるかを考えた。それにはOAuth認証においてconsumer secretがどのような役割を果たすのかを知る必要がある。
OAuth認証で、consumer secretはそのままサーバーに送信されたりはしない。signatureの生成にHMAC-SHA1が使われ、その鍵にconsumer secretが使われる。HMACは次のように算出される。
HMAC (K,m) = H ((K ⊕ opad) ∥ H ((K ⊕ ipad) ∥ m))
ここで
である。
まずはこのあたりから攻めようと思った。SHA-1の計算にはいくつか特徴的な定数が使われるので、そこからSHA-1の計算に使われているであろう関数444190を特定する。この関数のエントリーポイントに中断点(ブレークポイント)を設定してOAuth認証をさせるべくもふったーの「ブラウザで認証」ボタンを押す。狙い通り中断するので関数を抜けるまで実行する。関数401100の4012DAに出た。少し下を見るとこのようになっている。
CPU Disasm Address Hex dump Command Comments 00401311 |. 33F6 xor esi, esi 00401313 | 8D8C24 A40000 /lea ecx, [local.54] 0040131A |. 394C24 14 |cmp dword ptr ss:[local.90], ecx 0040131E |. 75 0E |jne short 0040132E 00401320 |. 3BF5 |cmp esi, ebp 00401322 |. 73 29 |jae short 0040134D 00401324 |. 0FB68434 A400 |movzx eax, byte ptr ss:[esi+esp+0A4] 0040132C |. EB 21 |jmp short 0040134F 0040132E | 3BF5 |cmp esi, ebp 00401330 |. 73 1B |jae short 0040134D 00401332 |. 8B5424 18 |mov edx, dword ptr ss:[local.89] 00401336 |. 52 |push edx ; /Arg1 = [LOCAL.89] 00401337 |. 8D8C24 FC0000 |lea ecx, [local.33] ; | 0040133E |. 8BD6 |mov edx, esi ; | 00401340 |. E8 CB4D0000 |call 00406110 ; \mofooter.00406110 00401345 |. 83C4 04 |add esp, 4 00401348 |. 0FB6C0 |movzx eax, al 0040134B |. EB 02 |jmp short 0040134F 0040134D | 33C0 |xor eax, eax 0040134F | 34 5C |xor al, 5C 00401351 |. 888434 B80000 |mov byte ptr ss:[esi+esp+0B8], al 00401358 |. 83C6 01 |add esi, 1 0040135B |. 83FE 40 |cmp esi, 40 0040135E |.^ 72 B3 \jb short 00401313 00401360 |. 895C24 3C mov dword ptr ss:[local.80], ebx
0040134F | 34 5C |xor al, 5C
が注意を引く。もしかしてこれはopadとのxorではないか?
00401351 |. 888434 B80000 |mov byte ptr ss:[esi+esp+0B8], al
はxorした結果を格納している。
先ほどの中断点は無効化しこのループを抜けた地点である401360まで飛ばす。この時点でesp+0B8を見ると次のようになっている。
Hex dump 64 2E 16 64|37 04 32 6D|0F 0D 26 29|3A 37 1F 2F| 18 69 6E 6E|0D 25 29 33|11 34 29 69|12 36 24 1E| 05 16 33 6A|04 3B 0E 68|7A 5C 5C 5C|5C 5C 5C 5C| 5C 5C 5C 5C|5C 5C 5C 5C|5C 5C 5C 5C|5C 5C 5C 5C|
あとはこれと5Cとをxorすればconsumer secretが手に入る。終わり。
はてなは増田のスーパーpre記法で半角の<>が含まれていると投稿が出来ないのを早く直してください。
もふったーの作者から反応があった。「本気だったつもりのもふったーのデバッグ処理が残ってた」らしい(http://blog.livedoor.jp/blackwingcat/archives/1763951.html)。修正したとのことなので最新版(v0.9.6e)を見てみた。確かに若干変更されているが何の問題もない。SHA-1の呼び出しに中断点を設置して渡されているバイト列を見るだけ。
CPU Disasm Address Hex dump Command Comments 00401324 |. 8D4424 20 |lea eax, [local.102] 00401328 |. 50 |push eax ; /Arg1 = 00401329 |. E8 623A0400 |call 00444D90 ; \mofooter.00444D90
ここでeaxが指すメモリーを見ると以下のようになっている。
01 23 45 67|89 AB CD EF|FE DC BA 98|76 54 32 10| F0 E1 D2 C3|00 02 00 00|00 00 00 00|40 00 00 00| 40 4F 73 53|62 54 5C 7E|59 57 53 42|55 45 7A 57| 61 47 7A 5B|42 4F 7B 61|5D 66 5E 7A|42 7F 40 63| 79 66 05 55|79 4C 60 42|02 10 36 36|36 36 36 36| 36 36 36 36|36 36 36 36|36 36 36 36|36 36 36 36|
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 http://anond.hatelabo.jp/20111006234714 http://twitter.com/i315 さんでしょうか さてわたしも不登校なわけですが,お前とはどうかんがえても方向性が違うので ただおもしろがって見ているだけにしますね!!!! sora_h でした!!! 匿名性ないね!!! 追記: http://twitter.com/#!/Glass_saga/status/124131595606167554 ということでPGP署名を施しました. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (Darwin) iQEcBAEBAgAGBQJOlaZiAAoJEIHMzVZz47asMIsH/0AUmA8eAkXrtNzDVX7asUYs 5FO06sNUxMYZEeVDTyOwDsYxjPkDnW7QGe7na7ZRHFm1/WeaYepRhvf7Q4QePCjX B0ZTPwt0liQpRecZIwh615UmDVv5nd6wLJiNNQZqJQc+CMfeT1tzqr/nwuqfTJSz wU1MeVBVaxKbpl+iOIDGu/nbXlcTsNSE0gKieTuLFcoHOmXyKDwbF27+s2vt0TkK oBwJZWZVCQRHTMCLSRc/iAaQnV6zjQpeRPVxyd8fzuLedcArKYGDQsgvpPP7Gycy yxPuJHc5q5Q5LiHVYkcMQ1FzzGTKy7U0b5MIkm6es6qMutPTOM3CA7BA6fuGDgw= =qKpD -----END PGP SIGNATURE-----
gpg: Signature made Wed Oct 12 23:38:26 2011 JST using RSA key ID 73E3B6AC
gpg: Good signature from "Shota Fukumori <sorah@tubusu.net>"
本当に「真剣に」車輪の再生産を防止することに我々は取り組んでいるのだろうか?
調べるよりやってみるほうが早い(モノづくりに比べてソフトウェアはその傾向が強い)しより深く理解できるので現状のように車輪は再発明されまくりです。
自動車や、まして航空機の歴史を1からやりなおす人はいないし(誰も好き好んで死にたくはない)、マイクロプロセッサやDRAMの歴史にしてもそうだとは思うのですが(プロセスルールが最新の45nm、32nmといかないまでもたとえ130nmであってもLSI工場を個人で建設できるとは思えないから)、並列アルゴリズムの工夫と称して、「8コアを使って64*8bit同士の乗算器を作りました」みたいな話がないといいけどなぁとは思います。(PHPで実装したblowfishとか、JavaScriptで実装したSHA1とか、どう見ても馬鹿げてるのですが実際必要なんだよなぁ)
あと会社の文化とか宗教の車輪の再生産はよくありますね、福音主義とかスターリン主義とか偶像崇拝の禁止とか、そういう教義のパターンは遠くはなれた無関係な文明で再発明されたりします。これもまあ人類のソフトウェアの問題といえなくもなく。
LiveDoor認証がでたらしいので、とりあえず寝際にちゃちゃっと書こうとしたのだけどなんかうまくいかない。
「ログインURLの有効期限が切れています」とかでちゃうんだ。
なにか間違ってるかな?
<?php // LiveDoor認証に必要なリンクの生成 // 定数がクラス内に切ってあるので環境にあわせ変更してください include_once('authlivedoor.class.php'); // Livedoor認証用クラス $obj_auth = new AuthLiveDoor(LIVEDOOR_APIKEY, LIVEDOOR_SECRET); $livedoorloginurl = $obj_auth->getLoginUrl(); ?> <div style="border:solid 1px #666666;"> <a href="<?= $livedoorloginurl ?>">ライブドア認証を利用してログインする<br /> <img src="http://auth.livedoor.com/img/cmn/head_livedoor.gif" border="0"> <img src="http://auth.livedoor.com/img/cmn/head_logo.gif" border="0"> </a><br />
<?php // this code is writen by utf-8 & lf //http://auth.livedoor.com/login/?app_key=<app_key>&perms=<perms>&t=<time>&v=1.0&userdata=<userdata>&sig=<sig> // LiveDoor外部認証APIを利用する // キーは各開発者ごとに取得が必要です。 http://auth.livedoor.com/ ここより取得できます。 // コールバックURLには authlivedoor.php を指定してください // --- 下記宣言を環境に合わせて変更してください。 --- define("LIVEDOOR_APIKEY" ,""); // アプリケーションキー define("LIVEDOOR_SECRET" ,""); // LiveDoor認証秘密キー // --- ここまで --- class AuthLiveDoor { const LIVEDOOR_AUTH_PORT = 80; // ポート const LIVEDOOR_AUTH_TIMEOUT = 10; // タイムアウト const LIVEDOOR_AUTH_VERSION = '1.0'; // 認証APIのプロトコルバージョン const LIVEDOOR_AUTH_PERMS = 'id'; // 認証APIのアクセス権 const LIVEDOOR_AUTH_FORMAT = 'xml'; // 認証APIの取得フォーマット const LIVEDOOR_AUTHURL = "auth.livedoor.com"; // LiveDoor認証URL private $login_state = false; private $login_id = ""; private $err_msg = ""; private $apikey = ""; private $secret = ""; public function __construct($apikey, $secret) { $this->apikey = $apikey; $this->secret = $secret; } // // $cert = $_GET['token']; public function getAuth($token) { if ($token == "" ) { return; } $api_time = date('U'); // エポック秒で $param_ary = array($this->apikey ,AuthLiveDoor::LIVEDOOR_AUTH_FORMAT ,$token ,api_time ,AuthLiveDoor::LIVEDOOR_AUTH_VERSION ); sort($param_ary); $api_sig = hash_hmac('sha1',implode('',$param_ary),$this->secret); $param = "app_key=".$this->apikey ."&format=".AuthLiveDoor::LIVEDOOR_AUTH_FORMAT ."&token=".$token ."&t=".$api_time ."&v=".AuthLiveDoor::LIVEDOOR_AUTH_VERSION ."&sig=".$api_sig; $fp = fsockopen(AuthLiveDoor::LIVEDOOR_AUTHURL , AuthLiveDoor::LIVEDOOR_AUTH_PORT , $errno , $errstr , AuthLiveDoor::LIVEDOOR_AUTH_TIMEOUT); if (!$fp) { $this->err_msg = "$errstr ($errno)<br />\n"; } else { $out = "POST /rpc/auth?$param HTTP/1.1\r\n"; $out .= "Host: auth.livedoor.com\r\n"; $out .= "Connection: Close\r\n\r\n"; fwrite($fp, $out); $ret = ""; while (!feof($fp)) { $ret .= fgets($fp, 2048); } fclose($fp); } // LiveDoorの認証XMLのパターン $pattern = '/(\s*<livedoor_id>)(.*)(<\/livedoor_id>)/'; preg_match_all($pattern,$ret,$getAry); $livedooruserid = $getAry[2][0]; // ユーザーIDを取得できた場合 if ($livedooruserid != "") { // ログイン成功 $this->login_state = true; $this->login_id = $livedooruserid; return ture; } } public function getLoginState(){ return $this->login_state; } public function getLoginId(){ return $this->login_id; } public function getLoginUrl() { # http://auth.livedoor.com/guide/ # http://auth.livedoor.com/login/?app_key=<app_key>&perms=<perms>&t=<time>&v=1.0&userdata=<userdata>&sig=<sig> # app_key 必須 登録時に発行されたアプリケーションキー # perms 必須 要求するアクセス権、現状userhashとidの2種類がある # t 必須 URLが生成された時間をエポック秒で表したもの # v 必須 プロトコルバージョン、現在は1.0で固定 # userdata 任意 コールバックURLに引き継ぎたい値を255バイトまで自由に設定できる # sig 必須 このURLの正当性を確認するためのシグネチャ // ログインURLの有効期限が切れています // ヾ(。o、゜)ノ ここらへんがわからん!! // $api_time = time()+32400; // エポック秒で $api_time = date('U')+32400; // エポック秒で // $api_time = date('U'); // エポック秒??もしかして、それはポエティック病ではありませんか? $param_ary = array($this->apikey ,AuthLiveDoor::LIVEDOOR_AUTH_PERMS ,api_time ,AuthLiveDoor::LIVEDOOR_AUTH_VERSION // ,data ); sort($param_ary); $api_sig = hash_hmac('sha1',implode('',$param_ary),$this->secret); $loginurl = "http://auth.livedoor.com/login/" ."?app_key=".$this->apikey ."&perms=".AuthLiveDoor::LIVEDOOR_AUTH_PERMS ."&t=".$api_time ."&v=".AuthLiveDoor::LIVEDOOR_AUTH_VERSION // ."&userdata=" ."&sig=".$api_sig; return $loginurl; } }
もう疲れたので寝る。ライブドアなんてーーーー!!!
訂正。
秘密キーとか、そのままのっけちゃった (ーωー|||)
そしてなかなか訂正できなくてあせった。。