Skip to content

Security: Zeroshcat/LicenseManager

Security

docs/SECURITY.md

安全分析文档

当前架构

生成端(服务器)

  • 私钥(private_key.pem):用于签名许可证
  • AES密钥(aes_key.bin):用于加密许可证内容

验证端(客户端)

  • 公钥(public_key.pem):用于验证许可证签名
  • AES密钥(aes_key.bin):用于解密许可证内容

安全风险分析

1. 公钥(public_key.pem)泄露风险:

可以公开的原因:

  • 公钥密码学的基础就是公钥可以公开
  • 即使泄露,攻击者也无法:
    • ❌ 生成新的有效许可证(需要私钥签名)
    • ❌ 修改现有许可证(修改后签名会失效)
    • ❌ 伪造许可证(无法生成有效签名)

建议:

  • 公钥可以随客户端程序一起分发
  • 可以嵌入到程序中,或作为配置文件

2. AES密钥(aes_key.bin)泄露风险:中等 ⚠️

如果泄露,攻击者可以:

  • ✅ 解密许可证内容(看到设备ID、过期时间等信息)
  • ✅ 修改许可证内容(但无法重新签名)
  • ❌ 无法伪造新的有效许可证(需要私钥签名)

风险:

  • 虽然无法伪造新许可证,但可以:
    • 查看许可证中的敏感信息
    • 尝试修改许可证(虽然签名会失效,但可能用于其他攻击)

建议:

  • 不要明文存储 AES 密钥
  • 可以考虑使用代码混淆
  • 或者使用更安全的方案(见下文)

3. 私钥(private_key.pem)泄露风险:极高 🚨

如果泄露,攻击者可以:

  • ✅ 伪造任意许可证
  • ✅ 为任意设备生成有效许可证
  • ✅ 绕过所有安全措施

建议:

  • 绝对不要分发私钥
  • 私钥只存在于服务器端
  • 使用密钥管理服务(如 AWS KMS、HashiCorp Vault)
  • 定期轮换密钥

改进方案

方案1:使用代码混淆保护 AES 密钥(推荐)

将 AES 密钥嵌入到程序中,并使用代码混淆技术保护:

// 在编译时嵌入 AES 密钥
//go:embed aes_key.bin
var embeddedAESKey []byte

// 使用代码混淆工具(如 garble)编译

优点:

  • 不需要单独分发 AES 密钥文件
  • 代码混淆可以增加逆向难度

缺点:

  • 仍然可能被逆向工程
  • 需要额外的构建步骤

方案2:使用公钥加密 AES 密钥(更安全)

在许可证中包含用公钥加密的 AES 密钥:

  1. 每次生成许可证时,生成一个随机的 AES 密钥
  2. 用公钥加密这个 AES 密钥
  3. 将加密的 AES 密钥包含在许可证中
  4. 客户端用私钥解密 AES 密钥(但客户端没有私钥...)

问题: 这个方案需要客户端有私钥,但私钥不能分发。

方案3:仅使用 RSA 签名(最简单)

移除 AES 加密,只使用 RSA 签名:

  • 许可证内容:JSON(明文)+ RSA 签名
  • 客户端:只需要公钥验证签名

优点:

  • 只需要分发公钥
  • 更简单,更安全

缺点:

  • 许可证内容是明文的(但签名仍然有效)
  • 攻击者可以看到许可证内容,但无法修改(签名会失效)

方案4:使用在线验证(最安全)

对于高安全要求的场景,使用在线验证:

  • 客户端只需要公钥验证签名
  • 所有验证逻辑在服务器端
  • 服务器端可以实时检查许可证状态

当前方案的安全性评估

离线验证场景

当前方案(公钥 + AES 密钥):

  • ✅ 可以防止伪造许可证(需要私钥)
  • ✅ 可以防止修改许可证(签名会失效)
  • ⚠️ 无法防止查看许可证内容(如果有 AES 密钥)
  • ⚠️ 无法防止重放攻击(如果许可证被复制)

安全等级:中等

适用场景:

  • 一般商业软件
  • 不需要极高安全性的场景
  • 可以接受一定程度的逆向工程

不适用场景:

  • 高安全要求的软件
  • 需要防止许可证内容泄露的场景
  • 需要防止许可证复制的场景

建议

对于当前方案:

  1. 公钥可以公开分发

    • 可以嵌入到程序中
    • 可以作为配置文件
  2. AES 密钥需要保护 ⚠️

    • 考虑使用代码混淆
    • 或者嵌入到程序中
    • 不要明文存储在配置文件中
  3. 私钥绝对不能泄露 🚨

    • 只存在于服务器端
    • 使用密钥管理服务
    • 定期备份和轮换

对于高安全要求:

  1. 使用在线验证(推荐)

    • 所有验证逻辑在服务器端
    • 可以实时检查许可证状态
    • 可以防止许可证复制
  2. 使用代码混淆

    • 保护 AES 密钥
    • 增加逆向难度
  3. 定期轮换密钥

    • 定期更换密钥对
    • 通知用户更新许可证

总结

当前方案的安全性:

  • 公钥泄露:无风险
  • AES 密钥泄露:中等风险 ⚠️(可以查看内容,但无法伪造)
  • 私钥泄露:极高风险 🚨(可以伪造任意许可证)

建议:

  • 对于一般场景,当前方案足够安全
  • 公钥可以公开,AES 密钥需要一定保护
  • 对于高安全要求,考虑使用在线验证或代码混淆

There aren't any published security advisories