siling-license
v1.0.7
Published
Node SDK for encryption and authorization
Maintainers
Readme
Node.js 授权 SDK
一个安全、可靠的 Node.js 软件授权和验证机制。该 SDK 通过客户端与服务端结合的方式,实现了基于机器唯一指纹的许可证(License)生成、请求和验证的完整闭环。
特性
- 基于机器指纹的许可证绑定,确保许可证无法在未授权的设备上使用
- 非对称加密架构,使用四个完全不同的密钥(A1、A2、B1、B2)确保最高级别的安全性
- 全面的错误处理和日志记录
- 完整的 TypeScript 类型定义
- 高覆盖率的单元测试
安装
npm install siling-license系统要求
- Node.js 16.0.0 或更高版本
快速开始
编译项目
# 安装依赖
npm install
# 编译TypeScript代码
npm run build
# 运行测试
npm test运行演示程序
我们提供了一个完整的演示程序,展示SDK的所有核心功能:
# 编译项目
npm run build
# 运行演示
node dist/examples/demo.js演示程序展示了完整的授权流程:
- 生成密钥对
- 客户端获取机器ID
- 客户端创建许可证请求
- 服务端解析许可证请求
- 服务端创建许可证
- 客户端验证许可证
更多详情请查看 examples/README.md。
安全架构
该 SDK 采用了非对称加密(公钥/私钥)体系,涉及两对独立的公私钥对:
密钥对 A (用于许可证请求流程)
- A1 (服务端公钥): 安全地分发给客户端,用于加密许可证请求。
- A2 (服务端私钥): 在服务端严格保密,用于解密客户端的请求。
密钥对 B (用于许可证分发流程)
- B1 (服务端公钥): 安全地分发给客户端,用于解密和验证服务端下发的许可证。
- B2 (服务端私钥): 在服务端严格保密,用于加密和签名生成最终的许可证。
使用方法
客户端使用示例
import { getMachineId, createLicenseRequest, verifyLicense } from 'siling-license';
import { readFileSync } from 'fs';
// 读取公钥
const keyA1 = readFileSync('path/to/keyA1.pem', 'utf8');
const keyB1 = readFileSync('path/to/keyB1.pem', 'utf8');
async function main() {
try {
// 1. 获取机器指纹ID
const machineId = await getMachineId();
console.log('Machine ID:', machineId);
// 2. 创建许可证请求
const payload = {
username: 'testuser',
email: '[email protected]',
product: 'ExampleApp',
features: ['basic', 'premium']
};
const licenseRequest = await createLicenseRequest({
machineId,
payload,
keyA1
});
console.log('License Request:', licenseRequest);
// 3. 将请求发送到服务器(例如使用HTTP请求)
// const response = await sendRequestToServer(licenseRequest);
// const license = response.data.license;
// 4. 验证并解析从服务器接收到的许可证
const license = '...'; // 从服务器获取的许可证
const content = await verifyLicense({
license,
machineId,
keyB1
});
console.log('License is valid, content:', content);
// 根据许可证内容授权应用程序功能
} catch (error) {
console.error('License verification failed:', error);
}
}
main();服务端使用示例
import { parseLicenseRequest, createLicense } from 'siling-license';
import { readFileSync } from 'fs';
// 读取私钥
const keyA2 = readFileSync('path/to/keyA2.pem', 'utf8');
const keyB2 = readFileSync('path/to/keyB2.pem', 'utf8');
async function handleLicenseRequest(requestString: string) {
try {
// 1. 解析和验证许可证请求
const { machineId, payload } = await parseLicenseRequest({
request: requestString,
keyA2
});
console.log('Received request from machine:', machineId);
console.log('Payload:', payload);
// 2. 在实际应用中,此处应验证用户身份、检查付款状态等
// if (!isValidUser(payload.username) || !hasPaidSubscription(payload.username)) {
// throw new Error('Unauthorized license request');
// }
// 3. 创建许可证内容 - 这部分将发送回客户端
const licenseContent = {
username: payload.username,
product: payload.product,
features: payload.features,
expiresAt: new Date(Date.now() + 365 * 24 * 60 * 60 * 1000).toISOString(), // 1年有效期
issuedAt: new Date().toISOString()
};
// 4. 生成加密许可证
const license = await createLicense({
machineId,
content: licenseContent,
keyB2
});
console.log('License created successfully');
return license;
} catch (error) {
console.error('Failed to process license request:', error);
throw error;
}
}
// 示例请求处理
async function main() {
const requestString = '...'; // 从客户端接收的加密请求
const license = await handleLicenseRequest(requestString);
console.log('License to send back to client:', license);
}
main();密钥生成指南
您需要生成两对 RSA 密钥对(A 和 B)以使用此 SDK。以下是使用 OpenSSL 生成密钥的方法:
# 生成密钥对 A
openssl genrsa -out keyA2.pem 4096
openssl rsa -pubout -in keyA2.pem -out keyA1.pem
# 生成密钥对 B
openssl genrsa -out keyB2.pem 4096
openssl rsa -pubout -in keyB2.pem -out keyB1.pem注意: 推荐使用 4096 位密钥长度以确保在 Node.js 16+ 版本中有足够的加密容量。
安全考量
- 私钥(A2 和 B2)必须严格保密,建议存储在安全的密钥管理系统中
- 公钥(A1 和 B1)可以分发给客户端
- 建议定期轮换密钥以提高安全性
- 在生产环境中,请勿在代码中硬编码密钥
- 使用环境变量或安全的配置管理解决方案存储密钥路径
调试与日志
SDK 提供了可配置的日志级别,默认情况下:
- 在生产环境中,日志级别为 ERROR
- 在开发环境中,日志级别为 INFO
您可以通过以下方式调整日志级别:
import { setLogLevel, LogLevel } from 'siling-license';
// 设置详细日志以便调试
setLogLevel(LogLevel.DEBUG);API 文档
更详细的 API 文档请查看 API.md 文件。
贡献
欢迎贡献代码和提出问题!请确保遵循项目的代码规范并添加适当的测试。
许可证
ISC
