python实现的一个简易注册机,用于离线工控机验证注册码
简易的设计流程
有一批工控机长期是断网离线的,而我们又想检查这批工控机的设备上的注册码是否已经过期,那该怎么办呢?工控机是交付出去了,需要用到非对称加密机制来设计,防止算法被破解之后,别人有能力能破解我们所有的工控机。下面废话不多说,直接上代码
服务端程序
1. 安装 cryptography
库
pip install cryptography
2. 生成密钥对(一次性操作)
在服务器端生成 RSA 公钥和私钥,这个过程只需要进行一次,并且私钥需要保密。
# 注册机密钥对生成代码
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives import serialization
# 生成 RSA 密钥对
private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048,
)
# 将私钥保存到文件
with open("private_key.pem", "wb") as private_file:
private_file.write(
private_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.PKCS8,
encryption_algorithm=serialization.NoEncryption(),
)
)
# 将公钥保存到文件
public_key = private_key.public_key()
with open("public_key.pem", "wb") as public_file:
public_file.write(
public_key.public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo,
)
)
private_key.pem
文件将用于服务器端签名注册码。(千万不要泄漏)
public_key.pem
文件可以安全地分发给客户端,用于验证签名。
3. 服务器端生成注册码并签名
服务器端生成注册码并用私钥签名。这里我们基于 IP、MAC 地址和注册时间生成注册信息。
# 注册码生成程序
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives import serialization
import hashlib
# 加载私钥
with open("private_key.pem", "rb") as private_file:
private_key = serialization.load_pem_private_key(
private_file.read(),
password=None,
)
# 生成注册信息
def generate_registration_info(ip, mac, reg_time):
return f"{ip}#{mac}#{reg_time}"
# 生成签名
def sign_registration_info(private_key, registration_info):
# 先对注册信息进行哈希处理
hash_value = hashlib.sha256(registration_info.encode()).digest()
# 使用私钥对哈希值签名
signature = private_key.sign(
hash_value,
padding.PSS(
mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH,
),
hashes.SHA256(),
)
return signature
# 示例使用
ip = "192.168.1.1"
mac = "00:1A:2B:3C:4D:5E"
reg_time = "2023-09-03T12:00:00"
registration_info = generate_registration_info(ip, mac, reg_time)
signature = sign_registration_info(private_key, registration_info)
print(f"注册信息: {registration_info}")
print(f"签名: {signature.hex()}")
客户端程序(可参考修改)
1.安装在工控机上,用于验证注册码是否正确,是否过期,设置有效期365天
2.客户端使用公钥来验证签名,以确保注册码的有效性。
# 注册机尝试
import hashlib
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives import serialization
from datetime import datetime
# 加载公钥
with open("public_key.pem", "rb") as public_file:
public_key = serialization.load_pem_public_key(public_file.read())
# 验证签名
def verify_registration_info(public_key, registration_info, signature):
# 对注册信息进行哈希处理
hash_value = hashlib.sha256(registration_info.encode()).digest()
# 使用公钥验证签名
try:
public_key.verify(
signature,
hash_value,
padding.PSS(
mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH,
),
hashes.SHA256(),
)
return True
except Exception as e:
print(f"签名验证失败: {e}")
return False
# 检查注册码是否过期
def is_registration_expired(registration_info):
# 假设 registration_info 的格式为 "IP#MAC#DATE"
try:
_, _, date_str = registration_info.split("#")
registration_date = datetime.strptime(date_str, "%Y-%m-%dT%H:%M:%S")
current_date = datetime.now()
# 计算日期差
difference = current_date - registration_date
if difference.days > 365:
print("注册码已过期。")
return True
else:
print(f"注册码有效,距离到期还有 {365 - difference.days} 天。")
return False
except Exception as e:
print(f"无法解析注册信息中的日期: {e}")
return True
# 示例使用
registration_info = "192.168.1.1#00:1A:2B:3C:4D:5E#2023-09-03T12:00:00"
signature = "4747554cb3bc12f1b25f7079f435338f78f8b9a096f7a40fe6f4d22535d5d1038ae0cff10f1f7d648201e585b19b15d45a0b0903886abda9096f7ce3dbba78b3076f7df9cec9f19616512c7dd20a4448ab1eb544be0163e84cb811cf415986551f4be21878c4ca620843e4109d4e625756560f0746dbbccd2f57ee1ba6d8f751bde45839e75229160371c955bc8d19931d647d1281f4ae6baa08dd460dbf3de0d1ac76f2217ed8e81657cce00da6342ef5d453afb0c24da10197896f89347a3dc81a482eab2e41ffe311222e86d0e6a0901ae6cce38e69700d7d4a18c9e902ea802b05292c166d561b4877619283026542e319ca35708fa32e6f86e5615f6fb0"
is_valid = verify_registration_info(
public_key, registration_info, bytes.fromhex(signature)
)
if is_valid:
print("注册码验证成功。")
# 检查注册码是否过期
is_expired = is_registration_expired(registration_info)
if not is_expired:
print("激活成功!")
else:
print("注册码验证失败。")