欢迎加入开源鸿蒙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+。

核心作用分类
  1. 对称加密(AES、DES)
    同一密钥加密/解密,速度快,适合加密大段报文、接口数据、表单文本;项目最常用 AES。
  2. 非对称加密(RSA)
    公私钥分离:公钥加密、私钥解密;用于加密 AES 密钥、前端登录密码加密。
  3. 哈希摘要(MD5、SHA1、SHA256、SHA512)
    不可逆,仅做校验:文件完整性校验、用户密码加盐存储。
  4. HMAC 带密钥哈希签名(HMAC-SHA256)
    接口请求签名,防止中间人篡改请求参数,后端校验合法性。
  5. 辅助工具
    随机安全密钥生成、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 对称加密(前后端接口最常用)

规则
  1. AES-256 密钥固定 32字节;AES-128 16字节
  2. CBC 模式必须传入 16字节 IV 向量,加密解密一致
  3. 明文必须是16字节整数倍,使用 PKCS7 填充
  4. 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)

请添加图片描述


这份代码是标准 AES-256-CBC 对称加密实现,使用 PKCS7 填充、随机IV、IV与密文拼接Base64输出,是业务开发最常用的加密方案,下面分依赖、类方法、主函数、加密流程、解密流程、安全要点完整拆解。

一、导入模块说明

from Crypto.Cipher import AES
import base64
from Crypto.Random import get_random_bytes
from Crypto.Util.Padding import pad, unpad
  1. Crypto.Cipher.AES:PyCryptodome 库提供的AES加密核心类,负责创建加密/解密器
  2. base64:二进制密文、密钥无法直接传输存储,转Base64字符串方便接口/数据库保存
  3. get_random_bytes:密码学安全随机数生成器,用来生成密钥key偏移向量IV,比random安全百倍
  4. pad / unpad:PKCS7填充工具。AES块固定16字节,明文长度不整除16时必须填充,解密后去除填充

安装依赖:pip install pycryptodome(旧库pycrypto已废弃)

二、工具类 AesCBCUtil 全静态方法解析

1. generate_aes_key() 生成AES-256密钥

@staticmethod
def generate_aes_key():
    return get_random_bytes(32)
  • AES密钥长度规则:16字节=AES-128,24字节=AES-192,32字节=AES-256(本代码用最高安全等级)
  • get_random_bytes(32) 生成32个字节的密码学安全随机二进制密钥
  • 静态方法:不用实例化类,直接AesCBCUtil.xxx()调用

2. encrypt() 加密函数(核心流程)

入参:明文字符串、二进制key;返回:Base64密文字符串

@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")

分步拆解加密逻辑:

  1. 生成16字节IV(偏移向量)
    CBC模式必须携带IV,且每次加密必须随机、不可复用;IV长度固定等于AES块大小16字节。
    作用:相同明文+相同key,不同IV会产出完全不同密文,抵御重放攻击。
  2. 创建AES CBC加密器:AES.new(密钥, 模式, IV)
  3. 明文转二进制:plain_text.encode("utf-8"),兼容中文、数字、特殊符号
  4. PKCS7填充 pad(二进制明文, 16)
    AES只能加密长度为16整数倍的数据。比如明文18字节,差14字节,就补14个0x0E;刚好16字节就补16个0x10
  5. 执行加密得到密文字节串 encrypt_data
  6. IV + 密文拼接 combine = iv + encrypt_data
    解密时必须拿到加密时用的同一个IV,所以直接拼在密文头部,不用单独存IV。
  7. 二进制拼接结果转Base64字符串返回,方便网络传输、数据库存储

3. decrypt() 解密函数(反向流程)

入参:加密输出的Base64密文、二进制key;返回原始明文字符串

@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")

分步拆解解密逻辑:

  1. Base64解码,还原回 iv+密文 的二进制拼接串 combine
  2. 切片拆分:前16字节是IV,剩下全部是加密后的二进制密文
  3. 使用相同key+加密时的IV,创建CBC解密器
  4. 解密得到带填充的原始二进制数据 raw_decrypt
  5. unpad 移除PKCS7填充,还原纯净明文二进制
  6. 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)
  1. 运行时先随机生成32字节AES256密钥,打印Base64格式方便保存
  2. 定义测试明文,包含中文、数字、特殊符号,验证utf-8兼容性
  3. 调用encrypt得到一串Base64密文,每次运行密文都不一样(因为IV随机)
  4. 用同一个密钥解密密文,完整还原原始文本

四、整体加密&解密完整数据流

加密链路

明文(str) → utf-8二进制 → PKCS7填充 → AES-CBC加密(随机IV) → IV拼接密文 → Base64字符串输出

解密链路

Base64密文字符串 → 解码二进制 → 切分IV+密文 → AES-CBC解密(对应IV) → 去除PKCS7填充 → utf-8明文

五、关键安全知识点(代码设计亮点+注意事项)

  1. 为什么每次加密结果不同?
    每次加密生成全新随机IV,即使明文和密钥不变,输出密文完全不同,防止攻击者通过重复密文推断数据。
  2. IV为什么不用单独存储?
    IV无保密需求,可以公开,所以直接拼接在密文头部,简化接口传参、数据库存储。
  3. 密钥绝对不能硬编码
    测试代码仅演示,线上必须放在环境变量、配置中心、密钥管理服务,不能写死在代码里;密钥丢失数据无法解密。
  4. 填充选用PKCS7
    行业标准填充方案,兼容性最好;不能用Zero填充,会存在数据歧义漏洞。
  5. CBC模式优缺点
    优点:成熟通用、兼容性强;缺点:不能并行加密,现代可选GCM模式(自带完整性校验防篡改)。当前代码只加密,无校验,有被篡改风险,高安全场景建议升级AES-GCM。
  6. 异常隐患(生产要补充try-except)
    • 传入错误密钥、篡改密文、Base64格式错误、填充不匹配都会直接抛异常;线上需要捕获ValueErrorbinascii.Error做容错。

六、运行示例效果

每次执行输出密钥和密文都随机变化,解密一定和原文一致:

AES密钥(Base64): xxxxx随机32字节base64串
加密结果:yyyyy随机base64密文
解密原文:测试AES加密,包含中文123!@#$%^&*()

七、生产环境改造建议

  1. 增加异常捕获,封装统一错误返回
  2. 密钥从环境变量读取,禁止运行时临时生成密钥持久化使用
  3. 高安全场景替换为AES-GCM,增加消息认证码,防止密文篡改
  4. 封装密钥Base64转换工具,方便配置文件读写密钥
  5. 增加入参判空,避免空字符串加密报错

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无法加密长字符串,标准方案:

  1. 随机生成AES密钥加密业务明文
  2. RSA公钥加密AES密钥
  3. 同时传递加密后的密钥 + 加密报文
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])

三、生产环境关键注意事项

  1. 密钥安全规范
    AES密钥、RSA私钥、HMAC密钥禁止硬编码在代码,统一通过环境变量、配置中心读取;私钥绝不前端暴露。
  2. AES禁止ECB模式
    ECB无IV向量,相同明文密文一致,存在严重安全漏洞,统一使用CBC/GCM。
  3. Base64统一传输
    二进制密文、密钥网络传输必须转Base64字符串,避免二进制乱码丢失数据。
  4. 哈希仅做校验,不能解密
    MD5/SHA256不可逆,仅用于密码存储、文件校验,不能用来加密传输数据。
  5. 解密必须加try-except
    传入非法密文、错误密钥会直接抛出异常,业务代码捕获异常防止服务崩溃:
try:
    res = AesCBCUtil.decrypt(cipher, key)
except Exception as e:
    print("解密失败,数据非法")
  1. RSA加密长度限制
    2048位RSA最多加密245字节文本,长文本必须搭配AES使用。
Logo

这里是“一人公司”的成长家园。我们提供从产品曝光、技术变现到法律财税的全栈内容,并连接云服务、办公空间等稀缺资源,助你专注创造,无忧运营。

更多推荐