# PCIe密码卡强类型封装设计(第一期) - 日期:2026-02-28 - 范围:基于 `0018接口.pdf`(国密标准SDF)与 `PCIE密码卡应用接口说明书.docx`(SDFE扩展) - 目标:为上层提供强类型业务方法,屏蔽底层JNA细节 ## 1. 设计目标与约束 ### 1.1 目标 1. 提供强类型业务方法,不要求上层使用 `execute(command, params)`。 2. 采用短连接会话模型:每个业务方法内部完成 `openDevice/openSession/call/closeSession/closeDevice`。 3. 第一期开通核心子集接口,覆盖设备管理、会话、HMAC、LMK与常用密钥管理。 4. 统一错误模型与错误码映射,便于上层处理与运维排障。 ### 1.2 非目标 1. 不在第一期覆盖文档所有SDF/SDFE接口。 2. 不在第一期做多设备负载均衡与高并发优化。 3. 不在第一期实现JNI桥代码生成。 ## 2. 方案选型 ### 2.1 备选方案 1. 动态命令入口(`execute(command, params)`)+ 强类型外观。 2. 纯强类型服务(推荐)。 3. 从头文件自动生成绑定与服务代码。 ### 2.2 选型结论 采用方案2:新增 `PcieCryptoService` 及其 `JnaPcieCryptoService` 实现, 强类型方法直接调用JNA映射,统一通过短连接模板管理句柄生命周期。 ## 3. 总体架构 ### 3.1 分层 1. `PcieCryptoService`:面向上层的强类型业务接口。 2. `JnaPcieCryptoService`:服务实现,调用 `PcieNativeLibrary`。 3. `PcieSessionTemplate`:统一短连接模板。 4. `PcieNativeLibrary`:JNA native函数映射。 5. `PcieErrorMapper`:错误码映射(`retCode -> 业务可读信息`)。 ### 3.2 调用路径 上层业务 -> `PcieCryptoService` 强类型方法 -> `PcieSessionTemplate` -> `PcieNativeLibrary` -> 厂商 `.so` ## 4. 第一期开通接口(核心子集) ### 4.1 设备与会话 1. `getDeviceNumber()` -> `SDFE_GetDeviceNumber` 2. `getNormalDeviceNumber()` -> `SDFE_GetNormalDeviceNumber` 3. `deviceSelfTest()` -> `SDFE_DeviceSelfTest` 4. `deviceConfGet()` -> `SDFE_DeviceConfGet` 5. `initIdentify(oldPin, newPin)` -> `SDFE_InitIdentify` > 注:`open/close` 作为模板内部行为,不暴露给上层业务接口。 ### 4.2 常用密钥管理(用户确认的8组) 1. `generateKeyPairEcc` / `generateKeyPairRsa` 2. `generateKek` 3. `backupUserKey` / `recoverUserKey` 4. `backupKek` / `recoverKek` 5. `deleteUserKey` / `deleteKek` 6. `statusUserKeyEcc` / `statusUserKeyRsa` 7. `statusKek` 8. `changePrivateKeyAccessPassword` ### 4.3 HMAC 1. `hmac(algId, key, data)` 2. 内部流程:`SDFE_HmacInit` -> `SDFE_HmacUpdate` -> `SDFE_HmacFinal` ### 4.4 LMK(核心) 1. `generateLmk` / `loadLmk` / `backupLmk` / `recoverLmk` / `destroyLmk` 2. `checkLmk` / `exportLmkSeedMac` ## 5. 强类型模型 ### 5.1 请求对象 1. `GenerateKeyRequest`:`keyIndex`, `keyBits`, `keyType` 2. `RecoverUserKeyRequest`:`keyIndex`, `keyType`, `cipherKeyData`, `storeFlag` 3. `RecoverKekRequest`:`keyIndex`, `cipherKeyData` 4. `ChangePrivateKeyPasswordRequest`:`keyIndex`, `oldPassword`, `newPassword` 5. `HmacRequest`:`algId`, `key`, `data` ### 5.2 响应对象 1. `OperationResult`:`success`, `retCode`, `message` 2. `DeviceCountResult`:`deviceNumber`, `normalDeviceNumber` 3. `DeviceConfResult`:映射 `SDFE_DeviceConf` 4. `BackupUserKeyResult` / `BackupKekResult`:`data`, `length` 5. `KeyStatusResult`:`keyState` 6. `HmacResult`:`hmac`, `hmacLength` ## 6. 会话模板(短连接) 定义统一模板方法: ```text executeWithSession(apiName, callback): SDF_OpenDevice SDF_OpenSession callback(session) SDF_CloseSession SDF_CloseDevice ``` 约束: 1. 所有强类型方法必须通过模板执行。 2. 关闭失败仅记录日志,不覆盖主调用错误。 3. 模板保证异常场景也能回收句柄。 ## 7. 错误处理 1. `retCode == 0`:成功。 2. `retCode != 0`:抛 `PcieCryptoException(apiName, retCode, mappedMessage)`。 3. 映射文档补充错误码: - `SDR_UKEYERR` - `SDR_GENKEYERR` - `SDR_STATEERR` - `SDR_RETRYERR` - `SDR_DEVICE_BUSY` - `SDR_RET_ERR_STATUS` - `SDR_RET_INIT_STATUS` - `SDR_RET_LOGINED` - `SDR_RET_GD32_TIMEOUT` 4. 参数校验失败在服务层抛 `IllegalArgumentException`,不下发至设备。 ## 8. 并发与安全 1. 第一期开启串行访问(单设备锁)避免状态错乱。 2. PIN/口令参数不打印明文日志。 3. 密钥备份字节在服务层保持二进制,不做文本日志输出。 ## 9. 对上层的使用方式 示例: 1. `pcieCryptoService.generateLmk()` 2. `pcieCryptoService.backupKek(keyIndex, outBufferSize)` 3. `pcieCryptoService.hmac(request)` 上层仅依赖强类型接口与DTO,不直接依赖JNA类型和指针。 ## 10. 验收标准 1. 强类型接口可完成第一期核心子集调用。 2. 每个方法均使用短连接模板。 3. 统一异常中包含 `apiName + retCode + mappedMessage`。 4. `mvn -DskipTests compile` 通过。 5. 关键路径联调用例可跑通: - `getDeviceNumber` - `deviceConfGet` - `hmac` - `generateKek + statusKek` ## 11. 后续扩展 1. 第二期覆盖U盾与内部密钥管理。 2. 第三期覆盖全量SDF/SDFE并补充结构体严格对齐校验。 3. 加入真实设备集成测试与回放测试。