現代の情報社会は暗号技術に支えられているといっても過言ではありません。にもかかわらず、我々はとくに暗号技術を意識することなくその恩恵に授かっています。しかも、暗号技術は古くは紀元前100年ほど前から存在していたという古参っぷりです。おまけに、現代暗号は高度な数学を駆使して高いセキュリティを確保しようとしており、果てはブロックチェーン技術にも派生していきます。
何だこの歴史の長さと守備範囲の広さは!!
ということで、暗号技術のエモさに気付いた私が、知識のメンテナンスやアップデートのためにPythonで暗号を実装し倒そうとしている話をします。
暗号技術の基本的な考え方
暗号は大きく鍵生成、暗号化、復号の3つの要素によって成立しています。
特に、暗号技術において鍵は非常に重要な要素をしめています。というより、暗号技術はこの鍵をいかに生成するかという技術だとも言えるかと思っています。何故なら、この鍵は暗号化でも復号でも使われるものであり、安全性に直結するものだからです。
鍵の扱い方によって、共通鍵暗号と公開鍵暗号の二種類に分類できます。
共通鍵暗号は、暗号化と復号の両方のプロセスで同じ鍵を利用するものです。暗号技術が誕生してしばらくはこちらが主流でしたが、鍵を第三者に知られずに当事者だけでやりとりしなければいけないため、鍵の管理にコストがかかるという欠点がありました。
公開鍵暗号は、共通鍵暗号の欠点を克服するために、秘密鍵と公開鍵という対応する2種類を生成して、公開鍵を文字通り公開してしまうことで、鍵の管理のコストを激減させることができるというものです。公開鍵暗号は公開鍵をオープンにして利用できるため、インターネットでの情報のやりとりと相性が良いためよく利用されます。公開鍵暗号の場合は、秘密鍵と公開鍵がまるで割印のように対応関係を持っていると同時に、公開鍵から秘密鍵が推測されてはならないという関係性も持っていなければいけません。そのため、巨大数の素因数分解や離散対数問題などといった数学が利用されています。
まずは古典暗号から
暗号技術は20世紀前半を境に様変わりしました。それまでは古典暗号と呼ばれており、暗号の解読は主に言語学者の仕事とされていました。アルファベットを何文字かずらしてみる、予め用意されている対応表を使ってみるなどといったようにあくまで文字をいじりながら暗号を作ったり、復号したりしていたからです。
しかし第2次世界大戦時に、ドイツ軍が開発したエニグマとイギリスの情報科学者であるチューリング率いる暗号解読チームの言わば暗号戦争が一つに契機となり、次第に暗号技術は数学者や情報学者の仕事となってきたのでした。
加えて、暗号技術は開発と解読のいたちごっこをひたすら繰り返しています。実際、エニグマを解読したイギリス軍は解読できた事実を20年ほど隠していました。これは、解読できたと公表してしまうと、さらに強力な暗号が開発される恐れがあるからです。
これはあくまで一つの見方ですが、このような背景があるため、暗号技術は古典暗号から現代暗号と学んでいくと比較的すんなり理解できるのではないかと思っています。暗号技術の発展の系譜をなぞるように学んでいくと、どのあたりが改良されたのかといった差分が理解できるため、非常にオススメです。
例えば、シーザー暗号
シーザー暗号は世界で一番古い暗号(?)だと言われています。名前の通り、紀元前1世紀ごろに活躍したユリウス・カエサルによって作られた暗号です。これは、アルファベット順に文字を並べた際に、3文字だけずらして文字を変換するというものです。暗号化部分をPythonで実装すると以下のようになります。文字をずらす部分はASCIIコードを利用しています。
def enc(text):
result = ""
for i in range(len(text)):
cha = text[i]
if(cha.isupper()):
result += chr((ord(cha) - 62) % 26 + 65)
else:
result += chr((ord(cha) - 94) % 26 + 97)
return print(result)
実際暗号化するとこんな感じ。
enc("Caesar")
#暗号文: Fdhvdu
復号する時は、暗号化の逆をしてあげればいいので、実装は以下の通りです。
def dec(text):
result = ""
for i in range(len(text)):
cha = text[i]
if(cha.isupper()):
result += chr((ord(cha) - 42) % 26 + 65)
else:
result += chr((ord(cha) - 74) % 26 + 97)
return print(result)
実行するとこんな感じ。
dec("Fdhvdu")
#解読文: Caesar
シフト暗号
シーザー暗号は3文字ずらすという3が鍵となっていました。例えば、スパイがいたとして、3文字ずらしているとバレてしまえばそれで一巻の終わりです。そこで、3の部分、つまり鍵の部分を変えてみる暗号も考案されました。それがシフト暗号と呼ばれるものです。
暗号化の部分は以下の通りです。今回は引数として、シフトする文字数を指定しています。鍵を生成するための関数を作ってもいいですが、入ってきた数値をそのまま返すだけのものになるので引数で指定することにしました。
def enc(plaintext, rot):
if(rot > 25):
rot = rot % 26
result = ""
for i in range(len(plaintext)):
cha = plaintext[i]
if(cha.isupper()):
result += chr((ord(cha) + rot - 65) % 26 + 65)
else:
result += chr((ord(cha) + rot - 97) % 26 + 97)
return print(result)
復号は暗号化の逆を行います。
def dec(encryptedtext, rot):
if(rot > 25):
rot = rot % 26
result = ""
for i in range(len(encryptedtext)):
cha = encryptedtext[i]
if(cha.isupper()):
result += chr((ord(cha) - rot - 39) % 26 + 65)
else:
result += chr((ord(cha) - rot - 71) % 26 + 97)
return print(result)
これから
知識のメンテナンスやアップデートも兼ねて、紀元前の古典暗号から現代の最先端な暗号までをPythonで実装し倒していこうと思っています。いざやってみると、暗号技術の歴史や先人たちの四苦八苦の跡が見えるようになってきて、案外楽しくなってきました。
とりあえずは、ブロックチェーン界隈でもよく登場するゼロ知識証明系や秘密分散までたどり着くことを当面の目標にしています。