下巻のp101~103の暗号化をPythonでやってみました。どれも、HELLOを暗号化します。
#1-1. 転置式の暗号化
<入力>
HELLO
s=input()
n=len(s)
l=[]
for i in range(n):
l.append(str(bin(ord(s[i])))[2:])
m="".join(l)
odd=m[::2]
even=m[1::2]
num=len(even)
for j in range(num):
print(even[j],end="")
print(odd[j],end="")
print(odd[-1])
<出力>
01100010001010011001100011000110111
まずはASCIIに変換。
これはord()でOK。UnicodeとASCIIはアルファベットは同じ数字なんですね。へえ。
2進数は扱いづらいので、
str()で文字列にすれば、それぞれの位の数字を取り出せる。
str(bin(ord(s[i])))[2:]で、頭の0bを取る。
どうやって1番目の数字と2番目の数字を交換しようかなと考えたけど、
AtCoderのA問題でありそうな処理にしてみました。
奇数番目と偶数番目に分けて、交互に出力していく。
oddの方が一文字多いので、最後にodd[-1]だけ出力。
入力が偶数個のアルファベットだとまた変えなきゃいけないけど、
とりあえず今回はこれで。
#1-2. 転置式の解読
今度は逆に、01100010001010011001100011000110111をHELLOに戻してみます。
<入力>
01100010001010011001100011000110111
s=input()
even=s[:-2:2]
odd=s[1::2]
l=[]
n=len(even)
for i in range(n):
l.append(odd[i])
l.append(even[i])
l.append(s[-1])
m="".join(l)
num=len(l)//7
for j in range(num):
print(chr(int(m[7*j:7*(j+1)],2)),end="")
基本的には暗号化の逆なので、まだ簡単でした。
2進数を10進数に戻すのに、int('二進数表記の数字', 2) でいいと知ったので、シンプルに記述できました。
Pythonで2進数、8進数、16進数の数値・文字列を相互に変換
#2-1. 換字式の暗号化
まず、DAVIDをASCIIコードに変換します。
10001001000001101011010010011000100
これが鍵になります。
暗号化のルールは、
・平文と鍵の各要素が同じならば、暗号文は0になる。
・平文と鍵の各要素が異なる場合は、暗号文は1になる。
排他的論理和(XOR)ですね。
<入力>
HELLO
DAVID
s=input()
key=input()
n=len(s)
#ASCII変換
l_s=[]
l_k=[]
for i in range(n):
l_s.append(str(bin(ord(s[i])))[2:])
l_k.append(str(bin(ord(key[i])))[2:])
a_s="".join(l_s)
a_k="".join(l_k)
num=len(a_s)
cipher=[]
for j in range(num):
if a_s[j]==a_k[j]:
cipher.append("0")
else:
cipher.append("1")
print(*cipher,sep="")
<出力>
00011000000100001101000001010001011
#2-2. 転置式の解読
今度は逆に、00011000000100001101000001010001011 を鍵DAVIDを使用して、HELLOに戻します。
暗号文と鍵の各要素が同じなら平文は0、違うなら1になります。暗号化の時と同じですね。
<入力>
00011000000100001101000001010001011
DAVID
s=input()
key=input()
n=len(key)
#keyをASCII変換
l_k=[]
for i in range(n):
l_k.append(str(bin(ord(key[i])))[2:])
k="".join(l_k)
num=len(s)
l_p=[]
for j in range(num):
if s[j]==k[j]:
l_p.append("0")
else:
l_p.append("1")
p="".join(l_p)
n_p=len(p)//7
for l in range(n_p):
print(chr(int(p[7*l:7*(l+1)],2)),end="")
<出力>
HELLO