zoukankan      html  css  js  c++  java
  • Security and Cryptography in Python

    Security and Cryptography in Python - Frequency Analysis

    Frequency Analysis

    cipher = """lrvmnir bpr sumvbwvr jx bpr lmiwv yjeryrkbi jx qmbm wi
    bpr xjvni mkd ymibrut jx irhx wi bpr riirkvr jx
    ymbinlmtmipw utn qmumbr dj w ipmhh but bj rhnvwdmbr bpr
    yjeryrkbi jx bpr qmbm mvvjudwko bj yt wkbrusurbmbwjk
    lmird jk xjubt trmui jx ibndt
      wb wi kjb mk rmit bmiq bj rashmwk rmvp yjeryrkb mkd wbi
    iwokwxwvmkvr mkd ijyr ynib urymwk nkrashmwkrd bj ower m
    vjyshrbr rashmkmbwjk jkr cjnhd pmer bj lr fnmhwxwrd mkd
    wkiswurd bj invp mk rabrkb bpmb pr vjnhd urmvp bpr ibmbr
    jx rkhwopbrkrd ywkd vmsmlhr jx urvjokwgwko ijnkdhrii
    ijnkd mkd ipmsrhrii ipmsr w dj kjb drry ytirhx bpr xwkmh
    mnbpjuwbt lnb yt rasruwrkvr cwbp qmbm pmi hrxb kj djnlb
    bpmb bpr xjhhjcwko wi bpr sujsru msshwvmbwjk mkd
    wkbrusurbmbwjk w jxxru yt bprjuwri wk bpr pjsr bpmb bpr
    riirkvr jx jqwkmcmk qmumbr cwhh urymwk wkbmvb"""
    
    alphabet = "abcdefghijklmnopqrstuvwxyz"
    
    freq = {}
    for c in alphabet:
        freq[c] = 0
    
    letter_count = 0
    for c in cipher:
        if c in freq:
            freq[c] += 1
            letter_count += 1
    
    for c in freq:
        freq[c] = round(freq[c]/letter_count, 4)
    
    new_line_count = 0
    for c in freq:
        print(c, ':', freq[c], ' ', end='')
        if new_line_count % 3 == 2:
            print()
        new_line_count += 1
    
    
    
    
    
    

    Running Result:

    image-20210205201634154

    Refactor our code

    cipher = """lrvmnir bpr sumvbwvr jx bpr lmiwv yjeryrkbi jx qmbm wi
    bpr xjvni mkd ymibrut jx irhx wi bpr riirkvr jx
    ymbinlmtmipw utn qmumbr dj w ipmhh but bj rhnvwdmbr bpr
    yjeryrkbi jx bpr qmbm mvvjudwko bj yt wkbrusurbmbwjk
    lmird jk xjubt trmui jx ibndt
      wb wi kjb mk rmit bmiq bj rashmwk rmvp yjeryrkb mkd wbi
    iwokwxwvmkvr mkd ijyr ynib urymwk nkrashmwkrd bj ower m
    vjyshrbr rashmkmbwjk jkr cjnhd pmer bj lr fnmhwxwrd mkd
    wkiswurd bj invp mk rabrkb bpmb pr vjnhd urmvp bpr ibmbr
    jx rkhwopbrkrd ywkd vmsmlhr jx urvjokwgwko ijnkdhrii
    ijnkd mkd ipmsrhrii ipmsr w dj kjb drry ytirhx bpr xwkmh
    mnbpjuwbt lnb yt rasruwrkvr cwbp qmbm pmi hrxb kj djnlb
    bpmb bpr xjhhjcwko wi bpr sujsru msshwvmbwjk mkd
    wkbrusurbmbwjk w jxxru yt bprjuwri wk bpr pjsr bpmb bpr
    riirkvr jx jqwkmcmk qmumbr cwhh urymwk wkbmvb"""
    
    class Attack:
        def __init__(self):
            self.alphabet = "abcdefghijklmnopqrstuvwxyz"
            self.freq = {}
    
        def calculate_freq(self, cipher):
            for c in self.alphabet:
                self.freq[c] = 0
    
            letter_count = 0
            for c in cipher:
                if c in self.freq:
                    self.freq[c] += 1
                    letter_count += 1
    
            for c in self.freq:
                self.freq[c] = round(self.freq[c]/letter_count, 4)
    
        def print_freq(self):
            new_line_count = 0
            for c in self.freq:
                print(c, ':', self.freq[c], ' ', end='')
                if new_line_count % 3 == 2:
                    print()
                new_line_count += 1
    
    attack = Attack()
    attack.calculate_freq(cipher)
    attack.print_freq()
    

    Running Result:

    image-20210205202737483

    Making guesses(not lucky ones):

    import operator
    
    cipher = """lrvmnir bpr sumvbwvr jx bpr lmiwv yjeryrkbi jx qmbm wi
    bpr xjvni mkd ymibrut jx irhx wi bpr riirkvr jx
    ymbinlmtmipw utn qmumbr dj w ipmhh but bj rhnvwdmbr bpr
    yjeryrkbi jx bpr qmbm mvvjudwko bj yt wkbrusurbmbwjk
    lmird jk xjubt trmui jx ibndt
      wb wi kjb mk rmit bmiq bj rashmwk rmvp yjeryrkb mkd wbi
    iwokwxwvmkvr mkd ijyr ynib urymwk nkrashmwkrd bj ower m
    vjyshrbr rashmkmbwjk jkr cjnhd pmer bj lr fnmhwxwrd mkd
    wkiswurd bj invp mk rabrkb bpmb pr vjnhd urmvp bpr ibmbr
    jx rkhwopbrkrd ywkd vmsmlhr jx urvjokwgwko ijnkdhrii
    ijnkd mkd ipmsrhrii ipmsr w dj kjb drry ytirhx bpr xwkmh
    mnbpjuwbt lnb yt rasruwrkvr cwbp qmbm pmi hrxb kj djnlb
    bpmb bpr xjhhjcwko wi bpr sujsru msshwvmbwjk mkd
    wkbrusurbmbwjk w jxxru yt bprjuwri wk bpr pjsr bpmb bpr
    riirkvr jx jqwkmcmk qmumbr cwhh urymwk wkbmvb"""
    
    class Attack:
        def __init__(self):
            self.alphabet = "abcdefghijklmnopqrstuvwxyz"
            self.freq = {}
            self.freq_eng = {'a': 0.0817, 'b': 0.0150, 'c': 0.0278, 'd': 0.0425, 'e': 0.1270, 'f': 0.0223,
                   'g': 0.0202, 'h': 0.0609, 'i': 0.0697, 'j': 0.0015, 'k': 0.0077, 'l': 0.0403,
                   'm': 0.0241, 'n': 0.0675, 'o': 0.0751, 'p': 0.0193, 'q': 0.0010, 'r': 0.0599,
                   's': 0.0633, 't': 0.0906, 'u': 0.0276, 'v': 0.0098, 'w': 0.0236, 'x': 0.0015,
                   'y': 0.0197, 'z': 0.0007}
            self.mappings = {}
    
        def calculate_freq(self, cipher):
            for c in self.alphabet:
                self.freq[c] = 0
    
            letter_count = 0
            for c in cipher:
                if c in self.freq:
                    self.freq[c] += 1
                    letter_count += 1
    
            for c in self.freq:
                self.freq[c] = round(self.freq[c]/letter_count, 4)
    
        def print_freq(self):
            new_line_count = 0
            for c in self.freq:
                print(c, ':', self.freq[c], ' ', end='')
                if new_line_count % 3 == 2:
                    print()
                new_line_count += 1
    
        def calculate_matches(self):
            for cipher_char in self.alphabet:
                map = {}
                for plain_char in self.alphabet:
                    map[plain_char] = round(abs(self.freq[cipher_char] - self.freq_eng[plain_char]),4)
                self.mappings[cipher_char] = sorted(map.items(), key=operator.itemgetter(1))
    
    
    attack = Attack()
    attack.calculate_freq(cipher)
    attack.print_freq()
    attack.calculate_matches()
    
    print()
    for c in attack.mappings:
        print(c, attack.mappings[c])
    
    
    
    

    Running Result:

    image-20210205204801184

    Make a calculated guess of the key:

    import operator
    
    cipher = """lrvmnir bpr sumvbwvr jx bpr lmiwv yjeryrkbi jx qmbm wi
    bpr xjvni mkd ymibrut jx irhx wi bpr riirkvr jx
    ymbinlmtmipw utn qmumbr dj w ipmhh but bj rhnvwdmbr bpr
    yjeryrkbi jx bpr qmbm mvvjudwko bj yt wkbrusurbmbwjk
    lmird jk xjubt trmui jx ibndt
      wb wi kjb mk rmit bmiq bj rashmwk rmvp yjeryrkb mkd wbi
    iwokwxwvmkvr mkd ijyr ynib urymwk nkrashmwkrd bj ower m
    vjyshrbr rashmkmbwjk jkr cjnhd pmer bj lr fnmhwxwrd mkd
    wkiswurd bj invp mk rabrkb bpmb pr vjnhd urmvp bpr ibmbr
    jx rkhwopbrkrd ywkd vmsmlhr jx urvjokwgwko ijnkdhrii
    ijnkd mkd ipmsrhrii ipmsr w dj kjb drry ytirhx bpr xwkmh
    mnbpjuwbt lnb yt rasruwrkvr cwbp qmbm pmi hrxb kj djnlb
    bpmb bpr xjhhjcwko wi bpr sujsru msshwvmbwjk mkd
    wkbrusurbmbwjk w jxxru yt bprjuwri wk bpr pjsr bpmb bpr
    riirkvr jx jqwkmcmk qmumbr cwhh urymwk wkbmvb"""
    
    class Attack:
        def __init__(self):
            self.alphabet = "abcdefghijklmnopqrstuvwxyz"
            self.plain_chars_left = "abcdefghijklmnopqrstuvwxyz"
            self.cipher_chars_left = "abcdefghijklmnopqrstuvwxyz"
            self.freq = {}
            self.freq_eng = {'a': 0.0817, 'b': 0.0150, 'c': 0.0278, 'd': 0.0425, 'e': 0.1270, 'f': 0.0223,
                   'g': 0.0202, 'h': 0.0609, 'i': 0.0697, 'j': 0.0015, 'k': 0.0077, 'l': 0.0403,
                   'm': 0.0241, 'n': 0.0675, 'o': 0.0751, 'p': 0.0193, 'q': 0.0010, 'r': 0.0599,
                   's': 0.0633, 't': 0.0906, 'u': 0.0276, 'v': 0.0098, 'w': 0.0236, 'x': 0.0015,
                   'y': 0.0197, 'z': 0.0007}
            self.mappings = {}
    
        def calculate_freq(self, cipher):
            for c in self.alphabet:
                self.freq[c] = 0
    
            letter_count = 0
            for c in cipher:
                if c in self.freq:
                    self.freq[c] += 1
                    letter_count += 1
    
            for c in self.freq:
                self.freq[c] = round(self.freq[c]/letter_count, 4)
    
        def print_freq(self):
            new_line_count = 0
            for c in self.freq:
                print(c, ':', self.freq[c], ' ', end='')
                if new_line_count % 3 == 2:
                    print()
                new_line_count += 1
    
        def calculate_matches(self):
            for cipher_char in self.alphabet:
                map = {}
                for plain_char in self.alphabet:
                    map[plain_char] = round(abs(self.freq[cipher_char] - self.freq_eng[plain_char]),4)
                self.mappings[cipher_char] = sorted(map.items(), key=operator.itemgetter(1))
    
        def guess_key(self):
            key = {}
            for cipher_char in self.cipher_chars_left:
                for plain_char, diff in self.mappings[cipher_char]:
                    if plain_char in self.plain_chars_left:
                        key[cipher_char] = plain_char
                        self.plain_chars_left = self.plain_chars_left.replace(plain_char, '')
                        break
            return key
    
    def decrypt(key, cipher):
        message = ""
        for c in cipher:
            if c in key:
                message += key[c]
            else:
                message += c
        return message
    
    attack = Attack()
    attack.calculate_freq(cipher)
    attack.print_freq()
    attack.calculate_matches()
    key = attack.guess_key()
    print()
    print(key)
    message = decrypt(key, cipher)
    print(message)
    
    
    

    Running Result:

    image-20210205210359437

    Finalize the guess and read the encrypted text

    import operator
    import sys
    
    cipher = """lrvmnir bpr sumvbwvr jx bpr lmiwv yjeryrkbi jx qmbm wi
    bpr xjvni mkd ymibrut jx irhx wi bpr riirkvr jx
    ymbinlmtmipw utn qmumbr dj w ipmhh but bj rhnvwdmbr bpr
    yjeryrkbi jx bpr qmbm mvvjudwko bj yt wkbrusurbmbwjk
    lmird jk xjubt trmui jx ibndt
      wb wi kjb mk rmit bmiq bj rashmwk rmvp yjeryrkb mkd wbi
    iwokwxwvmkvr mkd ijyr ynib urymwk nkrashmwkrd bj ower m
    vjyshrbr rashmkmbwjk jkr cjnhd pmer bj lr fnmhwxwrd mkd
    wkiswurd bj invp mk rabrkb bpmb pr vjnhd urmvp bpr ibmbr
    jx rkhwopbrkrd ywkd vmsmlhr jx urvjokwgwko ijnkdhrii
    ijnkd mkd ipmsrhrii ipmsr w dj kjb drry ytirhx bpr xwkmh
    mnbpjuwbt lnb yt rasruwrkvr cwbp qmbm pmi hrxb kj djnlb
    bpmb bpr xjhhjcwko wi bpr sujsru msshwvmbwjk mkd
    wkbrusurbmbwjk w jxxru yt bprjuwri wk bpr pjsr bpmb bpr
    riirkvr jx jqwkmcmk qmumbr cwhh urymwk wkbmvb"""
    
    class Attack:
        def __init__(self):
            self.alphabet = "abcdefghijklmnopqrstuvwxyz"
            self.plain_chars_left = "abcdefghijklmnopqrstuvwxyz"
            self.cipher_chars_left = "abcdefghijklmnopqrstuvwxyz"
            self.freq = {}
            self.key = {}
            self.freq_eng = {'a': 0.0817, 'b': 0.0150, 'c': 0.0278, 'd': 0.0425, 'e': 0.1270, 'f': 0.0223,
                   'g': 0.0202, 'h': 0.0609, 'i': 0.0697, 'j': 0.0015, 'k': 0.0077, 'l': 0.0403,
                   'm': 0.0241, 'n': 0.0675, 'o': 0.0751, 'p': 0.0193, 'q': 0.0010, 'r': 0.0599,
                   's': 0.0633, 't': 0.0906, 'u': 0.0276, 'v': 0.0098, 'w': 0.0236, 'x': 0.0015,
                   'y': 0.0197, 'z': 0.0007}
            self.mappings = {}
    
        def calculate_freq(self, cipher):
            for c in self.alphabet:
                self.freq[c] = 0
    
            letter_count = 0
            for c in cipher:
                if c in self.freq:
                    self.freq[c] += 1
                    letter_count += 1
    
            for c in self.freq:
                self.freq[c] = round(self.freq[c]/letter_count, 4)
    
        def print_freq(self):
            new_line_count = 0
            for c in self.freq:
                print(c, ':', self.freq[c], ' ', end='')
                if new_line_count % 3 == 2:
                    print()
                new_line_count += 1
    
        def calculate_matches(self):
            for cipher_char in self.alphabet:
                map = {}
                for plain_char in self.alphabet:
                    map[plain_char] = round(abs(self.freq[cipher_char] - self.freq_eng[plain_char]),4)
                self.mappings[cipher_char] = sorted(map.items(), key=operator.itemgetter(1))
    
        def set_key_mapping(self, cipher_char, plain_char):
            if cipher_char not in self.cipher_chars_left or plain_char not in self.plain_chars_left:
                print("ERROR: key mapping error", cipher_char, plain_char)
                sys.exit(-1)
            self.key[cipher_char] = plain_char
            self.plain_chars_left = self.plain_chars_left.replace(plain_char, '')
            self.cipher_chars_left = self.cipher_chars_left.replace(cipher_char, '')
    
        def guess_key(self):
            for cipher_char in self.cipher_chars_left:
                for plain_char, diff in self.mappings[cipher_char]:
                    if plain_char in self.plain_chars_left:
                        self.key[cipher_char] = plain_char
                        self.plain_chars_left = self.plain_chars_left.replace(plain_char, '')
                        break
    
        def get_key(self):
            return self.key
    
    def decrypt(key, cipher):
        message = ""
        for c in cipher:
            if c in key:
                message += key[c]
            else:
                message += c
        return message
    
    attack = Attack()
    attack.calculate_freq(cipher)
    attack.print_freq()
    attack.calculate_matches()
    
    attack.set_key_mapping('r', 'e')
    attack.set_key_mapping('p', 'h')
    attack.set_key_mapping('v', 'c')
    attack.set_key_mapping('m', 'a')
    attack.set_key_mapping('w', 'i')
    attack.set_key_mapping('t', 'y')
    attack.set_key_mapping('q', 'k')
    attack.set_key_mapping('y', 'm')
    attack.set_key_mapping('e', 'v')
    attack.set_key_mapping('s', 'p')
    attack.set_key_mapping('u', 'r')
    attack.set_key_mapping('x', 'f')
    attack.set_key_mapping('d', 'd')
    attack.set_key_mapping('a', 'x')
    attack.set_key_mapping('c', 'w')
    attack.set_key_mapping('f', 'q')
    attack.set_key_mapping('g', 'z')
    attack.set_key_mapping('o', 'g')
    
    attack.guess_key()
    key = attack.get_key()
    print()
    print(key)
    message = decrypt(key, cipher)
    message_lines = message.splitlines()
    cipher_lines = cipher.splitlines()
    
    for i in range(len(message_lines)):
        print('P:', message_lines[i])
        print('C:', cipher_lines[i])
    
    
    

    Running Result:

    image-20210205221022050

    相信未来 - 该面对的绝不逃避,该执著的永不怨悔,该舍弃的不再留念,该珍惜的好好把握。
  • 相关阅读:
    习题解答chapter-01
    Java-chapter-01 菜鸟初见Java
    ijkdemo
    1027
    avformat_seek_file
    pla
    android1010横屏等
    文件浏览对话框
    智能指针处理---bo
    Js为Dom元素绑定事件须知
  • 原文地址:https://www.cnblogs.com/keepmoving1113/p/14379962.html
Copyright © 2011-2022 走看看