加密和解密的总结

一.加密算法的分类

  1.对称加密算法具有更高的加密速度,但双方都需要事先知道秘钥,秘钥在传输过程中可能会被窃取,因此安全性没有非对称加密高

    常见的对称加密算法:DES, AES, 3DES等等

  2.非对称加密算法的加密速度低于对称加密算法,但是安全性更高

    非对称加密算法:RSA, DSA, ECC 等算法

  3.利用字典的格式转换加密

    MAKETRANS()

二.详细分析

  1.DES加密

    即数据加密标准,是一种使用秘钥加密的块算法

    入口参数有三个:key, Data,  Mode

      key为7个字节共56位,是DES算法的工作秘钥;

      Data为DES的工作方式,有两种:加密和解密

    3DES是DES向AES过渡的加密算法,使用两个秘钥,执行三次DES算法,

    加密的过程是加密-解密-加密

    解密的过程是解密-加密-解密

 1 from Crypto.Cipher import DES
 2 key = b'abcdefgh' # 密钥 8位或16位,必须为bytes
 3  
 4 def pad(text):
 5   """
 6   # 加密函数,如果text不是8的倍数【加密文本text必须为8的倍数!】,那就补足为8的倍数
 7   :param text: 
 8   :return: 
 9   """
10   while len(text) % 8 != 0:
11     text += ' '
12   return text
13  
14  
15 des = DES.new(key, DES.MODE_ECB) # 创建一个DES实例
16 text = 'Python rocks!'
17 padded_text = pad(text)
18 encrypted_text = des.encrypt(padded_text.encode('utf-8')) # 加密
19 print(encrypted_text)
20 # rstrip(' ')返回从字符串末尾删除所有字符串的字符串(默认空白字符)的副本
21 plain_text = des.decrypt(encrypted_text).decode().rstrip(' ') # 解密
22 print(plain_text)

  2.AES加密

    高级加密标准(英语:Advanced EncryptionStandard,缩写:AES),这个标准用来替代原先的DES

    AES的区块长度固定为128 比特,密钥长度则可以是128,192或256比特(16、24和32字节)

    大致步骤:

      1、密钥扩展(KeyExpansion),

      2、初始轮(Initial Round),

      3、重复轮(Rounds),每一轮又包括:SubBytes、ShiftRows、MixColumns、AddRoundKey,

      4、最终轮(Final Round),最终轮没有MixColumns。

普通方式

 1 from Cryptodome.Cipher import AES
 2 from binascii import b2a_hex, a2b_hex
 3 #秘钥,此处需要将字符串转为字节
 4 key = 'abcdefgh'
 5 #加密内容需要长达16位字符,所以进行空格拼接
 6 def pad(text):
 7   while len(text) % 16 != 0:
 8     text += ' '
 9   return text
10 #加密秘钥需要长达16位字符,所以进行空格拼接
11 def pad_key(key):
12   while len(key) % 16 != 0:
13     key += ' '
14   return key
15 #进行加密算法,模式ECB模式,把叠加完16位的秘钥传进来
16 aes = AES.new(pad_key(key).encode(), AES.MODE_ECB)
17 #加密内容,此处需要将字符串转为字节
18 text = 'hello'
19 #进行内容拼接16位字符后传入加密类中,结果为字节类型
20 encrypted_text = aes.encrypt(pad(text).encode())
21 encrypted_text_hex = b2a_hex(encrypted_text)
22 print(encrypted_text_hex)
23  
24  
25 # #此处是为了验证是否能将字节转为字符串后,进行解密成功
26 # #实际上a 就是 encrypted_text ,也就是加密后的内容
27 # #用aes对象进行解密,将字节类型转为str类型,错误编码忽略不计
28 de = str(aes.decrypt(a2b_hex(encrypted_text_hex)), encoding='utf-8',errors="ignore")
29 # #获取str从0开始到文本内容的字符串长度。
30 print(de[:len(text)])

面向对象方式

 1 from Cryptodome.Cipher import AES
 2 from binascii import b2a_hex, a2b_hex
 3  
 4 AES_LENGTH = 16
 5  
 6 class prpcrypt():
 7   def __init__(self, key):
 8     self.key = key
 9     self.mode = AES.MODE_ECB
10     self.cryptor = AES.new(self.pad_key(self.key).encode(), self.mode)
11  
12   # 加密函数,如果text不是16的倍数【加密文本text必须为16的倍数!】,那就补足为16的倍数
13   # 加密内容需要长达16位字符,所以进行空格拼接
14   def pad(self,text):
15     while len(text) % AES_LENGTH != 0:
16       text += ' '
17     return text
18  
19   # 加密密钥需要长达16位字符,所以进行空格拼接
20   def pad_key(self,key):
21     while len(key) % AES_LENGTH != 0:
22       key += ' '
23     return key
24  
25   def encrypt(self, text):
26  
27     # 这里密钥key 长度必须为16(AES-128)、24(AES-192)、或32(AES-256)Bytes 长度.目前AES-128足够用
28     # 加密的字符需要转换为bytes
29     # print(self.pad(text))
30     self.ciphertext = self.cryptor.encrypt(self.pad(text).encode())
31     # 因为AES加密时候得到的字符串不一定是ascii字符集的,输出到终端或者保存时候可能存在问题
32     # 所以这里统一把加密后的字符串转化为16进制字符串
33     return b2a_hex(self.ciphertext)
34  
35     # 解密后,去掉补足的空格用strip() 去掉
36  
37   def decrypt(self, text):
38     plain_text = self.cryptor.decrypt(a2b_hex(text)).decode()
39     return plain_text.rstrip(' ')
40  
41  
42 if __name__ == '__main__':
43   pc = prpcrypt('abcdef') # 初始化密钥
44   e = pc.encrypt("0123456789ABCDEF")
45   d = pc.decrypt(e)
46   print(e, d)
47   e = pc.encrypt("00000000000000000000000000")
48   d = pc.decrypt(e)
49   print(e, d)

  3.RSA加密

    公钥加密算法,一种非对称密码算法

    公钥加密,私钥解密

    公有三个参数:rsa_n, rsa_e, message

    rsa_n, rsa_e 用于生成公钥

    message:需要加密的消息

 1 import rsa
 2 from binascii import b2a_hex, a2b_hex
 3  
 4  
 5  
 6 class rsacrypt():
 7   def __init__(self, pubkey, prikey):
 8     self.pubkey = pubkey
 9     self.prikey = prikey
10  
11   def encrypt(self, text):
12     self.ciphertext = rsa.encrypt(text.encode(), self.pubkey)
13     # 因为rsa加密时候得到的字符串不一定是ascii字符集的,输出到终端或者保存时候可能存在问题
14     # 所以这里统一把加密后的字符串转化为16进制字符串
15     return b2a_hex(self.ciphertext)
16  
17   def decrypt(self, text):
18     decrypt_text = rsa.decrypt(a2b_hex(text), prikey)
19     return decrypt_text
20  
21  
22 if __name__ == '__main__':
23   pubkey, prikey = rsa.newkeys(256)
24   rs_obj = rsacrypt(pubkey,prikey)
25   text='hello'
26   ency_text = rs_obj.encrypt(text)
27   print(ency_text)
28   print(rs_obj.decrypt(ency_text))
29  
30 """
31 b'7cb319c67853067abcd16aad25b3a8658e521f83b1e6a6cf0c4c2e9303ad3e14'
32 b'hello'
33 """

  4.使用base64或pycrypto模块

    1.使用base64

1 s1 = base64.encodestring('hello world')
2 s2 = base64.decodestring(s1)
3 print s1, s2
4 
5 #  结果
6 #  aGVsbG8gd29ybGQ=
7 #  hello world

      优点:方法简单

      缺点:不保险,别人拿到密文可以解密出明文

      编码原理:将3个字节转换成4个字节((3 X 8)=24=(4X6)),先读入3个字节,每读一个字节,左移8位,再右移四次,每次6位,这样就有4个字节了。

      解密原理:将4个字节转换成3个字节,先读入4个6位(用或运算),每次左移6位,再右移3次,每次8位,这样就还原了。

    2.使用pycrypto模块

 1 from Crypto.Cipher import AES
 2 obj = AES.new('This is a key123', AES.MODE_CBC, 'This is an IV456')
 3 message = "The answer is no"
 4 ciphertext = obj.encrypt(message)
 5 print(ciphertext)
 6 #   '\xd6\x83\x8dd!VT\x92\xaa`A\x05\xe0\x9b\x8b\xf1'
 7 obj2 = AES.new('This is a key123', AES.MODE_CBC, 'This is an IV456')
 8 decryptext = obj2.decrypt(ciphertext)
 9 print(decryptext)
10 #  'The answer is no'

      AES只是个基本算法,实现AES有若干模式。其中的CBC模式因为其安全性而被TLS(就是https的加密标准)和IPSec(win采用的)作为技术标准。

      简单地说,CBC使用密码和salt(起扰乱作用)按固定算法(md5)产生key和iv。然后用key和iv(初始向量,加密第一块明文)加密(明文)和解密(密文)。

 1 import sys
 2 from Crypto.Cipher import AES
 3 from binascii import b2a_hex, a2b_hex
 4   
 5 class prpcrypt():
 6   def __init__(self, key):
 7     self.key = key
 8     self.mode = AES.MODE_CBC
 9     
10   #加密函数,如果text不是16的倍数【加密文本text必须为16的倍数!】,那就补足为16的倍数
11   def encrypt(self, text):
12     cryptor = AES.new(self.key, self.mode, self.key)
13     #这里密钥key 长度必须为16(AES-128)、24(AES-192)、或32(AES-256)Bytes 长度.目前AES-128足够用
14     length = 16
15     count = len(text)
16     add = length - (count % length)
17     text = text + ('\0' * add)
18     self.ciphertext = cryptor.encrypt(text)
19     #因为AES加密时候得到的字符串不一定是ascii字符集的,输出到终端或者保存时候可能存在问题
20     #所以这里统一把加密后的字符串转化为16进制字符串
21     return b2a_hex(self.ciphertext)
22     
23   #解密后,去掉补足的空格用strip() 去掉
24   def decrypt(self, text):
25     cryptor = AES.new(self.key, self.mode, self.key)
26     plain_text = cryptor.decrypt(a2b_hex(text))
27     return plain_text.rstrip('\0')
28   
29 if __name__ == '__main__':
30   pc = prpcrypt('keyskeyskeyskeys')   #初始化密钥
31   e = pc.encrypt("00000")
32   d = pc.decrypt(e)           
33   print(e, d)
34   e = pc.encrypt("00000000000000000000000000")
35   d = pc.decrypt(e)         
36   print(e, d)

  5.Python  maketrans()方法  也可以用来进行加密

    描述:用于创建字符串映射的转换表,对于接受两个参数的最简单的调用方式,第一个参数是字符串,表示需要转换的字符,第二个参数也是字符串表示转换的目标

    注:两个字符串的长度必须相同,为一一对应的关系

    语法: str.maketrans(in_tab, out_tab)

    参数:in_tab - 字符串中要替换的字符串组成的字符串

        out_tab - 相应的映射字符的字符串

1 from string import maketrans   # 必须调用 maketrans 函数。
2 
3 intab = "aeiou"
4 outtab = "12345"
5 trantab = maketrans(intab, outtab)
6 
7 str = "this is string example....wow!!!"
8 print(str.translate(trantab))

参考链接:https://www.jb51.net/article/152209.htm

猜你喜欢

转载自www.cnblogs.com/chenxi67/p/11611923.html