replyツイート「車輪の再発明」ですが、javascriptでMD5を計算するスクリプトを作成しました。2049通りのテストケースを作成し、各ブラウザでテストしました。おまけに各ブラウザのjavascript実行速度のベンチマークもしました。はじめにさくらレンタルサーバーのApacheはmod_digestが入っていないようで、Digest認証ができません。パスワードを平文で毎回送るベーシック認証も如何なものだろう?と思っていました。(まあSSLにすればよいんですが。)ふと、「ブラウザ側で、javascriptにてDigest認証と同様にハッシュを生成してやればよいのでは?」と思いつきました。そこで、javascriptでMD5が実装されているか調べてみました。md5test.html)の再利用や改変は、ご自由に行って下さい。_)m)(2015年1月19日追記:リンクしているyjdmd5.jsを更新しました。これを利用したダイジェスト認証について「javascriptのMD5を用いたダイジェスト認証」を書きましたので、こちらも合わせてご参照下さい。)(2015年1月25日追記:「javascriptでSHA-512」では、ハッシュ関数SHA-512をjavascriptで実装し、それをスクリプトによるダイジェスト認証にて使うことを提案しています。)調査javascriptにmd5関数があることを期待してGoogle先生に聞いてみたのですが、どうやらjavascriptの組み込み関数にはないみたいです。代わりに、沢山の実装事例がありました。参考にさせて頂いたページは以下です。RFC1321のサンプルに忠実な実装があります。「同種のライブラリに比べて3~7倍ほど高速」なコードが有ります。「RFC1321」(の日本語訳サイト(^_^;)。アルゴリズムの解説とC言語のサンプルコードがあります。(sanakiさんのページには、既に「javascriptでチャレンジ/レスポンス認証」のアイデアが書かれています。)以上のページは古めです。2つのソースコードを見させていただいて、「現在でもビット演算を16bitに区切って行う必要があるのか?」と疑問に思いました。labsさんはFirefoxの場合のみ16bit区切り。)またPHPと互換にするために「文字列はUTF-8で処理したい」とも思い、RFC1321を見ると比較的簡単に実装できそうだったので作ってみることにしました。(本来であれば車輪の再発明はしないに限るのですが...。)(2015年1月22日追記:code.google.comに、暗号ライブラリ「crypto-js」がありました。コミットの日付が2012-2013年の、新し目の実装です。リンク先のページには使い方がありますが、googleさんに置かれたjsを読み込むだけなので、お手軽です。)javascriptでバイナリ操作javascriptにはビット演算子があり、32bit整数としてビット演算ができるそうです。(私はjavascriptをいじり始めてから若干ヶ月です。)しかしMD5のアルゴリズムでは足し算が多用されています。0xFFFFFFFFする)必要があるでしょうか?疑問点をざっくり調べてみたところ、javascriptでは以下のようです。Scriptの仕様書は見ていません(^_^;)。)Number型(64bitの浮動小数点型)は2^53までなら整数を正確に表せる。ビット演算子を使うと、Number型は32bit整数になる。(下位32bitのみに丸められるイメージ。)Uint32Arrayを使うと高速。(javascriptの配列はハッシュテーブルなので遅そう。)Uint32Arrayに代入するときも適当な32bit整数になる。上記より、2^20回(くらい)以上連続で足し算しない限りは、ビット演算があったときに自動で32bitになるので、最後以外は意識してまるめてあげる必要はなさそうです。Firefoxについての特記事項もありませんでしたので、とりあえず32bit演算を基本に作ってみることにしました。(根本的にアセンブラ・C言語ならスマートに実装できるアルゴリズムをスクリプト上で、しかも浮動小数点型で実装するって、何か残念な気がします。)UTF-8への変換javascriptのstringをUTF-8に変換するには、「Blobのコンストラクタに渡してFileReaderで読めば早い」という記事がありました。コールバック関数(あるいはワーカー)が必要で、またjavascriptにはミューテックスがなく関数内で同期ができなさそうなので、「よくある方法」で変換することにしました。要件としては以下を考えました。文字列のハッシュ値が得られればよい。(今のところ、巨大なファイルのハッシュ値を得ることはない。)従って、RFCのサンプルコードにある、Updateのような関数は(今のところ)必要ない。文字列はUTF-8として処理。あと、速度はそれほど必要ありません。速度と、そこそこのコードのきれいさを勘案します。実装したコードはこちらをご参照下さい。(文字コードはUTF-8です。)Uint32Arrayを使っているので古いブラウザ(IE9以前とか)は未対応です。ROTATE等の関数を作成し、スクリプトを使ってインライン展開したらこうなりました。実装の特徴は、バッファにUint32Arrayを使ってダイレクトに32bitリトルエンディアンを扱っていることでしょうか。Uint32Arrayはコンストラクタで0で初期化されるので、1byteのキャラクターを「シフトして”|=”(OR代入)」でセットできます。(byteのセットもインライン展開したのでコードは汚いです。)テストテストの入力は0文字から1024文字までのランダムなASCIIと日本語の文字列(2049ケース)としました。テストケース(入力と正解)はPHPで書いたスクリプトで生成しました。テストケースはこちらをご参照下さい。(文字コードはUTF-8です。)テストドライバはこちらです。:md5test.htmlボタンを押してもテスト実行時間が表示されるだけなので面白くありませんが、ソースを見るとちゃんとテストを実行していることがお分かり頂けるかと思います。UTF-8のテストは日本語だけなので、4byteコードの検証はなされていません。テスト結果Windows7にて、以下のブラウザでテストした結果、OKでした。22.0.1471.70おまけ:ブラウザのベンチマークテストドライバでは、ボタンを連打すると繰り返しテストの実行時間が表示されます。そこでテストのついでに10回実行時間を測定して、平均値を出してブラウザのベンチマークをしてみました。1111.0.9600.17207218.5Safari5.1.7765.1Opera22.0.1471.70412.1何となく「ChromeのV8が速い」と思い込んでいたので、以外な結果でした。Firefoxに至っては、「きっと途中でエラーが起きて、すべてのテストを実行してないに違いない」とさえ思い、デバッガで確認しました。JavaScript実行速度、C++に迫る」(マイナビニュース)という昨年末(2013年)の記事がありました。これによると、「C++より1.5倍遅い」だけだとのことです。(このテストであれば、実行エンジン内ではほとんどの変数が整数として動いているのかもしれません。)Safariはがんばりが必要ですね。このベンチマークはjavascriptの様々な要素を測定していません。ご参考程度に御覧ください。まとめjavascriptでMD5を計算するスクリプトを作成し、テストしました。おまけに各ブラウザのjavascript実行速度のベンチマークもしました。バイナリ操作の仕方もわかったので、「DH鍵交換して、ストリーム暗号でAJAX」も実装可能ですが、さすがにそれだったらSSLを使えって感じでしょうか。コメントをキャンセルメールアドレスが公開されることはありません。