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や暗号では鍵の引き延ばしとかいろいろ別の要素が出てくる。
乱数の生成のようなものもあり、最終的なところで暗号かな。

次回は暗号のざっくり?

2019年11月23日土曜日

RaspberryPi 4 Model B 日本発売

RaspberryPi 4 Model B 4GBモデルがKSYから発売された。
今回の製造はOkdo社、RSコンポーネント関連の企業らしい。
電源、ケースなどのセットモデルもあるが、2GB、1GBモデルは未定となっている。

その他の取り扱いがありそうなショップはスイッチサイエンス、ヨドバシカメラ、などがあるが、予約はまだはじまっていない。


告知ページ
https://raspberry-pi.ksyic.com/news/page/nwp.id/86

KEY Twitter
https://twitter.com/ksy_raspi_shop/

RSコンポーネント Twitter
https://twitter.com/RSJapanMK

スイッチサイエンス
https://www.switch-science.com/

セットなどで購入しておきたいものは、電源、4B対応ケース、microSD(XC)、microHDMIケーブルが主なところ。
microSD、キーボード、マウスなども必要。LANケーブルもあるといい。
電源は現在販売中の4Bは問題ありなのでUSB PD GaNで18W以上 + USB 2.0 Type-C ケーブルがおすすめなのか。GaNなUSB PDで変換効率はどれくらいなのかも気になる。
発熱の問題も深刻なようなのでヒートシンクもおすすめらしい。つけないけど。

3B以上対応のもので試してみたいのはWebThingsのMozillaのなど。
それ以外はいつもどおりのサーバ用途かもしれないが、メモリがあるのでデスクトップ用途でもつかえなくはないのかもしれない。
2台くらい買ってみる予定でUSB PDとUSBケーブル、microSDなどを注文してしまうが本体は買えなかった。

2019年11月17日日曜日

Google Homeの新機能 ステレヲ

どこのご家庭にでもあるGoogle Home miniを2台用意します。
AndoridのGoogle HomeアプリからGoogle Home miniの設定を開き、スピーカーペアという項目を探しましょう。
項目が出てこない場合にはプレビュープログラムをオンにしてから再度試してみましょう。
ペアとなるもう一方のスピーカーを選択すればステレヲ環境のできあがりです。あとは左右どちらにするかを決めてみましょう。

というわけで、Google Home かHome mini 2個でステレオスピーカーにできる機能が登場していました。
オーディオをキャストするときにペアを指定するとステレオ再生されるようになります。
これまでもグループというのはありましたが、左右分かれるわけではないようです。
ちょっとした音もステレヲはいいですね。
対応アプリはGoogle Play MusicやYouTube Music、Spotify、Xperiaのミュージックアプリ、VNCなどなどがあるかもしれません。
Google Cast対応ではない機器でSpotify対応を謳っているものは、大抵Spotify Premiumなのですね。BOSEのスピーカーやfitbitのスマートウォッチが対応していたのでなんだかなと。

ASUS X470 TUF GAMING Ryzen 5 2600X メモリ増設は難しかった

Amazonでメモリ試用する機会があったので久しぶりにPCを組んでみたのだけどメモリ増設は難しかったというお話。
まずはRyzen 5 2600X + ASUS X470 TUF GAMINGをベースにPC組みました。
メモリはHyperX というDDR4-3200なOCものLEDつきでKingstonのゲーミングブランドらしい。
試用なので8GB、2枚差しでは問題なし。次にKlevvとかいうこところのを増設してみたところまでは書いたかな。同じSK Hynixのチップが載っていたけどこれはなぜか不安定。CLも若干違ってた。

メモリの刺し方

スロットの形状にもよると思うがASUSの場合? は片側固定、片側にノッチがあるタイプ。
下側の溝にはめ、上側までぐっと差し込む。切欠きの上が長いのか下が長いのかの判別に迷う。
LEDタイプだと電源を入れてみて点灯していればだいたい刺さってる。が半差しになっていることもある。
DDR4メモリは2枚単位で増設するのが基本。マザーボードによって、どのスロットからメモリを刺すのかが決まっているので2枚のときは要注意。違う方に刺すとOCで安定しなくなることもある。

Ryzen 5 2600X に DDR4-3200 4枚差し

で、HyperXのLEDなしモデルがあったので増設してみた。これが最初のHyperXと同じDDR4-3200でCLも同じ。メーカー同じ、チップも同じなのでXMPのタイミングテーブルも同じ。LEDがないのとヒートシンクが若干小さいのでコンパクト。
というわけでさくっといけるかと思ったのだけどそうはいかなかった。
単純に増設してみると起動せず…。全く。
LED付きの方だけ外してみても、様子は変わらず。何回か再起動を繰り返して2400くらいで起動したのかな。3200では動かないようす。
で、スロットを増設の優先順位の高い方に変えてみたところ、3200MHzで動いてくれた。
2枚差しに成功したら次は4枚。
優先スロットにLEDつき、増設側にLEDなしをセット。起動せず。3000MHzや2400MHzだと起動するようだ。
優先スロットにLEDなし、増設側にLEDつきをセット。起動。何か1回フリーズして再起動してみたが、起動してしまえば安定しているような勢い。
軽くベンチマークでも問題なし。2~3日で1回くらい不安定になったので完全に安定というわけでもないがほぼ問題ない、というような感じに落ち着いているので様子見。

2019年11月6日水曜日

PostgreSQLでIPv6、リンクローカルアドレスにはまる

IPv6、使いたくないという声の方がよく聞きますが、いまさらなので使っていきましょう。
今回はリンクローカルアドレスを使おうとしてはまる。

とある停電でDHCPのIPv4アドレスが振り直されてしまったのでRaspberryPiのIPv6使っておくかというふうに考えてみました。
ということで、RaspberryPiのPostgreSQLにもIPv6使ってみてもいいんじゃない?

IPv6のアドレス

IPv6に限らずですが、使われているアドレスの使われ方は いくつかあります。ローカルかつブロードキャストなど除くと127.0.0.1/8と、192.168.0.0/16 や172.168.0.0/16、10.0.0.0/8、それ以外に知られていないかもしれない169.254.0.0/16、などなどローカルなものもいろいろと。
IPv6でローカル的なアドレスを使おうとすると、ループバックアドレス(::1)、リンクローカルアドレス(fe80::/?)とユニークローカルアドレス(fd00::/8)などなどがあり、IPv4のプライベートIPアドレスのようなものです。
リンクローカルアドレスはルータ越えができず、ユニークローカルアドレスはルータ越えも可能です。
日本でネットに繋いでいればグローバルなIPv6アドレスも振られていると思いますが、外からも見えるので違うアドレスを使おうという今回の計画。

リンクローカルアドレス

今回は同一ネットワーク上にある機器を繋ぐということではじめから振られているリンクローカルアドレスを使ってみようと思ったのですが、PostgreSQLで。
 変更箇所は、postgresql.conf の listen_addressesと pg_hba.conf にIPv6アドレスの接続許可を加えることです。
まずはIPアドレスを確認します。
# ifconfig
でざっくりアドレスなどが出てくるのでinet6でlinkなアドレスを調べます。fe80::ではじまっているはずです。
IPv4の192.0.2.77, IPv6の2001:db8:: は例示用アドレスなので気にしない。
wlan0: flags=xxxxxxx
          inet: 192.0.2.77
          inet6: fe80::7777:7777:7777:7777  prefixlen: 64  scopeid 0x20<link>
          inet6: 2001:db8:123:4567:89ab:cdef:123:7777 prefixlen 64  scopeid 0x0<global>


lo: とそれ以外があるのでそれ以外の方で fe80::はじまりの <link> のついたものをpostgresql.confのlisten_addressesに追加。

losten_address = '127.0.0.1,192.0.2.77,::1,fe80::7777:7777:7777:7777'

などとしてみます。77は例です。RaspberryPiな環境でPostgreSQLを再起動します。
# systemctl  restart postgresql
待ち受け状態を確認します。
# netstat -ant
tcp6 0 0 ::1:5432  :::* LISTEN

postgresqlのポートは5432ですが、IPv6では::1:5432しか見つかりません。::1なアドレスやグローバルなアドレスはこれで使えているのですが。

解決


リンクローカルアドレスを記述する場合、インターフェースが特定できないと困るので指定しないといけない場合があるようです。Linuxの場合、アドレスの後ろに%wlan0 などとつけます。ZoneIDとかいいます。インターフェースの名前は ifconfigコマンドの頭に出てくるものです。
losten_address = '127.0.0.1,192.168.0.77,::1,fe80::7777:7777:7777:7777%wlan0'

他の場合には%をエスケープする必要があるかもしれません。
これでもう一度再起動したところ接続可能になりました。

参考

URIの場合

古いURL(RFC 1738)ではZoneIDをサポートしていません。URIでも使えませんでしたが、RFC 6874でURIのZoneID拡張が入っています。
  • RFC 6874 ZoneIDをURIで
  • RFC 3986 URI
  • RFC 1738 URL

2019年10月23日水曜日

SQL標準はどこから

SQLはPostgreSQLばかり使っていて標準は少ししか意識していなかったり。
標準化もされていて、SQL99などという名前は聞いたことがあるかもしれないが、今は2003とか2011とかもっと新しいものまである。標準SQLというらしい。
最新版から見ればいいのか、ある程度古いところから差分を追いかけるのがいいのか。
Javaなどのオブジェクト指向に対応したというSQL99あたりから見てみることにしたい。

PostgreSQL 7.3のドキュメントによるとSQLはISO/IEC 9075 Database Language SQLというところが標準らしい。
SQL-92くらいでは実装は最小から大きいところまで分かれていたが大きすぎたので、SQL99ではコアとその他に分けてみたとか。
  • 標準SQL ISO/IEC 9075 Database Language SQL
    • SQL-92
    • SQL99 Javaなどオブジェクト化対応
    • SQL:2003
    • SQL:2011
    • SQL:2016
あまり関係ないがJDBCにオブジェクトを突っ込めそうなライブラリを作ってみた。
JSONでマッピング系を作っていたので流用した結果 Object → JSON → Map → JDBC(SQL) という変換をかけている。未実装だらけなので(仮)。要望等(謎)ないだろうから完成形にするつもりはあまりない。
 GitHub SoftLibD3BIF
動作確認はPostgreSQL 11のみ。
table定義を書かずに主キーなどはアノテーションをクラスに埋めるだけでも可。
そのうちJSONなど中間外して効率化するかもしれない。
EJBとかどうなったんだろか。

2019年10月9日水曜日

ASUS TUF X470 PLUS GAMING + Ryzen 5 2600X にメモリ増設

Ryzen 5 2600Xも快適ながら、早速DDR4メモリ、M.2 NVMeを入手したので増設してみることにしてみたのだけどちょっとエラーも多かったという話。
  • KLeVV CRAS C700 M.2 PCIe 3.0x4 NVMe1.3 480GB
  • KLeVV DDR4-3200 CL16-18-18-38-54 1.350 Vくらい
環境
  • AMD Ryzen 5 2600X
  • ASUS TUF X470-PLUS GAMING
  • キングストン HyperX DDR4-3200 CL16-18-18-36-74 1.350 Vくらい
  • とらんせんど M.2 PCIe 3.0x4 NVMe 1TB
  • GeForce RTX 2070 OC品

KLeVVというメーカーはメモリメーカーのSK Hynixの子会社っぽいところらしいのでほぼSK Hynix純正といえるようなところらしい。
Ryzen 5 2600X といえばメモリはオーバークロックメモリが標準的とも言えるような状態なので、最初からDDR4-3200なオーバークロックメモリを使っていた。というよりDDR4-3200(8GBx2)なメモリを入手したので新PCを組んだ。
今回さらにDDR4-3200(8GBx2)とM.2 Gen.3 x4 480GBを足して試してみることにした。

初回撃退


試用的なメモリなので8GBx2構成。どうせなら8GBx4にして使いたいのでそういうふうに使おうと単純に足してみたところ、起動はするものの、謎のエラーだらけで挫折。
増設して最初はそのまま何の問題もなく起動。
UEFIの設定を開くと設定が一部だけ大きな方向へ変わった。保存して再起動するとしばらくは起動するが不安定に。
2つのメモリ、CPU IDではtRAS、tRCが違うので CL16-18-18-38-54くらいになっているらしい。たぶん。

メモリスロットにうまく刺さっていなかったのか。それでもLEDが点灯するので動いていたとは思うとややコワイ。DDR4-3200 8GB x2構成に戻してしばらく使ってみたが安定した。
M.2を2つめの端子に入れようと思ったがネジとネジの台座がないので挫折。M.2に新しくOSを入れて怖くない環境でテストしてみてからにしよう。
というわけで。

準備。

microSDXCにWindowsイメージを焼き。 メモリを全部抜き、KLEVVのメモリだけを投入。M.2をKLEVVに交換。そのままWindows 10 Proをインストール。
シリアル番号は必須になっていた。が、省略も可能でマザーボードなどの環境情報から引き継がれたようだ。
インストール前に2、3の質問、インストール中にさらに2、3の質問あり。ネットワーク系は前の方にまとめるのは無理なのか。
起動してみると安定している様子。GPUなど各種ドライバなども中途半端に入れてみるが問題ないことを確認。
この段階での予想はメモリ混載がコワイのか? という感じ。

挑戦

KLEVVのメモリ単体では問題なかったのでこれまで使っていたキングストン HyperXと混載してみることに。今度は落ちた状態とは逆の順番で差し。起動してみるもHyperX刺さっていなくて光らず…コワイ。刺し直した。
UEFIの方は後から刺したスロットの方(若い番号の方)のXMP情報に合わせられた。遅い方に合わせるわけではなかったらしい。CL16-18-18-36-74 ということでいいのか?
結果安定しているように見える。何が悪かったのか。
M.2をトランセンドに戻して起動。落ちる様子がないので安定しているらしい。
半日ぐらいしたらエラー吐いた…。

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

デジタルな暗号の実装はいろいろあるのだけど、中身はあまり把握していないなということで、暗号やハッシュの実装を見てみようと思いいくつか実装してみた。  暗号の中でも使われていることもあり、実装が簡単そうなのがハッシュ関数というわけなのか、最初に目についたからかハッシュのMD4、M...