接口加密思路
简述
使用加密算法实现接口加密,实现一定程度上的防爬及数据安全。
悉知:没有绝对安全的系统,只有破解成本的高低。
加密算法
目前密码学通常将加密算法分为以下三类:
对称加密算法
- 特点:加密和解密使用相同的密钥(或可相互推导)。
- 核心问题:密钥需要在通信双方之间安全共享。
- 常见算法:AES(高级加密标准)、DES(已淘汰)、SM4(国密)。
- 应用场景:大数据量加密(如文件加密、数据库存储、SSL/TLS通信的会话密钥)。
非对称加密算法
- 特点:使用公钥(公开)和私钥(保密)组成的密钥对,公钥加密的数据只能由私钥解密,反之亦然。
- 核心问题:解决密钥分发难题,但计算效率低于对称加密。
- 常见算法:RSA(基于大数分解)、ECC(椭圆曲线密码学,如ECDSA)、ElGamal、SM2(国密)。
- 应用场景:密钥交换(如DH算法)、数字签名、身份认证(如SSL/TLS证书)。
哈希算法
- 特点:将任意长度输入映射为固定长度的输出(哈希值),且不可逆。
- 核心要求:抗碰撞性、单向性。
- 常见算法:SHA-256、SHA-3(Keccak)、MD5(已不安全)、SM3(国密)。
- 应用场景:数据完整性校验(如文件校验)、密码存储(加盐哈希)、区块链(默克尔树)。
对称加密与非对称加密对比
对称加密 (如AES) 非对称加密 (如RSA) 密钥机制 单密钥(加密/解密相同) 密钥对(公钥加密,私钥解密) 算法复杂度 基于位运算(快速) 基于数学难题(大数分解/椭圆曲线) 密钥长度 短(128/256位) 长(2048位以上) 典型算法 AES
,ChaCha20
,SM4
RSA
,ECC
,SM2
加密速度 极快(GB/s级) 慢(比对称加密慢100-1000倍) 资源消耗 低(适合IoT/移动设备) 高(需强大CPU) 大数据处理能力 优秀(适合流数据) 仅适合小数据(如加密密钥) 密钥分发风险 高(需安全通道共享密钥) 低(公钥可公开)
实现思路
客户端:
- 生成随机AES密钥 (会话密钥)
- 用RSA公钥加密AES密钥
- 用AES密钥加密实际数据
- 发送 [加密后的AES密钥] + [AES加密的数据]
服务端:
- 用RSA私钥解密获取AES密钥
- 用AES密钥解密数据
- 用AES加密响应数据返回
客户端:
- 使用会话中的AES密码解密响应数据
sequenceDiagram participant Client as 客户端 participant Server as 服务端 Note over Client: 请求加密阶段 Client->>Client: 1. 生成随机AES密钥 Client->>Client: 2. 用AES加密请求数据 Client->>Client: 3. 用RSA公钥加密AES密钥 Client->>Server: 4. 发送[加密的AES密钥]+[AES加密请求] Note over Server: 请求处理阶段 Server->>Server: 5. 用RSA私钥解密AES密钥 Server->>Server: 6. 用AES密钥解密请求数据 Server->>Server: 7. 处理业务逻辑 Note over Server: 响应加密阶段 Server->>Server: 8. 用同一AES密钥加密响应 Server->>Client: 9. 返回[AES加密响应] Note over Client: 响应解密阶段 Client->>Client: 10. 用缓存的AES密钥解密响应
Python
RSA
、AES
工具类1
$ pip install pycryptodome
RSA
工具类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#!/usr/bin/env python
# -*- coding: UTF-8 -*-
# time : 2022/2/7
# __author__ = Ysc
import base64
import json
import os
from Crypto import Random
from Crypto.Cipher import PKCS1_v1_5 as Cipher_pkcs1_v1_5
from Crypto.PublicKey import RSA
PEM_DIR = os.path.join('.')
def GeneratePEM():
# rsa算法生成实例
rsa = RSA.generate(1024, Random.new().read)
# Server的秘钥对的生成
private_pem = rsa.exportKey()
with open("%s/server-public.pem" % PEM_DIR, "wb") as f:
f.write(private_pem)
public_pem = rsa.publickey().exportKey()
with open("%s/server-private.pem" % PEM_DIR, "wb") as f:
f.write(public_pem)
class DeEncrypt:
__instance = None
__hasInit = False
def __new__(cls):
if cls.__instance is None:
cls.__instance = object.__new__(cls)
return cls.__instance
else:
return cls.__instance
def __init__(self):
if not self.__hasInit:
with open("%s/server-public.pem" % PEM_DIR) as f:
public_key = f.read()
f.close()
self.public_key = public_key
with open("%s/server-private.pem" % PEM_DIR) as f:
private_key = f.read()
f.close()
self.private_key = private_key
self.__hasInit = True
# todo 长度隐患旧方法
# 使用公钥对内容进行rsa 加密
def Encrypt(self, msg):
key = self.public_key
rsakey = RSA.importKey(key)
cipher = Cipher_pkcs1_v1_5.new(rsakey)
cipher_text = base64.b64encode(cipher.encrypt(msg.encode('utf-8')))
return cipher_text.decode('utf-8')
# 使用私钥对内容进行rsa 解密
def Decrypt(self, msg):
random_generator = Random.new().read
key = self.private_key
rsakey = RSA.importKey(key)
cipher = Cipher_pkcs1_v1_5.new(rsakey)
text = cipher.decrypt(base64.b64decode(msg), random_generator)
return text.decode('utf-8')AES
工具类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#!/usr/bin/env python
# -*- coding: UTF-8 -*-
# time : 2022/2/8
# __author__ = Ysc
from Crypto.Cipher import AES
import base64
class AESCipher:
def __init__(self, key: str, iv: str):
if len(key) != 16 or len(iv) != 16:
log.error(f"key or iv 长度异常: {key}, {iv} ")
raise ValueError("length error")
self.key = bytes(key, encoding='utf-8')
self.iv = bytes(iv, encoding='utf-8')
def pkcs7padding(self, text):
"""
明文使用PKCS7填充
最终调用AES加密方法时,传入的是一个byte数组,要求是16的整数倍,因此需要对明文进行处理
:param text: 待加密内容(明文)
:return:
"""
bs = AES.block_size # 16
length = len(text)
bytes_length = len(bytes(text, encoding='utf-8'))
# tips:utf-8编码时,英文占1个byte,而中文占3个byte
padding_size = length if (bytes_length == length) else bytes_length
padding = bs - padding_size % bs
# tips:chr(padding)看与其它语言的约定,有的会使用'\0'
padding_text = chr(padding) * padding
return text + padding_text
def pkcs7unpadding(self, text):
"""
处理使用PKCS7填充过的数据
:param text: 解密后的字符串
:return:
"""
try:
length = len(text)
unpadding = ord(text[length - 1])
return text[0:length - unpadding]
except Exception as e:
pass
def encrypt(self, content):
"""
AES加密
key,iv使用同一个
模式cbc
填充pkcs7
:param key: 密钥
:param content: 加密内容
:return:
"""
cipher = AES.new(self.key, AES.MODE_CBC, self.iv)
# 处理明文
content_padding = self.pkcs7padding(content)
# 加密
aes_encode_bytes = cipher.encrypt(bytes(content_padding, encoding='utf-8'))
# 重新编码
result = str(base64.b64encode(aes_encode_bytes), encoding='utf-8')
return result
def decrypt(self, content):
"""
AES解密
key,iv使用同一个
模式cbc
去填充pkcs7
:param key:
:param content:
:return:
"""
try:
cipher = AES.new(self.key, AES.MODE_CBC, self.iv)
# base64解码
aes_encode_bytes = base64.b64decode(content)
# 解密
aes_decode_bytes = cipher.decrypt(aes_encode_bytes)
# 重新编码
result = str(aes_decode_bytes, encoding='utf-8')
# 去除填充内容
result = self.pkcs7unpadding(result)
except Exception as e:
pass
if result == None:
return ""
else:
return result