用户密钥加解密签名验签接口

This commit is contained in:
waner
2026-04-18 10:23:24 +08:00
parent a02c9959b7
commit 350fa4d89d
17 changed files with 1122 additions and 5 deletions
@@ -0,0 +1,23 @@
package com.cisd.tms.integration.crypto.pcie.model;
public class UserKeyDecryptRequest {
private int keyIndex;
private byte[] cipherBlob;
public int getKeyIndex() {
return keyIndex;
}
public void setKeyIndex(int keyIndex) {
this.keyIndex = keyIndex;
}
public byte[] getCipherBlob() {
return cipherBlob;
}
public void setCipherBlob(byte[] cipherBlob) {
this.cipherBlob = cipherBlob;
}
}
@@ -0,0 +1,23 @@
package com.cisd.tms.integration.crypto.pcie.model;
public class UserKeyEncryptRequest {
private int keyIndex;
private byte[] data;
public int getKeyIndex() {
return keyIndex;
}
public void setKeyIndex(int keyIndex) {
this.keyIndex = keyIndex;
}
public byte[] getData() {
return data;
}
public void setData(byte[] data) {
this.data = data;
}
}
@@ -0,0 +1,23 @@
package com.cisd.tms.integration.crypto.pcie.model;
public class UserKeySignRequest {
private int keyIndex;
private byte[] data;
public int getKeyIndex() {
return keyIndex;
}
public void setKeyIndex(int keyIndex) {
this.keyIndex = keyIndex;
}
public byte[] getData() {
return data;
}
public void setData(byte[] data) {
this.data = data;
}
}
@@ -0,0 +1,32 @@
package com.cisd.tms.integration.crypto.pcie.model;
public class UserKeyVerifyRequest {
private int keyIndex;
private byte[] data;
private byte[] signature;
public int getKeyIndex() {
return keyIndex;
}
public void setKeyIndex(int keyIndex) {
this.keyIndex = keyIndex;
}
public byte[] getData() {
return data;
}
public void setData(byte[] data) {
this.data = data;
}
public byte[] getSignature() {
return signature;
}
public void setSignature(byte[] signature) {
this.signature = signature;
}
}
@@ -79,6 +79,10 @@ import com.cisd.tms.integration.crypto.pcie.model.SymmetricCryptoRequest;
import com.cisd.tms.integration.crypto.pcie.model.SymmetricKekCryptoRequest;
import com.cisd.tms.integration.crypto.pcie.model.StandardKeyPairResult;
import com.cisd.tms.integration.crypto.pcie.model.UpdateBackedKeyRequest;
import com.cisd.tms.integration.crypto.pcie.model.UserKeyDecryptRequest;
import com.cisd.tms.integration.crypto.pcie.model.UserKeyEncryptRequest;
import com.cisd.tms.integration.crypto.pcie.model.UserKeySignRequest;
import com.cisd.tms.integration.crypto.pcie.model.UserKeyVerifyRequest;
import com.sun.jna.Memory;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;
@@ -86,6 +90,7 @@ import com.sun.jna.ptr.IntByReference;
import com.sun.jna.ptr.PointerByReference;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.function.Supplier;
public class JnaPcieCryptoService implements PcieCryptoService {
@@ -96,6 +101,7 @@ public class JnaPcieCryptoService implements PcieCryptoService {
private static final int IK_KEY_TYPE_AUTH = 2;
private static final int HMAC_MAX_LENGTH = 64;
private static final int ECC_CIPHER_PREFIX_LENGTH = (EccRefPublicKey.MAX_LEN * 2) + 32 + Integer.BYTES;
private static final String DEFAULT_PRIVATE_KEY_ACCESS_PASSWORD = "88888888";
private final PcieSessionTemplate sessionTemplate;
private final boolean strictAlgIdValidation;
@@ -1642,6 +1648,55 @@ public class JnaPcieCryptoService implements PcieCryptoService {
});
}
@Override
public BackupDataResult userKeyEncrypt(UserKeyEncryptRequest request) {
UserKeyEncryptRequest req = requireRequest("request", request);
EccInternalEncryptRequest encryptRequest = new EccInternalEncryptRequest();
encryptRequest.setKeyIndex(requireNonNegative("keyIndex", req.getKeyIndex()));
encryptRequest.setData(requireBytes("data", req.getData()));
return sdfeInternalEncryptEcc(encryptRequest);
}
@Override
public BackupDataResult userKeyDecrypt(UserKeyDecryptRequest request) {
UserKeyDecryptRequest req = requireRequest("request", request);
int keyIndex = requireNonNegative("keyIndex", req.getKeyIndex());
byte[] cipherBlob = requireNonEmptyBytes("cipherBlob", req.getCipherBlob());
EccCipher cipher = toEccCipher("cipherBlob", cipherBlob);
int outBufferSize = cipher.l;
if (outBufferSize <= 0) {
throw new IllegalArgumentException("cipherBlob contains invalid plaintext length: " + outBufferSize);
}
EccInternalDecryptRequest decryptRequest = new EccInternalDecryptRequest();
decryptRequest.setKeyIndex(keyIndex);
decryptRequest.setCipherBlob(cipherBlob);
decryptRequest.setOutBufferSize(outBufferSize);
return withDefaultPrivateKeyAccess(keyIndex, () -> sdfeInternalDecryptEcc(decryptRequest));
}
@Override
public BackupDataResult userKeySignWithSm3(UserKeySignRequest request) {
UserKeySignRequest req = requireRequest("request", request);
int keyIndex = requireNonNegative("keyIndex", req.getKeyIndex());
byte[] digest = digestWithSm3(requireBytes("data", req.getData()));
EccInternalSignRequest signRequest = new EccInternalSignRequest();
signRequest.setKeyIndex(keyIndex);
signRequest.setData(digest);
return withDefaultPrivateKeyAccess(keyIndex, () -> eccInternalSign(signRequest));
}
@Override
public void userKeyVerifyWithSm3(UserKeyVerifyRequest request) {
UserKeyVerifyRequest req = requireRequest("request", request);
EccInternalVerifyRequest verifyRequest = new EccInternalVerifyRequest();
verifyRequest.setKeyIndex(requireNonNegative("keyIndex", req.getKeyIndex()));
verifyRequest.setData(digestWithSm3(requireBytes("data", req.getData())));
verifyRequest.setSignature(requireNonEmptyBytes("signature", req.getSignature()));
eccInternalVerify(verifyRequest);
}
@Override
public HmacResult hmac(HmacRequest request) {
HmacRequest req = requireRequest("request", request);
@@ -2128,4 +2183,24 @@ public class JnaPcieCryptoService implements PcieCryptoService {
}
return request;
}
private <T> T withDefaultPrivateKeyAccess(int keyIndex, Supplier<T> action) {
PrivateKeyAccessRequest accessRequest = new PrivateKeyAccessRequest();
accessRequest.setKeyIndex(keyIndex);
accessRequest.setPassword(DEFAULT_PRIVATE_KEY_ACCESS_PASSWORD.getBytes(StandardCharsets.UTF_8));
getPrivateKeyAccessRight(accessRequest);
try {
return action.get();
} finally {
releasePrivateKeyAccessRight(keyIndex);
}
}
private byte[] digestWithSm3(byte[] data) {
DigestRequest digestRequest = new DigestRequest();
digestRequest.setAlgId(Gm0018AlgorithmIds.SM3);
digestRequest.setData(data);
digestRequest.setOutBufferSize(32);
return requireNonEmptyBytes("sm3Digest", digest(digestRequest).getData());
}
}
@@ -1,5 +1,6 @@
package com.cisd.tms.integration.crypto.pcie.service;
import com.cisd.tms.integration.crypto.pcie.Gm0018AlgorithmIds;
import com.cisd.tms.integration.crypto.pcie.PcieKeyState;
import com.cisd.tms.integration.crypto.pcie.PcieUserKeyType;
import com.cisd.tms.integration.crypto.pcie.jna.EccCipher;
@@ -66,13 +67,20 @@ import com.cisd.tms.integration.crypto.pcie.model.SymmetricCryptoRequest;
import com.cisd.tms.integration.crypto.pcie.model.SymmetricKekCryptoRequest;
import com.cisd.tms.integration.crypto.pcie.model.StandardKeyPairResult;
import com.cisd.tms.integration.crypto.pcie.model.UpdateBackedKeyRequest;
import com.cisd.tms.integration.crypto.pcie.model.UserKeyDecryptRequest;
import com.cisd.tms.integration.crypto.pcie.model.UserKeyEncryptRequest;
import com.cisd.tms.integration.crypto.pcie.model.UserKeySignRequest;
import com.cisd.tms.integration.crypto.pcie.model.UserKeyVerifyRequest;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.function.Supplier;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
public class MockPcieCryptoService implements PcieCryptoService {
private static final int ECC_KEY_BITS = 256;
private static final String DEFAULT_PRIVATE_KEY_ACCESS_PASSWORD = "88888888";
@Override
public DeviceCountResult getDeviceCount() {
@@ -701,6 +709,45 @@ public class MockPcieCryptoService implements PcieCryptoService {
return mockBackup(size, 0x76);
}
@Override
public BackupDataResult userKeyEncrypt(UserKeyEncryptRequest request) {
UserKeyEncryptRequest req = requireRequest("request", request);
EccInternalEncryptRequest encryptRequest = new EccInternalEncryptRequest();
encryptRequest.setKeyIndex(requireNonNegative("keyIndex", req.getKeyIndex()));
encryptRequest.setData(requireBytes("data", req.getData()));
return sdfeInternalEncryptEcc(encryptRequest);
}
@Override
public BackupDataResult userKeyDecrypt(UserKeyDecryptRequest request) {
UserKeyDecryptRequest req = requireRequest("request", request);
byte[] cipherBlob = requireNonEmptyBytes("cipherBlob", req.getCipherBlob());
EccInternalDecryptRequest decryptRequest = new EccInternalDecryptRequest();
decryptRequest.setKeyIndex(requireNonNegative("keyIndex", req.getKeyIndex()));
decryptRequest.setCipherBlob(cipherBlob);
decryptRequest.setOutBufferSize(Math.max(1, cipherBlob.length));
return withDefaultPrivateKeyAccess(req.getKeyIndex(), () -> sdfeInternalDecryptEcc(decryptRequest));
}
@Override
public BackupDataResult userKeySignWithSm3(UserKeySignRequest request) {
UserKeySignRequest req = requireRequest("request", request);
EccInternalSignRequest signRequest = new EccInternalSignRequest();
signRequest.setKeyIndex(requireNonNegative("keyIndex", req.getKeyIndex()));
signRequest.setData(digestWithSm3(requireBytes("data", req.getData())));
return withDefaultPrivateKeyAccess(req.getKeyIndex(), () -> eccInternalSign(signRequest));
}
@Override
public void userKeyVerifyWithSm3(UserKeyVerifyRequest request) {
UserKeyVerifyRequest req = requireRequest("request", request);
EccInternalVerifyRequest verifyRequest = new EccInternalVerifyRequest();
verifyRequest.setKeyIndex(requireNonNegative("keyIndex", req.getKeyIndex()));
verifyRequest.setData(digestWithSm3(requireBytes("data", req.getData())));
verifyRequest.setSignature(requireNonEmptyBytes("signature", req.getSignature()));
eccInternalVerify(verifyRequest);
}
@Override
public HmacResult hmac(HmacRequest request) {
HmacRequest req = requireRequest("request", request);
@@ -926,4 +973,24 @@ public class MockPcieCryptoService implements PcieCryptoService {
}
return request;
}
private <T> T withDefaultPrivateKeyAccess(int keyIndex, Supplier<T> action) {
PrivateKeyAccessRequest accessRequest = new PrivateKeyAccessRequest();
accessRequest.setKeyIndex(requireNonNegative("keyIndex", keyIndex));
accessRequest.setPassword(DEFAULT_PRIVATE_KEY_ACCESS_PASSWORD.getBytes(StandardCharsets.UTF_8));
getPrivateKeyAccessRight(accessRequest);
try {
return action.get();
} finally {
releasePrivateKeyAccessRight(keyIndex);
}
}
private byte[] digestWithSm3(byte[] data) {
DigestRequest digestRequest = new DigestRequest();
digestRequest.setAlgId(Gm0018AlgorithmIds.SM3);
digestRequest.setData(data);
digestRequest.setOutBufferSize(32);
return digest(digestRequest).getData();
}
}
@@ -57,6 +57,10 @@ import com.cisd.tms.integration.crypto.pcie.model.SymmetricCryptoRequest;
import com.cisd.tms.integration.crypto.pcie.model.SymmetricKekCryptoRequest;
import com.cisd.tms.integration.crypto.pcie.model.StandardKeyPairResult;
import com.cisd.tms.integration.crypto.pcie.model.UpdateBackedKeyRequest;
import com.cisd.tms.integration.crypto.pcie.model.UserKeyDecryptRequest;
import com.cisd.tms.integration.crypto.pcie.model.UserKeyEncryptRequest;
import com.cisd.tms.integration.crypto.pcie.model.UserKeySignRequest;
import com.cisd.tms.integration.crypto.pcie.model.UserKeyVerifyRequest;
/**
* PCIe 密码卡强类型服务接口。
@@ -455,6 +459,26 @@ public interface PcieCryptoService {
*/
BackupDataResult sdfeInternalDecryptEcc(EccInternalDecryptRequest request);
/**
* 使用指定用户加密密钥对原文执行内部 ECC 加密。
*/
BackupDataResult userKeyEncrypt(UserKeyEncryptRequest request);
/**
* 使用指定用户加密密钥对密文执行内部 ECC 解密,并自动处理私钥访问授权。
*/
BackupDataResult userKeyDecrypt(UserKeyDecryptRequest request);
/**
* 先对原文执行 SM3 摘要,再使用指定用户签名密钥完成内部 ECC 签名,并自动处理私钥访问授权。
*/
BackupDataResult userKeySignWithSm3(UserKeySignRequest request);
/**
* 先对原文执行 SM3 摘要,再使用指定用户签名公钥完成内部 ECC 验签。
*/
void userKeyVerifyWithSm3(UserKeyVerifyRequest request);
/**
* 使用 SD FE HMAC 流程计算 HMAC。
*/
@@ -4,6 +4,7 @@ import static com.cisd.tms.modules.device.support.crypto.CryptoPayloadCodec.*;
import static com.cisd.tms.modules.device.support.crypto.CryptoRequestMapper.*;
import com.cisd.tms.common.api.ApiResponse;
import com.cisd.tms.integration.crypto.pcie.Gm0018AlgorithmIds;
import com.cisd.tms.modules.device.dto.crypto.request.*;
import com.cisd.tms.integration.crypto.pcie.model.AgreementDataAndKeyEccResult;
import com.cisd.tms.integration.crypto.pcie.model.BackupDataResult;
@@ -14,6 +15,10 @@ import com.cisd.tms.integration.crypto.pcie.model.DeviceStatusResult;
import com.cisd.tms.integration.crypto.pcie.model.DigestRequest;
import com.cisd.tms.integration.crypto.pcie.model.EccAgreementSessionKeyRequest;
import com.cisd.tms.integration.crypto.pcie.model.EccAgreementSessionKeyResult;
import com.cisd.tms.integration.crypto.pcie.model.EccInternalDecryptRequest;
import com.cisd.tms.integration.crypto.pcie.model.EccInternalEncryptRequest;
import com.cisd.tms.integration.crypto.pcie.model.EccInternalSignRequest;
import com.cisd.tms.integration.crypto.pcie.model.EccInternalVerifyRequest;
import com.cisd.tms.integration.crypto.pcie.model.ExchangeDigitEnvelopeEccRequest;
import com.cisd.tms.integration.crypto.pcie.model.ExchangeDigitEnvelopeRsaRequest;
import com.cisd.tms.integration.crypto.pcie.model.ExportKekComponentRequest;
@@ -29,18 +34,25 @@ import com.cisd.tms.integration.crypto.pcie.model.HmacRequest;
import com.cisd.tms.integration.crypto.pcie.model.HmacResult;
import com.cisd.tms.integration.crypto.pcie.model.KeyStatusResult;
import com.cisd.tms.integration.crypto.pcie.model.MacCalcRequest;
import com.cisd.tms.integration.crypto.pcie.model.PrivateKeyAccessRequest;
import com.cisd.tms.integration.crypto.pcie.model.RecoverUserKeyRequest;
import com.cisd.tms.integration.crypto.pcie.model.SymmetricCryptoRequest;
import com.cisd.tms.integration.crypto.pcie.model.SymmetricKekCryptoRequest;
import com.cisd.tms.integration.crypto.pcie.model.StandardKeyPairResult;
import com.cisd.tms.integration.crypto.pcie.model.UserKeyDecryptRequest;
import com.cisd.tms.integration.crypto.pcie.model.UserKeyEncryptRequest;
import com.cisd.tms.integration.crypto.pcie.model.UserKeySignRequest;
import com.cisd.tms.integration.crypto.pcie.model.UserKeyVerifyRequest;
import com.cisd.tms.integration.crypto.pcie.service.PcieDeviceStatusFormatter;
import com.cisd.tms.integration.crypto.pcie.service.PcieCryptoService;
import com.cisd.tms.security.internal.ReplayProtected;
import com.google.gson.Gson;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import jakarta.validation.constraints.Min;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Base64;
import java.util.LinkedHashMap;
@@ -65,6 +77,8 @@ import org.springframework.web.bind.annotation.RestController;
@Tag(name = "密码卡调试", description = "密码卡设备调试、密钥操作和文件管理接口")
public class CryptoCardController {
private static final String DEFAULT_USER_KEY_ACCESS_PASSWORD = "88888888";
private final PcieCryptoService pcieCryptoService;
@GetMapping("/device-count")
@@ -514,6 +528,76 @@ public class CryptoCardController {
return ApiResponse.success(hexPayload("dataHex", result.getData(), result.getLength()));
}
@PostMapping("/user-key/encrypt")
@Operation(summary = "用户密钥加密", description = "使用用户加密密钥完成内部 ECC 加密,输入输出均使用 Base64。")
public ApiResponse<Map<String, Object>> encryptUserKey(
@Valid @RequestBody CryptoUserKeyEncryptInternalRequest request
) {
UserKeyEncryptRequest encryptRequest = new UserKeyEncryptRequest();
encryptRequest.setKeyIndex(request.getKeyIndex());
encryptRequest.setData(Base64.getDecoder().decode(request.getDataBase64()));
BackupDataResult result = pcieCryptoService.userKeyEncrypt(encryptRequest);
int length = result.getLength() > 0 && result.getLength() <= result.getData().length
? result.getLength()
: result.getData().length;
byte[] cipherBlob = Arrays.copyOf(result.getData(), length);
return ApiResponse.success(Map.of(
"length", length,
"cipherBase64", Base64.getEncoder().encodeToString(cipherBlob)
));
}
@PostMapping("/user-key/decrypt")
@Operation(summary = "用户密钥解密", description = "使用用户加密密钥完成内部 ECC 解密,接口内部自动申请和释放私钥访问权限。")
public ApiResponse<Map<String, Object>> decryptUserKey(
@Valid @RequestBody CryptoUserKeyDecryptInternalRequest request
) {
UserKeyDecryptRequest decryptRequest = new UserKeyDecryptRequest();
decryptRequest.setKeyIndex(request.getKeyIndex());
decryptRequest.setCipherBlob(Base64.getDecoder().decode(request.getCipherBase64()));
BackupDataResult result = pcieCryptoService.userKeyDecrypt(decryptRequest);
int length = result.getLength() > 0 && result.getLength() <= result.getData().length
? result.getLength()
: result.getData().length;
byte[] plain = Arrays.copyOf(result.getData(), length);
return ApiResponse.success(Map.of(
"length", length,
"dataBase64", Base64.getEncoder().encodeToString(plain)
));
}
@PostMapping("/user-key/sign")
@Operation(summary = "用户密钥签名", description = "使用用户签名密钥对原文先做 SM3,再完成内部 ECC 签名。")
public ApiResponse<Map<String, Object>> signUserKey(
@Valid @RequestBody CryptoUserKeySignInternalRequest request
) {
UserKeySignRequest signRequest = new UserKeySignRequest();
signRequest.setKeyIndex(request.getKeyIndex());
signRequest.setData(Base64.getDecoder().decode(request.getDataBase64()));
BackupDataResult result = pcieCryptoService.userKeySignWithSm3(signRequest);
int length = result.getLength() > 0 && result.getLength() <= result.getData().length
? result.getLength()
: result.getData().length;
byte[] signature = Arrays.copyOf(result.getData(), length);
return ApiResponse.success(Map.of(
"length", length,
"signatureBase64", Base64.getEncoder().encodeToString(signature)
));
}
@PostMapping("/user-key/verify")
@Operation(summary = "用户密钥验签", description = "使用用户签名密钥对原文先做 SM3,再完成内部 ECC 验签。")
public ApiResponse<Map<String, Object>> verifyUserKey(
@Valid @RequestBody CryptoUserKeyVerifyInternalRequest request
) {
UserKeyVerifyRequest verifyRequest = new UserKeyVerifyRequest();
verifyRequest.setKeyIndex(request.getKeyIndex());
verifyRequest.setData(Base64.getDecoder().decode(request.getDataBase64()));
verifyRequest.setSignature(Base64.getDecoder().decode(request.getSignatureBase64()));
pcieCryptoService.userKeyVerifyWithSm3(verifyRequest);
return ApiResponse.success(Map.of("passed", true));
}
@PostMapping("/user-key/self-test")
@Operation(summary = "执行用户密钥全流程自测", description = "依次执行 ECC 用户密钥生成、备份、删除、重建槽位、恢复和状态校验,返回备份 HEX 与关键状态。")
public ApiResponse<Map<String, Object>> selfTestUserKey(
@@ -556,6 +640,132 @@ public class CryptoCardController {
return ApiResponse.success(payload);
}
@PostMapping("/user-key/crypto-self-test")
@Operation(summary = "执行用户密钥算法全流程自测", description = "分阶段生成 ECC 用户加密钥和签名钥,完成内部加解密、签名验签,并在每个阶段结束后销毁槽位密钥。")
public ApiResponse<Map<String, Object>> cryptoSelfTestUserKey(
@Valid @RequestBody CryptoUserKeyCryptoSelfTestInternalRequest request
) {
byte[] encryptPlain = Base64.getDecoder().decode(request.getEncryptPlainBase64());
byte[] signData = Base64.getDecoder().decode(request.getSignDataBase64());
GenerateKeyPairRequest encGenerateRequest = new GenerateKeyPairRequest();
encGenerateRequest.setKeyBits(256);
encGenerateRequest.setKeyIndex(request.getKeyIndex());
encGenerateRequest.setKeyType(1);
GenerateKeyPairRequest signGenerateRequest = new GenerateKeyPairRequest();
signGenerateRequest.setKeyBits(256);
signGenerateRequest.setKeyIndex(request.getKeyIndex());
signGenerateRequest.setKeyType(0);
boolean encDeleted = false;
boolean signDeleted = false;
try {
pcieCryptoService.generateKeyPairEcc(encGenerateRequest);
EccInternalEncryptRequest encryptRequest = new EccInternalEncryptRequest();
encryptRequest.setKeyIndex(request.getKeyIndex());
encryptRequest.setData(encryptPlain);
BackupDataResult cipherResult = pcieCryptoService.sdfeInternalEncryptEcc(encryptRequest);
int cipherLength = cipherResult.getLength() > 0 && cipherResult.getLength() <= cipherResult.getData().length
? cipherResult.getLength()
: cipherResult.getData().length;
byte[] cipherBlob = Arrays.copyOf(cipherResult.getData(), cipherLength);
EccInternalDecryptRequest decryptRequest = new EccInternalDecryptRequest();
decryptRequest.setKeyIndex(request.getKeyIndex());
decryptRequest.setCipherBlob(cipherBlob);
decryptRequest.setOutBufferSize(encryptPlain.length);
PrivateKeyAccessRequest decryptAccessRequest = new PrivateKeyAccessRequest();
decryptAccessRequest.setKeyIndex(request.getKeyIndex());
decryptAccessRequest.setPassword(DEFAULT_USER_KEY_ACCESS_PASSWORD.getBytes(StandardCharsets.UTF_8));
BackupDataResult decryptResult;
pcieCryptoService.getPrivateKeyAccessRight(decryptAccessRequest);
try {
decryptResult = pcieCryptoService.sdfeInternalDecryptEcc(decryptRequest);
} finally {
pcieCryptoService.releasePrivateKeyAccessRight(request.getKeyIndex());
}
int decryptLength = decryptResult.getLength() > 0 && decryptResult.getLength() <= decryptResult.getData().length
? decryptResult.getLength()
: decryptResult.getData().length;
byte[] decryptPlain = Arrays.copyOf(decryptResult.getData(), decryptLength);
Map<String, Object> payload = new LinkedHashMap<>();
payload.put("keyIndex", request.getKeyIndex());
payload.put("encryptPlainBase64", Base64.getEncoder().encodeToString(encryptPlain));
payload.put("cipherLength", cipherLength);
payload.put("cipherBase64", Base64.getEncoder().encodeToString(cipherBlob));
payload.put("decryptLength", decryptLength);
payload.put("decryptBase64", Base64.getEncoder().encodeToString(decryptPlain));
payload.put("decryptMatched", Arrays.equals(encryptPlain, decryptPlain));
log.info("keyIndex:{}", request.getKeyIndex());
log.info("encryptPlainBase64:{}", Base64.getEncoder().encodeToString(encryptPlain));
log.info("cipherLength:{}", cipherLength);
log.info("cipherBase64:{}", Base64.getEncoder().encodeToString(cipherBlob));
log.info("decryptLength:{}", decryptLength);
log.info("decryptBase64:{}", Base64.getEncoder().encodeToString(decryptPlain));
log.info("decryptMatched:{}", Arrays.equals(encryptPlain, decryptPlain));
pcieCryptoService.deleteUserKey(request.getKeyIndex());
encDeleted = true;
KeyStatusResult encDeleteStatus = pcieCryptoService.statusUserKeyEcc(request.getKeyIndex(), 1);
payload.put("encDeleteStatus", encDeleteStatus);
pcieCryptoService.generateKeyPairEcc(signGenerateRequest);
DigestRequest digestRequest = new DigestRequest();
digestRequest.setAlgId(Gm0018AlgorithmIds.SM3);
digestRequest.setData(signData);
byte[] signDigest = pcieCryptoService.digest(digestRequest).getData();
EccInternalSignRequest signRequest = new EccInternalSignRequest();
signRequest.setKeyIndex(request.getKeyIndex());
signRequest.setData(signDigest);
PrivateKeyAccessRequest signAccessRequest = new PrivateKeyAccessRequest();
signAccessRequest.setKeyIndex(request.getKeyIndex());
signAccessRequest.setPassword(DEFAULT_USER_KEY_ACCESS_PASSWORD.getBytes(StandardCharsets.UTF_8));
BackupDataResult signatureResult;
pcieCryptoService.getPrivateKeyAccessRight(signAccessRequest);
try {
signatureResult = pcieCryptoService.eccInternalSign(signRequest);
} finally {
pcieCryptoService.releasePrivateKeyAccessRight(request.getKeyIndex());
}
int signatureLength = signatureResult.getLength() > 0 && signatureResult.getLength() <= signatureResult.getData().length
? signatureResult.getLength()
: signatureResult.getData().length;
byte[] signature = Arrays.copyOf(signatureResult.getData(), signatureLength);
EccInternalVerifyRequest verifyRequest = new EccInternalVerifyRequest();
verifyRequest.setKeyIndex(request.getKeyIndex());
verifyRequest.setData(signDigest);
verifyRequest.setSignature(signature);
pcieCryptoService.eccInternalVerify(verifyRequest);
pcieCryptoService.deleteUserKey(request.getKeyIndex());
signDeleted = true;
KeyStatusResult signDeleteStatus = pcieCryptoService.statusUserKeyEcc(request.getKeyIndex(), 0);
payload.put("signatureLength", signatureLength);
payload.put("signatureBase64", Base64.getEncoder().encodeToString(signature));
payload.put("signDigestBase64", Base64.getEncoder().encodeToString(signDigest));
payload.put("verifyPassed", true);
payload.put("signDeleteStatus", signDeleteStatus);
return ApiResponse.success(payload);
} finally {
if (!signDeleted) {
try {
pcieCryptoService.deleteUserKey(request.getKeyIndex());
} catch (Exception cleanupError) {
log.warn("failed to cleanup user key after crypto self test, keyIndex={}", request.getKeyIndex(), cleanupError);
}
}
}
}
@PostMapping("/user-key/recover")
@Operation(summary = "恢复用户密钥", description = "从备份数据恢复用户密钥。")
public ApiResponse<Void> recoverUserKey(
@@ -0,0 +1,40 @@
package com.cisd.tms.modules.device.dto.crypto.request;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
public class CryptoUserKeyCryptoSelfTestInternalRequest {
@Min(0)
private int keyIndex;
@NotBlank
private String encryptPlainBase64;
@NotBlank
private String signDataBase64;
public int getKeyIndex() {
return keyIndex;
}
public void setKeyIndex(int keyIndex) {
this.keyIndex = keyIndex;
}
public String getEncryptPlainBase64() {
return encryptPlainBase64;
}
public void setEncryptPlainBase64(String encryptPlainBase64) {
this.encryptPlainBase64 = encryptPlainBase64;
}
public String getSignDataBase64() {
return signDataBase64;
}
public void setSignDataBase64(String signDataBase64) {
this.signDataBase64 = signDataBase64;
}
}
@@ -0,0 +1,29 @@
package com.cisd.tms.modules.device.dto.crypto.request;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
public class CryptoUserKeyDecryptInternalRequest {
@Min(0)
private int keyIndex;
@NotBlank
private String cipherBase64;
public int getKeyIndex() {
return keyIndex;
}
public void setKeyIndex(int keyIndex) {
this.keyIndex = keyIndex;
}
public String getCipherBase64() {
return cipherBase64;
}
public void setCipherBase64(String cipherBase64) {
this.cipherBase64 = cipherBase64;
}
}
@@ -0,0 +1,29 @@
package com.cisd.tms.modules.device.dto.crypto.request;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
public class CryptoUserKeyEncryptInternalRequest {
@Min(0)
private int keyIndex;
@NotBlank
private String dataBase64;
public int getKeyIndex() {
return keyIndex;
}
public void setKeyIndex(int keyIndex) {
this.keyIndex = keyIndex;
}
public String getDataBase64() {
return dataBase64;
}
public void setDataBase64(String dataBase64) {
this.dataBase64 = dataBase64;
}
}
@@ -0,0 +1,29 @@
package com.cisd.tms.modules.device.dto.crypto.request;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
public class CryptoUserKeySignInternalRequest {
@Min(0)
private int keyIndex;
@NotBlank
private String dataBase64;
public int getKeyIndex() {
return keyIndex;
}
public void setKeyIndex(int keyIndex) {
this.keyIndex = keyIndex;
}
public String getDataBase64() {
return dataBase64;
}
public void setDataBase64(String dataBase64) {
this.dataBase64 = dataBase64;
}
}
@@ -0,0 +1,40 @@
package com.cisd.tms.modules.device.dto.crypto.request;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
public class CryptoUserKeyVerifyInternalRequest {
@Min(0)
private int keyIndex;
@NotBlank
private String dataBase64;
@NotBlank
private String signatureBase64;
public int getKeyIndex() {
return keyIndex;
}
public void setKeyIndex(int keyIndex) {
this.keyIndex = keyIndex;
}
public String getDataBase64() {
return dataBase64;
}
public void setDataBase64(String dataBase64) {
this.dataBase64 = dataBase64;
}
public String getSignatureBase64() {
return signatureBase64;
}
public void setSignatureBase64(String signatureBase64) {
this.signatureBase64 = signatureBase64;
}
}