ROT13とは?こんな場所でも使われてた!
ROT13はとても単純な暗号化アルゴリズムのひとつです。シーザー暗号(後述)の特殊系として知られています。有名な暗号なので、名前を聞いたことのある方も多いと思います。この記事ではこの暗号について詳しく解説していきます。
ROT13とは
ROT13は平文の各文字を13文字ずらすことで暗号化を行う暗号のことです。“Rotate by 13 places”の略が名前の由来になっています。なぜ13文字なのかというと、アルファベットがAからZまでの26文字あるから(その半分が13だから)です。
「13文字ずらす」とは”A”の次は”B”、その次は”C”というように13回次の文字に移動することを指しています。”Z”の次はまた”A”です。小文字も同様に変換し、スペースなどのアルファベット以外の文字はそのまま残します。
より一般的な手法としてシーザー暗号があります。シーザー暗号については以下にまとめてあります。ROT13をより深く理解する助けにもなると思うので読んでみてください。
真面目な暗号化目的では使われない
実際には真面目に暗号化するような場面ではなく、ネット上の書き込みで一部の文を伏せる場合などに利用されています。昔は背景色と同じ色の文字を書いたりしていましたが、それと同じような感じです。
あとは、求職者への初級のコーディングテストに使用しているという話も聞いたことがあります。ROT13自体の説明ができるか、プログラミング言語を使って実装ができるか、といったことが問われるようです。
例えば、”How razorback-jumping frogs can level six piqued gymnasts!”という文を暗号化する場合は”Ubj enmbeonpx-whzcvat sebtf pna yriry fvk cvdhrq tlzanfgf!“という文に暗号化されます。
Pythonでの実装例
Pythonでの実装例を以下に示します。組み込みの実装が用意されている(後述)ので自分で作成する必要はありませんが、理解を深めるために読んでみてください。
def shift(c, k):
if c.isupper():
return chr((ord(c) - ord('A') + k) % 26 + ord('A'))
elif c.islower():
return chr((ord(c) - ord('a') + k) % 26 + ord('a'))
else:
return c
def rot13(s):
return "".join([shift(c, 13) for c in s])
text = "How razorback-jumping frogs can level six piqued gymnasts!"
print(text)
enc = rot13(text)
print(enc)
print(rot13(enc))
愚直に実装すると、暗号化時には13文字後ろにずらして複合時には13文字前にずらすことになります。しかし、アルファベットが26文字であることから、複合も13文字後ろにずらすことで行うことができます。つまり、暗号化と複合が同じ実装ですむようになります。
codecs.encode(暗号化), codecs.decode(複合)を利用
PythonにはROT13の組み込み実装が存在します。codecsというモジュール内に用意されており、以下のようにして使用することができます。
import codecs
text = "How razorback-jumping frogs can level six piqued gymnasts!"
print(text)
enc = codecs.encode(text, "rot13")
print(enc)
print(codecs.decode(enc, "rot13"))
おまけ: PythonのthisにROT13が使われている
Pythonでthisをインポートするとどうなるか知っていますか?やったことのない方はimport this
と書いたコードを実行してみてください。すると、
The Zen of Python, by Tim Peters
Beautiful is better than ugly. …
という文章が長々と表示されます。これはZen of Pythonというもので、Pythonの設計における考え方が記述されています。
なぜこの話を持ち出したかというと、thisモジュールのコード内でROT13が使用されているからです(!?)
組み込みモジュールであるthis.pyの実装は以下のようになっています。
s = """Gur Mra bs Clguba, ol Gvz Crgref ...""" # 省略
d = {}
for c in (65, 97):
for i in range(26):
d[chr(i+c)] = chr((i+13) % 26 + c)
print("".join([d.get(c, c) for c in s]))
先頭には、Zen of PythonをROT13で暗号化した文字列が記述されています。そして、複合した文字列を出力することでこのモジュールの仕事は終わりです。暗号化することには全く意味がないのですが、ある種のジョークみたいなものですね。
Ermi
termina.ioの記事全般を書いています。東京大学 大学院 情理でコンピュータサイエンスを学びました。プログラミング言語など計算機科学全般に興味があります。キーボードやイヤホンなど、身の回りのものに強い拘りを持つ傾向があります。そして、沼にハマって帰らぬ人へと...。
最近の記事
Ermi
termina.ioの記事全般を書いています。東京大学 大学院 情理でコンピュータサイエンスを学びました。プログラミング言語など計算機科学全般に興味があります。キーボードやイヤホンなど、身の回りのものに強い拘りを持つ傾向があります。そして、沼にハマって帰らぬ人へと...。