暗号について考えてみる (1) — RSA 暗号と Shor のアルゴリズム
目的
RSA 暗号と Shor のアルゴリズムについて過去に書いた自分用メモが転がっていたので整理したい。整理したいが、正直あまり覚えていないので、またメモがなくならないように書き出しておこうという程度で、実験の詳細もあまり覚えていない。故に、これは物凄い適当な記事である。
RSA 暗号
以下で言いたいことは、「とても大きな “ほぼ素数” として開示されている公開鍵が素因数分解されると、秘密鍵が推測できてしまう」ということである。
文献 [S] を参考にしよう[1]。詳細を全て割愛して、ひたすら記号だけ導入する。
-
,p を 201 桁以上の素数とし、非公開とする。q -
とおく。これは素因数分解の難しい 400 桁以上の数になる。N = pq -
とおく。L = (p-1) (q-1) とp が特定できないと算出できない。q -
: 400 桁以下の自然数で\mathcal{M} と互いに素なもの。平文の集合。N -
: 400 桁以下の自然数で\mathcal{C} と互いに素なもの。暗号文の集合。N
次に公開鍵
-
:e と互いに素な自然数。L e > 1 -
:d ed \equiv 1 \mod L - この
はd を満たす整数ae + b L = 1 \tag{1} の中から適当に選ぶ。a
- この
この設定下で公開鍵
暗号化と復号を以下で定める:
暗号化
復号
まずいのは「秘密鍵
例
今回は動きだけ見たいので、小さな数で試そう。
Alice は Bob に重大なメッセージ「i_love_you_bob
」を送りたい。
N = 35
L = 24
e = 5
d = 5
message = "i_love_you_bob"
enc_text = [(ord(v)-90)**e % N for v in list(message)]
print(enc_text)
[15, 10, 23, 21, 28, 16, 10, 26, 21, 27, 10, 8, 21, 8]
暗号化[2]により謎の数列ができた。これを復号しよう。
dec_text = "".join([chr((v**d % N) + 90) for v in enc_text])
print(dec_text)
i_love_you_bob
元のメッセージが復元された。これは大事な内容なので、途中で攻撃されたくないわけである。
n 桁の整数の素因数分解
例えば文献 [NC2] p.103 によると、文献 [L] に解説がある Lenstra による提案された「数体篩法 (すうたいふるいほう)」というものが知られている中では大変高速な素因数分解のアルゴリズムとのことである。文献 [QND] によると、
という準指数関数的な計算量になるそうである。公開鍵
現実的な時間で素因数分解できないという前提のもとで設計された暗号方式のアルゴリズムであったので、現実的な時間で解かれると根底が崩れるわけである。
Shor のアルゴリズム
折角なので、文献 [QT] に従いながら 35 を素因数分解したい[3]。Alice のメッセージは攻撃を受けてしまうのであろうか?
細かいことは文献 [QT] に書いてあるので、ここではざっと流す。以下のような量子回路を実装する。
今回は計算の都合で、突如
突然、量子位相推定
さて、上記の量子回路自体はあるユニタリゲート
ここで、量子位相推定の回路は、
閑話休題、Shor のアルゴリズム
では、上記の量子位相推定の回路はどういうユニタリゲートの固有値を求めているのか?そして固有ベクトルがどうやって求まるのか?という話である。
さて、文献 [QT] から答えを引っ張ってくると、
を出力する相当にトリッキーなゲートである。
こんなものの固有ベクトルなど事前に分かるわけがない・・・気もするのだが、
を満たす。この
となることが分かり、この右辺の状態
かくして量子回路の “下側” に
つまり、確率的に
少しインチキな式で書くと以下のような感じだろうか。
ここで、
実装
必要なモジュールを import する。以下、本質的には文献 [QT] のままである。
import time
import matplotlib.pyplot as plt
import numpy as np
from qiskit import QuantumCircuit, transpile
from qiskit.visualization import plot_histogram
from qiskit.circuit.library import QFT
from qiskit_aer import AerSimulator
from math import gcd
from fractions import Fraction
「
def ctrl_9_mod35(power):
...
return c_U
def qpe_amod35():
n_count = 8 # QPE の精度
qc = QuantumCircuit(6+n_count, n_count)
for q in range(n_count):
qc.h(q)
qc.x(n_count) # |1> の準備
for q in range(n_count): # 量子位相推定前半の階段
qc.append(ctrl_9_mod35(2**q),
[q] + [i+n_count for i in range(6)])
iqft_circuit = QFT(n_count).inverse() # 量子位相推定後半の IQFT
qc.append(iqft_circuit, range(n_count))
qc.measure(range(n_count), range(n_count))
aer_sim = AerSimulator()
job = aer_sim.run(transpile(qc, aer_sim), shots=1, memory=True)
readings = job.result().get_memory()
phase = int(readings[0],2)/(2**n_count)
return phase
量子位相推定実行。
a = 9
factor_found = False
attempt = 0
while not factor_found:
attempt += 1
print("\nAttempt %i:" % attempt)
phase = qpe_amod35(a) # 位相 = s/r
frac = Fraction(phase).limit_denominator(35)
r = frac.denominator # s/r の分母 r はこれだろうという値
print("Result: r = %i" % r)
if phase != 0:
# 因数をgcd(x^{r/2} ±1 , 15)から推定
guesses = [gcd(a**(r//2)-1, 35), gcd(a**(r//2)+1, 35)]
print("Guessed Factors: %i and %i" % (guesses[0], guesses[1]))
for guess in guesses:
if guess != 1 and (35 % guess) == 0: # 推定した因数が正しいか確認
print("*** Non-trivial factor found: %i ***" % guess)
factor_found = True
Attempt 1:
Register Reading: 11010110
Corresponding Phase: 0.8359375
Result: r = 6
Guessed Factors: 7 and 5
*** Non-trivial factor found: 7 ***
*** Non-trivial factor found: 5 ***
(何度かやり直して)
よって、Alice のメッセージは途中で攻撃を受けて解読されてしまった・・・かもしれない。
ctrl_9_mod35
の実装)
オマケ(インチキな どういう値を返せば良いのか分かっているので、雰囲気を見るだけなら実質ハードコードして作ってしまえば良い[6]:
def ctrl_9_mod35(power):
# 9 -> 11 -> 29 -> 16 -> 4 -> 1
power_ = power%6
pow2val = {0:1, 1:9, 2:11, 3:29, 4:16, 5:4}
U = QuantumCircuit(6)
U.x(0)
for i, b in enumerate(bin(pow2val[power_])[::-1]):
if b == '1':
U.x(i)
U = U.to_gate()
U.name = f"9^{power} mod 35"
c_U = U.control()
return c_U
まとめ
相当にでたらめな記事で、手元のメモの発掘がメインなので内容は大変微妙だが、とりあえず写経はできた気がする。あやしい部分は追々追記なりしていきたい・・・。
とにかく、RSA 暗号が破られてしまうのでは?という内容である。
参考文献
[S] 澤田秀樹, 暗号理論と代数学, 海文堂出版, 1997.
[NC2] 量子コンピュータと量子通信II -量子コンピュータとアルゴリズム-
[L] A. K. Lenstra and H. W. Lenstra, Jr. The development of the number field sieve. Lecture Notes in Mathematics, vol.1554. Springer-Verlag, Berlin, 1993.
[QND] Quantum Native Dojo - 位相推定アルゴリズム(入門編)
[QT] Qiskit Textbook (beta) - Shor's Algorithm
-
文献 [NC2] の付録 E にも似たような内容がある。 ↩︎
-
今回小さい鍵で試行しているため、暗号化して復号できる文字の集合が小さい。よって、範囲に入るように適当にオフセット
をかましている。 ↩︎90 -
相当なインチキをするが、よくある 15 の素因数分解よりは何かやっている気持ちになれそうな気がする。 ↩︎
-
↩︎\begin{align*} \ket{u_s} := \frac{1}{\sqrt{r}} \sum_{k=0}^{r-1} \exp\left(- \frac{2 \pi i s k}{r}\right) \ket{a^k \mod N} \end{align*} -
上記の量子回路の左に
ゲートがいるのはそういうことである。 ↩︎X -
お手軽な実装にできるのが
だったので、9 を選んだのである。 ↩︎a=9
Discussion