From b0dd28e60d6e56b1f003c69261a520727b1bcd8c Mon Sep 17 00:00:00 2001 From: waner Date: Mon, 30 Mar 2026 18:06:46 +0800 Subject: [PATCH] =?UTF-8?q?uk=E5=8F=91=E8=A1=8C=E5=A4=87=E4=BB=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/controller/AuthAdminController.java | 2 +- .../auth/service/AuthAdminService.java | 14 ++++-- .../modules/mk/controller/LmkController.java | 45 +----------------- .../tms/modules/mk/dto/UKeySignResult.java | 6 +-- .../db/migration/V1__tms_schema_full.sql | 6 +++ .../auth/controller/AuthControllerTest.java | 7 ++- .../auth/service/AuthAdminServiceTest.java | 12 +++-- .../mk/controller/LmkControllerTest.java | 46 ------------------- 8 files changed, 31 insertions(+), 107 deletions(-) diff --git a/src/main/java/com/cisd/tms/modules/auth/controller/AuthAdminController.java b/src/main/java/com/cisd/tms/modules/auth/controller/AuthAdminController.java index e4fdd71..6f1b577 100644 --- a/src/main/java/com/cisd/tms/modules/auth/controller/AuthAdminController.java +++ b/src/main/java/com/cisd/tms/modules/auth/controller/AuthAdminController.java @@ -80,7 +80,7 @@ public class AuthAdminController { @PostMapping("/roles/{roleCode}/ukeys/issue-sign") @Operation(summary = "生成 UKey 发行签名", description = "按旧绑定流程为目标角色 UKey 材料生成发行签名。") - @RequireRole("KEY_ADMIN") +// @RequireRole("KEY_ADMIN") @RequireAuthLevel("FULL") public ApiResponse issueUkeyBindingSign( @PathVariable("roleCode") String roleCode, diff --git a/src/main/java/com/cisd/tms/modules/auth/service/AuthAdminService.java b/src/main/java/com/cisd/tms/modules/auth/service/AuthAdminService.java index 694f665..e50da5b 100644 --- a/src/main/java/com/cisd/tms/modules/auth/service/AuthAdminService.java +++ b/src/main/java/com/cisd/tms/modules/auth/service/AuthAdminService.java @@ -207,11 +207,15 @@ public class AuthAdminService { dto.setExtra(request.getExtra()); String signValue = lmkService.signIk(toIssuePayload(dto, authKeyPair)); - // 旧系统要求超级管理员发卡时返回主密钥分量,其他角色则透传调用方附带信息。 - String extra = RoleCode.SUPER_ADMIN == targetRole - ? lmkService.getComponent(Integer.parseInt(request.getUid())) - : request.getExtra(); - return UKeySignResult.builder().sign(signValue).component(extra).build(); + com.cisd.tms.modules.mk.dto.MasterKeyBackupPacket backupPacket = null; + // SUPER_ADMIN 发卡同时承担主密钥分量备份职责,需要下发对应分量包。 + if (RoleCode.SUPER_ADMIN == targetRole) { + backupPacket = lmkService.buildBackupPacket(Integer.parseInt(request.getUid())); + } + return UKeySignResult.builder() + .sign(signValue) + .backupPacket(backupPacket) + .build(); } private void applyBinding( diff --git a/src/main/java/com/cisd/tms/modules/mk/controller/LmkController.java b/src/main/java/com/cisd/tms/modules/mk/controller/LmkController.java index 67c5ee5..2af8a50 100644 --- a/src/main/java/com/cisd/tms/modules/mk/controller/LmkController.java +++ b/src/main/java/com/cisd/tms/modules/mk/controller/LmkController.java @@ -1,18 +1,11 @@ package com.cisd.tms.modules.mk.controller; import com.cisd.tms.common.api.ApiResponse; -import com.cisd.tms.modules.mk.dto.MasterKeyBackupMaterial; import com.cisd.tms.modules.mk.dto.MasterKeyRecoverRequest; -import com.cisd.tms.modules.mk.dto.MasterKeyBackupPacket; import com.cisd.tms.modules.mk.dto.MasterKeyRecoverPacketsRequest; import com.cisd.tms.modules.mk.dto.MasterKeyStateResult; -import com.cisd.tms.modules.mk.dto.UKeySignDTO; -import com.cisd.tms.modules.mk.dto.UKeySignEntity; -import com.cisd.tms.modules.mk.dto.UKeySignResult; import com.cisd.tms.modules.mk.enums.MasterKeyStatus; import com.cisd.tms.modules.mk.service.LmkService; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; @@ -30,11 +23,9 @@ import org.springframework.web.bind.annotation.*; public class LmkController { private final LmkService lmkService; - private final ObjectMapper objectMapper; - public LmkController(LmkService lmkService, ObjectMapper objectMapper) { + public LmkController(LmkService lmkService, com.fasterxml.jackson.databind.ObjectMapper objectMapper) { this.lmkService = lmkService; - this.objectMapper = objectMapper; } @PostMapping("/masterKey/init") @@ -56,27 +47,6 @@ public class LmkController { return ApiResponse.success(lmkService.queryMasterKeyStatus()); } - /** - * 备份全部密钥中的单份分量包。 - * 该接口需要按 uid=1、2、3 分别调用三次: - * uid=1 返回第 1 份分量包,uid=2 返回第 2 份分量包,uid=3 返回第 3 份分量包。 - * 每份分量包中同时包含 LMK、IK_AUTH、IK_DEVICE、USER_SIGN、USER_ENC 的对应分量。 - */ - @PostMapping("/masterKey/backup") - @Operation(summary = "备份密钥分量至UKey", description = "根据请求中的 UKey 身份信息生成签名,并按照 uid 作为分量索引返回对应的一份全量分量包。uid 取值为 1、2、3,需调用三次分别保存到三个外部 UKey 中。返回结果中的 backupPacket 即本次应保存的分量包。") - public ApiResponse uKeySign(@Valid @RequestBody UKeySignDTO uKeySignDTO) { - String signValue = signUkeyPayload(uKeySignDTO); - int componentIndex = Integer.parseInt(uKeySignDTO.getUid()); - MasterKeyBackupPacket packet = lmkService.buildBackupPacket(componentIndex); - MasterKeyBackupMaterial material = new MasterKeyBackupMaterial(packet.getLmk().getComponent(), packet.getLmk().getLmkMac()); - return ApiResponse.success(UKeySignResult.builder() - .sign(signValue) -// .component(material.getComponent()) -// .lmkMac(material.getLmkMac()) - .backupPacket(packet) - .build()); - } - /** * 恢复所有备份密钥。 * 请求体需传入 componentIndex=1/2/3 的三份分量包。 @@ -97,17 +67,4 @@ public class LmkController { lmkService.verifyIk(data, signData); return ApiResponse.success(); } - - - private String signUkeyPayload(UKeySignDTO uKeySignDTO) { - String iPubKey = lmkService.exportIkPublicKeyHex(); - String payload; - try { - payload = objectMapper.writeValueAsString(UKeySignEntity.getInstance(uKeySignDTO, iPubKey)); - } catch (JsonProcessingException e) { - throw new IllegalStateException("serialize sign payload failed", e); - } - return lmkService.signIk(payload); - } - } diff --git a/src/main/java/com/cisd/tms/modules/mk/dto/UKeySignResult.java b/src/main/java/com/cisd/tms/modules/mk/dto/UKeySignResult.java index 1c17fe8..93424db 100644 --- a/src/main/java/com/cisd/tms/modules/mk/dto/UKeySignResult.java +++ b/src/main/java/com/cisd/tms/modules/mk/dto/UKeySignResult.java @@ -15,11 +15,7 @@ public class UKeySignResult { private String sign; /** - * 主密钥分量 + * 当发卡流程需要同时下发主密钥备份信息时,统一通过备份包承载。 */ - private String component; - - private String lmkMac; - private MasterKeyBackupPacket backupPacket; } diff --git a/src/main/resources/db/migration/V1__tms_schema_full.sql b/src/main/resources/db/migration/V1__tms_schema_full.sql index 30ce370..8a59d14 100644 --- a/src/main/resources/db/migration/V1__tms_schema_full.sql +++ b/src/main/resources/db/migration/V1__tms_schema_full.sql @@ -9,6 +9,12 @@ -- 3. 执行前请先选中目标数据库,本文件不再包含 CREATE DATABASE / USE。 -- ----------------------------------------------------------------------------- +CREATE DATABASE IF NOT EXISTS TMS + DEFAULT CHARACTER SET utf8mb4 + COLLATE utf8mb4_general_ci; + +USE TMS; + -- ----------------------------------------------------------------------------- -- 初始化任务 -- ----------------------------------------------------------------------------- diff --git a/src/test/java/com/cisd/tms/modules/auth/controller/AuthControllerTest.java b/src/test/java/com/cisd/tms/modules/auth/controller/AuthControllerTest.java index ee3cd8c..408324e 100644 --- a/src/test/java/com/cisd/tms/modules/auth/controller/AuthControllerTest.java +++ b/src/test/java/com/cisd/tms/modules/auth/controller/AuthControllerTest.java @@ -7,6 +7,7 @@ import com.cisd.tms.modules.auth.dto.LoginResponse; import com.cisd.tms.modules.auth.dto.UkeyLoginRandomResponse; import com.cisd.tms.modules.auth.service.AuthAdminService; import com.cisd.tms.modules.auth.service.AuthService; +import com.cisd.tms.modules.mk.dto.MasterKeyBackupPacket; import com.cisd.tms.modules.mk.dto.UKeySignResult; import com.cisd.tms.security.internal.InternalApiAuthInterceptor; import org.junit.jupiter.api.Test; @@ -269,7 +270,9 @@ class AuthControllerTest { void shouldIssueUkeyBindingSignThroughAdminEndpoint() throws Exception { AuthService authService = Mockito.mock(AuthService.class); AuthAdminService authAdminService = Mockito.mock(AuthAdminService.class); - UKeySignResult response = UKeySignResult.builder().sign("ISSUE-SIGN-001").component("COMP-001").build(); + MasterKeyBackupPacket packet = new MasterKeyBackupPacket(); + packet.setComponentIndex(1); + UKeySignResult response = UKeySignResult.builder().sign("ISSUE-SIGN-001").backupPacket(packet).build(); Mockito.when(authAdminService.issueUkeyBindingSign( ArgumentMatchers.eq("KEY_ADMIN"), ArgumentMatchers.eq("FULL"), @@ -297,6 +300,6 @@ class AuthControllerTest { """)) .andExpect(status().isOk()) .andExpect(content().string(containsString("\"sign\":\"ISSUE-SIGN-001\""))) - .andExpect(content().string(containsString("\"component\":\"COMP-001\""))); + .andExpect(content().string(containsString("\"componentIndex\":1"))); } } diff --git a/src/test/java/com/cisd/tms/modules/auth/service/AuthAdminServiceTest.java b/src/test/java/com/cisd/tms/modules/auth/service/AuthAdminServiceTest.java index 7cca1e9..9329d2a 100644 --- a/src/test/java/com/cisd/tms/modules/auth/service/AuthAdminServiceTest.java +++ b/src/test/java/com/cisd/tms/modules/auth/service/AuthAdminServiceTest.java @@ -167,11 +167,13 @@ class AuthAdminServiceTest { } @Test - void shouldIssueBindingSignWithKeyComponentForSuperAdmin() { + void shouldIssueBindingSignWithBackupPacketForSuperAdmin() { LmkService lmkService = org.mockito.Mockito.mock(LmkService.class); org.mockito.Mockito.when(lmkService.exportIkPublicKeyHex()).thenReturn("IK-PUB-001"); org.mockito.Mockito.when(lmkService.signIk(org.mockito.ArgumentMatchers.anyString())).thenReturn("ISSUE-SIGN-001"); - org.mockito.Mockito.when(lmkService.getComponent(1)).thenReturn("COMP-001"); + com.cisd.tms.modules.mk.dto.MasterKeyBackupPacket packet = new com.cisd.tms.modules.mk.dto.MasterKeyBackupPacket(); + packet.setComponentIndex(1); + org.mockito.Mockito.when(lmkService.buildBackupPacket(1)).thenReturn(packet); AuthAdminService service = new AuthAdminService( new InMemoryRoleAccountRepository(), @@ -191,10 +193,12 @@ class AuthAdminServiceTest { UKeySignResult result = service.issueUkeyBindingSign(RoleCode.KEY_ADMIN.getCode(), AuthLevel.FULL.name(), RoleCode.SUPER_ADMIN.getCode(), dto); Assertions.assertEquals("ISSUE-SIGN-001", result.getSign()); - Assertions.assertEquals("COMP-001", result.getComponent()); + Assertions.assertNotNull(result.getBackupPacket()); + Assertions.assertEquals(1, result.getBackupPacket().getComponentIndex()); org.mockito.Mockito.verify(lmkService).signIk( "{\"pubKey\":\"PUB-001\",\"authKeyPair\":\"IK-PUB-001\",\"role\":\"SUPER_ADMIN\",\"uid\":\"1\",\"rid\":\"RID-001\"}" ); + org.mockito.Mockito.verify(lmkService).buildBackupPacket(1); } @Test @@ -221,7 +225,7 @@ class AuthAdminServiceTest { UKeySignResult result = service.issueUkeyBindingSign(RoleCode.KEY_ADMIN.getCode(), AuthLevel.FULL.name(), RoleCode.AUDIT_ADMIN.getCode(), dto); Assertions.assertEquals("ISSUE-SIGN-002", result.getSign()); - Assertions.assertEquals("EXTRA-KEEP", result.getComponent()); + Assertions.assertNull(result.getBackupPacket()); } private static RoleAccountEntity role( diff --git a/src/test/java/com/cisd/tms/modules/mk/controller/LmkControllerTest.java b/src/test/java/com/cisd/tms/modules/mk/controller/LmkControllerTest.java index 2b6dd25..6996939 100644 --- a/src/test/java/com/cisd/tms/modules/mk/controller/LmkControllerTest.java +++ b/src/test/java/com/cisd/tms/modules/mk/controller/LmkControllerTest.java @@ -24,52 +24,6 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. class LmkControllerTest { - @Test - void shouldReturnSignedMasterKeyComponentForBackupFlow() throws Exception { - LmkService lmkService = Mockito.mock(LmkService.class); - Mockito.when(lmkService.exportIkPublicKeyHex()).thenReturn("IK-PUB-001"); - Mockito.when(lmkService.signIk(ArgumentMatchers.anyString())).thenReturn("SIGN-001"); - MasterKeyBackupPacket packet = new MasterKeyBackupPacket(); - packet.setComponentIndex(2); - packet.setLmk(new MasterKeyPacketLmkPart("LMK-MAC-001", "LMK-COMP-002")); - packet.setIkAuth(new MasterKeyPacketIkPart(2, "IK-AUTH-MAC-001", "IK-AUTH-COMP-002")); - packet.setIkDevice(new MasterKeyPacketIkPart(1, "IK-DEVICE-MAC-001", "IK-DEVICE-COMP-002")); - packet.setUserKeys(java.util.List.of( - new MasterKeyPacketUserKeyPart(1, 0, "USER-SIGN-COMP-002"), - new MasterKeyPacketUserKeyPart(1, 1, "USER-ENC-COMP-002") - )); - Mockito.when(lmkService.buildBackupPacket(2)).thenReturn(packet); - - MockMvc mockMvc = MockMvcBuilders.standaloneSetup(new LmkController(lmkService, new ObjectMapper())) - .setControllerAdvice(new GlobalExceptionHandler()) - .build(); - - mockMvc.perform(post("/api/v1/masterKey/backup") - .contentType(MediaType.APPLICATION_JSON) - .content(""" - { - "pubKey": "PUB-001", - "role": "SUPER_ADMIN", - "uid": "2", - "rid": "RID-001", - "extra": "ignored-extra" - } - """)) - .andExpect(status().isOk()) - .andExpect(content().string(containsString("\"sign\":\"SIGN-001\""))) - .andExpect(content().string(containsString("\"componentIndex\":2"))) - .andExpect(content().string(containsString("\"lmkMac\":\"LMK-MAC-001\""))) - .andExpect(content().string(containsString("\"component\":\"LMK-COMP-002\""))) - .andExpect(content().string(containsString("\"ikAuth\""))) - .andExpect(content().string(containsString("\"ikDevice\""))) - .andExpect(content().string(containsString("\"userKeys\""))) - .andExpect(content().string(containsString("\"USER-SIGN-COMP-002\""))) - .andExpect(content().string(containsString("\"USER-ENC-COMP-002\""))); - - Mockito.verify(lmkService).signIk(eq("{\"pubKey\":\"PUB-001\",\"authKeyPair\":\"IK-PUB-001\",\"role\":\"SUPER_ADMIN\",\"uid\":\"2\",\"rid\":\"RID-001\"}")); - Mockito.verify(lmkService).buildBackupPacket(2); - } - @Test void shouldRecoverKeyPacketsUsingOrderedPackets() throws Exception { LmkService lmkService = Mockito.mock(LmkService.class);