AES对称加密
加密方式:AES算法,基本变换包括SubBytes(字节替代)、ShiftRows(行移位)、MixColumns(列混淆)、AddRoundKey(轮密钥加)。
加密模式:
CBC模式:通过密钥和salt(起扰乱作用)按固定算法(md5)产生key和iv。然后用key和iv(初始向量,加密第一块明文)加密(明文)和解密(密文)。 ECB模式:不需要iv偏移量
python中使用到的库:
from Crypto.Cipher import AES
安装:
**Linux**下使用AES时要安装的是pycrypto模块 pip install pycrypto **Windows**下使用AES时要安装的是pycryptodome 模块 pip install pycryptodome
实际使用:
1、准备key,可以理解成加密解密的密码 2、加密后还会使用base64再次加密,当然解密时先用base64先进行第一次解密 3、还可以将base64第二次加密换成ASCII码进行加密,使用到的包如下:from binascii import b2a_hex, a2b_hex
class AESCryptoHelper(): def encrypt(data, key): """ 加密时使用的key,只能是长度16,24和32的字符串 data: 要加密的内容,bytes key:密钥,len必须是16, 24, 32之一 bytes result:加密内容,bytes """ keySzie = len(key) if keySzie == 16 or keySzie == 24 or keySzie == 32: cipher = AES.new(key, AES.MODE_ECB) padData = AESCryptoHelper._padData(data) encrypted = cipher.encrypt(padData) result = base64.b64encode(encrypted) return result else: # 加密失败,返回原数据 return data # 解密后,去掉补足的空格用strip() 去掉 def decrypt(data, key): """ 加密时使用的key,只能是长度16,24和32的字符串 data: 要解密的内容,bytes key:密钥,bytes result:解密的内容,bytes """ keySzie = len(key) if keySzie == 16 or keySzie == 24 or keySzie == 32: cipher = AES.new(key, AES.MODE_ECB) tmpData = base64.b64decode(data) decrypted = cipher.decrypt(tmpData) result = AESCryptoHelper._unpadData(decrypted) return result else: # 解密失败,返回原数据 return data def _padData(data): """ 按AES加密的要求,填充内容,使其为block_size的整数倍 """ block_size = 16 padding = b" " padData = data + (block_size - len(data) % block_size) * padding return padData def _unpadData(data): """ 删除填充数据 """ padding = b" " index = -1 while data[index] == padding[0]: index += -1 if index != -1: return data[0: index+1] else: return data
RSA非对称加密
实际加密步骤:
1、生成公钥、私钥(服务器)
2、公钥加密数据得到密文,在使用base64加密密文(客户端)
3、base64逆向解码,私钥解密密文(服务器)
# -*- coding: UTF-8 -*- # ! /usr/bin/env python import base64 import rsa from rsa import common PUBLIC_KEY_PATH = '/Users/anonyper/Desktop/key/company_rsa_public_key.pem' # 公钥 PRIVATE_KEY_PATH = '/Users/anonyper/Desktop/key/company_rsa_private_key.pem' # 私钥 # -------------------------- 生成公私钥 -------------------------- class CreateKeys: def __init__(self): public_key, private_key = rsa.newkeys(1024) public_pkcs1 = public_key.save_pkcs1().decode() private_pkcs1 = private_key.save_pkcs1().decode() # 生成公钥和私钥 with open(PUBLIC_KEY_PATH, 'w') as pub_f, open(PRIVATE_KEY_PATH, 'w') as pri_f: pub_f.write(public_pkcs1) pri_f.write(private_pkcs1) print('>> 生成公私钥成功') def __str__(self): pass # -------------------------- RSA签名和加解密 -------------------------- class RsaUtil(object): # 初始化key def __init__(self, company_pub_file=PUBLIC_KEY_PATH, company_pri_file=PRIVATE_KEY_PATH): if company_pub_file: self.company_public_key = rsa.PublicKey.load_pkcs1(open(company_pub_file).read()) if company_pri_file: self.company_private_key = rsa.PrivateKey.load_pkcs1(open(company_pri_file).read()) def get_max_length(self, rsa_key, encrypt=True): """加密内容过长时 需要分段加密 换算每一段的长度. :param rsa_key: 钥匙. :param encrypt: 是否是加密. """ blocksize = common.byte_size(rsa_key.n) reserve_size = 11 # 预留位为11 if not encrypt: # 解密时不需要考虑预留位 reserve_size = 0 maxlength = blocksize - reserve_size return maxlength # 加密 支付方公钥 def encrypt_by_public_key(self, message): """使用公钥加密. :param message: 需要加密的内容. 加密之后需要对接过进行base64转码 """ encrypt_result = b'' max_length = self.get_max_length(self.company_public_key) while message: input = message[:max_length] message = message[max_length:] out = rsa.encrypt(input, self.company_public_key) encrypt_result += out encrypt_result = base64.b64encode(encrypt_result) return encrypt_result def decrypt_by_private_key(self, message): """使用私钥解密. :param message: 需要加密的内容. 解密之后的内容直接是字符串,不需要在进行转义 """ decrypt_result = b"" max_length = self.get_max_length(self.company_private_key, False) decrypt_message = base64.b64decode(message) while decrypt_message: input = decrypt_message[:max_length] decrypt_message = decrypt_message[max_length:] out = rsa.decrypt(input, self.company_private_key) decrypt_result += out return decrypt_result # 签名 商户私钥 base64转码 def sign_by_private_key(self, data): """私钥签名. :param data: 需要签名的内容. 使用SHA-1 方法进行签名(也可以使用MD5) 签名之后,需要转义后输出 """ signature = rsa.sign(str(data), priv_key=self.company_private_key, hash='SHA-1') return base64.b64encode(signature) def verify_by_public_key(self, message, signature): """公钥验签. :param message: 验签的内容. :param signature: 对验签内容签名的值(签名之后,会进行b64encode转码,所以验签前也需转码). """ signature = base64.b64decode(signature) return rsa.verify(message, signature, self.company_public_key) CreateKeys() message = 'hell world' print("明文内容:>>> ") print(message) rsaUtil = RsaUtil() encrypy_result = rsaUtil.encrypt_by_public_key(message) print("加密结果:>>> ") print(encrypy_result) decrypt_result = rsaUtil.decrypt_by_private_key(encrypy_result) print("解密结果:>>> ") print(decrypt_result) sign = rsaUtil.sign_by_private_key(message) print("签名结果:>>> ") print(sign) print("验签结果:>>> ") print(rsaUtil.verify_by_public_key(message, sign))
缓存实现连个两个接口数据
使用缓存机制可以实现后端两个接口的开关控制,如实现以下功能:
浏览器获取手机上传的数据,当获取到数据后不刷新界面。
在程序中实现如下:
1、**浏览器**不断请求存放数据的接口(浏览器无法判断数据是否是新数据还是旧数据,所以只要有数据页面就会不断刷新), 2、**手机**上传数据,调用存放数据的接口, 很明显手机上传数据的接口与浏览器下载数据的接口不是同一个,所以两个接口数据无法连接起来。
使用缓存可以实现两个接口数据的传输,步骤如下:
1、手机将数据存储到给某个id分配的缓存内,当浏览器发送请求时,从缓存提取这个id的缓存数据。
数据通信实现了,那么如何实现旧数据不刷新,新数据才刷新呢。
1、很简单,设置一个update的键值对,手机上传说明有新数据设置为True,当浏览器获取了数据就将update设置为False,这样就实现了开关功能。
使用缓存最大的好处是可以定时删除数据。