エアWriteup “DEFCON 2021 Quals: QOO or OOO”
はじめに
DEFCON 2021 Quals: QOO or OOOは量子コンピュータ(量子力学?)では有名なCHSHゲームを題材としたCTFの問題である。この問題のことを友人に教えてもらい[1]、筆者自身もCHSHゲーム(またはBell不等式)をきちんと追ったことがなかったこともあり、この記事ではこの問題とCHSHゲームについて、物理の知識や量子コンピュータの知識をなるべく必要としない形で、行列計算に基づいて具体的に計算しながら説明したい。
この記事を読んで改善するべきところや、不明な点を見つけた場合は気軽にコメントなどで教えてほしい。
問題の起動
DEFCON 2021 Quals: QOO or OOOのページへ行き、書いてあるとおりにDockerを起動すればOKである。macOSの問題なのか、筆者の環境では下記のようにポートをバインドしたらうまくいった。
$ docker run -p 127.0.0.1:5000:5000/tcp -d --name qoo-or-ooo archiveooo/pub:qoo-or-ooo
あとは次のようにnc
コマンドで問題サーバーへ接続できる。
$ nc localhost 5000
Matplotlib created a temporary config/cache directory at /tmp/matplotlib-r284hmrs because the default path (/root/.config/matplotlib) is not a writable directory; it is highly recommended to set the MPLCONFIGDIR environment variable to a writable directory, in particular to speed up the import of Matplotlib and to better support multiprocessing.
zardus: Hey hacker! Shall we play a game against QOO?
There are two competitors here and they each will bet on 0 or 1.
Let's put our numbers there so that the sum of ours is same as the multiplication of theirs
“QOO or OOO”の説明
この問題は自分も含めた次のような4人の参加者がいる。
- Hacker(自分)
- Zardus
- HackerのCompetitor
- 便宜上こちらをCompetitor Aとする
- ZardusのCompetitor
- 同様にこちらをCompetitor Bとする
そして、この4人は次のようなプロトコルを実行する。
- Competitor Aがベット(Bet)と呼ばれる1ビットの値をHackerへ公開する
- このベットを
とするa \in \{0, 1\} - このベット
をZardusは知ることができないa
- このベットを
- Hackerが1ビットの値
またはh \in \{0, 1\} magic qoin
を選ぶ- この
magic qoin
については後で説明する
- この
- Competitor Bが同様にベット
を選びZardusへ公開するb \in \{0, 1\} - ただしこの値
がどちらなのかHackerは知ることができないb
- ただしこの値
- ZardusはCompetitor Bの選んだベット
によって、後述する適応的な行動にしたがって値h を選択するz \in \{0, 1\} -
[2]であればHackerの勝利となり、そうでなければ敗北となるh \oplus z = a \times b - この(1)〜(5)を30回行って、勝率が 85% を越えればフラグが獲得できる
magic qoin
のところで量子性を利用するが、とりあえずこのゲームをHackerやZardusが適当に
ただし問題設定としてZardusはHackerの仲間である。ここで彼は手順(4)で「Competitor Bの選んだ値magic qoin
を利用することで無理やり解決していこうというのがこの問題の想定解となる。
量子ビットと量子計算
この章では量子ビットとそれの計算について説明する。基本的な行列に関する演算や用語(内積、複素共役など)そして量子計算で利用するディラック記法については過去に書いたガチャの記事にまとめたので、これからの説明のうち行列の計算などで不明な点があればこちらも参考にしてほしい。
1量子ビット
量子ビットと行列
まず1量子ビットは次のような行列で表現される。
このままだと古典コンピュータ[3]と同様に2通りしか表現できないので、ここに確率振幅という複素数
この確率振幅は
このように1量子ビットは古典コンピュータの1ビットとはことなり次のような性質を持つ。
- 2つの確率振幅と呼ばれる複素数により、
のどちらが観測されるか曖昧な状態を持つことができる\ket{0}, \ket{1}
また重要な性質として、我々は確率振幅を直接知ることはできない。あくまで量子ビットの測定によって生じる観測結果に確率振幅が寄与するのであって、この複素数を具体的に取り出す操作はできないことに注意が必要である。
1量子ビット計算
たとえば古典コンピュータにあるNOT演算子は次のような行列
さきほどの
たとえばこれを
量子ビットの測定
1量子ビットの測定にはまず基底[4]と呼ばれる2つの行列を選ぶ必要がある。たとえば
このとき
測定後の量子状態は観測結果によって次のように分岐する。
-
を基底\ket{+} で測定した結果が\{\ket{0}, \ket{1}\} となった場合[5]\ket{0} \def\braket#1#2{\mathinner{\left\langle{#1}\middle|#2\right\rangle}} \ket{0}\bra{0}\ket{+} = \ket{0}\braket{0}{+} = \ket{0}\left(\frac{1}{\sqrt{2}}\braket{0}{0} + \frac{1}{\sqrt{2}}\braket{0}{0}\right) = \frac{1}{\sqrt{2}}\ket{0} -
同様に測定した結果が
となった場合\ket{1} \def\braket#1#2{\mathinner{\left\langle{#1}\middle|#2\right\rangle}} \ket{1}\bra{1}\ket{+} = \ket{1}\braket{1}{+} = \ket{1}\left(\frac{1}{\sqrt{2}}\braket{1}{0} + \frac{1}{\sqrt{2}}\braket{1}{1}\right) = \frac{1}{\sqrt{2}}\ket{1}
このままでは確率振幅の満すべき式
このようにどちらも
さて、ここまで基底として
さきほどの
2量子ビット
ここまでの議論は全て1量子ビットについて議論してきたが、問題で必要となるためさらにここで1量子ビット追加して2量子ビットの議論をしていく。
2量子ビットの表現
2量子ビットはテンソル積
なお、表記を短縮するため今後は
CX ゲート
実は複数量子ビットを組みあわせた場合、テンソル積では表現できない状態となることがある。まずは次のような行列で表現される
ただし
- 1量子ビット目が
のとき、2量子ビット目には何も作用させない\ket{0} - 1量子ビット目が
のとき、2量子ビット目に\ket{1} ゲートを作用させるX
たとえば
このように2量子ビット目に
この結果は確率
また、古典コンピュータとの直感が大きく異なる点として、このように片方が
最後に余談ではあるが、このような量子操作を量子回路という下記の図で表わすこともできる。
量子回路では2量子ビットを共に
magic qoin
ここからはこれまで説明した量子ビットに関する知識を利用して、この問題でプレイヤーが選択できるmagic qoin
を使った想定解法がなぜそうなるのかを解説する。
Hackerの選択肢としてmagic qoin
を選ぶと、次のように追加の選択肢が表示される。
[Round 0]: Your competitor bets on 0
0. Bet for 0
1. Bet for 1
2. Use your magic qoin
2
Do you want to rotate your qoin before flipping?
0. No, do not rotate my qoin
1. Yes, rotate left
2. Yes, rotate right
そもそもこのmagic qoin
とは何かについては実は問題の時点では公開されていない。終了後に公開されたソースコードsecret_coin.py
[7]において、このmagic qoin
とは「ERPペアな2量子ビットをつくり、HackerとZardusがそれぞれ1量子ビットを持っている」状態であるということが分かる。ここでERPペアとはたとえば次のような2量子ビットである。
そして、このようなエンタングルメントした2量子ビットのうち、Zardusが1量子ビット目である
各プレイヤーの量子操作
Hacker
さて問題ではCompetitor Aのベットを知ったうえで、magic qoin
を左右に回転(rotate)させるか、あるいは何もしないかを選ぶことができる。
準備として、「左右」のような空間的な表現が登場したため、説明を直感的にするためにブロッホ球という量子ビットの空間的な表現を導入する。
ブロッホ球の各軸
このように
このブロッホ球の表面座標
ブロッホ球による空間的な表現について補足したところで、この問題が述べている左右の回転とは何か?というと配布されているソースコードcoin.py
[8]から次のような操作であることがわかる[9]。
この行列表現からは分かりにくいかもしれないが、rotate right
はrotate left
は
最後にHackerは基底
Zardus
ソースコードplayers.py
[10]からZardusはCompetitor Bの結果
-
であるときb = 0 - なにもせずにZardusが持つ量子ビットを基底
で測定する\{\ket{0}, \ket{1}\}
- なにもせずにZardusが持つ量子ビットを基底
-
であるときb = 1 - Zardusが持つ量子ビットにアダマールゲート
を作用させたうえで基底H で測定する\{\ket{0}, \ket{1}\}
- Zardusが持つ量子ビットにアダマールゲート
CHSHゲーム中の量子ビット変化と観測確率
ここまでHackerとZardusの量子操作をまとめて1つの量子回路で書くと次のようになる。
今回の問題の量子操作に対応する量子回路図
先に問題(CHSHゲーム)の模範解答を述べてしまうと、Hackerは次のような操作を行えばよい。
-
ならばa = 0 rotate left
を行う -
ならばa = 1 rotate right
を行う
なぜこのようになるのかについて、Competitorのベットである
b = 1 のとき
1. したがってこれは
-
のときz = 0\,(\ket{0}) -
Hackerの持つ量子ビットは
の確率で\frac{1}{2} のいずれかとなるため\ket{0}, \ket{1} \frac{1}{\sqrt{2}}\left(\ket{0}_2 + \ket{1}_2\right) = \ket{+}_2
-
-
のときz = 1\,(\ket{1}) -
同様に
の確率で\frac{1}{2} いずれかとなるため\ket{0}, -\ket{1} \frac{1}{\sqrt{2}}\left(\ket{0}_2 - \ket{1}_2\right) = \ket{-}_2
-
ここまででZardusの測定後のHackerの持つ量子ビット(magic qoin
)を調べ終わった。さて、ここに来たところでHackerのCompetitorのベット
-
ならばZardusの結果a = 0 と同じ結果となれば勝利するz -
ならばZardusと異なる結果となれば勝利するa = 1
今の量子ビットをそのまま測定した場合、
-
ならば\ket{+}_2\,(\Rightarrow z = 0) が出てほしい\ket{0} -
ならば\ket{-}_2\,(\Rightarrow z = 1) が出てほしい\ket{1}
このときrotate left
を行うと、次の図のように完全に
そして次のように確率振幅を計算すれば、そこから勝率を求めることができる。
したがって次のようにこのゲームで勝利する確率が求まる。
-
なら\ket{+}_2 が観測されたときに勝利するため\ket{0} \left|\frac{1}{\sqrt{2}}\left(\cos{\frac{\pi}{8}} + \sin{\frac{\pi}{8}}\right)\right|^2 = \frac{1}{2} + \frac{1}{2\sqrt{2}} -
なら\ket{-}_2 が観測されたときに勝利するため\ket{1} \left|\frac{1}{\sqrt{2}}\left(-\sin{\frac{\pi}{8}} - \cos{\frac{\pi}{8}}\right)\right|^2 = \frac{1}{2} + \frac{1}{2\sqrt{2}}
同様にrotate right
することによって次のように傾かせることができる。
確率振幅は次のようになる。
こちらの場合は先程とは勝利条件が異なり、XOR
の結果を
-
ならば\ket{+}_2\,(\Rightarrow z = 0) で勝利\ket{1} - したがって勝利する確率は
となる\left|\frac{1}{\sqrt{2}}\left(\sin{\frac{\pi}{8}} + \cos{\frac{\pi}{8}}\right)\right|^2 = \frac{1}{2} + \frac{1}{2\sqrt{2}}
- したがって勝利する確率は
-
ならば\ket{-}_2\,(\Rightarrow z = 1) で勝利\ket{1} - 同様に確率
で勝利する\left|\frac{1}{\sqrt{2}}\left(\cos{\frac{\pi}{8}} -\sin{\frac{\pi}{8}}\right)\right|^2 = \frac{1}{2} + \frac{1}{2\sqrt{2}}
- 同様に確率
したがって合計で4パターンの場合分けしてそれぞれの勝率が全て
b = 0 のとき
2.
しかしHackerは
-
のケースz = 0 -
この場合の確率振幅は次のようになる
\begin{align*} R_y\left(\pm\frac{\pi}{4}\right)\ket{0}_2 &= \left(\begin{array}{cc} \cos{\frac{\pi}{8}} & \mp\sin{\frac{\pi}{8}} \\ \pm\sin{\frac{\pi}{8}} & \cos{\frac{\pi}{8}} \end{array}\right) \left(\begin{array}{c} 1 \\ 0 \end{array}\right) = \left(\begin{array}{c} \cos{\frac{\pi}{8}} \\ \pm\sin{\frac{\pi}{8}} \end{array}\right) \\ &= \cos{\frac{\pi}{8}}\ket{0} \pm\sin{\frac{\pi}{8}}\ket{1} \end{align*}
なのでz = 0 のとき勝利するため、勝率はh = 0\,(\ket{0}) となる\left|\cos{\frac{\pi}{8}}\right|^2 = \frac{1}{2} + \frac{1}{2\sqrt{2}} -
のケースz = 1 -
同様に確率振幅は次のようになる
\begin{align*} R_y\left(\pm\frac{\pi}{4}\right)\ket{1}_2 &= \left(\begin{array}{cc} \cos{\frac{\pi}{8}} & \mp\sin{\frac{\pi}{8}} \\ \pm\sin{\frac{\pi}{8}} & \cos{\frac{\pi}{8}} \end{array}\right) \left(\begin{array}{c} 0 \\ 1 \end{array}\right) = \left(\begin{array}{c} \mp\sin{\frac{\pi}{8}} \\ \cos{\frac{\pi}{8}} \end{array}\right) \\ &= \mp\sin{\frac{\pi}{8}}\ket{0} + \cos{\frac{\pi}{8}}\ket{1} \end{align*} -
よって
が観測される確率h = 1\,(\ket{1}) が勝率となる\left|\cos{\frac{\pi}{8}}\right|^2 = \frac{1}{2} + \frac{1}{2\sqrt{2}}
最終的な勝率
このように全パターンの確率を求めると全てrotate left
を行い、rotate right
を行うという操作で
まとめ
CHSHゲームやBell不等式については以前から知っていたが、量子計算として詳しく数式で追ったことはなく、筆者としてもとても勉強になったと思う。
参考文献
- Quantum Native Dojo: コラム1:量子複製不可能 (No-Cloning) 定理
- 量子計算理論 量子コンピュータの原理
- 量子コンピューティング: 基本アルゴリズムから量子機械学習まで
-
なお、この友人は非想定解でクリアしたらしい。 ↩︎
-
はXOR演算を意味する。 ↩︎\oplus -
量子コンピュータと区別して従来のコンピュータをこのように呼ぶ。 ↩︎
-
基底の定義のため本当はここで線形空間や1次独立などの定義を述べるべきではあるが、この記事は完全に厳密性な数学的背景を明らかにしていくというよりは、CTFの問題を通して量子コンピュータなどに関する知識を少し深める手助けになればよいというスタンスであるため、いったんこれらの定義は記事が巨大になってしまうのを避けるためにあえて解説しない。 ↩︎
-
このように内積の分配法則などを利用して、量子計算では具体的な行列表現を使って計算するというよりは、このようにブラケット記法のまま計算を進めていくことも多いと思う。 ↩︎
-
通常の(古典)コンピュータでは右端から左側へ1ビット、2ビットとなるため、この表記に違和感があるかもしれないが、数学や日常の表現では
などと左から右へ大きくなっていくため、ここでは自分が普段参照している教科書の都合もあってこの表記とした。したがって、古典コンピュータの表現と統一するために右端を1量子ビットとしても問題はないと思う。 ↩︎1, 2, \dots -
https://github.com/o-o-overflow/dc2021q-qoo-or-ooo-public/blob/64164c2315395390b9a8f6cae970841ad777c401/service/src/secret_coin.py#L8 ↩︎
-
https://github.com/o-o-overflow/dc2021q-qoo-or-ooo-public/blob/64164c2315395390b9a8f6cae970841ad777c401/service/src/coin.py#L15-L19 ↩︎
-
については量子計算ライブラリーが提供している関数を利用していたため、ここでは筆者の所有する教科書から行列表現を用意してきた。 ↩︎R_y(\theta) -
https://github.com/o-o-overflow/dc2021q-qoo-or-ooo-public/blob/64164c2315395390b9a8f6cae970841ad777c401/service/src/players.py#L47-L52 ↩︎
Discussion
良い記事で非常に勉強になりました!
一点気になったのが、1. b = 1のとき内の下記式の
部分ですが、2行目および3行目の符号は下記ではないでしょうか。
コメントありがとうございます。下記のコミットで記事の方を修正しておきました!
ご返信&ご修正ありがとうございます!