2020年4月18日土曜日

HMACと暗号の実装

ハッシュを作ったので次はHMACなど作ってみた。
HMACはハッシュを使ってパスワード認証的なものもつけているので改変されていないかなどで有利なのかどうなのか。JavaではMacという分類のあれこれ。
ハッシュごとのハッシュ長は取得できてもブロック長やら何やらを取得するのがJavaの標準APIにはなさそうなので自作ハッシュではそのあたりも拡張しておく。
HMACに適当なハッシュを載せられるので、MD2とか対応してなさそうなのをあわせてみてもいいし、SHA-3ではべつのアルゴリズムKMACを使うようだけどもHMACでも問題なく対応しているし、仕様にもあるはず。 JDKにはまだHMAC-SHA3とかなかったかも。
HMAC-MD5とか、HMAC-SHA-256とかいろいろできるので広がる。
ただ、暗号という位置づけなのか、何もしないとHMACなどMac系のアルゴリズムはJavaに登録できない感じだったので、署名などつけないといけないのかもしれず、暗号だけのライブラリには分けてみたけど署名を試すのはまた次回。
登録しなくても、自作すればどうにでも使えるので動作は問題ない。
他にもMac系のものがあるようなので、KMacとか作ってみる予定は未定。SHA-3と別の資料なのでまた読むのが大変。

暗号

作る予定ではなかったかもしれないけど、ハッシュをいろいろ作ってみた勢いで暗号にも手を出してしまった。
詳細ではなくどんなのがあるかくらいのメモでいいかな?

ブロック暗号、ストリーム暗号


暗号の基本、大まかにはブロック単位の暗号と、バイト単位でデータと(疑似)乱数をXORで暗号を作るストリーム暗号とがある。他のもあるが、大量のデータを暗号化するにはこのふたつかな。よく使われるのはブロック暗号なのかどうか。ブロック暗号も組み合わせ方によってはストリーム暗号として使うこともできる。逆にストリーム暗号の長さを固定してブロック暗号として使えるのか、というと使える、がビット反転では弱くないのか謎。暗号強度に差が出る場合があるのでそれぞれのアルゴリズムで判断した方がいいかもしれない。
ブロック暗号もストリーム暗号もJavaのストリームとして使えるようにしておくと便利なのかもしれないので基本の部分は共通の設計にしておこう。
ストリーム暗号ではXORするだけなので、最後は必要な長さで切り取って終わらせられるのだけど、ブロック暗号ではデータの長さとブロックの長さとで端数が出てしまうので、PKCS#5などのPaddingの埋め方もいろいろあるよというところぐらいまで。
PKCS#5のPaddingでは、最後に長さの数値を繰り返し埋め込んで、複合化したときにその長さを読んで切り捨てる、という方式がPKCS5Paddingとかいう簡単な方式。

DSAは実装も暗号?


暗号はDSAからいってみよう、と思ったら大変。バイト単位で計算するんではなくてビット単位で並び替えてみたり、それなりに難しい箇所がたくさん。
DSAはもう廃止されているアルゴリズムなので、いろいろ参考にできるものが少なくて大変。まずテストパターンが見つからないので合っているのかどうかがわからない。 内部状態は紙の資料をコピーしたようなのが1つ見つかったので試してみることはできたけども。
というわけでDSAは、要所要所でどれが合ってるのか探るのに苦労した。
乱数表は、わかりやすく展開できるのにいつまであの形なんだろかという疑問もあり。コードを書きにくいのは、何の得にもならないと思うのだけど。そういう点が何カ所かあった気がする。暗号の練習には最適かどうか謎。

暗号モード

で、とりあえず動いたところでブロック暗号には暗号アルゴリズムとは別にモードというものもあったりなかったり。ECBとかCBCとか。単純に暗号コードを潜らせただけでは1つのブロックを暗号にはできてもつづくブロックを同じように暗号化していればバレてしまう。難しい暗号になるわけではないのでなるべく均一に解読されやすそうにならないように、いろいろと前後混ぜていく処理など。
それもHMACのように暗号とは別に作っておくことで、どの暗号とも組み合わせが効くので便利。ECBというのは何もしないモードかな。暗号自体にもNULL暗号という何もしない暗号があるので間違って使わないようTLSなどでは無効化してあったりなかったり。
暗号モードによってはブロック暗号をストリーム暗号にすることもできる。これはまた便利な場面も出てくるかも。
CBC,ECB,CFB,OFB,CTR,PCBCぐらいのものを作ってみた気がする。

ブロック暗号とストリーム暗号、のモード


ブロック暗号を使ってストリーム暗号の乱数を作っているのがCFBとかOFBとかのモード。これでブロック暗号でもバイト単位での暗号が可能。ビット単位で反転させる攻撃には弱そうだけども。CFB,OFBをとりあえずストリームモードにも対応してみた。CTRも対応できそうか。
ストリーム暗号専用の暗号はまだ実装してみていないのでまたあとで。KDDIの KCipher2作ってみようかと思う。

速度が出ない?

データをファイルなどから読んで、ハッシュや暗号にブロックサイズ単位で投げつける処理をまとめて作っていたのだけど、なかなか処理速度が上がらなかった。出力先のOutputStreamにもブロックサイズでしか出力していなかったからで、ある程度まとめてから吐き出す処理に変えると速くなった。ハッシュのときは出力先がなかったのでいろいろと改良しておいた。
モードによって連続して暗号化できるわけでもないので暗号を単純にまとめて速度アップもやりにくい。いろいろと難しい。

ストリームに暗号をはさめばよい

という考えでFilterOutputStreamっぽいものを書いたら速度が出なかったので、次はwriteした単位でまとめてから次に渡すようにしてみる。
パディングに引っかかりそうなデータを残して暗号化にかけ、送り出す、というのを暗号、復号、InputStream、OutputStreamの組み合わせで作ってみるといろいろ楽になる。
JavaのCipherにラップして放り込んでみたら復号側の処理単位が途中データを出してくれなくてあれでだめだった。暗号と復号をひっくり返すModeっぽいのも作っておくと楽しい?

AESは数学なあれ

AESは難しい。まず資料だけ見て書けるものではなかった。ガロア体とか有限体とかいうのが謎だったので調べまわり、ようやく動くものができた。行列の計算ぐらいは基礎だけどもAESでは桁が繰り上がらないとかガロア体特有でいろいろ難解。
動くようになれば最適化しがいのあるガロア体でもあり。
2ビットや4ビットの数と掛け合わされているので減らせる計算もある。
説明どおりに作れば鍵長128bit,192bit,256bitには対応できる。鍵は初期時に全パターン生成しておく。それは簡単。byte単位でもintサイズでもいいが、最初はバイト単位で作ってみたり。
次にsboxの生成方法を調べてみたがこれはほとんど正解なし。書籍でもお茶を濁したようなものばかり。正解らしきものは見つけたので使わせてもらう。
AESの中の処理はガロア体で掛け算、ガロア体で変換、シフト、鍵で混ぜの4種類くらい。

AES(バイト単位で暗号化するよう書いてみた)でJDKのAESと速度比較してみたら、完敗だったのでintで処理するように書き直して互角ぐらいの速度まで持ってきた。
KCipher2ではMixColumnsがテーブル化されてしまっていたのでAESでも真似てみるとたぶん最速の状態になった。

KCipher-2

九州大学とKDDI研究所とが作ったというストリーム暗号、AESと部分的に似ているが微妙に異なる処理なので、合っているのかいないのがも微妙にわかりずらいので難航。いつできるかな…。元の資料よりRFC 7008見た方がいいのかも?

2020年4月17日金曜日

Logicool UnifyingレシーバとUSB3電波干渉

Logicoolのワイヤレスマウスやキーボードは、USBのUnifyingとかいうコンパクトワイヤレスアダプタでPCと繋がっていい感じなのだが、USB3.xとは相性が悪く、隣の端子に(M.2型の)SSDを繋いだところ、ログイン後キーボードマウスが動かなくなってしまう現象に遭遇してしまった。
対処方法は、USB端子を離すこと、Bluetoothを使うこと。
最近のキーボード、マウスはBluetooth LEにも対応しているのでBluetoothにしてみるのがひとつの解決策。
Bluetoothにするとマザーボードの設定ができなくなったりするので可能ならUSB3とUnifyingのレシーバを離して繋ぐのがいいのかも。


2020年4月7日火曜日

4Kディスプレイのススメ

4K UHD Blu-rayなどを見るためにディスプレイを探していたのだけど、HDR対応で探してみるとあまり明るそうなものがなく、と数カ月様子見していたかもしれない。
24型くらいのJAPANNEXTの4Kディスプレイは購入してみたことはあったがHDR対応でもなく、小さすぎるので4Kっぽくもなく。
ディスプレイでHDRというとDisplayHDRという規格があるのでその中から候補を出してみた。
31.5インチ、DisplayHDR 600、というとわりと高級機で10万、30万という値段のものまであるようなないような。
以前50インチのPHILIPSのDisplayHDR1000のディスプレイを見たときは、ドットが崩れすぎてPCでは使えないなと感じてたのでPHILIPSも除外。
ASUSもDisplayHDR1400とかいう変態機を出していたが高すぎるだろうということでよくあるディスプレイの300nit(cd/㎡)越えはほしいのでDisplayHDR 600あたりを漂っていると、Acerの型番が難しそうな機種(ET322QKCbmiipzx)が5万円という破格で出てきた。1年前の機種ということなのでそれほど古くもなく、4KでHDRでDisplayHDR 600もある。ただし標準の輝度は400cd/㎡。
DisplayHDR 600の規格の方をよく見てみると、わりとプロ向け仕様になっていて色域も広い、10bit対応などとあり。
古い機種なのか人気なのか、在庫のある店があまりないのでポイントがつきそうなところで予約。au Payとかは使わなかったけど。1週間から2週間ぐらいで届いたように思う。
型番は類似品があるのでシリーズはET2、DisplayHDR600対応とET322QKC という頭の型番の最後にCがつくのを確認しよう。

開封設置

だいたい32型。今までのより大きい。ディスプレイとして使うなら4Kでは最適な最小サイズかもしれない。Windowsのテキストが100%でも読める。テレビだともう少し大きい方がいい。
足は細いので、物の上など平らな場所にちょっと置くことはできず、それなりのスペースを取る。謎の5cmぐらいの棒が1つついてきたがケーブルでも垂らすものなのか謎。
DisplayPort 1.2 1つとHDMI 2.0が2つ、音声出力端子と2W+2Wのスピーカー、4ポートのUSB 3.0 HUB付き。RATOCのHDMIから音声を分離する装置をはさむとUHD Blu-ray Playerとのネゴシエーションに失敗してしまったのでそれは外して接続。
ボタン類は右背面に縦に配置。十字とボタン4つくらい。押しやすいが下の電源スイッチとディスプレイ切り換えボタンが押し間違えやすい。

4K HDR

24インチとは迫力が違う、店頭で見ていたような色合いで繊細な4K HDRが表示できるのはなかなかよい。ただソースがYouTubeと数少ないUHD Blu-rayくらいしかないのでHDRがもっとほしい。4Kだけならスマホのカメラなどでも撮れるのだけどHDR対応だと最新機種ぐらいでしか撮れない。
HDRなだけあって、電力も持っていかれるらしい…か。
4K HDRに興味があれば、ITU-R BT.2100 とかいう規格を見てみれば。
電子書籍もさくっと拡大して綺麗なのでPCでマンガを読んでみるにはこのサイズ、お得かもしれない。これはHDRではなくていい。
音もヘッドホン端子からの出力はノイズもなく問題なさそう。スピーカーは安っぽいのでつけるなら別のスピーカーを外付けの方がいい。

GeForceで10bit出力

今までのディスプレイは10bitにも対応していたが、入力は8bit、明るさを調整して10bit、という位置づけだった。
GeForce RTX2070では10bit出力にも対応している、ということでディスプレイ側は10bit入力と出力ができるのか、軽くテストをしてみる。
GeForce ExperienceではなくNVIDIAコントロールパネル側の設定を開く。
ディスプレイの「解像度の変更」を開き、3.でNVIDIAのカラー設定を使用、出力の色深度を10 bpcにする。これで対応アプリで10bit出力ができる。設定しなくてもPhotoshopは対応しているかもしれないが。
Photoshopは持っていないので体験版を利用。10bitといわれるpsdファイルが世の中のどこかにあるので入手。
とりあえず設定なしで10bitなファイル開いてみてギザギザしているのを確認。
Photoshopでも設定が必要で、 Photoshop 2020体験版では[編集(E)] [環境設定] [パフォーマンス]を開く。
[グラフィックプロセッサーの設定] の[詳細設定]で[30bitディスプレイ] にチェック、OKで確定したらPhotoshopを再起動、画像が10bitで表示されバンディングがわからなくなっているのが確認できる。

弱点はあるか


HDR?の切り換え(YouTubeを全画面にしたときなど)に時間がかかるのが、気になるといえば気になる。HDMI音声分離機も切り換えが遅いか相性が悪くて使えず。
HDRモードにしていても、全画面とウインドウ表示では色味が違う。
それくらいしかないといえばない。VAパネル?なのでIPSほど横から見て綺麗ではないので近寄りすぎて真ん中以外で見ていると横の色が気になるかもしれない。

HDRはいいぞ?

2020年4月6日月曜日

ASUS RT-AX3000買ってメッシュWi-Fiの入り口へ

定評のないASUSルータ、その原因はセキュリティアプリにありそうなのだが、というわけでAmazon専売らしいASUS RT-AX3000購入してみたので、いろいろお試し期間。

今回の組み合わせ (Wi-Fi 6 802.11ax)
  • Intel AX200NGW
  • ASUS RT-AX3000
他ルータ (Wi-Fi 5 802.11ac)
  • BUFFALO WSR-2533DHP2
  • IODATA WN-AC1600DGR2か3か
Wi-Fi 6は802.11ax の高速なWi-Fi規格。デスクトップPCにIntelの拡張カードAX200NGWを載せてみているので、ルータ側を変えるタイミングを窺っていたら1年ぐらい経過していた。ASUSからWi-Fi 6対応で安価なRT-AX92Uよりさらに安いRT-AX3000が出たので購入。5GHz帯が2ストリーム(4804+800)から1ストリーム(2402)に減っている、アンテナ2本なので2402Mbpsという差がある。有線LAN/WANも1Gpbsに落ちる。
CPUなどの性能は同じくらいのようだ。とりあえず1Gbps以上の性能はまだ必要ないと思うところなので、必要になればAiMeshのサブ機にするくらいの買いやすさで購入。
RT-AX92Uから強化されている点はWPA3対応か。AiMeshでは全ルータが対応しているっぽいWPA2しか使えないが。

メッシュWi-Fiとローミングの違い


Wi-Fi 6に加え、今流行りのメッシュWi-Fiに対応している、という点が今回の要点。今回安定していれば次は強めのルータを買って2台でメッシュ、というお試しができるかもしれないのがよさそうなところ。
用語
  • ルータ 外部とも有線と無線とも繋がる機器
  • AP (Wi-Fi AP) Wi-Fiと有線LANと繋ぐ機能だけ使っている状態
  • 中継器 Wi-FiをWi-Fiに繋ぐ中継をするもの 
どれもAPの機能は持っている感じの括り。
子機が途切れずAPをまたいで繋がるのがローミング、それに加えてルータ/AP/中継器間を自動で中継してくれるのがメッシュWi-Fi、 という違いがあるのでどちらを使いたいのか把握しよう。ローミングだけのはあんまりないけども。
ローミングにも対応していない場合は電波がぎりぎりまで切れないが、近くの同名APに切り替わるタイミングで一度TCPなどが切断されたり場合によってはIPアドレスも変わったりすることになる。
メッシュWi-Fi 802.11sとローミングの違いがわかったら、ローミングの802.11vだとか11k、11rとかいうところの規格が関係しているのでそういうところの対応機器に注意。
  • 802.11s メッシュWi-Fiの仕組み 企業や機器間で互換性がない
  • 802.11k ローミング対象の一覧を知ることができる規格
  • 802.11r ローミングで認証を短縮するような機能
  • 802.11v APがローミング先を指定できる機能
それぞれ対応機器があるので調べてみては。最近のスマホなどはローミングには対応しているが、メッシュ非対応のルータはローミングにも対応していないものが多い。

ASUSはAiMeshと呼んでいて、ルータのCPUなどが異なってもメッシュWi-Fiを構築できるのが強み。メッシュは企業間で互換性がないが、ローミングは企業が違っても何とかなることがあるので中継器などでは期待できるのかもしれない。メッシュでなくていいなら、手動で親機と中継器(AP)をWi-Fiや有線LANで繋ぐことはできるが、親機がローミングに対応していないので移動すると切れる、などがある。
BUFFALO,Googleなどもメッシュ対応ルータを出しているが、高価だったり機能が少なすぎたりメッシュを構築できる機種の組み合わせが少なそうだったりといろいろと不自由。

RT-AX3000 設定

ASUS RT-AX3000をBUFFALOのWSR-2533なんとかと交換、APとしてIODATAのルータが残る形で開始。
さくっと設定するのはスマホからでもPCのブラウザからでも可能。PCのWeb画面の方が機能は豊富かもしれない。
ログインID、パスワードともに設定が可能。adminではなくてもいいのよと。忘れてしまいそうだけども。
2.4GHz帯、5GHz帯を別々のSSIDで運用していたが、2.4GHz帯の方のSSIDにまとめて設定してローミング具合の様子を見ることにする。
 さくっと一晩寝かせてみたらスマホからいろいろ繋がらないのでセキュリティ、ファイアウォール的な機能を切る。ファームウェアアップデートを適用するのは楽。
IPv6はパススルーで接続可能。IPv4はPPPoEにて接続。5GHz帯で繋いでいたGoogle Homeなどの接続先を共通のSSIDに変えてみる。が2.4GHz側を拾ってしまう。
安定したかのようにも見えたが、電波は若干弱いようにも見えるのでアンテナ角度など時間をかけて調整してみたり。11ac 5GHz対応スマホでも2.4GHz側に繋がることが多い。手動で再接続などすると5GHz帯11acを掴むのだが。
設定画面はhttpsにもすることができ、DDNSとあわせてLet's encryptまで簡単に使える。
2~3日目、ONU? が何度が死ぬ。ルータが死んでいるわけではないようで、ONUを再起動するまで繋がらなかったり、それが何度か繰り返されたり。速すぎるのか何かが原因? 切断している間、ルータにも内側から繋がらないという恐怖。IPv6も死。
ONU、ルータの順で電源を入れてみて安定するのを待ち。
という感じで不安定な要素も多いがBUFFALOルータも切れるとなかなか繋がらないし、年に数回落ちる。AX3000も安定したらしいのであとは何日もつかなという耐久。SSIDは5GHz帯と2.4GHz帯を分けておくことにする。
スピードテストはGoogleは上下共に200Mbps以上出るのでまずまず高速な方か。テストサイトによっては上り300Mb/s以上、下り700Mb/s以上とか出ていたかも。

ローミングテスト

WSR-2533DHP2 は以前からローミングに対応しているような動きをしていたので、APとして使ってみたところ、RT-AX3000と相互に強い方の電波をいい感じに掴んでくれるようになった。ローミング未対応のWN-AC1600DGR2のAP側から対応AP側に行くと切り替わり、逆に行っても弱い電波を掴んでいる間は切り替わってくれないような感じ。DHCPでIPアドレスを配っている中で、切り替わるタイミングで通信が切れるか切れないかは端末次第かもしれないが、ローミングに対応と表記があれば違うメーカーのAPでも切れずに切り替わる気がする。そうでなければ切れる覚悟で。NECかBUFFALOの上位機はルータ内で2.4GHzと5GHzのローミングのみ対応しているというようなのもあるっぽい。

外と繋ぐ VPN,Alexa,IFTTT


いろいろと機能が豊富なのでAndroidからVPN接続できるようにしてみる。対応しているのはPPTP,OpenVPN,IPSec VPNの3種類。BUFFALOのWSR系はこのVPN非対応なので今まではIODATA側に中継して接続するという変技を使っていたが、これで直接繋がる。設定を確認してみたところ、IPアドレスは詳細設定で指定可能。別のサブネットになるっぽい? これはLAN内に混ぜられるのか、ネット同士の接続に使えるのか、あまり解説などもないのでそれぞれのプロトコルで不明。
IPSec VPNではパスワードらしきものを詳細設定でいくつか、と、ユーザの作成。
いろいろ謎だがとりあえず繋がりはする。
Alexa Amazonの声の人、IFTTT、Wi-Fiで繋がったタイミングでIFTTTの何かを実行できる、というような機能。
どちらも初日にはなぜか使えず。DDNSや設定画面を外部に公開したり、Let's encryptがもしかしたら必要だったりしたのかもしれない。2日目にはどちらも問題なく連携完了。
IFTTTでは部屋を移動するとスマホの接続先が変わって電気をつける、というような変なことができる。帰宅すれば電気がつくなど、手持ちスマホと連携してちょっとした機能で連携してみたりするのがおすすめ。
Alexaは、使い所がみつからないし普段から使っていないので略。Wi-Fi、ゲストWi-Fiのオン/オフなどができるが、細かく切り換える必要はないんじゃないかな。

使える?

設定中は不安定すぎることもあり、IFTTTなどを試していると不安定になったのが今日。というわけでいつ不安定になるのかは未知数。設定してしまえば安定すると思うのだけど。ONU側が止まっていたのは想定外だったり。
ローミングができているようなので2台目は買わないかもしれないが、全く使えないほど酷いのはセキュリティなど使っている時ぐらいか、という感触は得たのでまずまずか。

2020年3月20日金曜日

暗号アルゴリズムのなかのハッシュを実装してみる MD5からSHA-3まで

デジタルな暗号の実装はいろいろあるのだけど、中身はあまり把握していないなということで、暗号やハッシュの実装を見てみようと思いいくつか実装してみた。
 暗号の中でも使われていることもあり、実装が簡単そうなのがハッシュ関数というわけなのか、最初に目についたからかハッシュのMD4、MD5からSHA-1、SHA-2、SHA-3を実装してみた。GitHubに公開してみたが、結局他の実装はあまり見なかったかもしれない。
入門程度に詳細は省略するのでソースかWikipediaでも見てもらえればハッシュの単純さがわかる。
ハッシュとは、データの固まりに固有の番号(乱数っぽいもの)を生成するアルゴリズムで、ダウンロードしたデータが正確かどうか判定するために使ってみたりする。
昔はチェックサムだとか、CRCだとかがあったところの延長線上でもあり。 結果が分散している、結果からデータを逆に辿れないというのもポイント。
構造は、入力データを512ビットや1024ビット毎に区切り、ビット演算を繰り返した結果256ビットくらいの結果が出力される。
1ビットの違いが出力のほぼ全ビットに影響するので同じ値を探すのも難しい。
入門レベルで書かれているものでは、1回の暗号の構造については書かれているが、初期値がどうなるとか繰り返しがどこからどこまでででどうなるのかなど、よくわからないことも多々ある。


実装するには、基本的にインターネット関連の情報はRFCを読めば見つかる。MD4、MD5などの廃止された古いものもしっかり残っているのはRFCのよいところ。SHA-3はまだRFCにはなさそうだ。日本語化されたものもIPAなどのサイトで見つかるかもしれない。

  • RFC 1319 MD2
  • RFC 1320 MD4
  • RFC 1321 MD5
  • RFC 3174,FIPS 180-1 SHA-1
  • RFC 6234,FIPS PUB 180-4 SHA-2, HMAC,HKDF
  • FIPS PUB 202 SHA-3

ハッシュの基本

SHA-2までとSHA-3では違うので別々に。
内部状態を持っている MD5の場合 32bit a,b,c,d で128bit、SHA2-256はa,b,c,d,e,f,g,hで256bit、SHA2-512では64bitの8つで1024bitなど。初期値は0ではない(MD5以降)。
暗号ではほぼ固定だけれど、これの初期値が変えられるものもあり、initial vector といってIVなどと略してよく見られるので覚えておくといい。暗号で使われる鍵とは別のもの。
入力はブロック単位(512bitや1024bit、SHA-3では異なる)。

  • 入力 ブロック
  • 内部状態 vector
  • 出力 vector から切り取ったハッシュ値

ブロック(512bit), vector (256bit) → ハッシュ計算(4x4回くらい) → vector の繰り返し。

SHA-3の場合はvectorがブロックより長い。 vectorの先頭にブロックをXORで足していくだけ。
 vectorは5x5x64の3次元配列っぽくなっていて、いろいろシャッフルする。逆計算は無理っぽい。

最後のブロック


ブロックの単位は512bitや1024bitなので、足りない部分は最後のブロックにpaddingといって空白を埋める。そのあとに長さのデータなどを足してちょうど512の倍数ビットになるようにして最後のブロックをハッシュ計算することになる。元のデータが512ビットの倍数丁度の場合にも終了フラグや長さなどのデータが必要なのでパディングが入る。


計算

基本はvector を複製してブロックを混ぜ込み、結果をvecrtorと足してvectorに戻す。

SHA-1, SHA-2 ではブロックはシフトなどしたデータで数倍にふくらませてから。
疑似乱数っぽい列を持っているか生成して使う(MD2,MD5,SHA-2,SHA-3)。MD4、SHA-1は固定。
ブロックを入力し、内部状態を変化させ、最終的な内部状態を切り出してハッシュ値とする。ブロック長より短い。

疑似SHA2 (256bit)

内部状態(vector) H[32x8(256)bit]

hash(block[8x64(512)bit])
{
 a,b,c,d,e,f,g,h = H[0,1,2,3,4,5,6,7]
 block をint列に写し、4倍くらいにする
 表に書けそうな計算 x 64回 ( abcdefghにblockと疑似乱数的なものを加える)
 H[0,1,2,3,4,5,6,7] += a,b,c,d,e,f,g,h
}

H[0...] += a...
があるのでHからaが取り出せなくなり戻れない。

データ並びのバイト列やビット列を上から数えるか下から数えるかは各プロトコルでバラバラなので仕様から読み解くか実装してみて気づく罠あり。

ハッシュの裏

計算している部分はビットの反転、シフト演算などが主な計算方法で、ビット操作ではXORやNOTだけでなく、データ量の減りそうなANDやORも使われているのだが、処理後のデータは内部状態の1つしか変化させないので他のデータは残っていて容易に逆計算で復元可能。(SHA-2など)
計算結果を加算していく過程(H[0,...] = a,... )があるので基本的に戻れない? 戻れそうな気がしてくるので謎。逆に戻る過程のabcdの初期値が出せないので安全なのだろうけど、よくわからない。

何回

入力はブロック単位で処理するので、細切れな入力を蓄積してまとめるところから作るのがいいが、そのあたりの作りが各者の最適化のしどころか。JavaならStreamを貯めてBlockの長さ以上ならループへ、くらいの形にすればいいのでStreamをBlockに変換する処理としてまとめてみたりもする。

abcdに同じことしてみる


変数の列を入れ換えているようなところは、入れ換えているのではなく列の先頭から順番に同じ処理をしているだけのものを処理しやすく組み立てているだけのものもあり、これがMD5、SHA-1などでは何回繰り返すというふうに誤魔化されている。MD5では変数が4つあり、1処理16回まわすので、abcd各4回まわしているくらいの攪拌量になる。SHA-2では8回か。
変数ではなく入力をシフトする作りにしてみれば、a,b,c,... に対して同じことをしている様子がわかる。 最終的にどちらが速いのかは最適化次第だと思うのでMD5は変な実装にしてみた。


完成品

最終的に作ったハッシュはMD2,MD4,MD5,SHA-1,SHA-2,SHA-3各シリーズとKeccakそれとCRC。
単体で使うこともJavaに登録して使うこともできるっぽい形になった。古い形式はオプション変えないと使えなくなっているのでその代わりに使ってみるのもいい。
RIPEMDみたいなのも作ってみる予定。 GitHubへ。

ハッシュの次、暗号になると 

ハッシュの次はHMACなどがあるのでそういうのも見てみるといい。HMACや暗号では鍵の引き延ばしとかいろいろ別の要素が出てくる。
乱数の生成のようなものもあり、最終的なところで暗号かな。

次回は暗号のざっくり?

HMACと暗号の実装

ハッシュを作ったので次はHMACなど作ってみた。 HMACはハッシュを使ってパスワード認証的なものもつけているので改変されていないかなどで有利なのかどうなのか。JavaではMacという分類のあれこれ。 ハッシュごとのハッシュ長は取得できてもブロック長やら何やらを取得するのがJ...