加密算法详解

yedaoxiaodi 2020-06-28

一、加密算法分为对称加密、非对称加密和散列算法 

1.对称加密算法:加密与解密的密钥相同,算法主要有DES、3DES、AES;AES、DES、3DES都是对称的块加密算法,加解密的过程是可逆的
	a.数据加密过程:在对称加密算法中,数据发送方将明文(原始数据)和加密密钥一起经过特殊加密处理,生成复杂的加密密文进行发送
	b.据解密过程:数据接收方收到密文后,若想读取原数据,则需要使用加密使用的密钥及相同算法的逆算法 对加密的密文进行解密,才能使其恢复成可读明文

2.非对称加密算法:加密与解密的密钥不同,算法主要有RSA、DSA
	a.如果使用 公钥 对数据 进行加密,只有用对应的 私钥 才能 进行解密
	b.如果使用 私钥 对数据 进行加密,只有用对应的 公钥 才能 进行解密
	
3.散列算法:不需要密钥,算法主要有SHA-1、MD5

二、md5算法(不可逆)

  md5用的是哈希函数,它的典型应用是对一段信息产生信息摘要,所以严格来说md5是摘要算法。无论有多长的输入,md5的输出长度为128bits消息摘要(通常用16进制表示,16进制占4位,即128/4=32个字符)

  例子:

import hashlib
1.第一种
m=hashlib.md5()
m.update(‘nba‘.encode(encoding=‘utf-8‘))
n = m.hexdigest()

2.第二种
hashlib.md5(‘nba‘.encode(encoding=‘utf-8‘)).hexdigest()

3.第三种
hashlib.new(‘md5‘, ‘nba‘.encode(encoding=‘utf-8‘)).hexdigest()

三、sha1算法(不可逆)

  sha1是和md5一样的摘要算法,然而sha1比md5的安全性更强。对于长度小于 2^64 位的输入,sha1的输出长度为160位的消息摘要 (通常用16进制表示,16进制占4位,即160/4=40个字符)

  例子:

import hashlib
1.第一种
s=hashlib.sha1()
s.update(‘nba‘.encode(encoding=‘utf-8‘))
n = s.hexdigest()

2.第二种
hashlib.sha1(‘nba‘.encode(encoding=‘utf-8‘)).hexdigest()

3.第三种
hashlib.new(‘sha1‘, ‘nba‘.encode(encoding=‘utf-8‘)).hexdigest()

四、base64算法

Base64是一种基于64个可打印字符("A-Z、a-z、0-9、+、/")来表示二进制数据的表示方法。64个字符都用6个bit位表示,一个字节有8个bit位,剩下两个bit就浪费掉了,这样就不得不牺牲一部分空间了

加密算法详解

8和6的最小公倍数是24,也就是说3个传统字节可以由4个Base64字符来表示,保证有效位数是一样的,这样就多了1/3的字节数来弥补Base64只有6个有效bit不足。你也可以说用两个Base64字符也能表示一个传统字符,但是采用最小公倍数的方案其实是最减少浪费的。 结合下边的图比较容易理解。Man是三个字符,一共24个有效bit,只好用4个Base64字符来凑齐24个有效位。红框表示的是对应的Base64,6个有效位转化成相应的索引值再对应 Base64字符表,查出"Man"对应的Base64字符是"TWFU"。说到这里有个原则不知道你发现了没有,要转 换成Base64的最小单位就是三个字节,对一个字符串来说每次都是三个字节三个字节的转换,对应的是Base64的四个字节。这个搞清楚了其实就差不多了

加密算法详解加密算法详解

但是转换到最后你发现不够三个字节了怎么办呢?我们可以用两个Base64来表示一个字符或用三个Base64表示两个字符,像下图的A对应的第二个Base64的二进制位只有两个,把后边的四个补0就是了。所以 A对应的Base64字符就是QQ。上边已经说过了,原则是Base64字符的最小单位是四个字符一组,那这才两个字符,后边补两个"="吧。其实不用"="也不耽误解码,之所以用"=",可能是考虑到多段编码 后的Base64字符串拼起来也不会引起混淆。由此可见 Base64字符串只可能最后出现一个或两个"=",中间是不可能出现"="的

加密算法详解

例子:

import base64
base64.b64encode(‘nbawnba‘.encode(encoding=‘utf-8‘))
base64.b64decode(b‘bmJhd25iYQ==‘).decode(‘utf-8‘)

五、AES算法(可逆)

  AES 加密算法是密码学中的高级加密标准,该加密算法采用对称分组密码体制,密钥长度的最少支持为128 位、192 位、256 位,分组长度为128位

例子:

pip install pycryptodome -i http://pypi.douban.com/simple --trusted-host=pypi.douban.com
from Crypto.Cipher import AES
def aes_encrypt(key, value):
    """
    aes加密
    :param key:open_key
    :param value:加密的data
    :return:
    """
    # 补足字符串长度为16的倍数
    def add_to_16(s):
        while len(s) % 16 != 0:
            s += (16 - len(s) % 16) * chr(16 - len(s) % 16)
        return str.encode(s)  # 返回bytes

    aes = AES.new(str.encode(key), AES.MODE_ECB)
    encrypted_text = str(base64.encodebytes(aes.encrypt(add_to_16(value))), encoding=‘utf8‘).replace(‘\n‘, ‘‘)  #加密明文,并将返回的字节型数据转进行base64编码,并将字节型数据转换成python中的字符串类型
    return encrypted_text

def aes_decrypt(key, value):
    """
    aes解密
    :param key: open_key
    :param value: 需要解密的data
    :return:
    """
    aes = AES.new(str.encode(key), AES.MODE_ECB)
    decrypted_text = aes.decrypt(base64.decodebytes(bytes(value, encoding=‘utf8‘))).decode("utf8")  # 解密
    decrypted_text = decrypted_text[:-ord(decrypted_text[-1])]  # 去除多余补位
    return decrypted_text

六、RSA算法

加密是为了防止信息被泄露,而签名是为了防止信息被篡改。总之,公钥加密、私钥解密、私钥签名、公钥验签

RSA的加密过程如下:

(1)A生成一对密钥(公钥和私钥),私钥不公开,A自己保留。公钥为公开的,任何人可以获取

(2)A传递自己的公钥给B,B用A的公钥对消息进行加密

(3)A接收到B加密的消息,利用A自己的私钥对消息进行解密


RSA签名的过程如下:

(1)A生成一对密钥(公钥和私钥),私钥不公开,A自己保留。公钥为公开的,任何人可以获取

(2)A用自己的私钥对消息加签,形成签名,并将加签的消息和消息本身一起传递给B

(3)B收到消息后,在获取A的公钥进行验签,如果验签出来的内容与消息本身一致,证明消息是A回复的

#生成公私钥
import rsa
# 生成密钥
(pubkey, privkey) = rsa.newkeys(1024)
# 保存密钥
with open(‘public.pem‘ ,‘w+‘) as f:
    f.write(pubkey.save_pkcs1().decode())
with open(‘private.pem‘ ,‘w+‘) as f:
    f.write(privkey.save_pkcs1().decode())
#导入密钥
with open(‘public.pem‘ ,‘r‘) as f:
	pubkey = rsa.PublicKey.load_pkcs1(f.read().encode())
with open(‘private.pem‘ ,‘r‘) as f:
	privkey = rsa.PrivateKey.load_pkcs1(f.read().encode())

#加密rsa
def rsa_encrypt(message):
    crypto_email_text = rsa.encrypt(message.encode(), pubkey)
    return crypto_email_text
text = rsa_encrypt("hello world")

#解密rsa
def rsa_decrypt(message):
    message_str = rsa.decrypt(message,privkey).decode()
    return message_str
rsa_decrypt(text)
#签名
message = ‘这是重要指令:...‘
crypto_email_text = rsa.sign(message.encode(), privkey, ‘SHA-1‘)
#验签
rsa.verify(message.encode(), crypto_email_text, pubkey)