• 替换密码


    替代密码是指先建立一个替换表,加密时将需要加密的明文依次通过查表,替换为相应的字符,明文字符被逐个替换后,生成无任何意义的字符串,即密文,替代密码的密钥就是其替换表 。

    分为单表替换与多表替换,此处讨论单表替换

    加密解密实例:

     1 # Simple Substitution Cipher
     2 # http://inventwithpython.com/hacking (BSD Licensed)
     3 
     4 import pyperclip, sys, random
     5 
     6 
     7 LETTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
     8 
     9 def main():
    10     myMessage = 'If a man is offered a fact which goes against his instincts, he will scrutinize it closely, and unless the evidence is overwhelming, he will refuse to believe it. If, on the other hand, he is offered something which affords a reason for acting in accordance to his instincts, he will accept it even on the slightest evidence. The origin of myths is explained in this way. -Bertrand Russell'
    11     myKey = 'LFWOAYUISVKMNXPBDCRJTQEGHZ'
    12     myMode = 'encrypt' # set to 'encrypt' or 'decrypt'
    13 
    14     checkValidKey(myKey)
    15 
    16     if myMode == 'encrypt':
    17         translated = encryptMessage(myKey, myMessage)
    18     elif myMode == 'decrypt':
    19         translated = decryptMessage(myKey, myMessage)
    20     print('Using key %s' % (myKey))
    21     print('The %sed message is:' % (myMode))
    22     print(translated)
    23     pyperclip.copy(translated)
    24     print()
    25     print('This message has been copied to the clipboard.')
    26 
    27 
    28 def checkValidKey(key):
    29     keyList = list(key)
    30     lettersList = list(LETTERS)
    31     keyList.sort()
    32     lettersList.sort()
    33     if keyList != lettersList:
    34         sys.exit('There is an error in the key or symbol set.')
    35 
    36 
    37 def encryptMessage(key, message):
    38     return translateMessage(key, message, 'encrypt')
    39 
    40 
    41 def decryptMessage(key, message):
    42     return translateMessage(key, message, 'decrypt')
    43 
    44 
    45 def translateMessage(key, message, mode):
    46     translated = ''
    47     charsA = LETTERS
    48     charsB = key
    49     if mode == 'decrypt':
    50         # For decrypting, we can use the same code as encrypting. We
    51         # just need to swap where the key and LETTERS strings are used.
    52         charsA, charsB = charsB, charsA
    53 
    54     # loop through each symbol in the message
    55     for symbol in message:
    56         if symbol.upper() in charsA:
    57             # encrypt/decrypt the symbol
    58             symIndex = charsA.find(symbol.upper())
    59             if symbol.isupper():
    60                 translated += charsB[symIndex].upper()
    61             else:
    62                 translated += charsB[symIndex].lower()
    63         else:
    64             # symbol is not in LETTERS, just add it
    65             translated += symbol
    66 
    67     return translated
    68 
    69 
    70 def getRandomKey():
    71     key = list(LETTERS)
    72     random.shuffle(key)
    73     return ''.join(key)
    74 
    75 
    76 if __name__ == '__main__':
    77     main()
    simpleSubCipher

    破译方法:

    对于单表替换密文与原文字母的字母是 一 一 对应的,所以可以统计出每个每个单词的格式 如:name:0,1,2,3   apple:0,1,1,2,3。 此处称为单词模式

    从词典得到单词结构,再与密文单词相互对应,最终统计到每一个密文与原文的对应关系

    1. 找出密文里每个单词的单词模式
    2. 找出每个密词可以解密成哪些英文单词
    3. 使用密词的候选单词列表为每个密词创建一个密字映射。(密字映射是字典值)
    4. 计算所有的密字交集,得到唯一的交集映射
    5. 从交集密字映射移除任何已破解的字母

    消息越长越有可能被破译

     1 # Makes the wordPatterns.py File
     2 # http://inventwithpython.com/hacking (BSD Licensed)
     3 
     4 # Creates wordPatterns.py based on the words in our dictionary
     5 # text file, dictionary.txt. (Download this file from
     6 # http://invpy.com/dictionary.txt)
     7 
     8 import pprint
     9 
    10 
    11 def getWordPattern(word):
    12     # Returns a string of the pattern form of the given word.
    13     # e.g. '0.1.2.3.4.1.2.3.5.6' for 'DUSTBUSTER'
    14     word = word.upper()
    15     nextNum = 0
    16     letterNums = {}
    17     wordPattern = []
    18 
    19     for letter in word:
    20         if letter not in letterNums:
    21             letterNums[letter] = str(nextNum)
    22             nextNum += 1
    23         wordPattern.append(letterNums[letter])
    24     return '.'.join(wordPattern)
    25 
    26 
    27 def main():
    28     allPatterns = {}
    29 
    30     fo = open('dictionary.txt')
    31     wordList = fo.read().split('
    ')
    32     fo.close()
    33 
    34     for word in wordList:
    35         # Get the pattern for each string in wordList.
    36         pattern = getWordPattern(word)
    37 
    38         if pattern not in allPatterns:
    39             allPatterns[pattern] = [word]
    40         else:
    41             allPatterns[pattern].append(word)
    42 
    43     # This is code that writes code. The wordPatterns.py file contains
    44     # one very, very large assignment statement.
    45     fo = open('wordPatterns.py', 'w')
    46     fo.write('allPatterns = ')
    47     fo.write(pprint.pformat(allPatterns))
    48     fo.close()
    49 
    50 
    51 if __name__ == '__main__':
    52     main()
    makeWordPatterns

    然后导入之前的文件并破解

      1 # Simple Substitution Cipher Hacker
      2 # http://inventwithpython.com/hacking (BSD Licensed)
      3 
      4 import os, re, copy, pprint, pyperclip, simpleSubCipher, makeWordPatterns
      5 
      6 if not os.path.exists('wordPatterns.py'):
      7     makeWordPatterns.main() # create the wordPatterns.py file
      8 import wordPatterns
      9 
     10 LETTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
     11 nonLettersOrSpacePattern = re.compile('[^A-Zs]')
     12 
     13 def main():
     14     message = 'Sy l nlx sr pyyacao l ylwj eiswi upar lulsxrj isr sxrjsxwjr, ia esmm rwctjsxsza sj wmpramh, lxo txmarr jia aqsoaxwa sr pqaceiamnsxu, ia esmm caytra jp famsaqa sj. Sy, px jia pjiac ilxo, ia sr pyyacao rpnajisxu eiswi lyypcor l calrpx ypc lwjsxu sx lwwpcolxwa jp isr sxrjsxwjr, ia esmm lwwabj sj aqax px jia rmsuijarj aqsoaxwa. Jia pcsusx py nhjir sr agbmlsxao sx jisr elh. -Facjclxo Ctrramm'
     15 
     16     # Determine the possible valid ciphertext translations.
     17     print('Hacking...')
     18     letterMapping = hackSimpleSub(message)
     19 
     20     # Display the results to the user.
     21     print('Mapping:')
     22     pprint.pprint(letterMapping)
     23     print()
     24     print('Original ciphertext:')
     25     print(message)
     26     print()
     27     print('Copying hacked message to clipboard:')
     28     hackedMessage = decryptWithCipherletterMapping(message, letterMapping)
     29     pyperclip.copy(hackedMessage)
     30     print(hackedMessage)
     31 
     32 
     33 def getBlankCipherletterMapping():
     34     # Returns a dictionary value that is a blank cipherletter mapping.
     35     return {'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': []}
     36 
     37 
     38 def addLettersToMapping(letterMapping, cipherword, candidate):
     39     # The letterMapping parameter is a "cipherletter mapping" dictionary
     40     # value that the return value of this function starts as a copy of.
     41     # The cipherword parameter is a string value of the ciphertext word.
     42     # The candidate parameter is a possible English word that the
     43     # cipherword could decrypt to.
     44 
     45     # This function adds the letters of the candidate as potential
     46     # decryption letters for the cipherletters in the cipherletter
     47     # mapping.
     48 
     49     letterMapping = copy.deepcopy(letterMapping)
     50     for i in range(len(cipherword)):
     51         if candidate[i] not in letterMapping[cipherword[i]]:
     52             letterMapping[cipherword[i]].append(candidate[i])
     53     return letterMapping
     54 
     55 
     56 def intersectMappings(mapA, mapB):
     57     # To intersect two maps, create a blank map, and then add only the
     58     # potential decryption letters if they exist in BOTH maps.
     59     intersectedMapping = getBlankCipherletterMapping()
     60     for letter in LETTERS:
     61 
     62         # An empty list means "any letter is possible". In this case just
     63         # copy the other map entirely.
     64         if mapA[letter] == []:
     65             intersectedMapping[letter] = copy.deepcopy(mapB[letter])
     66         elif mapB[letter] == []:
     67             intersectedMapping[letter] = copy.deepcopy(mapA[letter])
     68         else:
     69             # If a letter in mapA[letter] exists in mapB[letter], add
     70             # that letter to intersectedMapping[letter].
     71             for mappedLetter in mapA[letter]:
     72                 if mappedLetter in mapB[letter]:
     73                     intersectedMapping[letter].append(mappedLetter)
     74 
     75     return intersectedMapping
     76 
     77 
     78 def removeSolvedLettersFromMapping(letterMapping):
     79     # Cipher letters in the mapping that map to only one letter are
     80     # "solved" and can be removed from the other letters.
     81     # For example, if 'A' maps to potential letters ['M', 'N'], and 'B'
     82     # maps to ['N'], then we know that 'B' must map to 'N', so we can
     83     # remove 'N' from the list of what 'A' could map to. So 'A' then maps
     84     # to ['M']. Note that now that 'A' maps to only one letter, we can
     85     # remove 'M' from the list of letters for every other
     86     # letter. (This is why there is a loop that keeps reducing the map.)
     87     letterMapping = copy.deepcopy(letterMapping)
     88     loopAgain = True
     89     while loopAgain:
     90         # First assume that we will not loop again:
     91         loopAgain = False
     92 
     93         # solvedLetters will be a list of uppercase letters that have one
     94         # and only one possible mapping in letterMapping
     95         solvedLetters = []
     96         for cipherletter in LETTERS:
     97             if len(letterMapping[cipherletter]) == 1:
     98                 solvedLetters.append(letterMapping[cipherletter][0])
     99 
    100         # If a letter is solved, than it cannot possibly be a potential
    101         # decryption letter for a different ciphertext letter, so we
    102         # should remove it from those other lists.
    103         for cipherletter in LETTERS:
    104             for s in solvedLetters:
    105                 if len(letterMapping[cipherletter]) != 1 and s in letterMapping[cipherletter]:
    106                     letterMapping[cipherletter].remove(s)
    107                     if len(letterMapping[cipherletter]) == 1:
    108                         # A new letter is now solved, so loop again.
    109                         loopAgain = True
    110     return letterMapping
    111 
    112 
    113 def hackSimpleSub(message):
    114     intersectedMap = getBlankCipherletterMapping()
    115     cipherwordList = nonLettersOrSpacePattern.sub('', message.upper()).split()
    116     for cipherword in cipherwordList:
    117         # Get a new cipherletter mapping for each ciphertext word.
    118         newMap = getBlankCipherletterMapping()
    119 
    120         wordPattern = makeWordPatterns.getWordPattern(cipherword)
    121         if wordPattern not in wordPatterns.allPatterns:
    122             continue # This word was not in our dictionary, so continue.
    123 
    124         # Add the letters of each candidate to the mapping.
    125         for candidate in wordPatterns.allPatterns[wordPattern]:
    126             newMap = addLettersToMapping(newMap, cipherword, candidate)
    127 
    128         # Intersect the new mapping with the existing intersected mapping.
    129         intersectedMap = intersectMappings(intersectedMap, newMap)
    130 
    131     # Remove any solved letters from the other lists.
    132     return removeSolvedLettersFromMapping(intersectedMap)
    133 
    134 
    135 def decryptWithCipherletterMapping(ciphertext, letterMapping):
    136     # Return a string of the ciphertext decrypted with the letter mapping,
    137     # with any ambiguous decrypted letters replaced with an _ underscore.
    138 
    139     # First create a simple sub key from the letterMapping mapping.
    140     key = ['x'] * len(LETTERS)
    141     for cipherletter in LETTERS:
    142         if len(letterMapping[cipherletter]) == 1:
    143             # If there's only one letter, add it to the key.
    144             keyIndex = LETTERS.find(letterMapping[cipherletter][0])
    145             key[keyIndex] = cipherletter
    146         else:
    147             ciphertext = ciphertext.replace(cipherletter.lower(), '_')
    148             ciphertext = ciphertext.replace(cipherletter.upper(), '_')
    149     key = ''.join(key)
    150 
    151     # With the key we've created, decrypt the ciphertext.
    152     return simpleSubCipher.decryptMessage(key, ciphertext)
    153 
    154 
    155 if __name__ == '__main__':
    156     main()
    simpleSubHacker

    此方法密钥为一张对应表,不易记,可用一句话作为密钥,用程序处理后再用于加密

     1 def makeSimpleSubKey(keyword):
     2     # create the key from the keyword
     3     newKey = ''
     4     keyword = keyword.upper()
     5     keyAlphabet = list(simpleSubCipher.LETTERS)
     6     for i in range(len(keyword)):
     7         if keyword[i] not in newKey:
     8             newKey += keyword[i]
     9             keyAlphabet.remove(keyword[i])
    10     key = newKey + ''.join(keyAlphabet)
    11     return key
    makeSimpleSubKey
     1 # Simple Substitution Dictionary Hacker, http://inventwithpython.com/hacking (BSD Licensed)
     2 import pyperclip, simpleSubKeyword, detectEnglish
     3 
     4 SILENT_MODE = False
     5 
     6 def main():
     7     myMessage = r"""SJITDOPIQR: JIR RIQMUNQRO AY P WDQC QCR NRSMRQN JT A SJITDORO QJ CRMNRGT AY S. -PHAMJNR ADRMSR"""
     8 
     9     brokenCiphertext = hackSimpleSubDictionary(myMessage)
    10 
    11     if brokenCiphertext == None:
    12         # hackSimpleSubDictionary() will return the None value if it was unable to hack the encryption.
    13         print('Hacking failed. Unable to hack this ciphertext.')
    14     else:
    15         # The plaintext is displayed on the screen. For the convenience of the user, we copy the text of the code to the clipboard.
    16         print('Copying broken ciphertext to clipboard:')
    17         print(brokenCiphertext)
    18         pyperclip.copy(brokenCiphertext)
    19 
    20 
    21 def hackSimpleSubDictionary(message):
    22     print('Hacking with %s possible dictionary words...' % (len(detectEnglish.ENGLISH_WORDS) * 3))
    23 
    24     # Python programs can be stopped at any time by pressing Ctrl-C (on Windows) or Ctrl-D (on Mac and Linux)
    25     print('(Press Ctrl-C or Ctrl-D to quit at any time.)')
    26 
    27     tryNum = 1
    28 
    29     # brute-force by looping through every possible key
    30     for key in detectEnglish.ENGLISH_WORDS:
    31         if tryNum % 100 == 0 and not SILENT_MODE:
    32             print('%s keys tried. (%s)' % (tryNum, key))
    33 
    34         decryptedText = simpleSubKeyword.decryptMessage(key, message)
    35 
    36         if detectEnglish.getEnglishCount(decryptedText) > 0.20:
    37             # Check with the user to see if the decrypted key has been found.
    38             print()
    39             print('Possible encryption hack:')
    40             print('Key: ' + str(key))
    41             print('Decrypted message: ' + decryptedText[:100])
    42             print()
    43             print('Enter D for done, or just press Enter to continue hacking:')
    44             response = input('> ')
    45 
    46             if response.upper().startswith('D'):
    47                 return decryptedText
    48 
    49         tryNum += 1
    50     return None
    51 
    52 if __name__ == '__main__':
    53     main()
    simpleSubDictionaryHacker
      1 # Simple Substitution Cipher Editor, http://inventwithpython.com/hacking (BSD Licensed)
      2 
      3 import textwrap, string, pyperclip
      4 
      5 myMessage = ''
      6 SYMBOLS = ''
      7 
      8 
      9 def main(useText=None, useMapping=None):
     10     print('Simple Substitution Cipher Editor')
     11 
     12     while True:
     13         # Get the text to start editing:
     14         if useText == None:
     15             # start editing a new cipher
     16             print('Enter the cipher text you want to decrypt (or "quit"):')
     17 
     18             # Handle if the user wants to quit:
     19             ciphertext = input('> ').upper()
     20             if ciphertext == 'QUIT':
     21                 return
     22         else:
     23             ciphertext = useText
     24 
     25         if useMapping == None:
     26             mapping = getBlankMapping() # start with a new, blank mapping.
     27         else:
     28             mapping = useMapping
     29 
     30 
     31         while True:
     32             # On each iteration of this loop, display the current translation
     33             # and let the user type in a command to perform.
     34 
     35             # Display the current translation:
     36             print('
    
    
    ')
     37             printMessage(ciphertext, mapping)
     38             printMapping(mapping)
     39             print('COMMANDS: Enter ciphertext letter to substitute, or "quit", "clear",')
     40             print('"copy message", "copy key", "enter key", or "new":')
     41 
     42             # Get a command from the user and perform it:
     43             command = input('> ').upper()
     44             if command == 'QUIT':
     45                 return
     46             elif command == 'CLEAR':
     47                 # reset the mapping to a new, blank mapping
     48                 mapping = getBlankMapping()
     49             elif command == 'NEW':
     50                 print('
    ' * 25) # print a huge gap
     51                 break # break out of the inner loop
     52             elif command == 'COPY MESSAGE':
     53                 pyperclip.copy(getTranslation(ciphertext, mapping))
     54                 print('Copied the translated text to the clipboard.')
     55             elif command == 'COPY KEY':
     56                 key = ''
     57                 for letter in string.ascii_uppercase:
     58                     key += mapping[letter]
     59                 pyperclip.copy(key)
     60                 print('Copied the key to the clipboard.')
     61             elif command == 'ENTER KEY':
     62                 pass # TODO
     63             else:
     64                 # Assume the user is trying to suggest a ciphertext replacement:
     65 
     66                 # get the ciphertext letter
     67                 if len(command) != 1 or command not in string.ascii_uppercase:
     68                     print('Invalid character. Please specify a single letter.')
     69                     continue
     70 
     71                 # get the letter that will replace this ciphertext letter
     72                 print('Enter letter that %s should map to:' % command)
     73                 mapToLetter = input('> ').upper()
     74                 if mapToLetter == '':
     75                     # entering nothing means the user wants to reset that ciphertext letter
     76                     mapToLetter = '_'
     77                 if len(mapToLetter) != 1 or mapToLetter not in string.ascii_uppercase + '_':
     78                     print('Invalid character. Please specify a single letter.')
     79                     continue
     80 
     81                 # add this replacement letter to the current mapping
     82                 mapping[command] = mapToLetter.lower()
     83 
     84 
     85 def getTranslation(ciphertext, mapping):
     86     # Returns a string of the translation of ciphertext. Each character
     87     # in ciphertext is used as a key in mapping, and the returned
     88     # string uses the character that is the value for that key.
     89     result = ''
     90     for letter in ciphertext:
     91         if letter not in string.ascii_uppercase:
     92             result += letter
     93         else:
     94             result += mapping[letter]
     95     return result
     96 
     97 
     98 def getBlankMapping():
     99     # Returns a dict with keys of the uppercase letters and values of
    100     # the string '_'.
    101     mapping = {}
    102     for letter in string.ascii_uppercase:
    103         mapping[letter] = '_'
    104     return mapping
    105 
    106 
    107 def printMessage(ciphertext, mapping):
    108     # Print the cipher text, along with the translation according to the
    109     # current mapping. The text will never go past 80 characters in length
    110     # per line.
    111 
    112     # Split up the cipher text into lines of at most 80 characters in length,
    113     # and then put them in a list of these lines.
    114     wrappedText = textwrap.fill(ciphertext)
    115     lines = wrappedText.split('
    ')
    116 
    117     for line in lines:
    118         # Print each line of ciphertext, followed by its translation.
    119         print(line)
    120         print(getTranslation(line, mapping))
    121         print()
    122 
    123 
    124 def printMapping(mapping):
    125     # Print the mapping in a user-friendly format.
    126     print('Current Key:')
    127     print('    ' + ' '.join(list(string.ascii_uppercase)))
    128 
    129     print('    ', end='')
    130     for letter in string.ascii_uppercase:
    131         print(mapping[letter] + ' ', end='')
    132     print()
    133 
    134 
    135 if __name__ == '__main__':
    136     main()
    simpleSubEditor
  • 相关阅读:
    运输层:广播和多播
    ICMP:internet控制报文协议 PING
    traceroute 命令
    网络层:IP网际协议 ifconfig -a
    IP层:IP选路
    动态选路协议
    链路层:ARP和RARP命令arp -a/tcpdump -en
    链路层协议以及常用命令介绍netstat
    TCP/IP笔记
    0-1背包问题——回溯法
  • 原文地址:https://www.cnblogs.com/zhangzixian/p/10483385.html
Copyright © 2020-2023  润新知