用户密钥加解密签名验签接口
This commit is contained in:
@@ -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(
|
||||
|
||||
+40
@@ -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;
|
||||
}
|
||||
}
|
||||
+29
@@ -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;
|
||||
}
|
||||
}
|
||||
+29
@@ -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;
|
||||
}
|
||||
}
|
||||
+29
@@ -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;
|
||||
}
|
||||
}
|
||||
+40
@@ -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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user