栅栏加密 / 换位加密

字母种类数量相同,但顺序被打乱了

在简单的纵行换位密码中,明文以固定的宽度水平的写在一张图表纸上,密文按垂直方向读出,解密就是密文按相同的宽度垂直的写在图表纸上,然后水平的读出明文。

加密步骤:

  1. 数一下消息里的字符数
  2. 画一个行数等于密钥的格子
  3. 从左到右填充格子
  4. 当用完格子却还有字符时再画一行格子
  5. 从最上角开始向下读字符,到底后向右移一行
 1 # Transposition Cipher Encryption
 2 # http://inventwithpython.com/hacking (BSD Licensed)
 3 
 4 import pyperclip
 5 
 6 def main():
 7     myMessage = 'Common sense is not so common.'
 8     myKey = 8
 9 
10     ciphertext = encryptMessage(myKey, myMessage)
11 
12     # Print the encrypted string in ciphertext to the screen, with
13     # a | (called "pipe" character) after it in case there are spaces at
14     # the end of the encrypted message.
15     print(ciphertext + '|')
16 
17     # Copy the encrypted string in ciphertext to the clipboard.
18     pyperclip.copy(ciphertext)
19 
20 
21 def encryptMessage(key, message):
22     # Each string in ciphertext represents a column in the grid.
23     ciphertext = [''] * key
24 
25     # Loop through each column in ciphertext.
26     for col in range(key):
27         pointer = col
28 
29         # Keep looping until pointer goes past the length of the message.
30         while pointer < len(message):
31             # Place the character at pointer in message at the end of the
32             # current column in the ciphertext list.
33             ciphertext[col] += message[pointer]
34 
35             # move pointer over
36             pointer += key
37 
38     # Convert the ciphertext list into a single string value and return it.
39     return ''.join(ciphertext)
40 
41 
42 # If transpositionEncrypt.py is run (instead of imported as a module) call
43 # the main() function.
44 if __name__ == '__main__':
45     main()
transpositionEecrypt

解密步骤:

  1. 将消息长度除以密钥并向上取整得到列数
  2. 画出格子,行数与密钥一样
  3. 填入密文,从左上角开始,从左向右
  4. 从最左边一列开始,从上向下读
 1 # Transposition Cipher Decryption
 2 # http://inventwithpython.com/hacking (BSD Licensed)
 3 
 4 import math, pyperclip
 5 
 6 def main():
 7     myMessage = 'Cenoonommstmme oo snnio. s s c'
 8     myKey = 8
 9 
10     plaintext = decryptMessage(myKey, myMessage)
11 
12     # Print with a | (called "pipe" character) after it in case
13     # there are spaces at the end of the decrypted message.
14     print(plaintext + '|')
15 
16     pyperclip.copy(plaintext)
17 
18 
19 def decryptMessage(key, message):
20     # The transposition decrypt function will simulate the "columns" and
21     # "rows" of the grid that the plaintext is written on by using a list
22     # of strings. First, we need to calculate a few values.
23 
24     # The number of "columns" in our transposition grid:
25     numOfColumns = math.ceil(len(message) / key)
26     # The number of "rows" in our grid will need:
27     numOfRows = key
28     # The number of "shaded boxes" in the last "column" of the grid:
29     numOfShadedBoxes = (numOfColumns * numOfRows) - len(message)
30 
31     # Each string in plaintext represents a column in the grid.
32     plaintext = [''] * numOfColumns
33 
34     # The col and row variables point to where in the grid the next
35     # character in the encrypted message will go.
36     col = 0
37     row = 0
38 
39     for symbol in message:
40         plaintext[col] += symbol
41         col += 1 # point to next column
42 
43         # If there are no more columns OR we're at a shaded box, go back to
44         # the first column and the next row.
45         if (col == numOfColumns) or (col == numOfColumns - 1 and row >= numOfRows - numOfShadedBoxes):
46             col = 0
47             row += 1
48 
49     return ''.join(plaintext)
50 
51 
52 # If transpositionDecrypt.py is run (instead of imported as a module) call
53 # the main() function.
54 if __name__ == '__main__':
55     main()
transpositionDecrypt

测试程序

生成随机字符串加密再解密,二者比较

 1 # Transposition Cipher Test
 2 # http://inventwithpython.com/hacking (BSD Licensed)
 3 
 4 import random, sys, transpositionEncrypt, transpositionDecrypt
 5 
 6 def main():
 7     random.seed(42) # set the random "seed" to a static value
 8 
 9     for i in range(20): # run 20 tests
10         # Generate random messages to test.
11 
12         # The message will have a random length:
13         message = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' * random.randint(4, 40)
14 
15         # Convert the message string to a list to shuffle it.
16         message = list(message)
17         random.shuffle(message)
18         message = ''.join(message) # convert list to string
19 
20         print('Test #%s: "%s..."' % (i+1, message[:50]))
21 
22         # Check all possible keys for each message.
23         for key in range(1, len(message)):
24             encrypted = transpositionEncrypt.encryptMessage(key, message)
25             decrypted = transpositionDecrypt.decryptMessage(key, encrypted)
26 
27             # If the decryption doesn't match the original message, display
28             # an error message and quit.
29             if message != decrypted:
30                 print('Mismatch with key %s and message %s.' % (key, message))
31                 print(decrypted)
32                 sys.exit()
33 
34     print('Transposition cipher test passed.')
35 
36 
37 # If transpositionTest.py is run (instead of imported as a module) call
38 # the main() function.
39 if __name__ == '__main__':
40     main()
transpositionTest

加密文本文件:

 1 # Transposition Cipher Encrypt/Decrypt File
 2 # http://inventwithpython.com/hacking (BSD Licensed)
 3 
 4 import time, os, sys, transpositionEncrypt, transpositionDecrypt
 5 
 6 def main():
 7     inputFilename = 'frankenstein.txt'
 8     # BE CAREFUL! If a file with the outputFilename name already exists,
 9     # this program will overwrite that file.
10     outputFilename = 'frankenstein.encrypted.txt'
11     myKey = 10
12     myMode = 'encrypt' # set to 'encrypt' or 'decrypt'
13 
14     # If the input file does not exist, then the program terminates early.
15     if not os.path.exists(inputFilename):
16         print('The file %s does not exist. Quitting...' % (inputFilename))
17         sys.exit()
18 
19     # If the output file already exists, give the user a chance to quit.
20     if os.path.exists(outputFilename):
21         print('This will overwrite the file %s. (C)ontinue or (Q)uit?' % (outputFilename))
22         response = input('> ')
23         if not response.lower().startswith('c'):
24             sys.exit()
25 
26     # Read in the message from the input file
27     fileObj = open(inputFilename)
28     content = fileObj.read()
29     fileObj.close()
30 
31     print('%sing...' % (myMode.title()))
32 
33     # Measure how long the encryption/decryption takes.
34     startTime = time.time()
35     if myMode == 'encrypt':
36         translated = transpositionEncrypt.encryptMessage(myKey, content)
37     elif myMode == 'decrypt':
38         translated = transpositionDecrypt.decryptMessage(myKey, content)
39     totalTime = round(time.time() - startTime, 2)
40     print('%sion time: %s seconds' % (myMode.title(), totalTime))
41 
42     # Write out the translated message to the output file.
43     outputFileObj = open(outputFilename, 'w')
44     outputFileObj.write(translated)
45     outputFileObj.close()
46 
47     print('Done %sing %s (%s characters).' % (myMode, inputFilename, len(content)))
48     print('%sed file is %s.' % (myMode.title(), outputFilename))
49 
50 
51 # If transpositionCipherFile.py is run (instead of imported as a module)
52 # call the main() function.
53 if __name__ == '__main__':
54     main()
transpositionFileCipher

破解时仍是暴力破解,让计算机识别英文,方法是找一个字典,让程序将得到的字符串与字典内容比较,若一句话里的词在字典内出现的比率达到一定值计算机将其视为英语,让人判断

 1 # Detect English module
 2 # http://inventwithpython.com/hacking (BSD Licensed)
 3 
 4 # To use, type this code:
 5 #   import detectEnglish
 6 #   detectEnglish.isEnglish(someString) # returns True or False
 7 # (There must be a "dictionary.txt" file in this directory with all English
 8 # words in it, one word per line. You can download this from
 9 # http://invpy.com/dictionary.txt)
10 UPPERLETTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
11 LETTERS_AND_SPACE = UPPERLETTERS + UPPERLETTERS.lower() + ' 	
'
12 
13 def loadDictionary():
14     dictionaryFile = open('dictionary.txt')
15     englishWords = {}
16     for word in dictionaryFile.read().split('
'):
17         englishWords[word] = None
18     dictionaryFile.close()
19     return englishWords
20 
21 ENGLISH_WORDS = loadDictionary()
22 
23 
24 def getEnglishCount(message):
25     message = message.upper()
26     message = removeNonLetters(message)
27     possibleWords = message.split()
28 
29     if possibleWords == []:
30         return 0.0 # no words at all, so return 0.0
31 
32     matches = 0
33     for word in possibleWords:
34         if word in ENGLISH_WORDS:
35             matches += 1
36     return float(matches) / len(possibleWords)
37 
38 
39 def removeNonLetters(message):
40     lettersOnly = []
41     for symbol in message:
42         if symbol in LETTERS_AND_SPACE:
43             lettersOnly.append(symbol)
44     return ''.join(lettersOnly)
45 
46 
47 def isEnglish(message, wordPercentage=20, letterPercentage=85):
48     # By default, 20% of the words must exist in the dictionary file, and
49     # 85% of all the characters in the message must be letters or spaces
50     # (not punctuation or numbers).
51     wordsMatch = getEnglishCount(message) * 100 >= wordPercentage
52     numLetters = len(removeNonLetters(message))
53     messageLettersPercentage = float(numLetters) / len(message) * 100
54     lettersMatch = messageLettersPercentage >= letterPercentage
55     return wordsMatch and lettersMatch
detectEnglish

破解即为暴力破解:

 1 # Detect English module
 2 # http://inventwithpython.com/hacking (BSD Licensed)
 3 
 4 # To use, type this code:
 5 #   import detectEnglish
 6 #   detectEnglish.isEnglish(someString) # returns True or False
 7 # (There must be a "dictionary.txt" file in this directory with all English
 8 # words in it, one word per line. You can download this from
 9 # http://invpy.com/dictionary.txt)
10 UPPERLETTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
11 LETTERS_AND_SPACE = UPPERLETTERS + UPPERLETTERS.lower() + ' 	
'
12 
13 def loadDictionary():
14     dictionaryFile = open('dictionary.txt')
15     englishWords = {}
16     for word in dictionaryFile.read().split('
'):
17         englishWords[word] = None
18     dictionaryFile.close()
19     return englishWords
20 
21 ENGLISH_WORDS = loadDictionary()
22 
23 
24 def getEnglishCount(message):
25     message = message.upper()
26     message = removeNonLetters(message)
27     possibleWords = message.split()
28 
29     if possibleWords == []:
30         return 0.0 # no words at all, so return 0.0
31 
32     matches = 0
33     for word in possibleWords:
34         if word in ENGLISH_WORDS:
35             matches += 1
36     return float(matches) / len(possibleWords)
37 
38 
39 def removeNonLetters(message):
40     lettersOnly = []
41     for symbol in message:
42         if symbol in LETTERS_AND_SPACE:
43             lettersOnly.append(symbol)
44     return ''.join(lettersOnly)
45 
46 
47 def isEnglish(message, wordPercentage=20, letterPercentage=85):
48     # By default, 20% of the words must exist in the dictionary file, and
49     # 85% of all the characters in the message must be letters or spaces
50     # (not punctuation or numbers).
51     wordsMatch = getEnglishCount(message) * 100 >= wordPercentage
52     numLetters = len(removeNonLetters(message))
53     messageLettersPercentage = float(numLetters) / len(message) * 100
54     lettersMatch = messageLettersPercentage >= letterPercentage
55     return wordsMatch and lettersMatch
transpositionHacker

破解加密文本文件:

 1 # Transposition File Hacker
 2 # http://inventwithpython.com/hacking (BSD Licensed)
 3 
 4 import sys, time, os, sys, transpositionDecrypt, detectEnglish
 5 
 6 inputFilename = 'frankenstein.encrypted.txt'
 7 outputFilename = 'frankenstein.decrypted.txt'
 8 
 9 def main():
10     if not os.path.exists(inputFilename):
11         print('The file %s does not exist. Quitting.' % (inputFilename))
12         sys.exit()
13 
14     inputFile = open(inputFilename)
15     content = inputFile.read()
16     inputFile.close()
17 
18     brokenMessage = hackTransposition(content)
19 
20     if brokenMessage != None:
21         print('Writing decrypted text to %s.' % (outputFilename))
22 
23         outputFile = open(outputFilename, 'w')
24         outputFile.write(brokenMessage)
25         outputFile.close()
26     else:
27         print('Failed to hack encryption.')
28 
29 
30 # The hackTransposition() function's code was copy/pasted from
31 # transpositionHacker.py and had some modifications made.
32 def hackTransposition(message):
33     print('Hacking...')
34     # Python programs can be stopped at any time by pressing Ctrl-C (on
35     # Windows) or Ctrl-D (on Mac and Linux)
36     print('(Press Ctrl-C or Ctrl-D to quit at any time.)')
37 
38     for key in range(1, len(message)):
39         print('Trying key #%s... ' % (key), end='')
40         sys.stdout.flush()
41 
42         # We want to track the amount of time it takes to test a single key,
43         # so we record the time in startTime.
44         startTime = time.time()
45 
46         decryptedText = transpositionDecrypt.decryptMessage(key, message)
47         englishPercentage = round(detectEnglish.getEnglishCount(decryptedText) * 100, 2)
48 
49         totalTime = round(time.time() - startTime, 3)
50         print('Test time: %s seconds, ' % (totalTime), end='')
51         sys.stdout.flush() # flush printed text to the screen
52 
53         print('Percent English: %s%%' % (englishPercentage))
54         if englishPercentage > 20:
55             print()
56             print('Key ' + str(key) + ': ' + decryptedText[:100])
57             print()
58             print('Enter D for done, or just press Enter to continue:')
59             response = input('> ')
60             if response.strip().upper().startswith('D'):
61                 return decryptedText
62     return None
63 
64 
65 # If transpositionFileHacker.py is run (instead of imported as a module)
66 # call the main() function.
67 if __name__ == '__main__':
68     main()
transpositionFileHacker
原文地址:https://www.cnblogs.com/zhangzixian/p/10482668.html