Contents

Crypto_notes

一些密码学代码笔记…

密码学学习笔记

Transposition_Cipher

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#Python3
import re

class Transposition:
    __key = []  # 密钥
    __plaintext = ""  # 明文
    __encryptMsg = ""  # 密文
    __decryptMsg = ""  # 解密后明文
    __lenKey = 0  # 密钥长度 周期值

    def getKey(self, s):  # 密钥形成函数
        Key = {}
        antiKey = {}
        s = re.split(r'[()]', s)  # 以()分界
        while '' in s:  # 消除''
            s.remove('')
        temp = []

        for i in range(len(s)):
            for j in range(len(s[i])-1):
                Key[int(s[i][j])] = int(s[i][j+1])  # 密钥字典
                antiKey[int(s[i][j+1])] = int(s[i][j])  # 反密钥字典
                temp.append(int(s[i][j]))  # 钥匙收录
            Key[int(s[i][-1])] = int(s[i][0])  # 解决最后一个的问题
            antiKey[int(s[i][0])] = int(s[i][-1])
            temp.append(int(s[i][-1]))
        maxtemp = max(temp)  # 密钥长度
        self.__lenKey = maxtemp
        lenKey = {i+1 for i in range(maxtemp)}
        sameKey = lenKey-set(temp)  # 找到没有变化的密钥
        for i in sameKey:
            Key[i] = i
            antiKey[i] = i
        self.__key.append(Key)
        self.__key.append(antiKey)

    def encrypt(self, p):  # 加密函数
        self.__plaintext = p
        Key = self.__key[0]
        time = self.__lenKey
        p = p.replace(' ', '')  # 去除空格
        if len(p) % time != 0:
            p += ' '*(time-len(p) % time)  # 末尾补齐
        n = len(p)//time
        M = [p[i*time:(i+1)*time] for i in range(n)]  # 分组生成
        M = [M[i][Key[j+1]-1] for i in range(n) for j in range(time)]  # 矩阵转换
        M = ''.join(M)  # 列表转换为字符串
        self.__encryptMsg = M
        return M

    def decrypt(self, q):
        m = self.__lenKey
        n = len(q)//m
        Key = self.__key[1]
        M = [q[i*m:(i+1)*m] for i in range(n)]
        M = [M[i][Key[j+1]-1] for i in range(n) for j in range(m)]
        M = ''.join(M)
        self.__decryptMsg = M
        return M

    def Print(self):
        print("密钥:", Key)
        print("明文:", self.__plaintext)
        print("密文:", self.__encryptMsg)
        print("解密后明文:", self.__decryptMsg)
        print("密钥长度:", self.__lenKey)


Key = '(1425367)'
Plaintext = """
In several distributed systems a user should only be able to access data if a user posses a certain set of credentials or attributes Currently the only method for enforcing such policies is to employ a trusted server to store the data and mediate access control However if any server storing the data is compromised then the confidentiality of the data will be compromised In this paper we present a system for realizing complex access control on encrypted data that we call ciphertext-policy attribute-based encryption By using our techniques encrypted data can be kept confidential even if the storage server is untrusted moreover our methods are secure against collusion attacks
"""

a = Transposition()
a.getKey(Key)
encryptMsg = a.encrypt(Plaintext)
decryptMsg = a.decrypt(encryptMsg)
a.Print()

Affine_Cipher

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#Python3

#输入密钥
def accept():
    k1,k2 = map(int,input('请输入两个密钥(以空格隔开):').split())
    while gcd(k1, 26) !=1:
        k1,k2 = map(int,input('k1和26不互素,请重新输入密钥:').split())
    return k1,k2

#判断互素
def gcd(k1,m):
    t = 0
    while m!=0:
        t = m
        m = k1%m
        k1 = t
    return k1

#求逆元
def niyuan(k1):
    n = 1
    while (k1 * n) % 26 != 1:
        n += 1
    return n

#加密算法
def encrypt(plain):
    #输入密钥
    k1,k2 = accept()
    c = []
    for i in range(len(plain)):
        #小写字母
        if plain[i].islower():
            c.append(chr(((ord(plain[i])-97)*k1+k2)%26+97))
        #大写字母
        elif plain[i].isupper():
            c.append(chr(((ord(plain[i])-65)*k1+k2)%26+65))
        #其他
        else :
            c.append(plain[i])
    cipher = ''.join(c)
    return cipher

#解密算法
def decrypt(cipher):
    #输入密钥
    k1,k2 = accept()
    #逆元
    ny = niyuan(k1)
    p = []
    for i in range(len(cipher)):
        #小写字母
        if cipher[i].islower():
            t1 = ord(cipher[i])-97-k2
            if t1 < 0:
                t1 +=26
            p.append(chr((ny * t1)%26+97))
        #大写字母
        elif cipher[i].isupper():
            t2 = ord(cipher[i])-65-k2
            if t2 < 0:
                t2 +=26
            p.append(chr((ny * t2)%26+65))
        #其他
        else :
            p.append(cipher[i])

    plain = ''.join(p) 
    return plain

#输入一段字符串,统计各个字符出现的次数
def count_str(text):
    result = {}
    alphabet = "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"
    li = alphabet.split()
    for i in li:
        n = text.count(i)
        result[i] = n
        #print("%s:%d" % (i, n))
    return result

if __name__ == '__main__':
    plain = "In several distributed systems a user should only be able to access data if a user posses a certain set of credentials or attributes Currently the only method for enforcing such policies is to employ a trusted server to store the data and mediate access control However if any server storing the data is compromised then the confidentiality of the data will be compromised In this paper we present a system for realizing complex access control on encrypted data that we call ciphertext-policy attribute-based encryption By using our techniques encrypted data can be kept confidential even if the storage server is untrusted moreover our methods are secure against collusion attacks"
    cipher = encrypt(plain)
    print("加密后密文为:", cipher)
    de_plain = decrypt(cipher)
    print("解密后明文为:", de_plain)
    count_plain = count_str(plain)
    print("明文统计结果为:", count_plain)
    count_cipher = count_str(cipher)
    print("密文统计结果为:", count_cipher)

Playfair_Cipher

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#Python3

# 5*5的矩阵, I与J同, 注意是大写的,也可以自己定义矩阵(不要重复)
SECRET_LIST = [["M", "O", "N", "A", "R"],
            ["C", "H", "Y", "B", "D"],
            ["E", "F", "G", "J", "K"],
            ["L", "P", "Q", "S", "T"],
            ["U", "V", "W", "X", "Z"]]

# 加密
def encryption(clear_text):
    # 去除空格与逗号
    clear_text = clear_text.replace(" ", "").replace(",", "")
    list_clear_text = list(clear_text)  # 字符串转化为列表
    print(list_clear_text)
    # 两个字母为一组,在重复的明文字母中插入填充字母Z
    flag = False
    while not flag:
        list_clear_text = deal_repeat(list_clear_text)[0]
        flag = deal_repeat(list_clear_text)[1]
    print(list_clear_text)
    # 若分组到最后一组时只有一个字母,则补充字母Z
    if len(list_clear_text) % 2 == 1:
        list_clear_text.append("Z")
    print(list_clear_text)
    # 加密的核心代码
    encryption_list = core_encryption(list_clear_text)  # 返回密文列表
    return ("").join(encryption_list)

# 处理一组字线是重复明文字母
def deal_repeat(list_clear_text):
    count = 0  # 计算列表中有多少组是不同的
    flag = False
    for i in range(len(list_clear_text)):
        if(i % 2 == 1):  # 列表中的第d奇数个
            if(list_clear_text[i] == list_clear_text[i-1]):  # 第奇数个与前一个(偶数)是否相同
                list_clear_text.insert(i, "Z")  # 有重复明文字母则插入一个填充字母Z 并且退出循环
                break
            if (list_clear_text[i] != list_clear_text[i - 1]):
                count += 1
                if count == int(len(list_clear_text) / 2):
                    flag = True

    return list_clear_text, flag  # 返回的是元组 (list_clear_text, flag)

# 获得字母在矩阵中的行与列
def get_rows_columns(alphabet):
    if alphabet == "I":  # 矩阵中只有25个字母,I同J
        alphabet = "J"
    for i in range(len(SECRET_LIST)):
        for j in range(len(SECRET_LIST[i])):
            if (SECRET_LIST[i][j] == alphabet):
                return i, j

# 加密的核心代码,先找出每一组字母在5*5矩阵 的行与列
def core_encryption(list_clear_text):
    encryption_list = []
    for i in range(len(list_clear_text)):
        if(i % 2 == 0):
            x = list_clear_text[i].upper()  # 将一组字母转为大写,因为矩阵的字母全是大写的
            y = list_clear_text[i+1].upper()
            x_tuple = get_rows_columns(x)  # 返回元组形式
            y_tuple = get_rows_columns(y)
            # print(x_tuple)
            # print(y_tuple)
            if x_tuple[0] == y_tuple[0]:  # 若明文字母在矩阵中同行
                x_secret = SECRET_LIST[x_tuple[0]][(x_tuple[1] + 1) % 5]
                y_secret = SECRET_LIST[y_tuple[0]][(y_tuple[1] + 1) % 5]
            elif x_tuple[1] == y_tuple[1]:  # 若明文字母在矩阵中同列
                x_secret = SECRET_LIST[(x_tuple[0] + 1) % 5][x_tuple[1]]
                y_secret = SECRET_LIST[(y_tuple[0] + 1) % 5][y_tuple[1]]
            else:  # 若明文字母在矩阵中不同行不同列
                x_secret = SECRET_LIST[x_tuple[0]][y_tuple[1]]
                y_secret = SECRET_LIST[y_tuple[0]][x_tuple[1]]
            encryption_list.append(x_secret)
            encryption_list.append(y_secret)
    return encryption_list  # 返回字母加密后的列表

# 解密核心代码,返回解密后的明文列表,密文肯定是偶数的,每一组密文字母也肯定是不同的
def core_decryption(list_cipher_text):
    decryption_list = []
    for i in range(len(list_cipher_text)):
        if(i % 2 == 0):
            x = list_cipher_text[i]
            y = list_cipher_text[i+1]
            x_tuple = get_rows_columns(x)  # 返回元组形式
            y_tuple = get_rows_columns(y)
            if x_tuple[0] == y_tuple[0]:  # 若密文字母在矩阵中同行
                x_clear = SECRET_LIST[x_tuple[0]][(x_tuple[1] - 1) % 5]
                y_clear = SECRET_LIST[y_tuple[0]][(y_tuple[1] - 1) % 5]
            elif x_tuple[1] == y_tuple[1]:  # 若密文字母在矩阵中同列
                x_clear = SECRET_LIST[(x_tuple[0] - 1) % 5][x_tuple[1]]
                y_clear = SECRET_LIST[(y_tuple[0] - 1) % 5][y_tuple[1]]
            else:  # 若密文字母在矩阵中不同行不同列
                x_clear = SECRET_LIST[x_tuple[0]][y_tuple[1]]
                y_clear = SECRET_LIST[y_tuple[0]][x_tuple[1]]
            decryption_list.append(x_clear)
            decryption_list.append(y_clear)
    return decryption_list  # 返回解密后的明文列表(需进一步处理,eg:去掉Z)

# 解密
def decryption(cipher_text):
    cipher_text = cipher_text.replace(" ", "").replace(",", "")
    list_cipher_text = list(cipher_text.strip())  # 将密文转化为列表
    decryption_list = core_decryption(list_cipher_text)  # 调用函数
    if decryption_list[-1] == "Z":  # 若列表最后一个元素是Z,则删除
        decryption_list.pop(-1)
    # 找出列表应该删除的下标
    delete_list = []
    for i in range(len(decryption_list)):
        if i % 2 == 0:  # 第偶数个
            # 不越界
            if i+2 < len(decryption_list) and \
                    decryption_list[i] == decryption_list[i+2] and decryption_list[i+1] == "Z":
                delete_list.append(i+1)
                # decryption_list.pop(i+1)
    delete_list.reverse()
    for i in delete_list:
        print(i)
        decryption_list.pop(i)
    return "".join(decryption_list)

if __name__ == "__main__":
    while True:
        choice = input("Please input E for encryption or D for decryption:")
        if choice.strip() != "E" and choice.strip() != "D":
            print("Input Error")
        # 加密
        if choice.strip() == "E":
            clear_text = input("请输入明文:")
            print("加密成功!密文:%s" % encryption(clear_text))
        # 解密
        if choice.strip() == "D":
            cipher_text = input("请输入密文(大写字母/偶数):")
            print("解密成功!明文:%s" % decryption(cipher_text))

Hill_Cipher

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#Python3
import numpy as np

secret_key = [[10, 5,  12, 0, 0],
              [3,  14, 21, 0, 0],
              [8,  9,  11, 0, 0],
              [0,  0,  0,  11,8],
              [0,  0,  0,  3, 7]]

inverse_key = [[21, 15, 17, 0,  0 ],
               [23, 2,  16, 0,  0 ],
               [25, 4,  3,  0,  0 ],
               [0,  0,  0,  7,  18],
               [0,  0,  0,  23, 11]]

#取下标值
def pla_index(strs):
    result = []
    for i in strs:
        result.append(ord(i)-97)
    return result

#加密函数
def encrypt(pla):
    pla = pla.replace(" ", "")
    pla = pla.replace("-", "")
    pla = pla.lower()
    #秘钥的行数
    hang_len = len(secret_key)
    #将明文根据秘钥长度分组,取下标,存入列表
    pla_group = []
    for i in range(0,len(pla),hang_len):
        a = pla[i:i+hang_len]
        pla_group.append(list(pla_index(a)))
    #矩阵相乘,结果存入result中,是一个二维数组
    result = []
    for i in pla_group:
        result.append(list(np.dot(i,secret_key) % 26))
    #遍历result,转成密文
    cip = ""
    for i in result:
        for j in i:
                cip += chr(j + 97)
    return cip

#解密函数
def decrypt(cip):
    #秘钥逆矩阵的行数
    hang_len = len(inverse_key)
    #将密文根据秘钥逆矩阵长度分组,取下标,存入列表
    cip_group = []
    for i in range(0,len(cip),hang_len):
        a = cip[i:i+hang_len]
        cip_group.append(list(pla_index(a)))
    #矩阵相乘,结果存入result中,是一个二维数组
    result = []
    for i in cip_group:
        result.append(list(np.dot(i,inverse_key) % 26))
    #遍历result,转成明文
    pla = ""
    for i in result:
        for j in i:
            pla += chr(j + 97)
    return pla

#输入一段字符串,统计各个字符出现的次数
def count_str(text):
    result = {}
    alphabet = "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"
    li = alphabet.split()
    for i in li:
        n = text.count(i)
        result[i] = n
        #print("%s:%d" % (i, n))
    return result

if __name__ == "__main__":
    plaintext = "In several distributed systems a user should only be able to access data if a user posses a certain set of credentials or attributes Currently the only method for enforcing such policies is to employ a trusted server to store the data and mediate access control However if any server storing the data is compromised then the confidentiality of the data will be compromised In this paper we present a system for realizing complex access control on encrypted data that we call ciphertext-policy attribute-based encryption By using our techniques encrypted data can be kept confidential even if the storage server is untrusted moreover our methods are secure against collusion attacks"
    print("明文为:", plaintext)
    cipher = encrypt(plaintext)
    print("加密后密文为:", cipher)
    deplaintext = decrypt(cipher)
    print("解密后明文为:", deplaintext)
    cipher_count = count_str(cipher)
    print("密文统计结果为:", cipher_count)
    plaintext_count = count_str(plaintext)
    print("明文统计结果为:", plaintext_count)