回顧昨天講到,對稱加密是指加密和解密使用同一組密鑰
對稱加密的技術主要分兩種
再繼續深入講串流加密之前,我們先從比較容易理解的一次性密碼本出發
一次性密碼本是我們介紹的所有加密演算法中,難得可以被證明是安全的
要使用一次性密碼本,我們得先將字母對應至數字(二進位表示),這個對應方式可以是公開透明的(例如使用ASCII),為了方便說明,假設我們能使用的字母只有八個,其對應方式如下
字母 | e | h | i | k | l | r | s | t |
---|---|---|---|---|---|---|---|---|
對應數字 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111 |
假如Alice今天想要加密這段文字heilhitler
(這是課本的例子,不是我自己想的)
查表後可將明文轉成 001 000 010 100 001 010 111 100 000 101
,我們將轉換成數字表示的明文用p來表示
letters = ['e', 'h', 'i', 'k', 'l', 'r', 's', 't']
binary = ['000', '001', '010', '011', '100', '101', '110', '111']
onetime = dict(zip(letters, binary))
onetime_reverse = dict(zip(binary, letters))
P = 'heilhitler'
def transform(P):
p = ''
for letter in P:
p += onetime[letter]
return p
p = transform(P)
使用一次性密碼本加密時,每次Alice都會隨機生成與p相同長度的二進位數作為密鑰
加設Alice隨機生成了一組密鑰K 111101110101111100000101110000
生成K後,將p與K XOR
(相加除以2取餘數)來進行加密
def XOR(a,b):
return (a+b) % 2
得到
K = '111101110101111100000101110000'
def cipher(p, K):
c = ''
for a, b in zip(p,K):
c += str(XOR(int(a),int(b)))
return c
c = cipher(p, K)
110101100001110110111001110101
轉換過的英文是
def untransform(p):
P = ''
for binary in [p[i:i+3] for i in range(0, len(p), 3)]:
P += onetime_reverse[binary]
return P
untransform(c)
srlhssthsr
將這段沒有意義的密文傳送給Bob後,
假設他也有同樣的密鑰K
他可以再將此密文與K做XOR
進行還原
(XOR
兩次等於沒有效果,奇數加偶數還是奇數;偶數加偶數還是偶數)
假設身處敵營的Trudy認為Alice用的密鑰是101111000101111100000101110000
那麼他會得到
untransform(cipher(c, '101111000101111100000101110000'))
得到killhitler
,完全相反的意思
又或者他使用密鑰111101000O11101110001011101101
untransform(cipher(c, '111101000011101110001011101101'))
得到helikesike
,也是完全相反的意思(ike是美國艾森豪總統的別名,是當時二戰的將軍)
由以上的例子可以看出,將密文搭配上錯的密鑰可以產生出任何組合
因為每次的密碼都不同,也不能透過多次攔截將密碼比對出來
可以證明,只要每次加密所使用的密鑰K是隨機生成,一次性密碼本是安全的
雖說一次性密碼本很安全,實務上卻面臨一些問題,我們明天再來說明