English · 日本語
Day066 - 生成AIで作るセキュリティツール100
GrayNinjaは、グレイコード(反射2進符号)を、比較表・作り方・エンコーダー・ディスク・変換の計算過程・セキュリティの観点・座学の6つの画面で学ぶツールです。
グレイコードは、隣り合う値どうしで必ず1ビットだけが変わるように並べた2進の符号です。2枚のディスク(グレイと2進)を同じ角度で回して、セクターの境目を越える瞬間にいくつのリングが同時に変わるかを見比べられます。読み取りヘッドのセンサーをずらす誤読シミュレーターでは、2進がどれだけ遠い値を読み違えるかを数値で確かめられます。
👉 https://ipusiron.github.io/GrayNinja/
ブラウザーで直接お試しいただけます。
- 基本・しくみ・ディスク・変換・セキュリティ・座学の6つのタブで、グレイコードの性質と使われ方を順に学べます。
- しくみのタブでは、反射で列を作る過程を1段ずつ進め、反転するビットの位置(ルーラー列)とハノイの塔の手順、チャイニーズリングの手数の対応を確かめられます。
- 比較表は1〜12ビットに対応し、前の値から変わったビットを2進とグレイの両方で色分けします。
- 2枚のエンコーダー・ディスクを同じ角度で回し、読み取り線の下のセクターをグレイと2進で読み比べます。
- 誤読シミュレーターでリングごとのセンサーをずらし、一周したときに隣より遠い値を読む割合と最大のずれを、グレイと2進で比べられます。
- 変換は1,024桁まで受け付け、64桁までは1桁ずつの計算過程を表示します。
- セキュリティのタブでは、電力解析の3つの漏えいモデルでカウンターを比べ、スイッチの総当たりの切り替え回数とDe Bruijn列で送るビット数を計算します。
- 座学のタブは、特許・論文・規格・メーカーの資料に当たった内容で、各カードに出典のリンクがあります。
- 日本語・英語の切り替え、ライト・ダークのテーマ切り替えに対応します(選択は自動で保存されます)。
- ビット数n(1〜12)を決めます。
- 「次へ」「前へ」かスライダーで値を動かします。キーボードの← →でも動き、Spaceで自動再生を始めたり止めたりできます。
- 比較表で、前の値から変わったビットの数(Δ2進・Δグレイ)と、変わった位置の色を確かめます。
キーボードの操作は、基本のタブを表示していて、ボタンや入力欄にフォーカスがないときだけ働きます。
- 「反射して作る」で、作るビット数(2〜5)を決め、「次の段」で「鏡に映す」と「先頭に0と1を付ける」を1段ずつ進めます。できた列は、計算式(g = b ⊕ (b ≫ 1))と一致するかを検算して表示します。
- 「反転するビットとハノイの塔」で、円盤の枚数(2〜6)を決め、「次の手」で1手ずつ進めます。動かした円盤の番号と、グレイコードで反転したビットの位置が、ルーラー列の同じ場所に並びます。下に同じ枚数のチャイニーズリングの手数も出ます。
- 「ディスクの位置」のスライダーをゆっくり動かすか、「次のセクター」を押します。
- 読み取り線(赤い線)の下にあるセクターの符号と、それが表す値を、グレイと2進で見比べます。
- 「回転」を押すと、ディスクが一定の速さで回り続けます。速さは5〜360°/秒(360°/秒で1秒に1回転)で変えられます。速く回したときに、リングの模様がどう見えるかも試せます。
- 「リングごとのセンサーをずらす」をオンにすると、各リングを赤い点の位置で読みます。ずらし方(交互・外側から内側へ少しずつ・ランダム)と大きさ(セクター幅の0〜150%)を変え、一周の集計表とグラフで読み違いを比べます。
外側のリングが最上位ビット、内側が最下位ビットです。ディスクの色は、明るい色が0、濃い色が1です(テーマによらず同じ)。
- 2進かグレイコードのビット列を入れて「変換」を押します(Enterでも変換できます)。
- 結果、表す値(10進)、1桁ずつの計算過程を確かめます。
空白と「_」は区切りとして無視し、先頭の0bと全角の0・1も受け付けます。それ以外の文字があると、何文字目の何という文字かをエラーで知らせ、前の結果は残しません。
- 「電力解析のモデルでカウンターを比べる」で、ビット数(2〜10)と漏えいのモデル(反転したビットの数・値の1の個数・反転したビットの位置)を選び、1回の観測から残るiの候補の数を2進とグレイで比べます。
- 「スイッチの総当たりの順番」で、スイッチの数(1〜16)と順番(2進・グレイ)を選び、「次へ」で1通りずつ進めて、切り替えたスイッチと累計の回数を確かめます。下にDe Bruijn列で送るビット数も出ます。
歴史、使われている場面、セキュリティとの接点、よくある誤解を、出典つきのカードで読みます。
1ビットの列0, 1を逆順にして後ろに付け、前半の先頭に0、後半の先頭に1を付けると、2ビットの列00, 01, 11, 10ができます。これをくり返すとnビットの列になります。後半が前半の鏡写しになるので「反射2進符号」と呼びます。
n=1: 0, 1
n=2: 00, 01, 11, 10
n=3: 000, 001, 011, 010, 110, 111, 101, 100
ビットの添字は最下位を0、最上位をn−1とします。
- 2進→グレイ:
g = b ⊕ (b ≫ 1)。ビットごとに書くとgₙ₋₁ = bₙ₋₁、gᵢ = bᵢ₊₁ ⊕ bᵢです。 - グレイ→2進:
bₙ₋₁ = gₙ₋₁、bᵢ = bᵢ₊₁ ⊕ gᵢ。上の桁から順に、直前に求めた2進のビットとグレイのビットのXORを取ります。
例として、2進1010はグレイ1111に、グレイ1111は2進1010になります。
2進→グレイ(1010) グレイ→2進(1111)
g₃ = b₃ = 1 b₃ = g₃ = 1
g₂ = b₃ ⊕ b₂ = 1 ⊕ 0 = 1 b₂ = b₃ ⊕ g₂ = 1 ⊕ 1 = 0
g₁ = b₂ ⊕ b₁ = 0 ⊕ 1 = 1 b₁ = b₂ ⊕ g₁ = 0 ⊕ 1 = 1
g₀ = b₁ ⊕ b₀ = 1 ⊕ 0 = 1 b₀ = b₁ ⊕ g₀ = 1 ⊕ 1 = 0
Δは前の値から変わったビットの数です。0の行の「前の値」は15(巡回)です。
| 10進 | 2進 | グレイ | Δ2進 | Δグレイ |
|---|---|---|---|---|
| 0 | 0000 | 0000 | 4 | 1 |
| 1 | 0001 | 0001 | 1 | 1 |
| 2 | 0010 | 0011 | 2 | 1 |
| 3 | 0011 | 0010 | 1 | 1 |
| 4 | 0100 | 0110 | 3 | 1 |
| 5 | 0101 | 0111 | 1 | 1 |
| 6 | 0110 | 0101 | 2 | 1 |
| 7 | 0111 | 0100 | 1 | 1 |
| 8 | 1000 | 1100 | 4 | 1 |
| 9 | 1001 | 1101 | 1 | 1 |
| 10 | 1010 | 1111 | 2 | 1 |
| 11 | 1011 | 1110 | 1 | 1 |
| 12 | 1100 | 1010 | 3 | 1 |
| 13 | 1101 | 1011 | 1 | 1 |
| 14 | 1110 | 1001 | 2 | 1 |
| 15 | 1111 | 1000 | 1 | 1 |
全16通りを0から15まで順に巡ると、変わるビットの合計は2進で26、グレイで15です。一般にnビットでは、2進が2^(n+1)−n−2、グレイが2^n−1になります。
4ビットのディスクで、外側のリングから順にセンサーを交互にセクター幅の10%(±2.3°)ずらし、一周を4,096か所の角度で読むと次のようになります。
| ディスク | 正しい値 | 隣の値 | 隣より遠い値 | 最大のずれ |
|---|---|---|---|---|
| グレイ | 89.84% | 10.16% | 0.00% | なし |
| 2進 | 84.77% | 7.62% | 7.62% | 6セクター |
2進は7と8の境目の手前で13を読みます(1101)。グレイは境目の近くで隣の値を少し早く読むだけです。グレイが隣の値までで済むのは、どのセンサーのずれも半セクター未満のときで、60%ずらすとグレイでも7.62%の角度で2つ離れた値を読みます。
機械式のエンコーダーは接点で位置を読むので、接点が切り替わるときに跳ねて、オンとオフを数ミリ秒くり返します(チャタリング)。グレイコードは、この跳ねそのものは防ぎません。抑えられるのは、跳ねている間の読み違いの大きさです。
- 絶対型:境目で変わるのが1ビットなので、跳ねている間の読み値は、境目の両側の2つの値を行き来するだけです。2進では、7と8の境目で4ビットが同時に跳ねるので、0000〜1111の16通りのどの値も読むおそれがあります。
- インクリメンタル型:A相・B相は00, 01, 11, 10と変わる2ビットのグレイコードで(基本のタブでn=2にした比較表と同じ並び)、2つの相が同時には変わりません。両方の相の切り替わりで数えるカウンターは、片方の相だけが跳ねると+1と−1を交互に数え、切り替わりを読み落とさなければ、跳ねが収まったときに正しい数に戻ります。
どちらの場合も、値がちらつく間の扱いは、時間待ちや複数回の一致判定などのデバウンスで別に決めます。チャタリングの原因と、回路・ソフトウェア・部品選び・修理での防ぎ方は、関連記事「チャタリング対策を整理する」にまとめています。
8ビットのカウンターを1つ進めたときの1回の観測から、iの候補が平均で何通り残るかを、3つの漏えいモデルで比べると次のようになります(iは0〜255から一様に選ぶ)。
| 漏えいのモデル | 2進 | グレイ |
|---|---|---|
| 反転したビットの数(ハミング距離) | 85.34通り | 256.00通り |
| 値の1の個数(ハミング重み) | 50.27通り | 50.27通り |
| 反転したビットの位置 | 85.34通り | 85.34通り |
ハミング距離のモデルでは、グレイのカウンターから何も絞り込めません。しかし、ビットごとに漏れ方が違ってどのビットが反転したかがわかると、グレイは2進のハミング距離と同じだけ漏れます。グレイコードはサイドチャネル攻撃の対策ではありません。
- 誤りの検出・訂正はできません。nビットの2^n通りをすべて使うので、1ビットが反転すると別の正しい符号語になります。
- 「1ビットの誤りなら隣の値にしかならない」は成り立ちません。正しい性質は「隣の値への読み違いが1ビットで済む」で、
0000の最上位ビットが反転した1000は値15を表します。 - サイドチャネル攻撃の対策にはなりません。詳しくは座学のタブの「電力解析とハミング距離」と「よくある誤解」を参照してください。
- チャタリング(接点の跳ね)は防げません。跳ねている間の読み違いを、境目の両側の値までに抑えるだけです。
このツールならではの使い方
-
隣り合う符号が必ず1ビットだけ違うことを確かめる(符号・エンコーダーの授業):4ビットのグレイコードでは、隣り合う16通りの符号のハミング距離がすべて1になる。一方ふつうの2進では、7から8へ変わるときに0111から1000へと4ビットが一度に変わる。ロータリーエンコーダーが境目で読み取りを誤らないのは、グレイコードの隣が1ビット違いという性質のためだと確かめられる
-
総当たりの切り替え回数がグレイ順で最小になることを確かめる(計測・電力解析の授業):12個のスイッチの全4,096通りをグレイ順に試すと、1ステップで1個だけ変わるので切り替えは4,095回で済む。2進の数の順に試すと8,178回になる。切り替えの回数を最小にしたいとき(機械の摩耗や電力解析のモデル)にグレイ順が選ばれる理由を、回数で確かめられる
-
各ステップで反転するビットの位置がルーラー数列になることを確かめる(組合せ・パズルの授業):グレイコードを順にたどると、各ステップで変わるビットの位置は0, 1, 0, 2, 0, 1, 0, 3…という決まった並び(ルーラー数列)になる。これはハノイの塔で動かす円盤や、チャイニーズリングで外す輪の順番と同じ数列である。別々に見えるパズルが同じ構造を持つことを、反転の位置で確かめられる
-
情報系・電気電子系の授業や研修で、グレイコードとハミング距離を、表とディスクの動きで説明する。
-
電子工作でロータリーエンコーダーを使う前に、境目でグレイと2進の読み取り方がどう違うかを確かめる。接点が跳ねている間に読みうる値の数(変わるビットがdなら2のd乗通り)も、基本のタブのハミング距離から見積もれる。
-
FPGAの非同期FIFOや、カルノー図の並び(00, 01, 11, 10)を学ぶときの補助にする。
-
デジタル変調のグレイ配置(QAM・PSK)を学ぶ前に、隣が1ビット違いという性質を手で確かめる。
-
チャイニーズリングやハノイの塔のようなパズルと、反転するビットの位置(0, 1, 0, 2, 0, 1, 0, 3, …)の関係を、比較表で追う。
-
セキュリティの講義で、電力解析のハミング距離モデルや、スイッチの総当たりの順番(グレイ順なら12個で切り替え4,095回、2進順なら8,178回)を説明する入口にする。無線の固定コードなら、12ビットを1つずつ送ると49,152ビット、De Bruijn列なら4,107ビットで全通りを試せることも計算できる。
-
プログラミングの練習で、ビット演算やXORの結果を、計算過程と突き合わせて確かめる。
- 変換はビット列を文字列のまま行います。数値(32ビットの整数)に直さないので、32桁で最上位が1の入力でも符号が反転したり、処理が終わらなくなったりしません。10進の値はBigIntで計算します。
- ディスクの角度は1つだけで、読み取り線は真上に固定し、ディスクのほうを回します。読み取り値は、読み取り線の下にあるセクターの符号です。
- ディスクは、同じビットが続く区間を1つの弧にまとめて描いた絵をキャッシュし、回すたびにその絵を回転して描き直します。回転は経過時間に速さを掛けて進めるので、描画の重さで速さが変わりません。
- 比較表はビット数を変えたときだけ作り直し、値を変えたときは選んだ行の印を付け替えるだけにしています。
- 開いたときは、初期化(文言の差し込み)が終わるまで本文を描きません。文字の入っていない枠が先に出てから文字が入る切り替わりを避けるためで、スクリプトが途中で止まっても2秒後には表示します。初期化中は要素の位置を読まず(レイアウトを強制しない)、変換のタブの結果はそのタブを開いたときに作ります。
- 誤読シミュレーターは、リングkのセンサーが「ディスクの位置+ずれk」の角度のセクターを読むとして、一周を4,096か所以上の角度で読みます。正しいセクターとの円周上の距離で、正しい値・隣の値・隣より遠い値に分けます。
- 計算部(変換・入力の正規化・計算過程・比較表・ディスクの読み取り)を
js/gray-core.jsに分け、node --testで検証しています。
- 外部との通信をせず、スクリプト・スタイルを同じ場所のファイルだけに限るCSPを設定しています(
script-src 'self'・style-src 'self'・connect-src 'none'・object-src 'none')。 - 画面の文字はDOMのAPI(
textContent・createElement)で組み立て、innerHTMLでHTMLを作りません。 - 入力は1,024桁までに制限し、0と1以外の文字はエラーにします。
- ブラウザーに保存するのは、言語とテーマの選択だけです。保存できない環境でも動きます。
- 比較表とディスクは12ビットまでです。12ビットのディスクは内側のリングのセクターが細かく、拡大しないと見分けにくくなります。
- 誤読シミュレーターが扱うのは、リングごとのセンサーの角度のずれだけです。センサーの応答の遅れ、ノイズ、ディスクの製造誤差は扱いません。
- 座学のタブの内容は出典の範囲で書いています。応用分野の詳細は、各カードの出典を参照してください。
計算部・HTML・CSS・文言・READMEをまとめて検証します。
npm testGitHub Actions(.github/workflows/test.yml)でも同じテストを実行します。
- Frank Gray, US Patent 2,632,058 "Pulse Code Communication"(1947年11月13日出願、1953年3月17日登録)
- D. E. Knuth, The Art of Computer Programming 7.2.1.1 "Generating all n-tuples"(Pre-Fascicle 2A)
- オムロンFAQ00941(ロータリーエンコーダーのグレイコード)
- E. Agrell et al., On the optimality of the binary reflected Gray code, IEEE Trans. Inf. Theory, 2004
- C. E. Cummings, Simulation and Synthesis Techniques for Asynchronous FIFO Design, SNUG 2002
- Analog Devices, MT-020 ADC Architectures I: The Flash Converter
- E. Brier, C. Clavier, F. Olivier, Correlation Power Analysis with a Leakage Model, CHES 2004
- STMicroelectronics, RM0008 Reference manual(15.3.12 Encoder interface mode。片方の入力の跳ねを打ち消す数え方)
- アルプスアルパインEC11E15244G1(機械式エンコーダーのチャタリングの仕様)
- そのほかの出典は、座学のタブの各カードにあります。
GrayNinja/
├── .github/
│ └── workflows/
│ └── test.yml # テストを実行するGitHub Actions
├── assets/
│ ├── en/
│ │ ├── screenshot-basics.png # 英語・基本のタブのスクリーンショット
│ │ ├── screenshot-dark.png # 英語・ダークモードの変換のタブのスクリーンショット
│ │ ├── screenshot-how.png # 英語・しくみのタブのスクリーンショット
│ │ ├── screenshot-learn.png # 英語・座学のタブのスクリーンショット
│ │ ├── screenshot-security.png # 英語・セキュリティのタブのスクリーンショット
│ │ └── screenshot.png # 英語・ディスクのタブのスクリーンショット
│ ├── favicon.svg # ファビコン
│ ├── screenshot-basics.png # 基本のタブのスクリーンショット
│ ├── screenshot-dark.png # ダークモードの変換のタブのスクリーンショット
│ ├── screenshot-how.png # しくみのタブのスクリーンショット
│ ├── screenshot-learn.png # 座学のタブのスクリーンショット
│ ├── screenshot-security.png # セキュリティのタブのスクリーンショット
│ └── screenshot.png # ディスクのタブのスクリーンショット
├── js/
│ ├── app.js # 画面の処理(タブ・比較表・しくみ・ディスク・変換・セキュリティ・座学)
│ ├── gray-core.js # 計算部(変換・入力の正規化・計算過程・ディスクの読み取り)
│ ├── i18n.js # 言語の選択と静的な文言の差し替え
│ ├── messages.js # 日本語・英語の文言の辞書
│ ├── theme-init.js # 描画前にテーマを当てる
│ └── theme.js # ライト・ダークの切り替え
├── test/
│ ├── core.test.js # 計算部の検査
│ ├── css.test.js # CSS(変数・コントラスト・大きさ)の検査
│ ├── html.test.js # HTML(CSP・aria・辞書との一致)の検査
│ ├── i18n.test.js # 言語の判定の検査
│ ├── load.js # テストにスクリプトを読み込む補助と参照実装
│ ├── messages.test.js # 文言(日英の一致・出典)の検査
│ └── readme.test.js # READMEの検査
├── .gitignore # Gitの除外設定
├── .nojekyll # GitHub PagesでJekyllを無効化
├── CLAUDE.md # Claude Code向けのプロジェクト設定
├── LICENSE # MITライセンス
├── README.en.md # 英語版README
├── README.md # このファイル
├── index.html # メインのHTML
├── package.json # テストの定義
└── style.css # スタイルシート
- モダンなブラウザー(Chrome・Edge・Firefox・Safari)で動きます。
- インストールやビルドは不要です。
index.htmlを開くか、静的サーバーで配信してください。 - テストの実行にはNode.js 18以上が必要です。
MIT License - 詳細はLICENSEを参照してください。
本ツールは、「生成AIで作るセキュリティツール100」プロジェクトの一環として開発されました。 このプロジェクトでは、AIの支援を活用しながら、セキュリティに関連するさまざまなツールを100日間にわたり制作・公開していく取り組みを行っています。
プロジェクトの詳細や他のツールについては、以下のページをご覧ください。





