1. 背景与目标

在高校信息化项目(尤其是商业软件交付或SaaS私有化部署)中,需要解决两个核心问题:

  1. 授权控制:防止未授权使用、超期使用、盗版扩散。

  2. 敏感数据保护:配置文件、数据库连接、核心算法、学生隐私信息的存储与传输安全。

本方案设计一套基于 Java 原生加密体系(JCA/JCE) 的许可证管理与数据加密解密机制,支持离线/在线两种授权模式,确保系统在非授权状态下无法完整运行。


2. 总体设计思路

2.1 核心原则

  • 信任锚点:高校本地环境不可信,必须通过数字签名验证授权文件。

  • 分层加密:网络传输、配置文件、数据库字段采用不同强度算法。

  • 防调试/防篡改:结合环境指纹(MAC、CPU序列号、硬盘序列号)绑定许可证。

2.2 技术栈

层次 技术选型
对称加密 AES-256(GCM模式,兼顾加密+完整性)
非对称加密 RSA-2048 / 4096(私钥签名许可证,公钥验证)
哈希摘要 SHA-256 / SM3(国密可选)
编码方式 Base64(文本传输)、Hex(日志输出)
密钥管理 硬件加密机(HSM)或 JKS/PKCS12 密钥库

3. 许可证(License)设计

3.1 许可证内容结构(JSON格式)

json

{
  "licenseId": "HEU-2026-001",
  "customer": "哈尔滨工程大学",
  "version": "6.0",
  "modules": ["教务中心","选课中心","学工系统"],
  "maxConcurrent": 5000,
  "expiryDate": "2027-12-31",
  "fingerprint": "A3F5E2C9B1...",
  "signature": "RSA-SHA256..."
}

3.2 绑定策略:环境指纹

采集项

  • 主网卡 MAC 地址(SHA-256 哈希后存储)

  • 主板序列号(Windows: wmic baseboard / Linux: /sys/class/dmi/id/board_serial

  • 指定磁盘卷序列号

Java 代码示例(部分指纹采集)

java

// 获取 MAC 地址(去除非ASCII)
NetworkInterface ni = NetworkInterface.getByInetAddress(InetAddress.getLocalHost());
byte[] mac = ni.getHardwareAddress();
String fingerprint = DigestUtils.sha256Hex(Hex.encodeHexString(mac));

签名生成:服务端使用 RSA 私钥对 (license内容+指纹) 签名,本地公钥验证。

3.3 许可证验证流程(启动时执行)

3.4 离线与在线授权对比

模式 优点 实现方式
离线授权 高校内网安全,不依赖外网 提供 .lic 文件,定期更换
在线授权 可实时控制、吊销方便 启动时向授权服务器请求,返回 JWT 票据

推荐:离线为主 + 在线心跳(每7天校验一次在线状态,异常则降级)。


4. 数据加密解密设计

4.1 配置文件敏感信息加密

场景:数据库密码、Redis密码、第三方API Key。

方案:使用 AES-256 + 固定密钥(或密钥派生自环境变量)。

java

// 工具类示例
public class CryptoUtil {
    private static final SecretKey AES_KEY = new SecretKeySpec(
        "0123456789abcdef0123456789abcdef".getBytes(), "AES"
    );

    public static String encrypt(String plainText) {
        Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
        cipher.init(Cipher.ENCRYPT_MODE, AES_KEY);
        byte[] cipherText = cipher.doFinal(plainText.getBytes());
        return Base64.getEncoder().encodeToString(cipherText);
    }

    public static String decrypt(String cipherBase64) { ... }
}

配置加载

yaml

# application.yml 中存储密文
spring:
  datasource:
    password: ENC(U2FsdGVkX1/sFjKFmQJ9jR+6sG0=)

启动时用 @ConfigurationProperties 配合 PropertySource 自动解密。

4.2 数据库字段级加密(学生隐私)

适用字段:身份证号、手机号、家庭住址、银行卡号。

实现策略

策略 说明
JPA 监听器 @PrePersist / @PreUpdate 自动加解密
MyBatis TypeHandler 自定义 EncryptTypeHandler
数据库加密中间件 如 ShardingSphere 的加密模块

TypeHandler 示例

java

@MappedJdbcTypes(JdbcType.VARCHAR)
public class EncryptHandler extends BaseTypeHandler<String> {
    @Override
    public void setNonNullParameter(...) {
        ps.setString(i, CryptoUtil.encrypt(parameter));
    }
    @Override
    public String getNullableResult(...) {
        return CryptoUtil.decrypt(rs.getString(columnName));
    }
}

4.3 传输层加密

  • 强制 HTTPS:Nginx/Tomcat 配置 TLS 1.2+。

  • 二次加密:对极端敏感接口(如修改密码)额外使用 RSA 加密前端传输的临时密码。


5. 防破解与反调试简易措施

由于 Java 字节码容易被反编译,需要增加对抗措施:

措施 说明
代码混淆 使用 ProGuard / Allatori(混淆类名、方法名、字符串加密)
关键逻辑下沉 许可证验证核心写到 native 方法(JNI/C++),增加逆向难度
校验和自检 启动时校验关键 JAR 的 MD5,与内置白名单对比
时间反篡改 记录最近一次合法时间的缓存(存于加密 properties),对比系统时间突变

6. 密钥管理方案

风险:客户端必然拥有 RSA 公钥和 AES 密钥,但需要防止替换公钥。

对策

  • 将公钥硬编码在多个分散类中,并做完整性校验。

  • 使用 白盒密码(White-box cryptography)保护 AES 密钥(如使用 WhiteboxSDK)。

  • 国密改造场景下,使用 SM2(非对称)+ SM4(对称)。


7. 完整加解密调用链路示例(许可证启动验证)

java

@Component
public class LicenseValidator {
    @Value("${license.path}")
    private String licensePath;

    @PostConstruct
    public void validate() {
        String content = FileUtils.readFileToString(new File(licensePath));
        License license = JSON.parseObject(content, License.class);
        
        // 1. 验证RSA签名
        boolean sigOk = RSAUtil.verify(license.getData(), license.getSignature(), PUBLIC_KEY);
        if (!sigOk) throw new LicenseException("签名无效");
        
        // 2. 解密授权数据(内部字段可能AES加密)
        String decryptedModules = AESUtil.decrypt(license.getEncryptedModules());
        
        // 3. 比对指纹
        String currentFingerprint = FingerprintUtil.getCompositeFingerprint();
        if (!currentFingerprint.equals(license.getFingerprint())) {
            throw new LicenseException("环境非法");
        }
        
        // 4. 注入授权信息到容器
        LicenseContext.setLicense(license);
    }
}

8. 总结

目标 实现技术 防护等级
防止许可证伪造 RSA 数字签名 ★★★★★
防止移植到其他服务器 硬件指纹绑定 ★★★★☆
防止配置文件泄露敏感信息 AES 加密 + 启动时解密 ★★★★☆
防止数据库直读隐私字段 字段级加解密(TypeHandler) ★★★★☆
防止反编译调试 混淆 + JNI 关键逻辑 ★★★☆☆

本方案适用于高校私有化部署的商业软件,平衡了 安全性、开发成本、用户体验。对于极高安全要求场景(如涉及国家秘密),建议引入硬件加密机(HSM)及国密算法改造。

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐