feat: 更新许可证管理功能,使用AES-256-CBC加密和解密,增加生成许可证密钥的API
This commit is contained in:
@@ -5,7 +5,8 @@ import platform
|
|||||||
import uuid
|
import uuid
|
||||||
import hashlib
|
import hashlib
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from cryptography.fernet import Fernet
|
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
|
||||||
|
from cryptography.hazmat.backends import default_backend
|
||||||
import base64
|
import base64
|
||||||
|
|
||||||
|
|
||||||
@@ -21,7 +22,38 @@ class LicenseManager:
|
|||||||
"https://your-activation-server.com/verify" # 替换为您的验证服务器地址
|
"https://your-activation-server.com/verify" # 替换为您的验证服务器地址
|
||||||
)
|
)
|
||||||
self.key = b"Kj8nP9x2Qs5mY7vR4wL1hC3fA6tD0iB8"
|
self.key = b"Kj8nP9x2Qs5mY7vR4wL1hC3fA6tD0iB8"
|
||||||
self.fernet = Fernet(base64.b64encode(self.key))
|
|
||||||
|
def encrypt(self, text):
|
||||||
|
"""使用AES-256-CBC加密"""
|
||||||
|
cipher = Cipher(
|
||||||
|
algorithms.AES(self.key),
|
||||||
|
modes.CBC(self.key[:16]),
|
||||||
|
backend=default_backend(),
|
||||||
|
)
|
||||||
|
encryptor = cipher.encryptor()
|
||||||
|
|
||||||
|
# 添加PKCS7填充
|
||||||
|
length = 16 - (len(text) % 16)
|
||||||
|
text += bytes([length]) * length
|
||||||
|
|
||||||
|
encrypted = encryptor.update(text) + encryptor.finalize()
|
||||||
|
return base64.b64encode(encrypted).decode("utf-8")
|
||||||
|
|
||||||
|
def decrypt(self, encrypted_text):
|
||||||
|
"""使用AES-256-CBC解密"""
|
||||||
|
encrypted = base64.b64decode(encrypted_text)
|
||||||
|
cipher = Cipher(
|
||||||
|
algorithms.AES(self.key),
|
||||||
|
modes.CBC(self.key[:16]),
|
||||||
|
backend=default_backend(),
|
||||||
|
)
|
||||||
|
decryptor = cipher.decryptor()
|
||||||
|
|
||||||
|
decrypted = decryptor.update(encrypted) + decryptor.finalize()
|
||||||
|
|
||||||
|
# 移除PKCS7填充
|
||||||
|
padding_length = decrypted[-1]
|
||||||
|
return decrypted[:-padding_length]
|
||||||
|
|
||||||
def get_hardware_info(self):
|
def get_hardware_info(self):
|
||||||
"""获取硬件信息作为机器码"""
|
"""获取硬件信息作为机器码"""
|
||||||
@@ -127,8 +159,8 @@ class LicenseManager:
|
|||||||
"""加密保存许可证数据"""
|
"""加密保存许可证数据"""
|
||||||
try:
|
try:
|
||||||
os.makedirs(os.path.dirname(self.license_file), exist_ok=True)
|
os.makedirs(os.path.dirname(self.license_file), exist_ok=True)
|
||||||
encrypted_data = self.fernet.encrypt(json.dumps(license_data).encode())
|
encrypted_data = self.encrypt(json.dumps(license_data).encode())
|
||||||
with open(self.license_file, "wb") as f:
|
with open(self.license_file, "w") as f:
|
||||||
f.write(encrypted_data)
|
f.write(encrypted_data)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"保存许可证出错: {e}")
|
print(f"保存许可证出错: {e}")
|
||||||
@@ -136,9 +168,9 @@ class LicenseManager:
|
|||||||
def _load_license(self):
|
def _load_license(self):
|
||||||
"""加密读取许可证数据"""
|
"""加密读取许可证数据"""
|
||||||
try:
|
try:
|
||||||
with open(self.license_file, "rb") as f:
|
with open(self.license_file, "r") as f:
|
||||||
encrypted_data = f.read()
|
encrypted_data = f.read()
|
||||||
decrypted_data = self.fernet.decrypt(encrypted_data)
|
decrypted_data = self.decrypt(encrypted_data)
|
||||||
return json.loads(decrypted_data)
|
return json.loads(decrypted_data)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"读取许可证出错: {e}")
|
print(f"读取许可证出错: {e}")
|
||||||
|
|||||||
@@ -12,11 +12,50 @@ const app = express();
|
|||||||
app.use(cors());
|
app.use(cors());
|
||||||
app.use(express.json());
|
app.use(express.json());
|
||||||
|
|
||||||
|
// Encryption functions
|
||||||
|
function encryptLicenseKey(text) {
|
||||||
|
const cipher = crypto.createCipher('aes-256-cbc', process.env.ENCRYPTION_KEY);
|
||||||
|
let encrypted = cipher.update(text, 'utf8', 'hex');
|
||||||
|
encrypted += cipher.final('hex');
|
||||||
|
return encrypted;
|
||||||
|
}
|
||||||
|
|
||||||
|
function decryptLicenseKey(encrypted) {
|
||||||
|
const decipher = crypto.createDecipher('aes-256-cbc', process.env.ENCRYPTION_KEY);
|
||||||
|
let decrypted = decipher.update(encrypted, 'hex', 'utf8');
|
||||||
|
decrypted += decipher.final('utf8');
|
||||||
|
return decrypted;
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateLicenseKey() {
|
||||||
|
const randomBytes = crypto.randomBytes(16);
|
||||||
|
const timestamp = Date.now().toString();
|
||||||
|
const combined = randomBytes.toString('hex') + timestamp;
|
||||||
|
return encryptLicenseKey(combined).substring(0, 32); // 生成32位的许可证密钥
|
||||||
|
}
|
||||||
|
|
||||||
// Connect to MongoDB
|
// Connect to MongoDB
|
||||||
mongoose.connect(process.env.MONGODB_URI)
|
mongoose.connect(process.env.MONGODB_URI)
|
||||||
.then(() => console.log('Connected to MongoDB'))
|
.then(() => console.log('Connected to MongoDB'))
|
||||||
.catch(err => console.error('MongoDB connection error:', err));
|
.catch(err => console.error('MongoDB connection error:', err));
|
||||||
|
|
||||||
|
// Generate license key endpoint
|
||||||
|
app.post('/generate', async (req, res) => {
|
||||||
|
try {
|
||||||
|
const licenseKey = generateLicenseKey();
|
||||||
|
return res.json({
|
||||||
|
success: true,
|
||||||
|
license_key: licenseKey
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('生成许可证错误:', error);
|
||||||
|
return res.status(500).json({
|
||||||
|
success: false,
|
||||||
|
message: '服务器错误'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Activation endpoint
|
// Activation endpoint
|
||||||
app.post('/activate', async (req, res) => {
|
app.post('/activate', async (req, res) => {
|
||||||
try {
|
try {
|
||||||
@@ -30,6 +69,16 @@ app.post('/activate', async (req, res) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Validate license key format
|
||||||
|
try {
|
||||||
|
decryptLicenseKey(license_key);
|
||||||
|
} catch (error) {
|
||||||
|
return res.status(400).json({
|
||||||
|
success: false,
|
||||||
|
message: '无效的许可证密钥'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Check if license already exists
|
// Check if license already exists
|
||||||
const existingLicense = await License.findOne({ licenseKey: license_key });
|
const existingLicense = await License.findOne({ licenseKey: license_key });
|
||||||
if (existingLicense) {
|
if (existingLicense) {
|
||||||
@@ -90,6 +139,16 @@ app.post('/verify', async (req, res) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Validate license key format
|
||||||
|
try {
|
||||||
|
decryptLicenseKey(license_key);
|
||||||
|
} catch (error) {
|
||||||
|
return res.status(400).json({
|
||||||
|
success: false,
|
||||||
|
message: '无效的许可证密钥'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Find license
|
// Find license
|
||||||
const license = await License.findOne({ licenseKey: license_key });
|
const license = await License.findOne({ licenseKey: license_key });
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user