这篇文章上次修改于 192 天前,可能其部分内容已经发生变化,如有疑问可询问作者。

古典密码概论

一、密码学的发展阶段

1.古典密码学(1949年之前) 主要特点:数据的安全基于算法的保密
2.近代密码学(1949~1975年) 主要特点:数据的安全基于密钥而不是算法的保密,密码学从此开始成为一门科学
3.现代密码学(1976年以后) 密码学新方向一公钥密码学,主要特点:解决了密钥分发和管理的问题,密码学真正广泛在商业中应用

1.Affine(仿射加密)

单码加密法的另一种形式称为仿射加密法(affine cipher)。在仿射加密法中,字母表的字母被赋予一个数字,例如a=0,b=1,c=2…z=25。仿射加密法的密钥为0-25直接的数字对。

代码:

# 乘法逆元
def multiplicative_inverse(key_a, a_z=26):
    inv = 1
    while True:
        if (key_a * inv) % a_z == 1:
            break
        inv = inv + 1
    return inv


# 加密
def encipher(key_a, key_b, txt):
    result = ""
    if judge_a(key_a) == 0:
        result = "key_a必须是1, 3, 5, 7, 9, 11, 15, 17, 19, 21, 23, 25"
    else:
        if isinstance(key_b, int):
            for i in txt.lower():
                if i.isalpha():
                    temp = ((ord(i) - 97) * key_a + key_b) % 26 + 97
                    result = result + chr(temp)
                else:
                    result = result + i
        else:
            result = "key_b必须为整数"
    return result


# 解密
def decipher(key_a, key_b, cipher):
    result = ""

    if judge_a(key_a) == 0:
        result = "key_a必须是1, 3, 5, 7, 9, 11, 15, 17, 19, 21, 23, 25"
    else:
        if isinstance(key_b, int):
            a_inv = multiplicative_inverse(key_a)
            for i in cipher.lower():
                if i.isalpha():
                    temp = (((ord(i) - 97) - key_b) * a_inv) % 26 + 97
                    result = result + chr(temp)
                else:
                    result = result + i
        else:
            result = "key_b必须为整数"
    return result


def judge_a(key_a):
    range_a = (1, 3, 5, 7, 9, 11, 15, 17, 19, 21, 23, 25)
    if key_a in range_a:
        return key_a
    else:
        return 0


if __name__ == "__main__":
    a = 3
    b = -1
    text = 'hello word'
    print(encipher(a, b, text))
    print(decipher(a, b, 'ulggp npyi'))

2.Bacon(培根加密)

培根密码,又名倍康尼密码(英语:Bacon’s cipher)是由法兰西斯·培根发明的一种隐写术。
加密时,明文中的每个字母都会转换成一组五个英文字母。

'A': 'aaaaa', 'B': 'aaaab', 'C': 'aaaba', 'D': 'aaabb', 'E': 'aabaa', 'F': 'aabab',
'G': 'aabba',
'H': 'aabbb', 'I': 'abaaa', 'J': 'abaab', 'K': 'ababa', 'L': 'ababb', 'M': 'abbaa', 
'N': 'abbab',
'O': 'abbba', 'P': 'abbbb', 'Q': 'baaaa', 'R': 'baaab', 'S': 'baaba', 'T': 'baabb',
'U': 'babaa', 'V': 'babab', 'W': 'babba', 'X': 'babbb', 'Y': 'bbaaa', 'Z': 'bbaab'

培根密码实际上就是一种替换密码,根据所给表一一对应转换即可加密解密 。它的特殊之处在于:可以通过不明显的特征来隐藏密码信息,比如大小写、正斜体等,只要两个不同的属性,密码即可隐藏。
解密时,将上述方法倒转。所有字体一转回A,字体二转回B,以后再按上表拼回字母。

代码:

def encipher1(txt):
    bacon_dict1 = {'A': 'aaaaa', 'B': 'aaaab', 'C': 'aaaba', 'D': 'aaabb', 'E': 'aabaa', 'F': 'aabab', 'G': 'aabba',
                   'H': 'aabbb', 'I': 'abaaa', 'J': 'abaab', 'K': 'ababa', 'L': 'ababb', 'M': 'abbaa', 'N': 'abbab',
                   'O': 'abbba', 'P': 'abbbb', 'Q': 'baaaa', 'R': 'baaab', 'S': 'baaba', 'T': 'baabb',
                   'U': 'babaa', 'V': 'babab', 'W': 'babba', 'X': 'babbb', 'Y': 'bbaaa', 'Z': 'bbaab'}
    result = ""
    txt = txt.upper()
    for i in txt:
        try:
            result = result + bacon_dict1[i]
        except KeyError:
            result = result + i
    return result


def encipher2(txt):
    bacon_dict2 = {'a': 'AAAAA', 'b': 'AAAAB', 'c': 'AAABA', 'd': 'AAABB', 'e': 'AABAA', 'f': 'AABAB', 'g': 'AABBA',
                   'h': 'AABBB', 'i': 'ABAAA', 'j': 'ABAAA', 'k': 'ABAAB', 'l': 'ABABA', 'm': 'ABABB', 'n': 'ABBAA',
                   'o': 'ABBAB', 'p': 'ABBBA', 'q': 'ABBBB', 'r': 'BAAAA', 's': 'BAAAB', 't': 'BAABA',
                   'u': 'BAABB', 'v': 'BAABB', 'w': 'BABAA', 'x': 'BABAB', 'y': 'BABBA', 'z': 'BABBB'}
    result = ""
    txt = txt.lower()
    for i in txt:
        try:
            result = result + bacon_dict2[i]
        except KeyError:
            result = result + i
    return result


# 文本->bacon
def encipher(txt):
    results = [encipher1(txt), encipher2(txt)]
    return results


def decipher1(txt):
    bacon_dict1_txt = {'aaaaa': 'A', 'aaaab': 'B', 'aaaba': 'C', 'aaabb': 'D', 'aabaa': 'E', 'aabab': 'F', 'aabba': 'G',
                       'aabbb': 'H', 'abaaa': 'I', 'abaab': 'J', 'ababa': 'K', 'ababb': 'L', 'abbaa': 'M', 'abbab': 'N',
                       'abbba': 'O', 'abbbb': 'P', 'baaaa': 'Q', 'baaab': 'R', 'baaba': 'S', 'baabb': 'T',
                       'babaa': 'U', 'babab': 'V', 'babba': 'W', 'babbb': 'X', 'bbaaa': 'Y', 'bbaab': 'Z'}
    result = ""
    txt = txt.lower()
    for i in range(0, len(txt), 5):
        try:
            result = result + bacon_dict1_txt[txt[i:i + 5]]
        except KeyError:
            result = result + "?"
    return result


def decipher2(txt):
    bacon_dict2_txt = {'AAAAA': 'a', 'AAAAB': 'b', 'AAABA': 'c', 'AAABB': 'd', 'AABAA': 'e', 'AABAB': 'f', 'AABBA': 'g',
                       'AABBB': 'h', 'ABAAA': '(i/j)', 'ABAAB': 'k', 'ABABA': 'l', 'ABABB': 'm', 'ABBAA': 'n',
                       'ABBAB': 'o', 'ABBBA': 'p', 'ABBBB': 'q', 'BAAAA': 'r', 'BAAAB': 's', 'BAABA': 't',
                       'BAABB': '(u/v)', 'BABAA': 'w', 'BABAB': 'x', 'BABBA': 'y', 'BABBB': 'z'}
    result = ""
    txt = txt.upper()
    for i in range(0, len(txt), 5):
        try:
            result = result + bacon_dict2_txt[txt[i:i + 5]]
        except KeyError:
            result = result + '?'
    return result


# bacon->文本
def decipher(txt):
    results = [decipher1(txt), decipher2(txt)]
    return results


if __name__ == '__main__':
    print(encipher("sfauh"))
    print(decipher("abbaabbaaa"))

3.Brainfuck

是一种极小化的计算机语言,它是由Urban Müller在1993年创建的。由于fuck在英语中是脏话,这种语言有时被称为brainfck或brainf* k,甚至被简称为BF.
这种语言,是一种按照“Turing complete(图灵完备)”思想设计的语言,它的主要设计思路是:用最小的概念实现一种“简单”的语言,BrainF**k 语言只有八种符号,所有的操作都由这八种符号的组合来完成。

代码:

def brain_fuck(code):
    data = [0 for i in range(1000)]
    pc = 0
    ptr = 0
    skip_loop = False
    bracket_count = 0
    stack = []
    result = ''
    while pc < len(code):
        c = code[pc]
        if skip_loop:
            if c == '[':
                bracket_count += 1
            elif c == ']':
                bracket_count -= 1
                if bracket_count == 0:
                    skip_loop = False
            pc += 1
            continue
        if c == '>':
            ptr += 1
            pc += 1
        elif c == '<':
            ptr -= 1
            pc += 1
        elif c == '+':
            data[ptr] += 1
            pc += 1
        elif c == '-':
            data[ptr] -= 1
            pc += 1
        elif c == '.':
            result = result + chr(data[ptr])
            pc += 1
        elif c == ',':
            pc += 1
        elif c == '[':
            if data[ptr] == 0:
                # nonlocal bracket_count,skip_loop
                bracket_count = 1
                skip_loop = True
                pc += 1
            else:
                pc += 1
                stack.append(pc)
        elif c == ']':
            if data[ptr] == 0:
                pc += 1
                stack.pop()
            else:
                pc = stack[len(stack) - 1]
    return result


if __name__ == '__main__':
    print(brain_fuck('++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.'))

4.Caesar(凯撒加密)

凯撒加密是古罗马恺撒大帝用来保护重要军情的加密系统。

“恺撒密码”它是一种替代密码,通过将字母按顺序推后3位起到加密作用,如将字母A换作字母D,将字母B换作字母E。据说恺撒是率先使用加密函的古代将领之一,因此这种加密方法被称为恺撒密码。

代码:

# 判断密钥
def judge_key(k):
    if 0 < k < 27 and isinstance(k, int):
        return k
    else:
        return 0


def encipher(txt, k):
    result = ""
    if judge_key(k) == 0:
        result = "密钥应为[1,26]的整数"
    else:
        result = result + str(k) + ':'

        for i in txt:
            if i.isupper():
                result = result + chr(65 + (ord(i) - 65 + k) % 26)
            elif i.islower():
                result = result + chr(97 + (ord(i) - 97 + k) % 26)
            else:
                result = result + i
    return result


# 返回所有偏移结果
def all_result(txt):
    res = []
    for n in range(1, 27):
        res.append(encipher(txt, n))
    return res


def rot13(txt):
    res = "rot" + encipher(txt, 13)
    return res


if __name__ == '__main__':
    text=input("Please input the words : ")
    results = all_result(text)
    print(results)

5.Fence(栅栏加密)

所谓栅栏密码,就是把要加密的明文分成N个一组,然后把每组的第1个字连起来,形成一段无规律的话。 不过栅栏密码本身有一个潜规则,就是组成栅栏的字母一般不会太多。(一般不超过30个,也就是一、两句话)

代码:

# 栅栏范围
def get_field(txt):
    field = []
    for i in range(2, len(txt)):
        if len(txt) % i == 0:
            field.append(i)
    return field


def encipher(txt, k):
    field = get_field(txt)
    txt_length = len(txt)
    if k in field:
        result = '' + str(k) + '栏:'
        for m in range(k):
            for n in range(m, txt_length, k):
                result = result + txt[n]
    else:
        result = '密钥有误,应在范围'+str(field)
    return result


# 输出所有可能的结果
def all_result(txt):
    results = []
    for k in get_field(txt):
        results.append(encipher(txt, k))
    return results


if __name__ == '__main__':
    text = 'Helloworld'
    print(encipher(text, 2))
    print(all_result(text))

6.Fenham(费纳姆加密)

费纳姆密码其实是一种由二进制产生的替换密码。

是双方约定一个数,明文加上这个数就是密文。这个数相当于密钥(可以是单词 词组 句子 几个字母也行)。

'A': '1000001', 'B': '1000010', 'C': '1000011', 'D': '1000100', 'E': '1000101', 'F': '1000110',
'G': '1000111', 'H': '1001000', 'I': '1001001', 'J': '1001010', 'K': '1001011', 'L': '1001100',
'M': '1001101', 'N': '1001110', 'O': '1001111', 'P': '1010000', 'Q': '1010001', 'R': '1010010',
'S': '1010011', 'T': '1010100', 'U': '1010101', 'V': '1010110', 'W': '1010111', 'X': '1011000',
'Y': '1011001', 'Z': '1011010'

例如:
明文: hello=1001000 1000101 1001100 1001100 1001111
密钥:crude=1000011 1010010 1010101 1000100 1000101
异或得到密文=0001011 0010111 0011001 0001000 0001010

代码:

char_num = {'A': '1000001', 'B': '1000010', 'C': '1000011', 'D': '1000100', 'E': '1000101', 'F': '1000110',
            'G': '1000111', 'H': '1001000', 'I': '1001001', 'J': '1001010', 'K': '1001011', 'L': '1001100',
            'M': '1001101', 'N': '1001110', 'O': '1001111', 'P': '1010000', 'Q': '1010001', 'R': '1010010',
            'S': '1010011', 'T': '1010100', 'U': '1010101', 'V': '1010110', 'W': '1010111', 'X': '1011000',
            'Y': '1011001', 'Z': '1011010'}

num_char = {'1000001': 'A', '1000010': 'B', '1000011': 'C', '1000100': 'D', '1000101': 'E', '1000110': 'F',
            '1000111': 'G', '1001000': 'H', '1001001': 'I', '1001010': 'J', '1001011': 'K', '1001100': 'L',
            '1001101': 'M', '1001110': 'N', '1001111': 'O', '1010000': 'P', '1010001': 'Q', '1010010': 'R',
            '1010011': 'S', '1010100': 'T', '1010101': 'U', '1010110': 'V', '1010111': 'W', '1011000': 'X',
            '1011001': 'Y', '1011010': 'Z'}


# 转换
def txt_num(txt):
    txt = txt.upper()
    result = ""
    for i in txt:
        result = result + char_num[i]
    return result


# 最终数字转换为字母
def num_list(txt):
    num = 0
    s = []
    while True:
        s.append(txt[num:num + 7])
        num += 7
        if num > len(txt) - 7:
            break
    return s


# 加密 文本内容
def encipher(txt, k):
    result = ''
    if txt.isalpha() and k.isalpha():
        txt = txt_num(txt)
        k = txt_num(k)
        j = len(k)
        for i in range(0, len(txt)):
            if txt[i] == k[i % j]:
                result += '0'
            else:
                result += '1'
    else:
        result = "明文与密钥应为纯字母"
    return result


# 解密 文本为数字格式
def decipher(txt, k):
    result = ''
    if k.isalpha():
        k = txt_num(k)
        j = len(k)
        for i in range(0, len(txt)):
            if txt[i] == k[i % j]:
                result += '0'
            else:
                result += '1'
        result = num_list(result)
        result_char = ""
        for i in result:
            try:
                result_char = result_char + num_char[i]
            except KeyError:
                result_char = result_char + '?'
        result = result_char
    else:
        result = "密钥应为纯字母"
    return result


if __name__ == '__main__':
    # 加解密
    text = '00010110010111001100100010000001010'
    # 读文本文件
    key = "crude"
    text_2 = "hello"
    print(encipher(text_2, key))
    print(decipher(text, key))

7.Morse(摩斯密码)

摩尔斯电码是一种时通时断的信号代码,通过不同的排列顺序来表达不同的英文字母、数字和标点符号,是由美国人萨缪尔·摩尔斯在1836年发明。
每一个字符(字母或数字)对应不同的序列(由点和划组成)。
一般来说,任何一种能把书面字符用可变长度的信号表示的编码方式都可以称为摩尔斯电码。

2024-03-11T09:54:24.png

'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': '----.',

'.': '.-.-.-', ':': '---...', ',': '--..--', ';': '-.-.-.', '?': '..--..',
'=': '-...-', "'": '.----.', '/': '-..-.', '!': '-.-.--', '-': '-....-',
'_': '..--.-', '"': '.-..-.', '(': '-.--.', ')': '-.--.-', '$': '...-..-',
'@': '.--.-.', '+': '.-.-.'

代码:

# "01"—>".-"
def translate_string(txt):
    table = ''.maketrans('01', '.-')
    txt = txt.translate(table)
    return txt


# 文本->摩斯密码
def encipher(txt):
    result = ""
    morse_dict = {
        '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': '----.',

        '.': '.-.-.-', ':': '---...', ',': '--..--', ';': '-.-.-.', '?': '..--..',
        '=': '-...-', "'": '.----.', '/': '-..-.', '!': '-.-.--', '-': '-....-',
        '_': '..--.-', '"': '.-..-.', '(': '-.--.', ')': '-.--.-', '$': '...-..-',
        '@': '.--.-.', '+': '.-.-.'
    }
    txt = txt.upper()
    for i in txt:
        try:
            result = result + morse_dict[i] + '/'
        except KeyError:
            result = result + i + '/'
    return result.strip('/')


# 摩斯密码—>文本
def decipher(txt, sign=" "):
    result = ""
    morse_dict = {
        ".-": "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",

        ".-.-.-": ".", "---...": ":", "--..--": ",", "-.-.-.": ";", "..--..": "?",
        "-...-": "=", ".----.": "'", "-..-.": "/", "-.-.--": "!", "-....-": "-",
        "..--.-": "_", ".-..-.": '"', "-.--.": "(", "-.--.-": ")", "...-..-": "$",
        ".--.-.": "@", ".-.-.": "+",
    }

    # "0/1"->"./-"
    if '0' or '1' in txt:
        txt = translate_string(txt)

    # sign('/' or ' ')
    if '/' in txt:
        sign = '/'

    # 分割,字符串string,分割标识符sign
    lists = txt.split(sign)
    for code in lists:
        try:
            result = result + morse_dict[code]
        except KeyError:
            result = result + "?"
    return result


if __name__ == "__main__":
    print(encipher("Hello world"))
    print(decipher('...././.-../.-../---/ /.--/---/.-./.-../-..'))

8.Pigen(猪圈加密)

猪圈密码(亦称朱高密码、共济会暗号、共济会密码或共济会员密码),是一种以格子为基础的简单替代式密码。即使使用符号,也不会影响密码分析,亦可用在其它替代式的方法。

2024-03-11T09:54:44.png

代码:

def encipher(txt):
    pigpen_dict = {'a': 'j', 'b': 'k', 'c': 'l', 'd': 'm', 'e': 'n', 'f': 'o', 'g': 'p', 'h': 'q', 'i': 'r',
                   'j': 'a', 'k': 'b', 'l': 'c', 'm': 'd', 'n': 'e', 'o': 'f', 'p': 'g', 'q': 'h', 'r': 'i',
                   's': 'w', 't': 'x', 'u': 'y', 'v': 'z', 'w': 's', 'x': 't', 'y': 'u', 'z': 'v'}
    result = ""
    txt = txt.lower()
    for i in txt:
        try:
            result = result + pigpen_dict[i]
        except KeyError:
            result = result + i
    return result


if __name__ == '__main__':
    x = encipher("hello world")
    print(x)

2024-03-11T09:54:58.png

9.Vigenere(维吉尼亚加密)

维吉尼亚密码(又译维热纳尔密码)是使用一系列凯撒密码组成密码字母表的加密算法,属于多表密码的一种简单形式。
在一个凯撒密码中,字母表中的每一字母都会作一定的偏移,例如偏移量为3时,A就转换为了D、B转换为了E……而维吉尼亚密码则是由一些偏移量不同的恺撒密码组成。
为了生成密码,需要使用表格法。这一表格(如图1所示)包括了26行字母表,每一行都由前一行向左偏移一位得到。具体使用哪一行字母表进行编译是基于密钥进行的,在过程中会不断地变换。

2024-03-11T09:55:10.png

例如,假设明文为:
ATTACKATDAWN
选择某一关键词并重复而得到密钥,如关键词为LEMON时,密钥为:
LEMONLEMONLE
对于明文的第一个字母A,对应密钥的第一个字母L,于是使用表格中L行字母表进行加密,得到密文第一个字母L。类似地,明文第二个字母为T,在表格中使用对应的E行进行加密,得到密文第二个字母X。以此类推,可以得到:
明文:ATTACKATDAWN
密钥:LEMONLEMONLE
密文:LXFOPVEFRNHR

代码:

letter_list = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'  # 字母表


# 根据输入的key生成key列表
def get_key_list(k):
    k_list = []
    for ch in k:
        k_list.append(ord(ch.upper()) - 65)
    return k_list


# 加密
def encipher(txt, k):
    result = ""
    k_list = get_key_list(k)
    i = 0
    for ch in txt:  # 遍历明文
        if 0 == i % len(k_list):
            i = 0
        if ch.isalpha():  # 明文是否为字母,如果是,则判断大小写,分别进行加密
            if ch.isupper():
                result += letter_list[(ord(ch) - 65 + k_list[i]) % 26]
                i += 1
            else:
                result += letter_list[(ord(ch) - 97 + k_list[i]) % 26].lower()
                i += 1
        else:  # 如果密文不为字母,直接添加到密文字符串里
            result += ch
    return result


# 解密
def decipher(txt, k):
    result = ""
    k_list = get_key_list(k)
    i = 0
    for ch in txt:  # 遍历密文
        if 0 == i % len(k_list):
            i = 0
        if ch.isalpha():  # 密文为否为字母,如果是,则判断大小写,分别进行解密
            if ch.isupper():
                result += letter_list[(ord(ch) - 65 - k_list[i]) % 26]
                i += 1
            else:
                result += letter_list[(ord(ch) - 97 - k_list[i]) % 26].lower()
                i += 1
        else:  # 如果密文不为字母,直接添加到明文字符串里
            result += ch
    return result


if __name__ == '__main__':
    key = 'computer'
    plaintext = "hello world"
    ciphertext = encipher(plaintext, key)
    print(ciphertext)
    ciphertext = 'jsxai psinr'
    plaintext = decipher(ciphertext, key)
    print(plaintext)

10.棋盘密码

假设我们需要发送明文讯息 “Attack at once”, 用一套秘密混杂的字母表填满波利比奥斯方阵,像是这样:

  1 2 3 4 5
1 b t a l p 
2 d h o z k 
3 q f v s n 
4 g j c u x 
5 m r e w y 

i和j视为同一个字,使字母数量符合 5 × 5 格。之所以选择这五个字母,是因为它们译成摩斯密码时不容易混淆,
  可以降低传输错误的机率。使用这个方格,找出明文字母在这个方格的位置,再以那个字母所在的栏名称和列名称代替这个字母。
  可将该讯息转换成处理过的分解形式。

明文:A T T A C K A T O N C E
密文:AF AD AD AF GF DX AF AD DF FX GF XF
   13 12 12 13 43 25 13 12 23 35 43 53

棋盘密码(ADFGX加密法),也就是所谓的坐标加密法,早在公元2世纪就被希腊人发明出来了,是密码史上第一个密码,值得我们去了解。

2024-03-11T09:55:29.png

2024-03-11T09:55:37.png

11.乘法密码

乘法密码也是一种简单的替代密码,与凯撒密码相似,凯撒密码用的是加法,而乘法密码用的自然是乘法。
这种方法形成的加密信息保密性比较低。

加密公式:密文 = (明文 * 乘数) Mod 26

对于乘数密码,只有当乘数与26互质时,加密之后才会有唯一的解,因此乘数只可能有如下11种的选择:

乘数 = 3,5,7,9,11,15,17,19,21,23,25

仿射密码和希尔密码因为都用到了乘法,所以乘数也受到相同的局限。

12.仿射密码

仿射密码就是凯撒密码和乘法密码的结合。

加密公式:密文 = (明文 * 乘数 + 位移数) Mod 26

13.希尔密码

希尔密码(Hill Cipher)是运用基本矩阵论原理的替换密码,由Lester S. Hill在1929年发明。每个字母当作26进制数字:A=0, B=1, C=2… 一串字母当成n维向量,跟一个n×n的矩阵相乘,再将得出的结MOD26。

希尔密码就是矩阵乘法密码,运用基本矩阵论原理的替换密码。每个字母当作26进制数字:A=0, B=1, C=2... 一串字母当成n维向量,
  跟一个n×n的密钥矩阵相乘,再将得出的结果模26。希尔密码的优点是完全隐藏了字符的频率信息,弱点是容易被已知明文攻击击破。

加密
  例如:密钥矩阵
  1 3
  0 2

  明文:HI THERE

  去空格,2个字母一组,根据字母表顺序换成矩阵数值如下,末尾的E为填充字元:

  HI TH ER EE
  8 20 5 5
  9 8 18 5

  HI 经过矩阵运算转换为 IS,具体算法参考下面的说明:

  |1 3| 8 e18+39=35 MOD26=9 =I
  |0 2| 9 e08+29=18 MOD26=18=S

  用同样的方法把“HI THERE”转换为密文“IS RPGJTJ”,注意明文中的两个E分别变为密文中的G和T。

解密
  解密时,必须先算出密钥的逆矩阵,然后再根据加密的过程做逆运算。

  逆矩阵算法公式:
  |A B| = 1/(AD-BC) * | D -B|
  |C D| |-C A|

  例如密钥矩阵=
  |1 7|
  |0 3|
  AD-BC=13-07=3 3*X=1 mod26 所以 X=9
  因此
  |1 7| 的逆矩阵为: 9 * |3 -7|
  |0 3| |0 1|

  假设密文为“FOAOESWO”

  FO AO ES WO
   6 1 5 23
  15 15 19 15

  9 |3 -7| | 6| = 9(36-715)=-783 mod26 = 23=W
   |0 1| |15| = 9(06+1*15)= 135 mod26 = 5 =E

  所以密文“FOAOESWO”的明文为“WEREDONE”

14.键盘密码

加密的原理同棋盘密码,只是利用了键盘作为方阵。

键盘的字母分布:

~ ! @ # $ % ^ & * ( ) _ + |
` 1 2 3 4 5 6 7 8 9 0 - = \
 Q W E R T Y U I O P { }
 q w e r t y u i o p [ ]
 A S D F G H J K L : "
 a s d f g h j k l ; ’
 Z X C V B N M < > ?
 z x c v b n m , . /

密文:72 81 12 63 01 12 63
明文:jianpan

低下头看看键盘就知道了,密文就是键盘上的26个字母的坐标,72即第7列第2行,第7列正好是数字键[7]的位置,往下2个就是字母[J]。