Rust离线激活VIP功能实现笔记
学习笔记作者:admin日期:2025-09-02点击:1
摘要:本文详细介绍了如何在Rust中实现离线激活VIP功能,包括生成设备唯一ID、使用RSA签名机制进行激活码验证以及编译发布程序的命令。重点在于安全性和稳定性,避免激活码被破解。
一、生成设备唯一ID(机器码)
目标:基于当前设备硬件信息生成一个相对唯一的、稳定的字符串,作为“机器码”。
use std::process::Command;
use sysinfo::{System, SystemExt};
fn get_machine_id() -> String {
let mut system = System::new_all();
system.refresh_all();
let mut parts = Vec::new();
// 1. 主板序列号(Linux/Windows)
if cfg!(target_os = "windows") {
if let Ok(output) = Command::new("wmic")
.args(&["baseboard", "get", "serialnumber"])
.output()
{
let sn = String::from_utf8_lossy(&output.stdout);
let sn = sn.lines().nth(1).unwrap_or("").trim();
if !sn.is_empty() && sn != "null" {
parts.push(sn.to_string());
}
}
} else if cfg!(target_os = "linux") {
if let Ok(output) = Command::new("sh")
.args(&["-c", "sudo dmidecode -s baseboard-serial-number"])
.output()
{
let sn = String::from_utf8_lossy(&output.stdout).trim().to_string();
if !sn.is_empty() && sn != "Not Specified" {
parts.push(sn);
}
}
}
// 2. CPU ID(仅 x86/x86_64 可行)
if let Some(cpu) = system.cpus().first() {
parts.push(cpu.brand().to_string());
}
// 3. 系统主机名
if let Ok(hostname) = hostname::get() {
if let Ok(hostname_str) = hostname_str.into_string() {
parts.push(hostname_str);
}
}
// 4. MAC 地址(可选,但注意隐私和虚拟机问题)
for (_name, data) in pnet_datalink::interfaces() {
if let Some(mac) = data.mac {
parts.push(mac.to_string());
break; // 只取第一个
}
}
// 拼接后哈希,避免暴露原始信息
let combined = parts.join("|");
use sha2::{Sha256, Digest};
let mut hasher = Sha256::new();
hasher.update(combined.as_bytes());
format!("{:x}", hasher.finalize())
}
二、激活机制设计(机器码 + 激活码)
推荐方案:非对称签名(RSA)
原理:
- 你在服务器端用私钥对机器码签名,生成激活码。
- 客户端用内置的公钥验证签名。
- 攻击者无法伪造激活码(没有私钥)。
- 完全离线验证。
生成密钥对(一次)
openssl genpkey -algorithm RSA -out private.pem -pkeyopt rsa_keygen_bits:2048
openssl rsa -pubout -in private.pem -out public.pem
服务端:生成激活码
use rsa::{PaddingScheme, PublicKey, RsaPrivateKey, RsaPublicKey};
use sha2::{Sha256, Digest};
use base64;
fn generate_activation_code(private_key_pem: &str, machine_id: &str) -> Result> {
let mut rng = rand::thread_rng();
let private_key = RsaPrivateKey::from_pkcs1_pem(private_key_pem)?;
let hash = Sha256::digest(machine_id.as_bytes());
let signature = private_key.sign(&mut rng, PaddingScheme::PKCS1v15Sign {
hash: Some(rsa::Hash::SHA2_256),
}, &hash)?;
Ok(base64::encode(&signature))
}
客户端:验证激活码
use rsa::{PublicKey, RsaPublicKey, PaddingScheme};
use sha2::{Sha256, Digest};
use base64;
fn verify_activation_code(public_key_pem: &str, machine_id: &str, activation_code: &str) -> bool {
let public_key = match RsaPublicKey::from_pkcs1_pem(public_key_pem) {
Ok(k) => k,
Err(_) => return false,
};
let signature = match base64::decode(activation_code) {
Ok(sig) => sig,
Err(_) => return false,
};
let hash = Sha256::digest(machine_id.as_bytes());
public_key.verify(
PaddingScheme::PKCS1v15Sign {
hash: Some(rsa::Hash::SHA2_256),
},
&hash,
&signature,
).is_ok()
}
三、防破解增强建议
措施 | 说明 |
---|---|
代码混淆 | 使用 cargo-tamper 或手动混淆关键函数名 |
检查调试器 | 检测 is_debugger_present() |
时间绑定 | 在签名中加入有效期,如 machine_id|2025-12-31 |
多因子绑定 | 绑定机器码 + 用户名,防止共享 |
定期更新公钥 | 防止私钥泄露后长期失效 |
四、完整流程
用户安装软件
↓
程序生成机器码(如:a1b2c3d4...)
↓
用户提交机器码给你
↓
你用私钥签名,生成激活码(Base64字符串)
↓
用户输入激活码
↓
程序用内置公钥验证签名是否匹配当前机器码
↓
验证通过 → 启用VIP
五、编译发布命令
基本发布编译命令
cargo build --release
查看输出文件
ls -lh target/release/
进一步减小体积
[profile.release]
opt-level = 'z' # 最小化体积
lto = true # 全局优化
codegen-units = 1 # 更慢但更小
panic = 'abort' # 移除 unwind 支持(可选)
strip = true # 自动去除调试符号(需 nightly 或 Rust 1.70+)
打包发布
mkdir -p release-v1.0.0
cp target/release/myapp release-v1.0.0/
cp README.md release-v1.0.0/
cp LICENSE release-v1.0.0/
tar -czf myapp-linux-x64-v1.0.0.tar.gz release-v1.0.0/
六、总结
推荐使用 RSA 签名方案,确保安全性、离线验证和防伪造。