目录
1.需求
采用pyside6开发了一款客户端软件, 为保护核心算法源码, 采用Nuitka打包python代码,这仅仅保护了核心算法代码,不能限制用户使用软件,因此需要软件许可授权签名证书,python cryptography库是一个最优推荐!
本文着重使用private_key.sign签名,可设置mac地址列表、模块列表、到期日期等信息!
2.cryptography介绍
底层基于openssl,不需要单独安装openssl,直接pip install cryptography即可
用途1:加密-解密(数据保密,确保只有私钥拥有者解密),应用场景:加密传输对称密钥、加密敏感配置信息、安全消息传递;使用public_key.encrypt()加密,
private_key.decrypt()解密
用途2:签名(数据完整性验证、身份验证);应用场景:软件许可证签名、数字合同签名、SSL/TLS证书,使用private_key.sign()
3.实际代码
其它函数自行问deepseek、cursor等大模型,还有搜索教程!官网文档看不懂
这里仅作实例,实际python离线软件使用ca授权许可,还是可以被破解的;使用授权许可,那么就配合nuitka打包pyd、exe来保护源码,并且将公钥内置程序里面,不要将公钥写入到license中,将公钥拆分几段通过代码逻辑合并处理,增加破解难度。
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.primitives import hashes, serialization
import json
from base64 import b64encode, b64decode
# 生成密钥对
private_key = rsa.generate_private_key(public_exponent=65537, key_size=4096)
public_key = private_key.public_key()
# 保存私钥(bytes)
private_pem = private_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.TraditionalOpenSSL,
encryption_algorithm=serialization.BestAvailableEncryption(password=b"123456")
)
with open('private_key.pem', 'wb') as f:
f.write(private_pem)
# 保存公钥(不推荐)
public_pem = public_key.public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo
)
with open('public_key.pem', 'wb') as f:
f.write(public_pem)
# 加载公钥(不推荐)
with open('public_key.pem', 'rb') as f:
public_key = serialization.load_pem_public_key(f.read())
###########################################################################
上面为创建私钥、公钥,保存到本地;然后后续仅读取本地私钥即可,再用私钥创建公钥(推荐)
用私钥签名,保存相关数据签名到license.lc
###########################################################################
# 加载私钥
with open('private_key.pem', 'rb') as f:
private_key = serialization.load_pem_private_key(
f.read(),
password=b"Aa123456"
)
public_key = private_key.public_key()
# 用私钥签名许可证数据
license_data = {
"mac": "用户机器mac地址",
"expiry_date": "2024-12-31",
}
signature = private_key.sign(
json.dumps(license_data).encode(),
padding.PSS(
mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH
),
hashes.SHA256()
)
print(signature)
license = {
"data": license_data,
"signature": b64encode(signature).decode(),
"public_key": b64encode(public_key.public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo
)).decode()
}
# 实际使用 禁止将公钥存储到license中,要保证私钥和内置公钥配对,就不需要重复打包python程序了
with open("./license.lc", 'w') as f:
json.dump(license, f)
###########################################################################
客户端加载代码,实现签名授权[将lc文件放到软件指定路径下]
###########################################################################
with open("./license.lc", "r") as f:
license = json.load(f)
from cryptography.exceptions import InvalidSignature
public_key = serialization.load_pem_public_key(
b64decode(license["public_key"])
)
try:
public_key.verify(
b64decode(license["signature"]),
json.dumps(license["data"]).encode(),
padding.PSS(
mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH
),
hashes.SHA256()
)
print("签名验证通过")
except InvalidSignature:
print("无效签名!许可证可能被篡改")
4.结束语
通过签名授权证书,可以授权软件使用、到期、绑定mac地址、模块权限