Susumu Tomita

Advanced Cryptography Program 2026 / Week 0 自習ノート

有限体と楕円曲線

Week 0 は土台編です。扱うのは mod 演算・群環体・逆元・離散対数問題—— どれも「暗号の前に済ませておく数学」に見えて、実際には Week 1 以降でつまずく場所そのものです。

Week 1 の算術回路は F_p 上に組み、Week 2 の秘密分散も Beaver 三つ組も F_p 上で動き、 Week 3 は楕円曲線というもう一つの群の上に Schnorr を建てます。 前提はここに全部あります。単独で読めるように書いたので、 他の週で「これは何だったか」と思ったらここに戻ってきてください。

読了 35 分 対話ラボ 2 つ 検問クイズ 6 分野 Week 1〜3 の前提 外部通信なし

出発点

なぜ「普通の整数」では暗号にならないのか

有限体の定義から始めると、いちばん大事なことが抜け落ちます。 先に「整数のままだと何が壊れるのか」を見ます。

秘密の値 x を、素朴に整数のまま計算に使うとします。3 つのことが同時に困ります。

① 大きさが秘密を漏らす。 x + 100 という値を見せられたら、それが 3 桁なら x も 3 桁だと分かります。 暗号で欲しいのは「見ても何も分からない値」なのに、 整数には大小という手がかりが最初から付いています

② 割り算で分数が出る。 7 ÷ 2 は整数の世界から出てしまいます。かといって有理数まで広げると、 今度は分母がどこまでも育ちます。「その値」に固定できないのは、 あとで見る「回路の値」としては致命的です。

③ どこまでも大きくなる。 掛け算を繰り返せば桁は際限なく増えます。暗号は 256 ビットなら 256 ビットという固定長で扱いたいのに、整数は収まりません。

つまり欲しいのは、四則が全部できて、有限で、大小の手がかりがない世界。 この 3 つを同時に満たすものが有限体です。以降の全部はこの一言の展開です。

この 3 つが、そのまま設計になっている

整数だと困ること有限体での答え
大小が秘密を漏らす順序が存在しない(⑤)
割り算で外へ出る逆元の掛け算で中に閉じる(④)
桁が育つp で巻いて固定長(②)

右の列がこのノートの目次とほぼ一致します。 有限体の性質は「便利な数学」ではなく、暗号の要求から逆算された形だと思って読んでください。

先に言っておくこと

土台編で覚えるのは、最後に 3 つだけです。

「順序がない」「割り算は逆元の掛け算」「一方向だけ難しい」。 この 3 つが、Week 1 の回路制約・Week 2 のシェアの安全性・Week 3 の署名の安全性に、 それぞれ 1 対 1 で対応します。

この頁の地図

    道具

    mod 演算 — 時計の世界に数を閉じ込める

    「桁が育つ」を殺す道具が mod です。時計の比喩から入って、 最後は「正規化を忘れて課題に落ちる」という実務の話まで一気に降ります。

    1. 時計は 12 で巻いている

      10 時の 5 時間後は 15 時ですが、時計の文字盤では 3 時です。 12 を超えたら 12 を引く——これが mod 12 の世界です。 数直線ではなく円周の上で計算していることになります。

      なぜこれが暗号に効くのか: 何回足しても何回掛けても、 結果は必ず 0..11 の 12 個のどれかです。値が絶対に外へ出ない。 これが「固定長で扱える」の正体です。

    2. 合同 ≡ は「等しい」ではなく「巻いたら同じ」

      a ≡ b (mod p) は「a − b が p の倍数」という意味です。 15 ≡ 3 (mod 12) は、15 と 3 が等しいのではなく、 12 で巻いた世界では同じ場所に来るということ。

      15 ≡ 3 ≡ −9 ≡ 27 (mod 12)

      ここが分岐点です。 ≡ で結ばれた数は無限にあります。 その無限の仲間から代表を 1 つ選ぶのが次のステップで、 プログラムが落ちるのはたいていそこです。

    3. 代表元は 0..p−1 に取る(正規化)

      15, 3, −9, 27 はどれも mod 12 では同じものですが、 体の元として書くときは 0..11 の代表 3 に統一します。 この統一を正規化と呼びます。

      −3 mod 7 = 4  (−3 + 7 = 4。「余り」ではなく「巻いた先」で考える)
      30 mod 7 = 2  17 mod 7 = 3  0 mod 7 = 0

      なぜ 0..p−1 なのか: どれを選んでも数学的には同じですが、 比較・保存・テストのためには表現が 1 つに決まっていなければ困るから。 数学の都合ではなく、実装の都合で決めた約束です。

    4. 負の数の扱いが、いちばん事故る

      多くの言語の %符号を引きずります。 Python の -3 % 7 は 4 になりますが、 C / Java / JavaScript / Rust の -3 % 7-3 です。

      正しい正規化: ((n % p) + p) % p

      このノートの JS もこの 1 行で書いています。 「mod を取ったつもり」で負の値が残ると、値としては正しいのに 他の関数と噛み合わなくなります。次の実測がまさにそれです。

    実測 1 — Week 2 の秘密分散が落ちる

    正規化を忘れたシェアは、値が合っていても不合格になります。

    share(-3, [70, -2], 67) の正解は [3, 65, 63]。 mod を取らない実装はこう落ちます。

    AssertionError:
    Lists differ: [70, -2, -71] != [3, 65, 63]

    70 ≡ 3−2 ≡ 65−71 ≡ 63 (mod 67) なので、 数学的にはどちらも同じ秘密を表しています。それでも落ちる。 「同じ」であることと「同じ表現である」ことは別だからです。

    実測 2 — Week 3 の逆元が落ちる

    拡張ユークリッドの戻り値は、負のことがあります。

    schnorr-from-scratchfield_inv は、 extended_gcd(a % p, p) が返した x をそのまま返すと落ちます。 テストのメッセージがそのまま答えを言っています。

    AssertionError:
    逆元は 0..p-1 に正規化して返してください

    あとで見るように、5⁻¹ mod 13 を拡張ユークリッドで解くと 素直に出てくるのは −5 です。正しい逆元です。 ただし代表元としては 8 でなければならない。

    つまり

    Week 1・2・3 の課題で最初にぶつかる壁は、暗号ではなく ((n % p) + p) % p です。

    3 週にわたって同じ形で落ちるので、ここだけは手が覚えるまでやっておく価値があります。 このあとのラボとクイズは、全部この正規化の上で動いています。

    階層

    群・環・体 — 「何が使えるか」の階層

    群・環・体は、暗記する 3 つの定義ではありません。 「その世界で何ができるか」を強い順に並べた階層です。 できることが増えるほど、条件は厳しくなります。

    1. 群 — 演算 1 つ。行けて、戻れる

      集合 G と演算 ∗ がであるとは、次の 4 つが成り立つことです。

      ① 閉じている: a ∗ b は必ず G の中
      ② 結合則: (a ∗ b) ∗ c = a ∗ (b ∗ c)
      ③ 単位元 e がある: a ∗ e = e ∗ a = a
      ④ 逆元がある: 各 a に a ∗ a⁻¹ = e となる a⁻¹ が存在

      a ∗ b = b ∗ a(可換)は別条件で、 満たすものをアーベル群と呼びます。暗号で使う群はたいてい可換です。

      群の正体は「行って、戻れる」です。 単位元があるから「何もしない」が書けて、逆元があるから「元に戻す」が書ける。 暗号は「戻せない」を作りたいのに、道具の側は戻せる必要がある—— この緊張が離散対数(⑧)で効いてきます。

    2. 群の例は、思っているより広い

      集合演算単位元逆元
      整数 Z加法 +0−a
      F_p(p 個の元)加法 +0p − a
      F_p*(0 を除いた p−1 個)乗法 ×1a⁻¹
      楕円曲線の点 E点の加算 +無限遠点 Ox 軸反転 −P

      下の 2 行が今週の主役です。 F_p* の乗法群と、楕円曲線の点の群。 この 2 つはまったく違う見た目をしていて、群としては同じ形をしています。 だから ⑧ で見るように、離散対数問題も同じ言葉で書けます。

    3. 環 — 演算 2 つ。ただし割り算は保証されない

      は + と × の両方があり、分配則 a(b+c) = ab + ac が成り立つ世界です。 加法については群(0 があり、−a がある)ですが、 乗法の逆元は要求されません

      例: 整数 Z。2 × ? = 1 を満たす整数はありません。 例: Z/nZ(n で割った余り、n は素数でなくてよい)。

      環でできることは「+ と × と、その組み合わせ」だけです。 Week 1 の回路が「加算ゲートと乗算ゲートしかない」のは、 この定義に演算が 2 つしか無いことの直接の帰結です。 比較も分岐も、環の定義のどこにも書いてありません。

    4. 体 — 0 以外のすべてに逆元がある。割り算ができる

      は環であって、さらに 0 以外のすべての元に乗法逆元があるもの。 これでようやく四則が揃います。

      群 ⊂ 環 ⊂ 体  (できることが増えるほど、条件は厳しくなる)

      有理数・実数は無限個の元を持つ体。有限体は元の個数が有限な体で、 要素数を位数と呼びます。

      位数は必ず素数のべき pn です。 n = 1 なら F_p(このノートの主役)、 n ≥ 2 なら拡大体 F_{p^n}—— 既約多項式の根を追加して作る世界で、Week 0 のスライドの後半に出てきます。 この講座の課題で使うのはほぼ F_p の方なので、ここでは名前だけ置いておきます。

    階層の全体像

    構造使える演算逆元このプログラムでの出番
    群 (Group)1 つだけその演算について必ずあるZ の加法、F_p* の乗法、EC の点Week 3(EC と Schnorr)
    環 (Ring)+ と ×加法のみ保証整数 Z、Z/6Z「+ と × しかない」の根拠
    体 (Field)+ − × ÷0 以外すべてに乗法逆元有理数 Q、実数 R四則が揃う条件
    有限体 F_p+ − × ÷0 以外すべてp が素数のときの Z/pZWeek 1〜6 のほぼ全部

    Week 1 のノートで「なぜ + と × だけなのか」と書いた答えが、この表の 2 行目です。 環の定義に演算が 2 つしか無いので、回路にも 2 種類のゲートしか無い。

    核心

    なぜ法は素数でなければならないのか

    Z/6Z を見ます。0..5 の 6 個の世界です。ここで 2 × 3 を計算すると:

    2 × 3 = 6 ≡ 0 (mod 6)

    どちらも 0 でないのに、掛けたら 0 になりました。 こういう元を零因子と呼びます。整数の世界では絶対に起きないことです。

    零因子があると何が壊れるか。約分ができなくなります。

    2x ≡ 2y (mod 6) から x ≡ y は言えない
    (x = 1, y = 4 なら 2·1 = 2, 2·4 = 8 ≡ 2。x ≠ y なのに一致)

    そして逆元も存在しません。もし 2⁻¹ があったなら、 2 × 3 = 0 の両辺に掛けて 3 = 0 になってしまう。矛盾です。

    p が素数なら、零因子は消えます。 a·b ≡ 0 (mod p)p | a·b のこと。 p は素数なので p | ap | b のどちらかでなければならず、 つまり a ≡ 0b ≡ 0これが素数の効き目のすべてです。

    この一点のために素数を使う

    零因子が消える ⟺ 0 以外すべてに逆元がある ⟺ 体になる

    この 3 つは同じことの言い換えです。暗号が素数を選ぶ理由は、速いからでも安全そうだからでもなく、 体にならないと割り算ができないから

    すぐ下のラボで、法を 6 → 7 → 9 → 11 → 12 → 13 と切り替えてください。 合成数を選ぶと乗法表に赤いマス(積が 0)が現れ、素数を選ぶと消えます。 見えているのはこの証明そのものです。

    Week 1 での現れ方

    零因子が無いことは、回路の健全性の根拠になっています。

    (x−2)(x−5)(x−6) = 0 という制約は「x は 2 か 5 か 6」を意味します。 これが成立するのは、積が 0 なら因子のどれかが 0 だから。 零因子のある Z/6Z の上で同じ回路を書いたら、 許可リストに無い値でも制約を満たせてしまいます

    中核

    逆元 — 割り算の正体

    有限体に「割り算」という演算はありません。あるのは逆元の掛け算だけです。 求め方は 3 通りあり、計算量も使える条件も違います

    a の乗法逆元 a⁻¹ とは、次を満たす元のことです。

    a · a⁻¹ ≡ 1 (mod p)

    そして割り算はこう定義されます。定義であって、変形ではありません。

    b ÷ a := b · a⁻¹

    同じことが加法にもあります。a の加法逆元は p − a で、 引き算は b − a := b + (p − a)有限体には「引く」も「割る」も無く、あるのは「逆元を足す・掛ける」だけです。

    0 に逆元はありません。 0 · x = 0 がすべての x で成り立つので、1 になりようがない。 これは「まだ見つかっていない」ではなく「存在しない」です。

    ⑦ への伏線: この「0 だけは割れない」が、 楕円曲線の 2 倍算で y = 0 のときに 接線が垂直になって無限遠点に飛ぶという現象に直結します。 分母 2y が 0 になる、ただそれだけのことです。

    3 つの求め方と、その計算量

    方法計算量使える条件
    総当たりO(p)いつでも(実用外)
    フェルマーの小定理 ap−2O(log p) 回の乗算p が素数のときだけ
    拡張ユークリッドO(log p)・最速gcd(a, p) = 1 なら合成数でも可

    p が 2²⁵⁶ 級なら総当たりは即座に論外です。 実装で選ぶのは下 2 つで、Week 1 の採点器 solver.pypow(a, P−2, P)(フェルマー)、 Week 3 の課題は extended_gcd(拡張ユークリッド)を使います。

    フェルマーが素数を要求する理由

    ap−1 ≡ 1 が成り立つのは、p が素数だからです。

    両辺を a で割れば ap−2 ≡ a⁻¹合成数の法に同じ式を当てると、静かに間違った値を返します—— 例外も出ません。ラボで法 9 を選んで確かめてください。

    手で追う — F₁₃ で 5⁻¹ を求める

    1. まず、割り算を繰り返して 1 まで下りる

      13 と 5 に対してユークリッドの互除法を回します。

      13 = 2·5 + 3
       5 = 1·3 + 2
       3 = 1·2 + 1 ← 余りが 1 になったので gcd(13, 5) = 1

      gcd が 1 であることが、逆元が存在する条件です。 もし gcd が 1 でなければ、その時点で「逆元なし」が確定します。

    2. 今度は下から戻る(後退代入)

      余りが 1 になった式から、順に代入して戻します。

      1 = 3 − 1·2
       = 3 − 1·(5 − 1·3) = 2·3 − 1·5
       = 2·(13 − 2·5) − 1·5 = 2·13 − 5·5

      最後の形が ax + by = gcd の形(ここでは 13·2 + 5·(−5) = 1)です。 この式を mod 13 で見ると 13 の項が消えます。

    3. mod を取って、正規化する

      2·13 − 5·5 = 1
      → −5·5 ≡ 1 (mod 13)
      → 5⁻¹ ≡ −5 ≡ 8 (mod 13)

      検算: 5 · 8 = 40 = 3·13 + 1 ≡ 1 (mod 13)

      ここが Week 3 の落とし穴でした。 素直に出てくるのは −5 で、これは正しい逆元です。 でも 0..p−1 の代表に直さないと採点器に落とされる。 ②の正規化が、そのままここで効いています。

    4. フェルマーでも同じ答えになる

      513−2 = 5118 (mod 13)

      指数 11 は 2 進で 1011 なので、繰り返し二乗法で 7 回の乗算で終わります(総当たりなら 8 回試す)。 p が大きくなるほど差は開き、p ≈ 2²⁵⁶ では 総当たり 2²⁵⁶ 回に対して、フェルマーは約 500 回です。

      どちらも同じ 8 に着地します。 当然です——逆元は一意だから。 a·x ≡ 1a·y ≡ 1 なら、 両辺に掛け合わせて x ≡ y が出ます。 「求め方が 3 つある」は「答えが 3 つある」ではありません。

    ラボ A

    法を切り替えて、零因子と逆元を目で見る

    p を選ぶと、その世界の乗法表が描かれます。 積が 0 になったマスは赤積が 1 になったマス(逆元のペア)は緑合成数(6, 9, 12)を選ぶと赤が現れ、素数(7, 11, 13)を選ぶと消えます。 それが「なぜ素数か」の答えそのものです。

    世界の設定

    p = 7
    法 p素数と合成数が混ざっている
    元 a逆元を 3 通りで求める
    各元の逆元赤 = 逆元を持たない

    零因子(0 でない 2 つを掛けて 0 になる組)

    乗法表 — 縦 a × 横 b

    積が 0(0 を掛けた行と列を除く = 零因子) 積が 1(互いに逆元)

    逆元を 3 通りで求める(同じ答えに着地するか)

    拡張ユークリッドの中身

    見てほしいこと 1

    合成数の表には、赤いマスが必ず現れる。

    p = 6 なら 2·33·4 が 0。 p = 9 なら 3·33·66·6p = 12 にいたっては赤だらけです。 赤が 1 つでもあれば、その世界では割り算が定義できません。

    見てほしいこと 2

    素数の表では、各行にちょうど 1 つだけ緑がある。

    「各行に 1 つ」=すべての元にちょうど 1 つの逆元がある零因子が消えることと、逆元が全員に行き渡ることが、同じ表の裏表として見えます。 さらに、素数の行はどれも 0..p−1 の全部を 1 回ずつ含みます (a 倍は全単射)——これも零因子が無いことの言い換えです。

    性質

    有限体には「大小」がない

    整数から持ち込めなかったものがあります。順序です。 これは実装の都合ではなく、原理的に存在しないという話です。

    F_7 で「1 < 2」と言えるでしょうか。言えません。証明は 3 行です。

    もし 1 < 2 で、順序が加法と両立する(a < b なら a+c < b+c)なら
    1 < 2 < 3 < 4 < 5 < 6 < 7 = 0 < 1
    → 1 < 1。矛盾。

    時計の上で「3 時は 10 時より小さい」と言えないのと同じです。 巻いてしまう世界に、始点も終点もありません。

    注意すべきは、3 < 5 という比較を書くこと自体はできることです。 代表元は 0..p−1 の整数なので、機械的には比較できます。 できないのは「+ と × と噛み合う順序」を持つこと3 < 5 の両辺に 4 を足せば 0 < 2、 さらに 4 を足せば 4 < 6、もう一度で 1 < 3—— 足すたびに大小がひっくり返るので、比較として使えません。

    Week 1 では枷になる

    回路に x < 8 と書けません。

    算術回路の制約は「式 = 0」の形しか無く、その式は + と × でできています。 不等式はそこに存在しないので、 x をビットに分解して 1 本ずつ縛る(range proof)という 遠回りをすることになります。

    proof-of-exploit が許可リストを (x−2)(x−5)(x−6) = 0 という積の形で書くのは、 「集合に入っている」なら + と × だけで表せるからです。

    Week 2 では武器になる

    シェアの大きさから秘密が推測できません。

    秘密 sshare = rs − r に分けたとき、 片方が 65 だったとして、それは「大きい秘密」を意味しませんr は一様乱数で、s − r も一様分布。 大小に情報が乗らないので、大小からは何も漏れません。

    もし整数のまま分けていたら、share = 1000000 を見た人は 「秘密もそのくらいの桁だな」と推測できてしまいます。

    同じ性質が、片方では枷、片方では武器

    順序が無いことは、有限体の欠点でも利点でもなく、ただの性質です。

    Week 1(ZK)は「表現したいのに書けない」側に立つので枷になり、 Week 2(MPC)は「漏らしたくないのに漏れない」側に立つので武器になります。 どちらを向いているかで呼び方が変わるだけ—— 暗号の道具はだいたいこの形をしていて、 「制約」と「保証」は同じ 1 つの事実の裏表であることが多いです。

    構造

    位数と生成元 — 群は巡回する

    群の中で 1 つの元を選び、それを掛け続けると何が起きるか。 ここで出てくる言葉が、⑧ の離散対数と Week 3 のフーリエ変換の両方で使われます。

    1. 2 種類の「位数」がある

      同じ言葉で 2 つのものを指すので、最初に分けておきます。

      群の位数: 群に含まれる元の個数
      元の位数: gn = 1 となる最小の正整数 n

      混同しやすいのは、しばしば一致するからです。 F_7* の群の位数は 6、そして元 3 の位数も 6。 一致する元のことを生成元と呼びます。

    2. 生成元は、群を 1 人で埋め尽くす

      F_7* = {1, 2, 3, 4, 5, 6}(0 を除いた 6 個)で、3 のべきを並べます。

      3¹ = 3 3² = 9 ≡ 2 3³ = 6 ≡ 6
      3⁴ = 18 ≡ 4 3⁵ = 12 ≡ 5 3⁶ = 15 ≡ 1

      出てきたのは 3, 2, 6, 4, 5, 1——6 個すべてが 1 回ずつ。 そして 6 乗で 1 に戻り、そこから同じ列を繰り返します。 3 は F₇* の生成元であり、この群は巡回群です。

      順番に注目してください。 3, 2, 6, 4, 5, 1 は 大小の順ではありません。⑤ で見たとおり、掛け算は順序を壊します。 この「バラバラさ」が、⑧ の一方向性の材料になります。

    3. 生成元でない元は、部分群に閉じこもる

      同じ F_7* で、今度は 2 のべきを並べます。

      2¹ = 2 2² = 4 2³ = 8 ≡ 1 → 以降 2, 4, 1 の繰り返し

      2 の位数は 3。到達できるのは {1, 2, 4} の 3 個だけで、 これは F₇* の部分群です。

      ラグランジュの定理: 元の位数は必ず群の位数を割り切ります。 6 の約数は 1, 2, 3, 6 なので、F_7* の元の位数は この 4 通りしかありえません(実際: 1 → 1、6 → 2、2 と 4 → 3、3 と 5 → 6)。 群の位数が素数なら、単位元以外は全部生成元になります—— ⑦ の楕円曲線で、この事実がそのまま出てきます。

    4. 「位数 n の 1 の根」は、この言葉の言い直し

      Week 3 の講義スライドは、フーリエ変換の評価点として 位数 n の 1 の根 ω を使います。定義はこうです。

      ωn = 1 かつ ω⁰, ω¹, …, ωn−1 がすべて異なる

      これは「ω の位数がちょうど n」と言っているだけです。 スライドの例は F₇ω = 2—— 上で見た「2 の位数は 3」がそのまま 「2 は位数 3 の 1 の根」になります。

      H = {1, ω, ω²} = {1, 2, 4} ⊂ F₇*

      同じものに 2 つの名前が付いているだけです。 群の言葉では「位数 3 の元が生成する部分群」、 多項式の言葉では「フーリエ変換の評価点の集合」。 Week 3 以降で多項式を扱うとき、この節に戻れば下地は済んでいます。

    F₇* の全元の位数(ラボ A の計算器と同じ結果)

    gべき乗の列元の位数生成元か
    111
    22, 4, 13—(部分群 {1,2,4})
    33, 2, 6, 4, 5, 16生成元
    44, 2, 13
    55, 4, 6, 2, 3, 16生成元
    66, 12

    位数はすべて 6 の約数(1, 2, 3, 6)に収まっています。 Week 2 の OT ラボが使うトイ群も同じ構造で、F₂₃*(位数 22)の 位数 11 の部分群を使っていました——「なぜ 11 なのか」の答えがラグランジュの定理です。

    もう一つの群

    楕円曲線 — 点の集合が群になる

    ここまでは F_p の中の話でした。楕円曲線は その体の上に作る、まったく別の群です。 要素は数ではなく「点」、演算は掛け算ではなく「点の足し算」。 それでも群の定義は同じ 4 つです。

    1. 定義 — 標準形と、滑らかさの条件

      F_p(p > 3)上の楕円曲線は、次の式を満たす点の集合です。

      y² = x³ + a·x + b  (a, b ∈ F_p)

      ただし、次の条件を満たすものだけを楕円曲線と呼びます。

      4a³ + 27b² ≠ 0 (mod p)

      これは何の条件か: 右辺 x³ + ax + b が重根を持たない、という条件です。 重根があると曲線に尖った点や自分自身と交わる点ができ、 そこでは接線が 1 本に決まりません。 接線が決まらないと 2 倍算が定義できないので、群になりません。 ラボ B で a = 0, b = 0 を選ぶと、この条件で弾かれる様子が見られます。

    2. 無限遠点 O を 1 つ足す

      方程式を満たす点だけでは群になりません。単位元がないからです。 そこで仮想的な点 O(無限遠点)を 1 つ追加します。

      E = {O} ∪ { (x, y) ∈ F_p × F_p | y² = x³ + ax + b }

      O は「y 軸方向の無限の彼方」だと思ってください。 すべての垂直線が O を通る、と約束します。 そう約束すると「垂直線も 3 点で交わる」ことになり、 次の加法の定義に例外が要らなくなります。 数学が先で記号が後ではなく、都合のいい点を足して形を整えているのが実際です。

    3. なぜ「点の足し算」で群ができるのか

      出発点は 1 つの事実です。3 次曲線と直線は、ちょうど 3 点で交わる (接する場合は 2 重に数え、垂直線は O を 3 点目に数える)。

      2 点 P, Q を決める → 直線が決まる → 3 点目 R が自動的に決まる

      そこで P + Q := −R(R を x 軸に関して反転した点)と定めます。

      なぜわざわざ反転するのか: 反転せずに P + Q := R と決めると、 単位元が作れません。 「一直線上の 3 点の和は O」と約束すると、 P + Q + R = O つまり P + Q = −R となり、 O が単位元、x 軸反転が逆元、という群の形にぴたりと収まります。 結合則が成り立つことの証明だけは重く(射影幾何やベズーの定理を使う)、 ここでは事実として使います。

    4. 群の 4 条件を確認する

      群の条件楕円曲線では
      閉じている3 点目は必ず曲線上(反転しても曲線上:y² は符号に無関係)
      結合則成り立つ(証明は重い。ラボ B で総当たり検証している)
      単位元O。P + O = P
      逆元−P = (x, −y)。P + (−P) = O
      可換成り立つ(P と Q を通る直線は順番によらない)

      「y を反転しても曲線上にある」のは、方程式の左辺が だからです。 だから点は必ず上下 2 個ずつペアで現れます—— ラボ B の散布図で、点が中央の線に関して対称に並ぶのはこれが理由です。 例外は y = 0 の点だけで、そこは自分自身が自分の逆元になります。

    5. 加法公式 — 割り算は全部 ④ の逆元

      直線の傾き λ を求めて、3 点目を計算します。場合分けは 2 つだけです。

      弦(P ≠ Q): λ = (y₂ − y₁) / (x₂ − x₁)
      接線(P = Q): λ = (3x₁² + a) / (2y₁)

      x₃ = λ² − x₁ − x₂
      y₃ = λ(x₁ − x₃) − y₁

      この「/」は有限体の割り算——つまり (x₂ − x₁)⁻¹(2y₁)⁻¹ を掛けることです。 ④ で作った逆元が、ここで初めて実戦投入されます。

      y₃ の式に注意: λ(x₁ − x₃) − y₁ であって λ(x₃ − x₁) + y₁ ではありません。 符号の中に「x 軸反転」が畳み込まれています。 Week 3 の課題 README も 「乗らないときは公式のどこか(特に y_R の符号)が間違っています」と警告しています。

    6. 例外は 2 つだけ。どちらも「割れない」から起きる

      ① x₁ = x₂ かつ y₁ = −y₂ の場合: 分母 x₂ − x₁ = 0 → P + (−P) = O
      ② P = Q かつ y₁ = 0 の場合: 分母 2y₁ = 0 → 2P = O

      ④ の伏線を回収します。 0 に逆元が無いので、この 2 つは「計算できない」のではなく 「結果が O である」と定義するしかありません。 幾何で言えばどちらも垂直線—— ② は y = 0 の点での接線が垂直になる場合です。 「0 で割れない」という体の性質が、そのまま群の例外処理になっている。

      ラボ B で y² = x³ + x over F₁₁ を選ぶと、 (0, 0) という y = 0 の点が現れます。 これを生成点にすると 2P = O、位数はちょうど 2 です。

    手で追う — 2P を計算する

    y² = x³ + x + 6 over F₁₁、P = (2, 7) の 2 倍

    まず P が曲線上にあるか:
     左辺 7² = 49 ≡ 5  右辺 2³+2+6 = 16 ≡ 5

    接線の傾き(分母は 2y = 14):
     λ = (3·2² + 1) / (2·7) = 13 / 14
     13 ≡ 2、14 ≡ 3 (mod 11)
     3⁻¹ ≡ 4 (3·4 = 12 ≡ 1)
     λ = 2 · 4 = 8

    x₃ = λ² − x₁ − x₂ = 64 − 2 − 2 = 60 ≡ 5
    y₃ = λ(x₁ − x₃) − y₁ = 8·(2 − 5) − 7 = −31 ≡ 2

    → 2P = (5, 2)

    検算: 左辺 2² = 4、右辺 5³ + 5 + 6 = 136 = 12·11 + 4 ≡ 4

    途中で 2 回、有限体の作法が出ています。13/142·3⁻¹ に直すところ(先に代表元へ正規化)、 ② −312 に直すところ。 どちらか忘れると、曲線に乗らない点が出て 1 ステップで破綻します。

    スカラー倍 — double-and-add

    13P を、13 回足さずに 5 回で作る

    13 = 8 + 4 + 1 = 1101₂ と分解します。

    2P = P + P    (doubling 1)
    4P = 2P + 2P  (doubling 2)
    8P = 4P + 4P  (doubling 3)
    13P = 8P + 4P + P (加算 2 回)

    合計 5 回 / 定義どおりなら 12 回

    演算回数は k ではなく log₂k に比例します。 k ≈ 2²⁵⁶ でも約 384 回(doubling 256 + 加算 平均 128)で終わります。

    Week 3 の課題で必ずここを踏みます。 README にこう書かれています—— 「ec_add を k 回繰り返す実装ではテストが終わりません(テストには k = n ≈ 2²⁵⁶ のケースがあります)」。 素朴な実装は落ちるのではなく、返ってこない。

    そして、これが ⑧ の前半分です。 x ↦ xP が速いのは double-and-add があるから。 逆に、その逆をたどる同じくらい速い手が見つかっていない—— この非対称が次の節の主題です。

    一方向性

    離散対数問題 — 「戻れない」の正体

    群は定義からして「戻れる」世界でした(逆元があるので)。 にもかかわらず暗号が成立するのは、戻れることと、戻る手が速いことが別だからです。

    問題はこう書けます。乗法群の言い方と、楕円曲線の言い方があります。

    乗法記法: g と y = gx が与えられたとき、x を求めよ
    加法記法: P と Q = xP が与えられたとき、x を求めよ(ECDLP)

    速い向きは繰り返し二乗法 / double-and-add で O(log x)難しい向きには、いまのところ多項式時間の手がありません。

    ハッシュ関数と同じ非対称です。ただし決定的な違いが 1 つ。 ハッシュは情報を捨てているから戻れないのに対して、 離散対数は情報を捨てていません—— xgx の中に完全に残っていて、 原理的には総当たりで必ず見つかります。 戻れないのではなく、間に合わない。

    だから離散対数の安全性は「不可能」ではなく「計算量的に困難」と言います。 Week 2 の秘密分散が「情報理論的に不可能」だったのとは、根拠の強さが違います。 量子計算機の話が出るのはこちら側だけなのも、この違いからです。

    2 つの記法は同じことを言っている

    乗法記法 F_p*加法記法 EC意味
    g · hP + Q群演算
    1O単位元
    g⁻¹−P逆元
    gxxPx 回の群演算
    gx から xxP から x離散対数問題
    繰り返し二乗法double-and-add速い向きの手

    記法が違うだけで、群としては同じ話をしています。 EC を使う理由は、同じ安全性を短い鍵で買えるから—— F_p* は 2048 ビット必要なところ、EC なら 256 ビットで済みます (F_p* には指数計算法という部分的に速い攻撃があり、EC にはそれが効かないため)。

    DH 三兄弟を 1 行ずつ

    DLP: (P, xP) から x を求めよ。いちばん強い要求。

    CDH(計算 Diffie-Hellman): (P, aP, bP) から abP を作れ。 x を知らなくても共有鍵だけ作れれば破れるので、DLP より弱い要求です。

    DDH(判定 Diffie-Hellman): (P, aP, bP, Z) を見て、Z = abPランダムか判定せよ。 さらに弱い要求——値を作る必要すらありません。

    DLP が解ければ CDH が解け、CDH が解ければ DDH が解ける。

    だから安全性の仮定としては逆順に強くなります。 「DDH が難しい」は「DLP が難しい」より強い仮定。 暗号方式は必要な分だけ強い仮定を置きます—— ElGamal の意味論的安全性には DDH が要ります

    小さい群では、暗号は成立しない

    次のラボの「離散対数を総当たりで解く」ボタンは、必ず一瞬で当たります。

    位数 13 の群なら、試行は最悪 13 回。暗号でも何でもありません。 実用の曲線 secp256k1 の位数は約 2²⁵⁶ ≈ 1.16 × 10⁷⁷—— 観測可能な宇宙の原子数(約 10⁸⁰)と同じ桁です。 難しさは群の構造ではなく、位数の大きさが担保しています。

    なお総当たりは最悪 n 回ですが、実際の攻撃はPollard のロー法などで O(√n) まで落ちます。だから 128 ビットの安全性が欲しければ位数は 256 ビット必要—— secp256k1 の 256 ビットという数字は、この平方根から逆算されています。

    ラボ B

    楕円曲線の点をすべて並べて、巡回させる

    小さい曲線なら、点は全部数え上げられます。既定は y² = x³ + x + 6 over F₁₁生成点 P を選ぶと 1P, 2P, 3P … を辿って O に戻るところまで見え、 離散対数を総当たりで解くボタンで「小さい群では解けてしまう」ことが確かめられます。

    曲線の設定

    法 p体の大きさ
    係数 ay² = x³ + ax + b
    係数 ba = b = 0 は特異になる
    生成点 P押すと倍々に辿る
    目標の点 QQ = kP の k を当てさせる

    曲線上の全点(横 = x、縦 = y、破線 = 対称軸 y = p/2)

    「x 軸に関して対称」は、mod の世界では yp − y のペアという意味になります。 図では中央の破線に関して対称に見えます。y = 0 の点だけが相方を持たず、線の下端に単独で並びます

    P の倍々(O に戻るまで)

    計算の中身

    試してほしい設定 1 — 位数が素数の曲線

    y² = x³ + x + 6 over F₁₁ は、13 個の点を持つ。

    13 は素数なので、ラグランジュの定理から、O 以外のどの点も位数 13 の生成元です。 どの点を選んでも 13 個全部を巡ります。 実用の曲線が「位数が素数(またはほぼ素数)」であることを要求するのは、 部分群に閉じこもる点を作らないためです。

    試してほしい設定 2 — y = 0 の点がある曲線

    a = 1, b = 0 にすると y² = x³ + x、点は 12 個になる。

    この曲線には (0, 0) があります。選んで倍々を見てください—— 2P = O で終わり、位数は 2。 ⑦ で予告した「分母 2y が 0 になるので O」が、実際に起きています。 位数 12 の群には位数 1, 2, 3, 4, 6, 12 の点が混在します(12 の約数)。

    試してほしい設定 3 — 特異曲線

    a = 0, b = 0 は弾かれる。

    4·0³ + 27·0² = 0 なので滑らかさの条件を満たしません。 y² = x³ は原点に尖点(カスプ)を持ち、そこで接線が決まらない。 「群にならない」ことをラボが拒否として見せます。 p = 11 では (a,b) = (2,3) も特異です (4·8 + 27·9 = 275 = 25·11 ≡ 0)。

    試してほしい設定 4 — 総当たりの試行回数

    最悪でも位数と同じ回数で必ず当たる。

    p = 17 の曲線でも試行は数十回です。 secp256k1 なら 2²⁵⁶ 通り。 1 秒に 10¹² 回試せる機械を 10 億台並べても、宇宙の年齢では終わりません。 アルゴリズムは同じ、桁だけが違う。

    検問クイズ

    土台検問 — 手が動くかどうかを試す

    読んだだけでは定着しません。ここでは正規化・逆元・体の判定・群の性質・楕円曲線の加算を その場で出題します。問題は毎回生成され、判定は上の 2 つのラボと同じ計算器が行います。 3 回間違えたら、その回は終了。

    検問モードを選ぶ

    10 問・ライフ 3

    誤答するとその場で解説が出る。分野を絞って弱点だけ潰すこともできる。

    接続

    この土台が、どの週で効くのか

    Week 0 が「数学の準備」に見えて実は伏線だった、という構造になっています。 どこで回収されるかを先に並べておきます。

    テーマWeek 0 のどこが効くか
    Week 1算術回路・ZK(proof-of-exploit回路の値が住む場所が F_p。ゲートが + と × だけなのは環の定義(x−2)(x−5)(x−6)=0 が効くのは零因子が無いから。不等式が書けないのは順序が無いから
    Week 2MPC・秘密計算(toy-mpcシェアも Beaver 三つ組も F_p の元。正規化を忘れると採点器に落ちる。シェアの大小から何も漏れないのは順序が無いから。OT のトイ群は F₂₃*位数 11 の部分群
    Week 3楕円曲線と Schnorr(schnorr-from-scratchこのノートの後半そのもの。Part 1 = 逆元(拡張ユークリッド + 正規化)、Part 2 = 点の加算と double-and-add、Part 3 = 離散対数の困難性の上に建つ署名。講義の方は多項式とフーリエ変換で、位数 n の 1 の根を使う
    Week 4 以降多項式・コミットメント・KZG多項式の係数も評価値も F_p の元。評価点は1 の根の巡回群。KZG のコミットメントは楕円曲線の点で、その安全性は離散対数(と、その強化版)に乗る
    Week 5TFHE(tfhe-toy-python格子ベースなので土台は少し違うが、剰余環の上で乱数に埋めて隠すという発想は Week 2 と同じ形
    Week 6co-SNARK / zkVMBeaver 乗算(F_p)と回路(F_p)の合流点。ここまで来ても、値の住む場所は変わらない

    Week 5 だけ土台が少し違いますが、それ以外は全部この 1 ページの上に建っています

    持ち帰る 3 つ

    ① 順序がない。 だから大小比較は書けず(Week 1 の枷)、大小から秘密は漏れない(Week 2 の武器)。 同じ 1 つの性質が、立つ位置で意味を変えます。

    ② 割り算は逆元の掛け算。 a⁻¹ は拡張ユークリッドで求め、必ず 0..p−1 に正規化して返す。 そして 0 に逆元は無く、それが楕円曲線の 無限遠点という例外処理の正体でした。

    ③ 片方向だけ速い。 x ↦ xP は double-and-add で O(log x)、逆は手がない。 ただし「不可能」ではなく「間に合わない」—— ラボ B で総当たりが一瞬で当たったのは、位数が 13 しかなかったからです。 安全性を担保しているのは構造ではなく桁数。

    そして、この 3 つの手前に 0 番目があります。 暗号の道具立ては「数学的に美しいから」ではなく、 要求から逆算されて選ばれているということ。 素数を選ぶのは零因子を消すため。有限にするのは固定長で扱うため。 群を使うのは戻れる必要があるため。 「なぜこの形なのか」を毎回聞く癖が、この先いちばん効きます。