对称加密和非对称加密
对称加密:解密和加密都使用一个密钥。这样如果在传输过程中,或者在客户端的密钥被泄露,就会存在整个传输内容泄密的情况发生。显然这种加密方式是存在问题的。
非对称加密:非对称加密的加密和解密使用不同的密钥,分为公钥和私钥。公钥和私钥是成对出现的。公钥加密的数据,只有对应的私钥才能解密。私钥加密的程序只有对应的公钥才能解密。一般讲私钥存在服务器,公钥可以存在每个客户端。服务器向客户端发数据,由私钥加密数据,然后由客户端公钥解密。客户端向服务器发数据,由公钥加密,由私钥解密。整个过程中不存在传输密钥的情况,也就不会造成密钥的丢失。
对称加密和非对称加密的对比
安全性:
非对称加密依赖一对密钥,不存在传输问题,不易被第三方获取,安全性更高,算法更复杂。对称加密仅依赖一个密钥,安全性低。
加密速度:
非对称加密依赖复杂算法,速度较慢,因此只适合加密较短内容。对称加密速度较快,适合加密长数据
对称加密+非对称加密实际使用过程
1、客户端去请求服务器的公钥(rsaPublicKey),由服务器生成密钥对,服务器存公钥(rsaPublicKey)和私钥(rsaPrivateKey),将公钥发送给客户端(这一步一般会提供接口进行获取GetPubKey)
2、客户端拿到公钥,保存公钥;
3、客户端使用公钥对密码进行加密
def rsaEncrypt_PEM_RSA(content, key):
# Encrypts the given message using PKCS#1 v1.5
# -----BEGIN PUBLIC KEY-----
# MIGfMA0GC244234244fdSqGSIb3DQEBAQUAA4GNADCBiQKBgQDM6dGIA2naE3nGXi6O9vHskRSj
# uC5hn30msl+bk1yJl4NUqH1uhzjhgsk1et7S3C0NWMDHPkC0vyWtp8HTpV1bFN747zToegLOs
# n1+zsf1LSObVce+UU76wSHGzijksdHUWQd1J3oAHBPCHSTt+WuTe+FMbQzvX1CQAdzdqCvYFvb
# +L+ajto9raO0cfUYHG
# -----END PUBLIC KEY-----
public_key = '-----BEGIN PUBLIC KEY-----\n' + key + '\n-----END PUBLIC KEY-----'
print(public_key)
rsakey = RSA.importKey(public_key) # 导入读取到的公钥
cipher = PKCS1_v1_5.new(rsakey) # 生成对象
# 通过生成的对象加密message明文,注意,在python3中加密的数据必须是bytes类型的数据,不能是str类型的数据
cipher_text = base64.b64encode(cipher.encrypt(content.encode("utf-8")))
return cipher_text
4、客户端准备发起请求,首先生成随机aes密钥(aesKey);
def generate_key():
# 密钥长度可以为128位(16字节)、192位(24字节)、256位(32字节),根据密钥长度的不同,AES分为AES-128、AES-192、AES-256三种
# return get_random_bytes(32).decode('utf-8')
base64_bytes = base64.b64encode(get_random_bytes(32))
return base64_bytes.decode('utf-8')
6、客户端正式发起请求,将加密后密码及AES秘钥传给服务器
data = {"UserName": url.Account, "Pwd": RAS_PWD.decode(), "AES": url.AES_KEY}
requests.post(url.Base_uri + url.Login_uri, data=data)
result = json.loads(response.text)
token_dict[json.loads(result["Content"])["Key"]] = json.loads(result["Content"])["Value"]
token = token_dict
7、服务器收到请求,通过rsa的私要进行解析,确认用户鉴权成功,返回认证的token,并将AES的key保存至服务器
8、通过RSA的非对称加密获取到token后,其余接口使用token进行认证,业务中需要加密或解密时统一使用AES秘钥进行对称加密
AES加解密方法(python)
import base64
import binascii
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
from Crypto.Random import get_random_bytes
# 使用ECB模式加密
MODE = AES.MODE_ECB
# 使用默认的pkcs7 padding
# PKCS7:填充字符串由一个字节序列组成,每个字节填充该字节序列的长度
PAD_STYLE = 'pkcs7'
ENCODING = 'UTF-8'
def generate_key():
# 密钥长度可以为128位(16字节)、192位(24字节)、256位(32字节),根据密钥长度的不同,AES分为AES-128、AES-192、AES-256三种
# return get_random_bytes(32).decode('utf-8')
base64_bytes = base64.b64encode(get_random_bytes(32))
return base64_bytes.decode('utf-8')
def encrypt(plaintext: str, key: str) -> str:
# 将密钥编码为UTF-8格式的bytes
# key_bytes = key.encode(ENCODING)
key_bytes = base64.b64decode(key.encode(ENCODING))
# 创建AES对象
cipher = AES.new(key_bytes, MODE)
# 将明文编码为UTF-8格式的bytes
plaintext_bytes = plaintext.encode(ENCODING)
# 为编码后的明文添加padding
plaintext_bytes_padded = pad(plaintext_bytes, AES.block_size, PAD_STYLE)
# 执行加密
ciphertext_bytes = cipher.encrypt(plaintext_bytes_padded)
# 将加密后的bytes进行base64编码
ciphertext_base64_bytes = base64.b64encode(ciphertext_bytes)
# 将base64编码过的bytes,解码为Python中使用的字符串类型(即unicode字符串)
ciphertext = ciphertext_base64_bytes.decode(ENCODING)
return ciphertext
def decrypt(ciphertext: str, key: str) -> str:
# 将密钥编码为UTF-8格式的bytes
# key_bytes = key.encode(ENCODING)
key_bytes = base64.b64decode(key.encode(ENCODING))
# 创建AES对象
decrypter = AES.new(key_bytes, MODE)
# 将密文编码为UTF-8格式的(同时也是base64编码的)bytes
ciphertext_base64_bytes = ciphertext.encode(ENCODING)
# 将base64编码的bytes,解码为原始的密文bytes
ciphertext_bytes = base64.b64decode(ciphertext_base64_bytes)
# 解码为明文
plaintext_bytes_padded = decrypter.decrypt(ciphertext_bytes)
# 去掉Padding
plaintext_bytes = unpad(plaintext_bytes_padded, AES.block_size, PAD_STYLE)
# 将UTF-8格式编码的明文bytes,解码为Python中的字符串类型(即unicode字符串)
plaintext = plaintext_bytes.decode(ENCODING)
return plaintext
if __name__ == '__main__':
key = generate_key()
print("AES密钥:{}".format(key))
string_w = "hello world!~"
print("解密前数据:{}".format(string_w))
res = encrypt(string_w, key)
print("加密后数据:{}".format(res))
print("解密后数据:{}".format(decrypt(res, key)))
AES密钥:vhDfeMHxbvMiJMv0Tc/uSHBmOVqTSNYBxMymlUvJ2vg=
解密前数据:hello world!~
加密后数据:C993IuOo9FuFQa/UnezEkA==
解密后数据:hello world!~
RSA通过公钥或模及指数加密方法(python)
import rsa
import base64
import binascii
from ctl.core.HandleLog.handle_log import log
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric import rsa as cryptography_rsa, padding
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5
def rsaEncrypt_PEM_RSA(content, key):
# Encrypts the given message using PKCS#1 v1.5
# -----BEGIN PUBLIC KEY-----
# MIGfMA0GC244234244fdSqGSIb3DQEBAQUAA4GNADCBiQKBgQDM6dGIA2naE3nGXi6O9vHskRSj
# uC5hn30msl+bk1yJl4NUqH1uhzjhgsk1et7S3C0NWMDHPkC0vyWtp8HTpV1bFN747zToegLOs
# n1+zsf1LSObVce+UU76wSHGzijksdHUWQd1J3oAHBPCHSTt+WuTe+FMbQzvX1CQAdzdqCvYFvb
# +L+ajto9raO0cfUYHG
# -----END PUBLIC KEY-----
public_key = '-----BEGIN PUBLIC KEY-----\n' + key + '\n-----END PUBLIC KEY-----'
print(public_key)
rsakey = RSA.importKey(public_key) # 导入读取到的公钥
cipher = PKCS1_v1_5.new(rsakey) # 生成对象
# 通过生成的对象加密message明文,注意,在python3中加密的数据必须是bytes类型的数据,不能是str类型的数据
cipher_text = base64.b64encode(cipher.encrypt(content.encode("utf-8")))
return cipher_text
def rsaEncrypt_PKCS_1_5_RSA(content, rsaModulus, rsaExponent):
# Encrypts the given message using PKCS#1 v1.5
result = rsa.encrypt(content.encode(),
rsa.PublicKey(
int(binascii.b2a_hex(base64.b64decode(rsaModulus)), 16),
int(binascii.b2a_hex(base64.b64decode(rsaExponent)), 16)
)
)
return base64.b64encode(result)
def rsaEncrypt_PKCS_1_5_Crypto(content, public_exponent, modulus=None):
# Encrypts the given message using PKCS1_v1_5
e = int(binascii.b2a_hex(base64.b64decode(public_exponent)), 16) # 指数
n = int(binascii.b2a_hex(base64.b64decode(modulus)), 16)
rsa_key = RSA.construct((n, e)) # generate/export
# public key
public_key = rsa_key.publickey()
cipher = PKCS1_v1_5.new(public_key)
cipher_text = base64.b64encode(cipher.encrypt(content.encode("utf-8")))
return cipher_text
def rsa_encrypt(rsa_n: str, rsa_e: str, msg: str):
"""
:param rsa_n: rsa n
:param rsa_e: rsa e
:param msg: encryt str
:return:
"""
rsa_n = int(binascii.b2a_hex(base64.b64decode(rsa_n)), 16)
rsa_e = int(binascii.b2a_hex(base64.b64decode(rsa_e)), 16)
pubkey = cryptography_rsa.RSAPublicNumbers(rsa_e, rsa_n).public_key(default_backend())
key = pubkey.encrypt(msg.encode('utf-8'), padding.PKCS1v15())
# key = pubkey.encrypt(msg.encode('utf-8'), padding.OAEP(mgf=padding.MGF1(algorithm=hashes.SHA256()), algorithm=hashes.SHA256(), label=None))
# return str(binascii.b2a_base64(key))
return base64.b64encode(key)
def public_key(rsaExponent, rsaModulus, msg):
e = int(binascii.b2a_hex(base64.b64decode(rsaExponent)), 16)
n = int(binascii.b2a_hex(base64.b64decode(rsaModulus)), 16) # snipped for brevity
# pubkey = construct((n, e))
pubkey = rsa.RSAPublicNumbers(e, n).public_key(default_backend())
# pubkey = rsa.RSAPublicNumbers(e, n).public_key()
key = pubkey.encrypt(msg.encode('utf-8'), padding.OAEP(mgf=padding.MGF1(algorithm=hashes.SHA256()), algorithm=hashes.SHA256(), label=None))
log.info(str(binascii.b2a_base64(key)))