RSA暗号
はじめにパラメータを決める。はそれぞれ十分に巨大な素数で、その積がとなる。 \begin{align} n = pq \end{align} 平文について、 \begin{align} m < n \end{align} となるようなを選択する(大きい場合は分割したりする)。また、 \begin{align} \mathrm{gcd}((p-1)(q-1),e) = 1 \end{align} となるを定義する。つまりとは互いに素である。 から値を計算する。この値は、 \begin{align} d \equiv e^{-1} \pmod{\ (p-1)(q-1)} \end{align} で計算される。ただしは法上でのの逆元を表している。
逆元とは?
これから群論を学ぶ方のための入門講座 – びりあるの研究ノート - 逆元より
例えば、を法としての逆元とは、であり、をで割ったあまりがになる数。つまり以下のように計算されて、 \begin{align} 2 \times 1 &= 2 \\ 2 \times 2 &= 4 \\ 2 \times 3 &= 6 \\ 2 \times 4 &= 8 \equiv 1 \bmod 7 \\ 2 \times 5 &= 10 \equiv 3 \bmod 7 \\ 2 \times 6 &= 12 \equiv 5 \bmod 7 \\ \end{align}
にを掛けてで割ったあまりがになるので、を法としたの逆元はである。
とが互いに素ではない場合、法上での逆元を計算することができない(つまり、の計算ができない)。
これらのパラメータのうち、を公開鍵、を秘密鍵とする。がわかってしまうとを計算することができてしまうため、 の生成後に破棄されるのが望ましい。
暗号化
平文を、暗号文をとした時、RSAの暗号化関数は以下のように定義される。
\begin{align} c = \mathrm{Enc}(m) = m^{e} \bmod n \end{align}
復号
逆に暗号文をとした時、以下のように定義されたRSAの復号関数により平文が求まる。
\begin{align} m = \mathrm{Dec}(c) = c^{d} \bmod n \end{align}
根拠
フェルマーの小定理は素数の性質についての定理である。
フェルマーの小定理
を素数とし、をの倍数でない整数(とは互いに素)とするときに、 \begin{align} a^{p-1} \equiv 1 \pmod{\ p} \end{align} すなわち、の乗をで割ったあまりはであるというもの。
フェルマーの小定理の一般化がオイラーの定理である。
オイラーの定理
が正の整数でをと互いに素な正の整数としたとき、 \begin{align} a^{\phi(n)} \equiv 1 \pmod{\ n} \end{align} が成立する。ここではオイラーの関数である。
オイラーの関数はまでの自然数のうちと互いに素なものの個数である。
オイラーの関数
オイラーの関数(トーシェント関数)は正の整数に対して、からまでの自然数のうちと互いに素なものの個数返す関数である。
を素数とすると、からのうちにの素因子であるを因子として含むものは存在しないから、が成り立つ。 また、を互いに素な自然数とすると、が成り立つ。
証明
復号関数がもとの値を必ず復元できるかを証明する。
は、と書ける。 つまり、 \begin{align} c^{}\equiv m^{ed} \pmod{\ n} \end{align} となる。ここで、はを法としてと合同、つまりはの逆元なので、ある定数が存在し、 \begin{align} ed = 1 + k(p-1)(q-1) \end{align} と表せる。また、オイラーの関数より、 \begin{align} (p-1)(q-1) = \phi(pq) = \phi(n) \end{align} が成り立つ。したがって、 \begin{align} ed = 1 + k\phi(n) \end{align} 先程の式に代入すると、 \begin{align} c^{d} &\equiv m^{1+k\phi(n)} \pmod{\ n} \\ &\equiv m^{1} \cdot m^{k\phi(n)} \pmod{\ n} \end{align} オイラーの定理より、であるので、 \begin{align} \equiv m \pmod{\ n} \end{align} であるので、 \begin{align} = m \end{align} したがって必ず復元できることが証明できた。
環境
$ uname -a Linux XPS-13-9360 4.13.0-16-generic #19-Ubuntu SMP Wed Oct 11 18:35:14 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux $ lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 17.10 Release: 17.10 Codename: artful
Pythonのインストール
この記事において使用するPythonは以下でインストールしたものとする
# # Python with pyenv # # Install dependencies $ sudo apt install -y make build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev\ libsqlite3-dev wget curl llvm libncurses5-dev libncursesw5-dev xz-utils tk-dev # Install pyenv-installer $ curl -L https://raw.githubusercontent.com/pyenv/pyenv-installer/master/bin/pyenv-installer | bash # Add to env $ cat <<\EOF >> $HOME/.env # Initial setting of pyenv. export PYENV_ROOT=$HOME/.pyenv export PATH=$PYENV_ROOT/bin:$PATH eval "$(pyenv init -)" # Initial setting of pyenv-virtualenv. eval "$(pyenv virtualenv-init -)" EOF # reload .env $ source $HOME/.env # Add .env to .bashrc $ echo "source $HOME/.env" >> $HOME/.bashrc # Install Python 3.6.3. $ pyenv install 3.6.3 # Set the system default to Python3.6.2. $ pyenv global 3.6.3
GMPY2のインストール
plain RSAに対する攻撃手法を実装してみる - ももいろテクノロジーより
Pythonは標準で多倍長整数を扱うことができるため、GNU Multi-Precision Library(GMP)のような多倍長整数ライブラリを持ちなくても大きな整数を扱うことができる。しかし、整数の範囲でのn乗根や拡張ユークリッドの互除法、における逆元演算を行うに当たっては、GMPが提供する関数を使うと簡単である。
PythonでGMPを使うにはGMPY2を使うといい。GMPY2にはGMPに加えMPFR(多倍長浮動小数点)やMPC(多倍長複素数)も使うことができる。
$ sudo apt install libgmp3-dev $ sudo apt install libmpfr-dev libmpfr-doc libmpfr6 $ sudo apt install libmpc-dev $ pip install gmpy2
ソースコード・実行例
から平文を求めるスクリプト