小亮學加密解密-----凱撒加密法
a | b | c | d | e | f | g | h | i | j | k | l | m | n | o | p | q | r | s | t | u | v | w | x | y | z |
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 |
1.加密原理
所謂的“凱撒加密法”,就是將需要加密的原文,逐個字元轉化成其他字元的之後,形成新的密文。
如上圖,第一行,是所有可以被轉換的字元(為方便顯示,只列舉了26個小寫英文字元),
第二行,為第一行每個字元對應的索引。
接著,從1~X(X為需要加密的字元的最大索引值)中,選取一個數字,作為金鑰。
當我們拿到需要加密的字串時,將字串中每個字元逐一去上圖中尋找,找到其對應的索引,
之後,將得到的索引與金鑰相加,得到的新索引對應的字元,就是轉換後的新字元;
如果索引與金鑰相加後大於索引的最大值,則需要從頭尋找對應的新字元。
舉個例子:
我們將“helloworld”通過“凱撒加密法”進行加密,金鑰為10,
我們從第一個字元“h”開始,在上圖中找到h的索引為7,
將h的索引與金鑰相加,得到17,從上圖找到索引為17的字元為r;
根據上面的步驟,我們將每個字元按照順序逐個進行轉化,最終得到密文:“rovvygybvn”
需要注意的是:
字元“w”的索引22,加上金鑰後得到32,大於了加密源字元個數26,於是會從0開始繼續尋找,
直到找到索引為6(32 - 26 = 6)的字元“g”
2.解密原理:
由於“凱撒加密法”只是將原文中的每個字元進行轉化得到密文;
所以在拿到密文後,只要根據金鑰,反推加密過程,即可得到加密前的原文;
舉個例子:
密文為“rovvygybvn”,金鑰為10,
我們先找到密文的第1個字元r的索引,17;
通過金鑰,反推加密過程,我們可以知道密文在加密前的原文字元索引為7 (17 - 10 = 7),
從上圖中可知,索引為7的字元為 h;
需要注意:
如果密文字元的索引小於金鑰時,
需要將密文字元的索引與加密源字元個數(上圖最大索引值為26)相加,在減去金鑰,得到原文字元索引,
例如:
在解密密文字元g時,由於g的索引為6,小於金鑰10,
為了找到原文字元,我們需要將g的索引與26(加密源字元個數)相加,
再與金鑰10相減,即(6 + 26) - 10 = 22,由上圖可知,對應原文字元為w
通過上述過程,我們將每個字元逐一解密,得到原文“helloworld”
具體程式碼實現如下(python實現):
#密文源字串
#encryptSource = r"abcdefghigklmnopqrstuvwxyzABCDEFGHIGKLMNPOQRSTUVWXYZ1234567890 ,.\"'!"
encryptSource = r"abcdefghigklmnopqrstuvwxyz"
#加密源字元個數
encryptSourceMaxIndex = len(encryptSource)
#金鑰
key = 10
#原文
#source = "Hello,World!"
source = "helloworld"
cryptograph = "rovvygybvn"
#加密方法
def encryptByCaesar(source):
#密文
newSource = ""
#迴圈原文中的每個字元,
#將每個字元在密文源字串中的索引加上金鑰,得到一個新的索引值
#如果新索引值大於密文源字元個數,則取新索引與密文源字元個數的差的絕對值
#根據新索引值,得到加密後的字元,並加入到密文字串的末尾
for index in range(len(source)):
#找到原文字元的索引
oldEncryptSourceIndex = encryptSource.find(source[index])
#計算轉換後字元的索引
newEncryptSourceIndex = (oldEncryptSourceIndex + key) if (oldEncryptSourceIndex + key) <= encryptSourceMaxIndex else abs((oldEncryptSourceIndex + key) - encryptSourceMaxIndex)
#找到新字元,並拼接密文
newSource += encryptSource[newEncryptSourceIndex]
return newSource
#解密方法
def unencryptByCaesar(cryptograph):
#儲存原文字串
sourceStr = "";
#迴圈密文中的每個字元,
#將每個字元在密文源字串中的索引減上金鑰,得到一個新的索引值
#如果密文索引值小於金鑰,則將密文索引與密文源最大索引值相加,再減去金鑰,得到原文字元索引
#根據新索引值,得到加密後的字元,並加入到密文字串的末尾
for index in range(len(cryptograph)):
#獲取密文字元的索引值
cryptographIndex = encryptSource.find(cryptograph[index])
#計算原文字元的索引值
SourceIndex = (cryptographIndex - key) if cryptographIndex >= key else (cryptographIndex + encryptSourceMaxIndex) - key
#得到原文字元,拼接原文字串
sourceStr += encryptSource[SourceIndex]
return sourceStr
print("source:" + source + ", new source:" + encryptByCaesar(source))
print("cryptograph:" + cryptograph + ", source:" + unencryptByCaesar(cryptograph))