📖

DES暗号とFeistel構造について

2023/07/16に公開

この記事について

DES暗号の仕組みについて,素人が学んだことをメモします.内容は世の中に溢れている記事と大差ないのですが,もしそれで理解できなかった場合にご参考にしてください.

記法と前提

平文をp, 共通鍵をk \in \mathcal{K}と表記します.
平文や鍵は\{0, 1\}のビット列で書かれているとします.

Feistel構造について

DES暗号はFeistel構造と呼ばれている構造をしています.この節ではFeistel構造について説明します.
Festel構造では,平文をrラウンド回暗号化します.i回目のラウンドではf_{K_i}という関数を用いているのですが,このf_{K_i}が非線形であっても良いということがFeistel構造の最大の特徴です.

と言ってもよく分からないので,具体的に見ていきましょう.Feistel構造は以下の図のような方式をとります.構造の話をしているので,抽象的な内容ですが,お付き合いください.

巡回鍵の生成

Feistel構造では,一つの鍵k \in \mathcal{K}からr個の巡回鍵(サブ鍵)\{K_1, \ldots, K_r\}を生成します.
暗号化には,共通鍵kが直接的に用いられるのではなく,巡回鍵が用いられます.

暗号化について

  1. はじめに平文を左右二つに分けます.これをL_0, R_0とおきます.
  2. 暗号化関数E_kを用いて,c = E_{k}(L_0, R_0)と暗号化します.ここで,暗号化関数の添え字kは共通鍵kを用いていることを意味しますが,実質的にはr個の巡回鍵\{k_1, \ldots, k_r\}を使用しています.

暗号化関数E_kについて詳しく説明しましょう.
E_krラウンドに分かれており,(L_0, R_0), (L_1, R_1), \ldots, (L_r, R_r)を段階的に生成したのち,(L_r, R_r)の左と右をひっくり返した(R_r, L_r)を出力するものです.

(L_{i-1}, R_{i-1})から(L_{i}, R_{i})の生成方法は画像の通りですが,このように書けます.

\begin{align*} L_i &\leftarrow R_{i-1} \\ R_i &\leftarrow L_{i-1} + f_{K_i}(R_{i-1}) \end{align*}

各ラウンドで重要になってくるのはf_{K_r}(R_{i-1})であり,ここを複雑なものにしてデータを撹拌します.復号化の処理を見てもらえれば明らかですが,このfは非線形でどんなに複雑なものであっても良く,その嬉しさは後述します.

復号化について

暗号化の処理を後ろから追っていくだけです.R_{i-1}の複号はシンプルです.暗号化において,R_{i-1}は次のラウンドでL_{i}に代入されているので,復号化では,R_{i-1}に既知のL_iを代入すれば終わりです.

次に,L_{i-1}の復号です.任意のビット列m \in \{0, 1\}^{n}に対して,m \oplus m = 0となることに注意してください.例えば,\{0, 1, 1, 0\} \oplus \{0, 1, 1, 0\} = \{0, 0, 0, 0\}です.そのため,L_{i-1}を以下のように復号することができます.

\begin{align*} R_i + f_{K_i}(R_{i-1})&= L_{i-1} + f_{K_i}(R_{i-1}) + f_{K_i}(R_{i-1})\\ &= L_{i-1} \end{align*}

fの非線形性について

fの非線形性の嬉しさをもう少し語ります.任意の暗号は復号可能である必要があり,それは暗号が単射であることを要求していました.そのため,任意のブロック暗号は置換となります.そのこと自体はFeistel構造の暗号も例外ではないのですが,fの部分に着目すると,復号時にf_{K_i}(R_{i-1})からR_{i-1}を求める必要はありません.つまり,単射である必要がないのです.よって,ここでなるべく複雑な処理を行えれば,安全な暗号になりそうだというのがFeistel構造の特徴となります.

DES暗号について

さて,DES暗号はFeistel構造をしています.DES暗号では,ラウンド数r=16です.また,平文空間と鍵空間は\{0, 1\}^{64}です.つまり,平文も鍵もビット列であり,その長さは64文字であるということです.

DES暗号がFeistel構造から拡張されている点

DES暗号は,上記で説明したFeistel構造と二点の違いがあります.Feistel構造の最初と最後に処理が加わっています.

  • 平文pを直接(L_0, R_0)に分割するのではなく,置換IPを通してから分割を行います.つまり,(L_0, R_0) = IP(p)となります.
  • E_kによって出力された(R_r, L_r)を暗号文cとするのではなく,置換IP^{-1}を通してから暗号文として出力しまう.つまりc = IP^{-1}((R_r, L_r))となります.

ここでの置換IPはDES暗号で共通のものであり,全世界に公開されています.

ここからは,巡回鍵の生成方法と暗号化関数E_kを具体的に見ていきましょう.

巡回鍵の生成方法

f_{K_i}で用いられるK_iは48ビットです.なので,DES暗号の巡回鍵生成アルゴリズムでは,64ビットの鍵kから48ビットの鍵K_iを16個生成することになります.

※画像はWikipediaから引用

  1. kから,縮小転置PC1によって28ビット×2のビット列(C_0, D_0) = PC1(k)を生成します.PC1でやっていることは,C_0用にkから28ビットを選び,同様にD_0用にkから28ビットを選んでいるという作業です.

  2. 1 \le i \le 16について,以下の処理を順番に繰り返し,K_{1}, \ldots, K_{16}を生成します.

    1. (C_i, D_i)(C_{i-1}, D_{i-1})から良い感じに計算します.具体的には,i=1, 2, 9, 16のときは左に1ビット,それ以外のときは左に2ビット巡回させます.
    2. 縮小転置PC2を用いて,K_{i} = PC2((C_i, D_i))として生成します.

PC2では,56ビットの(C_i, D_i)から48ビットを選んでいます.

PC1, PC2はDES暗号で共通のものであり,全世界に公開されています.

(私見)縮小転置を使っているので,仮にK_{i}がバレたとしても,そこからK_{i-1}とかを求めるのが意外とむずいのかな?

f_{K_i}(R_{i-1})について

一番大事なところの説明がめんどくさくなってきてしまいました…

復習をします.f_{K_i}(R_{i-1}): \{0, 1\}^{32} \to \{0, 1\}^{32}という関数は各ラウンドiで鍵K_iを用いて,R_{i-1}からR_iを生成する際に使う関数です.与えられた鍵K_iは48ビットです.このf_{K_i}(R_{i-1})の構造をこの節では説明します.


※画像はWikipediaから引用したものを一部改変

  1. まずは拡大置換Eを使ってR_{i-1} \in \{0, 1\}^{32}からE(R_{i-1}) \in \{0, 1\}^{48}を作ります.拡大置換は32文字から重複ありで48文字を選んで並べる処理です.
  2. B = E(R_{i-1}) \oplus K_iによって,鍵との和をとります.
  3. B = (B_1, B_2, \ldots, B_8)という風にBを6ビット×8に分割する.
  4. Sボックス1 \le l \le 8, S_{l}: \{0, 1\}^{6} \to \{0, 1\}^{4}によって,c_l = S_l(B_l)を生成する.
  5. 最後に置換P: \{0, 1\}^{32} \to \{0, 1\}^{32}によってf_{K_i}(R_{i-1}) = P((c_1, \ldots, c_8))を出力する

拡大置換E, Sボックス, 置換Pは全て一般に公開されています.

Sボックスについて

この説明は完全に力尽きてしまいました…書籍とかを適宜参照してください…

Sボックスは6ビットのものを4ビットに変換する関数です.Sボックスは文字数を減らしているため単射ではなく,非線形になっており,強度のために非常に重要だとされています.

その他

kは64文字なのですが,8, 16, 24, ..., 64文字目はパリティビットと呼ばれ,伝送エラーを検知するためのものです.

どういうことでしょうか?鍵kを8バイト×8つの行に分割したとき,各行のビット和は奇数になるように鍵が生成されます.これによって,鍵の伝送時に各行のうち1ビットが欠けていても復号が可能になります.

具体的に見てみましょう.
k = 10000110|...|...|...|...|...|...|00110111というように64ビットを8ビット×8に分割します.
ここで,例えば一つ目に注目すると10000110の各ビット列の和は3であり,確かに奇数であることが分かります.もし,伝送時にどこかのビットが欠けて10?00110となったとしても,和が奇数であるということから,不明な部分が埋められるということです(今回は?以外の和が3であるので,?が0だとわかる).

実際,巡回鍵の生成方法で用いられたPC1を見てみると,8, 16, 24, ..., 64は捨てられています.これらの文字は暗号鍵というよりもパリティビットであるためです.

参考文献

暗号理論入門
暗号技術のすべて
https://tomonori4565.hatenablog.com/entry/2018/12/10/210524
https://note.com/fikastudio/n/n8f9a073a48ef
https://atmarkit.itmedia.co.jp/ait/articles/1505/21/news030.html

Discussion