1
2

More than 3 years have passed since last update.

『暗号解読』の暗号をPythonで作ってみる

Posted at

下巻の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

1
2
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2