おはこんハロジャロ~~~~~~~~~!!!!!
こんなサムいこと言ってる奴のブログをわざわざ覗いてまで情報を得なければいけない現状を,各位はもっと憂うべきである.
SSS4や5gensearch・プラスルツールでは満足できなくなった人向けの情報だ.普通の人はこれらのツールで大体の乱数調整には事欠かないであろう.
さびたコイルさんの資料を読めばだいたいわかるが,それだけではわからないことを書いていこうと思う。
エンディアン変換とは
簡単に言えば,0xPpQqRrSs→0xSsRrQqPpと並び替える変換.必要なところとそうでないところがある.計算をはやくするにはエンディアン変換が要らないところは省略したほうがいいと思うけど,変換するしないでいちいち分けるのが面倒.
SHA-1にぶち込む際,通常はひとつの文字列?数値?を32bitずつ細切れにするが,初期seed生成の場合はすでに細切れにした状態にして代入する.具体的には32bitの数値を16個用意してあげる必要がある.
さらに,いわゆる一般的なSHA-1では細切れにした32bitの数値をエンディアン変換してからSHA-1変換しているが,第5世代の初期seedはエンディアン変換をするしないが細かく分けられているので,そこに注意しないと正しく実装できない.特にSHA-1を自力で用意しなくても良い言語でプログラムを書こうとしている人は注意.
私のコードの実装ではarray<uint32_t, 16>& data>を入力値として実装している.以下,入力する32bitの数値をdata.at(0)-data.at(15)として話を進めていく.
data.at(0)-data.at(4) (1-5番目の値)
nazo値.ぼんじりさんがまとめているのを参照すればよい.エンディアン変換が必要.
初めからエンディアン変換したものをnazo値として実装したほうが速い気がするんですが
data.at(5) (6番目の値)
VCountとTimer0をくっつけて,エンディアン変換したもの.
たとえばVCountが0x0060,Timer0が0x0c7aならdata.at(5)は0x00600c7aをエンディアン変換し,0x7a0c6000となる.
data.at(6) (7番目の値)
MACアドレスの下位16bit.エンディアン変換は不要.
例えばMACアドレスが00-09-BF-6D-93-CEならdata.at(6)は0x000093ceとなる.
data.at(7) (8番目の値)
まずGxFrameとFrameの値をxorし,それをエンディアン変換する.
例えばGxFrameが0x06000000でFrameが0x8なら,0x08000006を用意する.xorというよりもはや足し算だろ
これをMACアドレスの真ん中(上位?)8桁とxorした値がdata.at(7)となる.
例えばMACアドレスが上と同じ00-09-BF-6D-93-CEならdata.at(7) = 0x0009bf6d ^ 0x08000006 で0x0809bf6bとなる.
data.at(8) (9番目の値)
日付・曜日を格納する.年は下位2桁,曜日は日曜を0,土曜を6として7個の値を入れる.エンディアン変換は不要.
この際,10進数表記をそのまま16進数として入れるので注意.
例えば2001年9月11日火曜日ならば,data.at(8) = 0x01091102となる.
プログラムの実装が下手だと日にちの11日を0xbと認識して01090b02としてしまうので注意.
data.at(9) (10番目の値)
時間の10進数表記を格納する.0xhhmmss00といった感じ.エンディアン変換は不要.
注意点としては日付と同様に10進数表記をそのまま16進数として入れるのと,時間が午後だった場合は40を足した値を入れること.
例えば12時34分56秒としたい場合は,data.at(9) = 0x52345600となる.
実装が下手だと12を0x12にせず0xcと認識したり,40を足す際に0x28を足してしまったり,0x40を足そうとして0x4cを入力してしまったりとぐちゃぐちゃになりやすいと予想される.
data.at(10)-(11) (11-12番目の値)
0x00000000.要するに0.エンディアン変換はお好きなように.
data.at(12) (13番目の値)
キー入力をbitで受け取ったもの.エンディアン変換が必要.
デフォルトは0x00002fffをエンディアン変換した0xff2f0000となる.
この上位20bitは0x00002で固定だが,下位12bitの0xfff,すなわち0b1111-1111-1111に各ボタンが対応している.
左から Y X L R 下 上 左 右 Start Select B Aという順番に対応している.
例えばBボタンだけを入力した際は,0b0010-1111-1111-1101,すなわち0x00002ffdとなり,これをエンディアン変換した0xfd2f0000がdata.at(12)として代入される.
実装する際はほぼ全探索が前提となるだろうが,入力不可能なボタン入力(上下・左右同時押し)やソフトリセット(上+B+Se)を含むものや,人類には不可能なボタンの組み合わせを除外できるといいだろう.
ちなみにTTS氏のpythonのツールでは値とボタンの組み合わせを全部列挙してkeypresses.pyとして用意していた.しかもエンディアン変換も事前に済ませた状態で.脳筋すぎだろ.
data.at(13)-data.at(15) (14-16番目の値)
実質固定値.エンディアン変換は不要.
data.at(13) = 0x80000000(2進数で0b1000000000……)
data.at(14) = 0x00000000(要するに0)
data.at(15) = 0x000001A0(10進数で416,つまり13*32)
詳しい話をすると,SHA-1は32bitの数値を16個,計512bitを一単位として変換をする.しかしながら当然入力される値の長さが512bit単位で入力されるとは限らない.そのような時に空いたところを埋めて512bitにする処理を行っている.これがパディング処理だ.
当然全て0で埋めておくのが一番簡単だが,それだと暗号化している感じがしないので,一応それっぽい処理をする.
と言っても,一番アタマのケタのbitを1にし,あとは途中まで全部0で埋めて,最後の32bit2つは,SHA-1に入れられたbit数を入れる,という処理をしている.
最後の0x01A0の意味はdata.at(0)からdata.at(12)までの416bitの情報のbit数を表しているということになる.
実は既に出回っているライブラリのSHA-1を用いる場合は,このパディング処理を勝手に行ってくれるので不要だ.だが,どうせSHA-1にぶち込むデータのbit数は同じなので,固定値とみなしても問題ない.なんなら固定値として入れたほうが計算は速くなるだろう.
参考
さびたコイルさん BW乱数調整解説 乱数の仕組み
TTS4life bw2-seed-filter
さきさんのボタン入力の解析