维吉尼亚密码(又译维热纳尔密码)是使用一系列凯撒密码组成密码字母表的加密算法,属于多表密码的一种简单形式。
在一个凯撒密码中,字母表中的每一字母都会作一定的偏移,例如偏移量为3时,A就转换为了D、B转换为了E……而维吉尼亚密码则是由一些偏移量不同的恺撒密码组成。
为了生成密码,需要使用表格法。这一表格(如图1所示)包括了26行字母表,每一行都由前一行向左偏移一位得到。具体使用哪一行字母表进行编译是基于密钥进行的,在过程中会不断地变换。
例如,假设明文为:ATTACKATDAWN
选择某一关键词并重复而得到密钥,如关键词为LEMON时,密钥为:LEMONLEMONLE
对于明文的第一个字母A,对应密钥的第一个字母L,于是使用表格中L行字母表进行加密,得到密文第一个字母L。类似地,明文第二个字母为T,在表格中使用对应的E行进行加密,得到密文第二个字母X。以此类推,可以得到:
明文:ATTACKATDAWN密钥:LEMONLEMONLE密文:LXFOPVEFRNHR
解密的过程则与加密相反。例如:根据密钥第一个字母L所对应的L行字母表,发现密文第一个字母L位于A列,因而明文第一个字母为A。密钥第二个字母E对应E行字母表,而密文第二个字母X位于此行T列,因而明文第二个字母为T。以此类推便可得到明文。
简而言之,使用一个单词作为密钥,将密钥不断重复并与明文逐一对齐,将明文的字符序加上密钥的字符序得到密文的字符序。每个明文字符用于加密的密钥不同。
1 # Vigenere Cipher (Polyalphabetic Substitution Cipher) 2 # http://inventwithpython.com/hacking (BSD Licensed) 3 4 import pyperclip 5 6 LETTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 7 8 def main(): 9 # This text can be copy/pasted from http://invpy.com/vigenereCipher.py 10 myMessage = """Alan Mathison Turing was a British mathematician, logician, cryptanalyst, and computer scientist. He was highly influential in the development of computer science, providing a formalisation of the concepts of "algorithm" and "computation" with the Turing machine. Turing is widely considered to be the father of computer science and artificial intelligence. During World War II, Turing worked for the Government Code and Cypher School (GCCS) at Bletchley Park, Britain's codebreaking centre. For a time he was head of Hut 8, the section responsible for German naval cryptanalysis. He devised a number of techniques for breaking German ciphers, including the method of the bombe, an electromechanical machine that could find settings for the Enigma machine. After the war he worked at the National Physical Laboratory, where he created one of the first designs for a stored-program computer, the ACE. In 1948 Turing joined Max Newman's Computing Laboratory at Manchester University, where he assisted in the development of the Manchester computers and became interested in mathematical biology. He wrote a paper on the chemical basis of morphogenesis, and predicted oscillating chemical reactions such as the Belousov-Zhabotinsky reaction, which were first observed in the 1960s. Turing's homosexuality resulted in a criminal prosecution in 1952, when homosexual acts were still illegal in the United Kingdom. He accepted treatment with female hormones (chemical castration) as an alternative to prison. Turing died in 1954, just over two weeks before his 42nd birthday, from cyanide poisoning. An inquest determined that his death was suicide; his mother and some others believed his death was accidental. On 10 September 2009, following an Internet campaign, British Prime Minister Gordon Brown made an official public apology on behalf of the British government for "the appalling way he was treated." As of May 2012 a private member's bill was before the House of Lords which would grant Turing a statutory pardon if enacted.""" 11 myKey = 'ASIMOV' 12 myMode = 'encrypt' # set to 'encrypt' or 'decrypt' 13 14 if myMode == 'encrypt': 15 translated = encryptMessage(myKey, myMessage) 16 elif myMode == 'decrypt': 17 translated = decryptMessage(myKey, myMessage) 18 19 print('%sed message:' % (myMode.title())) 20 print(translated) 21 pyperclip.copy(translated) 22 print() 23 print('The message has been copied to the clipboard.') 24 25 26 def encryptMessage(key, message): 27 return translateMessage(key, message, 'encrypt') 28 29 30 def decryptMessage(key, message): 31 return translateMessage(key, message, 'decrypt') 32 33 34 def translateMessage(key, message, mode): 35 translated = [] # stores the encrypted/decrypted message string 36 37 keyIndex = 0 38 key = key.upper() 39 40 for symbol in message: # loop through each character in message 41 num = LETTERS.find(symbol.upper()) 42 if num != -1: # -1 means symbol.upper() was not found in LETTERS 43 if mode == 'encrypt': 44 num += LETTERS.find(key[keyIndex]) # add if encrypting 45 elif mode == 'decrypt': 46 num -= LETTERS.find(key[keyIndex]) # subtract if decrypting 47 48 num %= len(LETTERS) # handle the potential wrap-around 49 50 # add the encrypted/decrypted symbol to the end of translated. 51 if symbol.isupper(): 52 translated.append(LETTERS[num]) 53 elif symbol.islower(): 54 translated.append(LETTERS[num].lower()) 55 56 keyIndex += 1 # move to the next letter in the key 57 if keyIndex == len(key): 58 keyIndex = 0 59 else: 60 # The symbol was not in LETTERS, so add it to translated as is. 61 translated.append(symbol) 62 63 return ''.join(translated) 64 65 66 # If vigenereCipher.py is run (instead of imported as a module) call 67 # the main() function. 68 if __name__ == '__main__': 69 main()