鸿蒙 PC使用ohos-pip-autosign激活自动签名工具,安装第三方库pycryptodome实现Python对称加密(AES、DES)
·
欢迎加入开源鸿蒙PC社区:https://harmonypc.csdn.net/
欢迎在PC社区平台申请新建项目:https://atomgit.com/OpenHarmonyPCDeveloper
AtomGit 仓库地址:https://atomgit.com/OpenHarmonyPCDeveloper/ohos_python_numpy
1. 环境搭建:
本文介绍在鸿蒙 PC+CodeArts IDE 搭建 Python 开发环境。借助鸿蒙专属包管理器 Harmonybrew 安装适配版 Python,搭配 ohos-pip-autosign 自动签名工具,解决系统对动态库的签名限制。通过虚拟环境隔离依赖,以 NumPy 完成安装与脚本测试,成功解决权限报错,搭建出可用的 Python 开发环境。
可以参考以下文章OpenHarmony 鸿蒙 PC + CodeArts IDE 实现 Python开发完整开发环境搭建指南
pycryptodome 完整教程 + 全套可运行Demo
一、pycryptodome 是什么
pycryptodome 是 Python 主流密码学工具库,是已经停止维护的 pycrypto 的官方替代升级版。
它封装了几乎所有业务常用加密、解密、签名、哈希算法,统一接口、修复大量旧库bug,兼容 Python3.7+。
核心作用分类
- 对称加密(AES、DES)
同一密钥加密/解密,速度快,适合加密大段报文、接口数据、表单文本;项目最常用 AES。 - 非对称加密(RSA)
公私钥分离:公钥加密、私钥解密;用于加密 AES 密钥、前端登录密码加密。 - 哈希摘要(MD5、SHA1、SHA256、SHA512)
不可逆,仅做校验:文件完整性校验、用户密码加盐存储。 - HMAC 带密钥哈希签名(HMAC-SHA256)
接口请求签名,防止中间人篡改请求参数,后端校验合法性。 - 辅助工具
随机安全密钥生成、PKCS7填充、Base64编码、字节转换。
安装命令
pip install pycryptodome
导入包名固定为
Crypto,不是pycryptodome

二、通用前置模块(所有示例共用)
import base64
from Crypto.Random import get_random_bytes
from Crypto.Util.Padding import pad, unpad
Demo1:AES-CBC 对称加密(前后端接口最常用)
规则
- AES-256 密钥固定 32字节;AES-128 16字节
- CBC 模式必须传入 16字节 IV 向量,加密解密一致
- 明文必须是16字节整数倍,使用 PKCS7 填充
- IV + 密文拼接后 Base64 传输,兼容HTTP参数
from Crypto.Cipher import AES
import base64
from Crypto.Random import get_random_bytes
from Crypto.Util.Padding import pad, unpad
class AesCBCUtil:
# 生成32字节 AES-256 安全密钥
@staticmethod
def generate_aes_key():
return get_random_bytes(32)
# 加密
@staticmethod
def encrypt(plain_text: str, key: bytes) -> str:
# 生成随机16位IV
iv = get_random_bytes(16)
cipher = AES.new(key, AES.MODE_CBC, iv)
# utf-8编码 + PKCS7填充
raw_data = pad(plain_text.encode("utf-8"), AES.block_size)
encrypt_data = cipher.encrypt(raw_data)
# iv拼接密文,统一base64输出
combine = iv + encrypt_data
return base64.b64encode(combine).decode("utf-8")
# 解密
@staticmethod
def decrypt(cipher_b64: str, key: bytes) -> str:
combine = base64.b64decode(cipher_b64)
# 前16字节为IV,剩余为密文
iv = combine[:16]
encrypt_data = combine[16:]
cipher = AES.new(key, AES.MODE_CBC, iv)
raw_decrypt = cipher.decrypt(encrypt_data)
plain_bytes = unpad(raw_decrypt, AES.block_size)
return plain_bytes.decode("utf-8")
if __name__ == "__main__":
# 1. 生成密钥(生产环境存入配置/环境变量,不要硬编码)
aes_key = AesCBCUtil.generate_aes_key()
print("AES密钥(Base64):", base64.b64encode(aes_key).decode())
# 待加密文本(支持中文、符号、数字)
text = "测试AES加密,包含中文123!@#$%^&*()"
# 加密
enc_result = AesCBCUtil.encrypt(text, aes_key)
print("加密结果:", enc_result)
# 解密还原
dec_result = AesCBCUtil.decrypt(enc_result, aes_key)
print("解密原文:", dec_result)

Demo2:RSA 非对称加密(登录密码加密场景)
特性
- 公钥公开给前端,私钥仅后端持有
- RSA单次加密长度有限,长文本需用RSA加密AES密钥
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5
import base64
class RSAUtil:
# 生成2048位公私钥对
@staticmethod
def generate_key_pair():
rsa_key = RSA.generate(2048)
private_key = rsa_key.export_key()
public_key = rsa_key.publickey().export_key()
return private_key, public_key
# 公钥加密
@staticmethod
def encrypt(plain_text: str, pub_key_bytes: bytes) -> str:
pub_key = RSA.import_key(pub_key_bytes)
cipher = PKCS1_v1_5.new(pub_key)
enc_bytes = cipher.encrypt(plain_text.encode("utf-8"))
return base64.b64encode(enc_bytes).decode("utf-8")
# 私钥解密
@staticmethod
def decrypt(cipher_b64: str, pri_key_bytes: bytes) -> str:
pri_key = RSA.import_key(pri_key_bytes)
cipher = PKCS1_v1_5.new(pri_key)
enc_bytes = base64.b64decode(cipher_b64)
dec_bytes = cipher.decrypt(enc_bytes, sentinel=b"")
return dec_bytes.decode("utf-8")
if __name__ == "__main__":
# 生成公私钥
private, public = RSAUtil.generate_key_pair()
print("=====私钥(后端保存,禁止泄露)=====")
print(private.decode())
print("=====公钥(可发给前端)=====")
print(public.decode())
password = "Admin@123456"
# 公钥加密密码
enc_pwd = RSAUtil.encrypt(password, public)
print("RSA加密密码:", enc_pwd)
# 私钥解密
dec_pwd = RSAUtil.decrypt(enc_pwd, private)
print("解密得到密码:", dec_pwd)
Demo3:SHA256 / MD5 哈希摘要(不可逆)
用于文件校验、用户密码存储(必须加盐,不可裸存MD5)
from Crypto.Hash import MD5, SHA256
# MD5摘要
def get_md5(text: str) -> str:
h = MD5.new(text.encode("utf-8"))
return h.hexdigest()
# SHA256摘要
def get_sha256(text: str) -> str:
h = SHA256.new(text.encode("utf-8"))
return h.hexdigest()
if __name__ == "__main__":
raw_pwd = "123456"
print("MD5:", get_md5(raw_pwd))
print("SHA256:", get_sha256(raw_pwd))
# 密码加盐(生产标准做法)
salt = "user_salt_2026_secret"
safe_hash = get_sha256(raw_pwd + salt)
print("加盐SHA256密码:", safe_hash)
Demo4:HMAC-SHA256 接口请求签名(防篡改)
前后端约定密钥,所有请求参数拼接生成签名,后端校验参数未被篡改
from Crypto.Hash import SHA256
from Crypto.HMAC import HMAC
import base64
# 生成签名
def hmac_sign(secret_key: str, data: str) -> str:
hmac_obj = HMAC(secret_key.encode("utf-8"), data.encode("utf-8"), SHA256)
return base64.b64encode(hmac_obj.digest()).decode("utf-8")
# 校验签名
def hmac_verify(secret_key: str, data: str, sign: str) -> bool:
real_sign = hmac_sign(secret_key, data)
return real_sign == sign
if __name__ == "__main__":
api_secret = "project_api_secret_666"
# 请求参数拼接字符串
params = "userId=10001&name=张三&time=1781712000"
# 生成签名随请求传递
sign = hmac_sign(api_secret, params)
print("请求签名:", sign)
# 后端校验
valid = hmac_verify(api_secret, params, sign)
print("签名校验通过:", valid)
# 参数被篡改后校验失败
bad_params = "userId=99999&name=李四&time=1781712000"
print("篡改参数校验:", hmac_verify(api_secret, bad_params, sign))
Demo5:业务组合方案 RSA+AES(加密超长文本)
RSA无法加密长字符串,标准方案:
- 随机生成AES密钥加密业务明文
- RSA公钥加密AES密钥
- 同时传递加密后的密钥 + 加密报文
if __name__ == "__main__":
# 1. 生成RSA密钥对
pri_key, pub_key = RSAUtil.generate_key_pair()
# 2. 随机生成AES密钥
aes_key = AesCBCUtil.generate_aes_key()
# 超长业务文本
long_text = "一段超长接口报文" * 100
# AES加密正文
body_enc = AesCBCUtil.encrypt(long_text, aes_key)
# RSA加密AES密钥
key_enc = RSAUtil.encrypt(base64.b64encode(aes_key).decode(), pub_key)
print("加密后的AES密钥:", key_enc)
print("加密报文:", body_enc)
# 后端解密流程
aes_key_b64 = RSAUtil.decrypt(key_enc, pri_key)
real_aes_key = base64.b64decode(aes_key_b64)
origin_text = AesCBCUtil.decrypt(body_enc, real_aes_key)
print("还原文本前20字符:", origin_text[:20])
三、生产环境关键注意事项
- 密钥安全规范
AES密钥、RSA私钥、HMAC密钥禁止硬编码在代码,统一通过环境变量、配置中心读取;私钥绝不前端暴露。 - AES禁止ECB模式
ECB无IV向量,相同明文密文一致,存在严重安全漏洞,统一使用CBC/GCM。 - Base64统一传输
二进制密文、密钥网络传输必须转Base64字符串,避免二进制乱码丢失数据。 - 哈希仅做校验,不能解密
MD5/SHA256不可逆,仅用于密码存储、文件校验,不能用来加密传输数据。 - 解密必须加try-except
传入非法密文、错误密钥会直接抛出异常,业务代码捕获异常防止服务崩溃:
try:
res = AesCBCUtil.decrypt(cipher, key)
except Exception as e:
print("解密失败,数据非法")
- RSA加密长度限制
2048位RSA最多加密245字节文本,长文本必须搭配AES使用。
更多推荐



所有评论(0)