Hatena::ブログ(Diary)

あたご型護衛艦日記

 

2011-12-04

RSA-SHA1署名をFlash(actionscript3)で検証する方法

| 20:27 | RSA-SHA1署名をFlash(actionscript3)で検証する方法を含むブックマーク

久しぶりの日記です。

ここのところ業務でも趣味でもPHPしか触っていなかったのですが、久しぶりにactionscriptを触ったりしてました。

お遊びの趣味プロで、セキュリティの勉強も兼ねて署名検証なんかをやってみました。

で、RSA署名検証についてKYUCON*BLOGさんに記述があったのですが、同じような感じでRSA-SHA1署名検証as3で実装したFlash(すなわちクライアント側)で行おうとしてつまずいたのでその解決方法をば。

  • sha1自体の脆弱性等の問題はここでは考えないでおきます
  • セキュリティはまだまだ勉強中なので、「それはちげーよ」等ツッコミありましたらお願いいたします

そもそも、RSA-SHA1形式の署名検証は、

  1. 秘密鍵により暗号化された署名が、公開鍵を用いて復号出来る
  2. 復号化した署名が、署名生成時に使用したデータのsha1ハッシュである

という2つの検証により、それぞれ、「1.送信元の妥当性」「2.署名の中身の妥当性」を検証しています。


署名アルゴリズムハッシュ関数を用いるためのactionscript3の代表的なライブラリである、as3cryptoライブラリRSA署名検証用の RSAKey.verify メソッドは、実は単に署名を公開鍵で復号してその結果を第二引数のByteArrayに入れているだけです。

なので上述のKYUCON*BLOGさんでも以下のようにverify後に、==演算子で元データとの比較を行なっています。(KYUCON*BLOGさんから抜粋)

var rsa_verify : RSAKey= RSAKey.parsePublicKey(public_modulus, public_exponent);
var srcDecryptBA:ByteArray = Base64.decodeToByteArray(encrypted_str);
//復号したデータを格納するためのByteArray
var dstDecryptBA:ByteArray = new ByteArray();
//復号実行
try{
    rsa_verify.verify(srcDecryptBA, dstDecryptBA, srcDecryptBA.length); // ここで「1.送信元の妥当性」を検証
    trace("復号した文字列:" + dstDecryptBA.toString());
    if(dstDecryptBA.toString()==original_str){ // ここで「2.署名の中身の妥当性」を検証
        trace("改竄なし");
    }else{
        trace("改竄あり");
    }
}catch (e) {
    trace("verify失敗。不正なデータ。");
}

単なるRSA暗号化の場合はこれで良いですが、サーバサイドのphpでopenssl_signメソッドなどを使って署名をした場合はハッシュ計算にSHA1が使われるため、元データとの単純比較では当然動作しません。

これを行う場合、以下のような実装が必要になります。

try{
    // as3cryptoのPEMモジュールを使ってopensslで生成できる.pemファイル公開鍵からRSAKeyオブジェクトを生成します
    var rsa:RSAKey = PEM.readRSAPublicKey(publicKey);
    var src:ByteArray = Base64.decodeToByteArray(rsasha1_signature); // RSA-SHA1形式の署名をByteArrayへ変換
    var dst:ByteArray = new ByteArray();
    rsa.verify(src, dst, src.length); // ここで「1.送信元の妥当性」を検証

    var signature:String = Hex.fromArray(dst); // 復号化した署名を16進文字列へ変換

    var prefixIndex:int = signature.indexOf('3021300906052b0e03021a05000414');

    // 署名生成時の元データをsha1ハッシュ化
    var ba:ByteArray = new ByteArray();
    ba.writeMultiByte(original_str, 'utf-8');
    var hashAlg:IHash = Crypto.getHash('sha1');
    var hashBa:ByteArray=hashAlg.hash(ba);
    var original_sha1 = Hex.fromArray(hashBa);

    var hashIndex:int = signature.indexOf(original_sha1);

    if(prefixIndex != 0 || hashIndex != 30){ // ここで「2.署名の中身の妥当性」を検証
    	trace('検証失敗');
    }else{
        trace('検証成功');
    }
}catch(e){
    trace('検証失敗');
}

実は、RSA-SHA1形式の署名をRSAKey.verifyメソッドで処理した場合、その第二引数(コード中で言うdst)には以下のような70byteのデータが入ります。(16進表記)

  • 3021300906052b0e03021a05000414{sha1(original_str)}

ここで前半30byteの「3021300906052b0e03021a05000414」とはRFC3447で規定されたsha1ハッシュプレフィックスです。

そしてこのプレフィックスよりも後ろの値40byteが元データのsha1ハッシュ値になっています。

そのため、復号化して16進表記に直した値からプレフィックスハッシュ値を探し出し、検証を行う必要があります。

僕はこれを知るのに2,3日ほど時間を費やしてしまったので、他にも同様なことをしたいという人がいるときに参考にでもなればと思います。

ちなみに、as3cryptoライブラリですが、google codeのas3cryptoページのTOPなどからダウンロード出来るファイルは古くて正常に動作しません。

その他にも、結構なバグが修正されているのでsvn上のファイルを用いることをおすすめします。


なにかご意見等ありましたらTwitterコメント欄までお願いします。

2011-07-12

ニコニコ動画のタグデータ

| 01:59 | ニコニコ動画のタグデータを含むブックマーク

以前の日記でお伝えした通り、現在、ユーザスクリプトを用いてニコニコ動画のタグデータの収集を行っています。

ある程度レコード数も溜まって来たので共起ネットワークなどの解析したいのですが、諸々の事情でなかなか出来ないため、とりあえずデータだけ公開しておきます。

解析自体はいつか必ずやりたい…

何か解析してみたいという奇特な方がいらっしゃいましたら、どうぞお使いください。

ダウンロードこちらから

  • zipファイルの中身はカンマ区切りのCSVファイルです。
  • 動画ID - タグ名 のレコードです。
  • 180万レコード以上あります。間違ってもエクセルで開こうなんて考えないで下さい。
  • 自己責任での使用をお願いいたします。(ウィルスチェックは一応行ってあります)

ご意見等ありましたら、ついったーかコメント欄までお願いします。

2011-05-24

リア充あやのちゃんで学ぶphpプログラミングの概念

| 02:10 | リア充あやのちゃんで学ぶphpプログラミングの概念を含むブックマーク

リア充を題材にプログラミングの話をして同期と話していて盛り上がって面白かったのでまとめてみました。

多分n番煎じでしょう。

長いことブログを更新してなくてアドセンスが表示され始めたので、丁度いいかなという感じの軽いノリの記事です。


はじめに

この記事では、とあるリア充の女の子を題材に、phpプログラミングにおける非常に大雑把な概念を記述していきます。

プログラミング初心者が対象のつもりです。

※CAUTION※

完全なネタ記事です!!

プログラミングなにそれおいしいの?という友達との話の中で上がった話題ですので、こじつけている部分も多く、色々と矛盾点があります。

正しいプログラミングの知識は正確なサイトや書籍を参考に身につけて下さい!!

phpの最低限

phpはwebプログラミング言語の一つです。

結構色んなサイトで用いられているものです。

phpの大前提として、

<?php

で書き始めるという約束事があります。

また、ソースコード中に出てくる「//」はコメントアウトといって、プログラムを実行するときには無視される単なるメモです。

その他、読み進めていって分からないことに関する詳細はぐぐってください><


あやのちゃん

今回の主人公になるのは、あやのちゃんという女の子です。

このあやのちゃんとはどのような人物なのでしょう。

まずは、あやのちゃんという人物像を考えてみましょう。

この時、人物像classとして以下のように書くことが出来ます。。

<?php
	class あやの{	}

これだけではあやのという人物像が存在ることしか分かりません。

そこで、まずは、あやのちゃんがこの世界で生活していることを記してみましょう。

<?php
	class あやの{	}
	
	$あやのちゃん = new あやの();

これで、あやのちゃんという人物がこの世界に存在することが出来ました。

「$」は名前(人物などだけでなく色々なモノの名前)を決める時の魔法の言葉です。


しかし、これではあやのちゃんがいるだけで、どんな人か全く分かりません。

そこで、あやのちゃんという人物像について詳しく調べてみましょう。


あやのちゃんの行動

調査の結果、あやのちゃんは起床後、時間に余裕があるときは徒歩で、余裕がない時は自転車で11時までに出社していることが分かりました。

これらの行動をあやのちゃんという人物像に付与してみましょう。

<?php
	class あやの{
		public function 起床(){
			目を覚ます;
			目覚ましのアラームを切る;
		}
		
		public function 出社(){
			if(時間に余裕がある){
				$this->歩いて通勤();
			}else{
				$this->自転車通勤();
			}
			11時までに出社してタイムカードを切る;
		}

		private function 歩いて通勤(){
			家を出る;
			歩く;
			会社に着く;
		}
		
		private function 自転車通勤(){
			家を出る;
			自転車を漕ぐ;
			会社に着く;
		}
	}
	
	$あやのちゃん = new あやの();
	
	$あやのちゃん->起床();
	$あやのちゃん->出社();

このように、どのように何をしているのかを実際に表すのがメソッド(function)です。

「出社」のメソッドにある、

if(時間に余裕がある){
	$this->歩いて通勤();
}else{
	$this->自転車通勤();
}

は、時間の余裕の有無によって歩いて通勤するのか自転車通勤で通勤するのかを表しています。

$thisというのは、あやのちゃん自信を指す魔法のキーワードです。

毎回、$thisの代わりにあやのちゃんと書くのは面倒なのでこういう決まりになっています。

$this->自転車通勤();

で、あやのちゃんの人物像が持っている、自転車通勤という行動を行うことを表します。

publicprivateという文言がfunctionの前にありますが、これは外圧によってその行動を行うのか否かを表します。

例えば「起床」や「出社」という行動が、目覚まし時計という外圧によって起こされたり、業務規則という外圧によって出社したりしているのに対し、自転車通勤や電車通勤は出社という行動の中で、あやのちゃんの意思で行っており、外から命令されているわけではありません。

ここがpublicとprivateの違いです。

(本来の解釈とは違いますが、ここではそんなもんなのか程度に知っておいてください)

また、この時、publicである「起床」は外圧だけでなく、自分の意思で起きることも可能ということもポイントです。

上の例では、実際に、何らかの外圧によってあやのちゃんは起床し、出社しているのを表しています。


さらに色々調べると、なんと、あやのちゃんには彼氏がおり、リア充であることが分かりました!!

爆発しろ!!

そこで、リア充ならではの行動をあやのちゃんに書き足してみましょう。

<?php
	class あやの{
		public function 起床(){
			目を覚ます;
			目覚ましのアラームを切る;
		}
		
		public function 出社(){
			if(時間に余裕がある){
				$this->歩いて通勤();
			}else{
				$this->自転車通勤();
			}
			11時までに出社してタイムカードを切る;
		}

		private function 歩いて通勤(){
			家を出る;
			歩く;
			会社に着く;
		}
		
		private function 自転車通勤(){
			家を出る;
			自転車を漕ぐ;
			会社に着く;
		}
		
		// ここからリア充の行動
		public function デート(){
			彼氏と二人で出かける;
			いちゃいちゃする;
			$this->キスする();
		}
		
		private function キスする(){
			唇を合わせる;
			$this->いやらしいことする();
		}
		
		private function いやらしいことする(){
			// 見せられないよ!
		}
		// ここまでリア充の行動
	}
	
	$あやのちゃん = new あやの();
	
	//休日になりました
	$あやのちゃん->デート();

休日になったとたん、謎の外圧(実際にはまあ、彼氏からの連絡とかでしょう)によってあやのちゃんはデートに行きます。

そしてそのままの流れで、いちゃいちゃしてキスして…

爆発してください。


リア充

さて、上記のように書きましたが、実際リア充なんてみんな同じ行動しますね。

そこでリア充特有のメソッドをまとめて記述して、「リア充」という人物像を作りましょう。

<?php
	class リア充{
		public function デート(){
			恋人と二人で出かける;
			いちゃいちゃする;
			$this->キスする();
		}
		
		private function キスする(){
			唇を合わせる;
			$this->いやらしいことする();
		}
		
		private function いやらしいことする(){
			// 見せられないよ!
		}
	}

あやのちゃんのリア充行動にあった「彼氏と二人で出かける」を「恋人と二人で出かける」に直してあげると、汎用性のあるリア充人物像が簡単に出来ました。

あやのちゃんがリア充であることはこれを継承してあげることで簡単に表現できます。

継承を行うにはextendsを用います。

<?php
	class あやの extends リア充{
		public function 起床(){
			目を覚ます;
			目覚ましのアラームを切る;
		}
		
		public function 出社(){
			if(時間に余裕がある){
				$this->歩いて通勤();
			}else{
				$this->自転車通勤();
			}
			11時までに出社してタイムカードを切る;
		}

		private function 歩いて通勤(){
			家を出る;
			歩く;
			会社に着く;
		}
		
		private function 自転車通勤(){
			家を出る;
			自転車を漕ぐ;
			会社に着く;
		}
	}

これで、あやのちゃんは、リア充であることが一目で分かり、また、キスするなどをあやのちゃん独自の行動として書かなくて済む分、あやのちゃんに関する記述がすっきりしました。

記述はすっきりしましたが、リア充継承をしているのでリア充の行動を行うことも当然可能になります。

この継承とは何が嬉しいのかと言うと、リア充がたくさんいる世界では非常に便利です。

例えば、あやのちゃん以外に、おはなちゃん、こうくん、みんこちゃんなども恋人がいるリア充どもだと言う場合、一人一人に「キスする」などの行動を書かずとも、

<?php
	class おはな extends リア充{
		...(省略)
	}

	class こう extends リア充{
		...(省略)
	}

	class みんこ extends リア充{
		...(省略)
	}

と書くだけで、みんな恋人とキスが出来るのです!!便利!!爆発しろ!!


このように継承は、似通った処理を1つだけ書くことですっきりした見た目になり非常に便利なのですが、人物像は1つしか継承することが出来ません。

なぜならば、たくさんの人物像を継承できてしまうと矛盾が出てくる場合があるからです。

例えば、以下のような非リアという人物像があるとします。

<?php
	class 非リア{
		public 引きこもる function(){
			数少ない友達もみんな予定あるし、自宅でニコ動でも見よう。あ、積みゲー消費するのでもいいな。
			んー、やっぱりアニメ見るか。あー、美琴は可愛いなぁぁぁ。
			俺にも美琴みたいな恋人がいればなぁ。
			というか、誰でもいいから恋人がいればねずみの海とかも張り切って遊びに行けるのにな。
			まあ、仕方ないんだから、今日はアニメ見て、ニコ動見て、ニコ生でJK見て、積みゲー消費して寝よう。
			よし、決めた。今日は引きこもる。
		}
		
		...(省略)
	}

何かの間違いで、この非リアという人物像と、リア充という人物像を同時に継承してしまったら、恋人の存在が矛盾してしまい病院送りになってしまいます。

こういった矛盾を最小限に防ぐためにも、人物像は1つしか継承出来ないのです。


援助交際

さて、あやのちゃんに話題を戻しましょう。

更なる調査を行った結果、実はあやのちゃん、彼氏もいてリア充なくせに社会人でありながら援助交際をしていることも分かりました。

<?php
	class あやの extends リア充{
		...(省略)
		
		public function 援助交際(金額 = 0){
			if(金額 < 10000){
				お断りします。
			}elseif(金額 < 20000){
				添い寝だけね。
			}elseif(金額 < 40000){
				尺八の吹き方を教えてください。
			}else{
				好きにしてっ!!
			}
		}
		
		...(省略)
	}

とんだビッチですね。

さて、この援助交際メソッドの(金額 = 0)というのは引数と呼ばれ、外から値を与えることが出来ます。

要はあやのちゃんに与えるお金です。「= 0」というのは、外から値を与えなかった場合、金額=0と一緒だよという意味です。

あやのちゃんは、この引数の金額をもとに、相手にどのような行為を行うかを決めるのです。

このように、外から値を得て、行動を変えたい場合は引数を使いましょう。


腐っても人間

あやのちゃんについて調査していたら、とんだ結果となってしまいましたが、それでもあやのちゃんは人間であることは間違いありませんね。

呼吸すれば、食事もします。もちろん、歩いて通勤するには歩くという基本的な行動も必要です。

要は、当たり前ですが、「あやのちゃんは人間」という情報を定義付けしてあげましょう。

しかし、そもそも人間とは一体どんなものなのでしょうか。まずは人間の概念(何をするのか)から決定する必要があります。

簡単に人間の概念を書くと下のようになります。

<?php
	interface 人間{
		public function 呼吸する();
		public function 歩く();
		public function 走る();
		public function 食事する();
		...(省略)
	}

こう書くと「人間」とは何となく、「ああ、呼吸したり、歩いたり、走ったりするのね」というのが分かります。

(もちろん、人間はそれ以外にも色々しますが、とても書ききれないので省略しています)

このように、どんなことをするのかの概念だけを表すときに用いるのがinterfaceです。

この時、intafaceは概念なので実際にどのようにその行動を行うかは書きません

食事するにしても箸を使ったり、スプーンを使ったりと人それぞれですので、詳しいことを概念として決定することは出来ないのです。

さて、人間の概念が出来たところで、実際にあやのちゃんが人間であるという定義をしましょう。

概念を定義付けるにはimplementsを用います。

<?php
	class あやの implements 人間{
		public function 呼吸する(){
			自発呼吸する;
		}
		
		public function 歩く(){
			2本の足で歩く;
		}
		
		public function 走る(){
			2本の足で、50mを8秒くらいで走る;
		}
		
		public function 食事をする(){
			箸をきちんと使って食事をする;
		}
		
		...(省略)
	}

概念が定義付けられたら、実際にその概念のなかで書かれた行動をどのように行うのかを書く必要があります。

人間と定義された以上、どのような形であれ、その定義がもつ行動は詳細を決めてあげないといけないのです。


あやのちゃんとはなんだったのか

さて、長々と書いてきましたが、結局あやのちゃんとはどんな存在なのでしょうか。

まとめて書いてみましょう。

<?php
	class あやの extends リア充 implements 人間{
		public function 呼吸する(){
			自発呼吸する;
		}
		
		public function 歩く(){
			2本の足で歩く;
		}
		
		public function 走る(){
			2本の足で、50mを8秒くらいで走る;
		}
		
		public function 食事をする(){
			箸をきちんと使って食事をする;
		}
		
		...(省略)
		//他にも人間としての基本的な動作に関する記述がたくさん...
		
		//ここから下はあやのちゃん独自の行動
		public function 起床(){
			目を覚ます;
			目覚ましのアラームを切る;
		}
		
		public function 出社(){
			if(時間に余裕がある){
				$this->歩いて通勤();
			}else{
				$this->自転車通勤();
			}
			11時までに出社してタイムカードを切る;
		}

		private function 歩いて通勤(){
			家を出る;
			歩く;
			会社に着く;
		}
		
		private function 自転車通勤(){
			家を出る;
			自転車を漕ぐ;
			会社に着く;
		}
		
		public function 援助交際(金額 = 0){
			if(金額 < 10000){
				お断りします。
			}elseif(金額 < 20000){
				添い寝だけね。
			}elseif(金額 < 40000){
				尺八の吹き方を教えてください。
			}else{
				好きにしてっ!!
			}
		}
	}

文章で書けば、あやのちゃんは人間であり、リア充という属性で、起床して、11時までに出社して(出社は時間に余裕があれば徒歩、なければ自転車)、援助交際をしている人物である、ということです。

最後に援助交際があって、酷い言いようになってしまっていますね。全国のあやのちゃん、ごめんなさい><


おわりに

だいぶ長々と書いてきましたが、実際、おおざっぱにプログラムなんてこのようなものです。(少なくとも個人的にはそう思います)

上記のソースコードは全く動作しないですので、実際のプログラムに生かすことは出来ないでしょう。

が、プログラミングが全く分からない方にとっては、身近な(?)話題である分、ほんの少しくらいでもプログラミングの面白さを知るとっかかりになってくれていればと思います。

だいぶヒドイ内容(笑)にここまでお付き合いくださり、ありがとうございました。

口頭でわいわい言い合っているのを文章にまとめるのは、非常に難しいのだなぁと実感しました…



※上記で出てきた名前などは、実在する人物やキャラクターとは一切関係ありません。全部嘘っぱちです。

2011-02-07

スクリプトを利用したタグ情報の収集について

| 05:11 | スクリプトを利用したタグ情報の収集についてを含むブックマーク

現在公開している、ニコ動の検索ページにタグクラウドを表示するユーザスクリプトを用いて、2011年2月8日5時15分頃よりタグ情報の収集を行います。

これに伴い、以下の通りお知らせいたします。

  • 目的
  • 期間
    • 2011年2月8日5時15分頃〜(終了時期未定)
  • サーバに送信する情報の種類
    • 動画ID
    • タグ
  • スクリプトのバージョン
    • 現行のバージョン(1.0.3)で対応いたします。特にアップデート等する必要はありません。
  • 特記事項

スクリプトのソースを見ていただくと分かりますが、そもそもユーザ情報は取得していません><

若干のスクリプト読み込み速度の低下があるかと思いますが、ご協力よろしくお願いしますm(_ _)m

また、申し訳ありませんが、情報を収集しないスクリプトは提供出来ませんので、どうしても嫌だと言う方はスクリプトアンインストールをお願いいたします。

ご協力、よろしくお願いいたします。

2010-10-31

ニコ動の動画検索ページにタグクラウドを表示するChrome拡張を改良したよ

| 02:57 | ニコ動の動画検索ページにタグクラウドを表示するChrome拡張を改良したよを含むブックマーク

[追記]バージョンアップ通知動作をきちんと行わない可能性があるため、修正しました

ニコニコ動画の動画検索ページに共起タグクラウドを表示するChrome拡張が、ニコニコ動画のスタイル変更に伴って動作しなくなっていたのを修正しました。

ついでに、少し体裁を整えたり、新しいバージョンが出た時に知らせる機能をつけてみたりしました。

f:id:aTaGo:20101101025015p:image

導入

ちなみに、新しいバージョンのスクリプトを公開した場合は以下のようなメッセージが出ます。(20101101より以前のバージョンではメッセージは出ません)

f:id:aTaGo:20101101025016p:image