用户密钥加解密签名验签接口
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;
|
||||
}
|
||||
}
|
||||
+133
@@ -12,16 +12,24 @@ import com.cisd.tms.integration.crypto.pcie.model.BackupDataResult;
|
||||
import com.cisd.tms.integration.crypto.pcie.model.DigestRequest;
|
||||
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.FirmwareInfoResult;
|
||||
import com.cisd.tms.integration.crypto.pcie.model.IkSignRequest;
|
||||
import com.cisd.tms.integration.crypto.pcie.model.IkVerifyRequest;
|
||||
import com.cisd.tms.integration.crypto.pcie.model.SymmetricCryptoRequest;
|
||||
import com.cisd.tms.integration.crypto.pcie.model.PrivateKeyAccessRequest;
|
||||
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.Pointer;
|
||||
import com.sun.jna.ptr.IntByReference;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
class JnaPcieCryptoServiceTest {
|
||||
@@ -452,4 +460,129 @@ class JnaPcieCryptoServiceTest {
|
||||
Assertions.assertArrayEquals(new byte[] {0x31, 0x32}, data);
|
||||
Mockito.verify(sessionTemplate).withSession(Mockito.eq("SDFE_InternalDecrypt_ECC"), Mockito.any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldEncryptViaHighLevelUserKeyEncrypt() {
|
||||
PcieSessionTemplate sessionTemplate = Mockito.mock(PcieSessionTemplate.class);
|
||||
CryptoCardProperties properties = new CryptoCardProperties();
|
||||
JnaPcieCryptoService service = Mockito.spy(new JnaPcieCryptoService(sessionTemplate, properties));
|
||||
BackupDataResult encrypted = new BackupDataResult();
|
||||
encrypted.setData(new byte[] {0x01, 0x02, 0x03});
|
||||
encrypted.setLength(3);
|
||||
Mockito.doReturn(encrypted).when(service).sdfeInternalEncryptEcc(Mockito.any(EccInternalEncryptRequest.class));
|
||||
|
||||
UserKeyEncryptRequest request = new UserKeyEncryptRequest();
|
||||
request.setKeyIndex(3);
|
||||
request.setData(new byte[] {0x11, 0x22});
|
||||
|
||||
BackupDataResult result = service.userKeyEncrypt(request);
|
||||
|
||||
Assertions.assertArrayEquals(new byte[] {0x01, 0x02, 0x03}, result.getData());
|
||||
ArgumentCaptor<EccInternalEncryptRequest> captor = ArgumentCaptor.forClass(EccInternalEncryptRequest.class);
|
||||
Mockito.verify(service).sdfeInternalEncryptEcc(captor.capture());
|
||||
Assertions.assertEquals(3, captor.getValue().getKeyIndex());
|
||||
Assertions.assertArrayEquals(new byte[] {0x11, 0x22}, captor.getValue().getData());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldDecryptViaHighLevelUserKeyDecrypt() {
|
||||
PcieSessionTemplate sessionTemplate = Mockito.mock(PcieSessionTemplate.class);
|
||||
CryptoCardProperties properties = new CryptoCardProperties();
|
||||
JnaPcieCryptoService service = Mockito.spy(new JnaPcieCryptoService(sessionTemplate, properties));
|
||||
byte[] cipherBlob = new byte[164];
|
||||
cipherBlob[160] = 0x05;
|
||||
BackupDataResult decrypted = new BackupDataResult();
|
||||
decrypted.setData(new byte[] {0x31, 0x32});
|
||||
decrypted.setLength(2);
|
||||
Mockito.doNothing().when(service).getPrivateKeyAccessRight(Mockito.any());
|
||||
Mockito.doNothing().when(service).releasePrivateKeyAccessRight(5);
|
||||
Mockito.doReturn(decrypted).when(service).sdfeInternalDecryptEcc(Mockito.any(EccInternalDecryptRequest.class));
|
||||
|
||||
UserKeyDecryptRequest request = new UserKeyDecryptRequest();
|
||||
request.setKeyIndex(5);
|
||||
request.setCipherBlob(cipherBlob);
|
||||
|
||||
BackupDataResult result = service.userKeyDecrypt(request);
|
||||
|
||||
Assertions.assertArrayEquals(new byte[] {0x31, 0x32}, result.getData());
|
||||
ArgumentCaptor<PrivateKeyAccessRequest> accessCaptor = ArgumentCaptor.forClass(PrivateKeyAccessRequest.class);
|
||||
ArgumentCaptor<EccInternalDecryptRequest> decryptCaptor = ArgumentCaptor.forClass(EccInternalDecryptRequest.class);
|
||||
Mockito.verify(service).getPrivateKeyAccessRight(accessCaptor.capture());
|
||||
Mockito.verify(service).sdfeInternalDecryptEcc(decryptCaptor.capture());
|
||||
Mockito.verify(service).releasePrivateKeyAccessRight(5);
|
||||
Assertions.assertEquals(5, accessCaptor.getValue().getKeyIndex());
|
||||
Assertions.assertArrayEquals("88888888".getBytes(StandardCharsets.UTF_8), accessCaptor.getValue().getPassword());
|
||||
Assertions.assertEquals(5, decryptCaptor.getValue().getKeyIndex());
|
||||
Assertions.assertArrayEquals(cipherBlob, decryptCaptor.getValue().getCipherBlob());
|
||||
Assertions.assertEquals(5, decryptCaptor.getValue().getOutBufferSize());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldSignViaHighLevelUserKeySignWithSm3() {
|
||||
PcieSessionTemplate sessionTemplate = Mockito.mock(PcieSessionTemplate.class);
|
||||
CryptoCardProperties properties = new CryptoCardProperties();
|
||||
JnaPcieCryptoService service = Mockito.spy(new JnaPcieCryptoService(sessionTemplate, properties));
|
||||
BackupDataResult digest = new BackupDataResult();
|
||||
digest.setData(new byte[] {0x01, 0x02, 0x03});
|
||||
digest.setLength(3);
|
||||
BackupDataResult signature = new BackupDataResult();
|
||||
signature.setData(new byte[] {0x11, 0x22});
|
||||
signature.setLength(2);
|
||||
Mockito.doReturn(digest).when(service).digest(Mockito.any(DigestRequest.class));
|
||||
Mockito.doNothing().when(service).getPrivateKeyAccessRight(Mockito.any());
|
||||
Mockito.doNothing().when(service).releasePrivateKeyAccessRight(6);
|
||||
Mockito.doReturn(signature).when(service).eccInternalSign(Mockito.any(EccInternalSignRequest.class));
|
||||
|
||||
UserKeySignRequest request = new UserKeySignRequest();
|
||||
request.setKeyIndex(6);
|
||||
request.setData("plain".getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
BackupDataResult result = service.userKeySignWithSm3(request);
|
||||
|
||||
Assertions.assertArrayEquals(new byte[] {0x11, 0x22}, result.getData());
|
||||
ArgumentCaptor<DigestRequest> digestCaptor = ArgumentCaptor.forClass(DigestRequest.class);
|
||||
ArgumentCaptor<PrivateKeyAccessRequest> accessCaptor = ArgumentCaptor.forClass(PrivateKeyAccessRequest.class);
|
||||
ArgumentCaptor<EccInternalSignRequest> signCaptor = ArgumentCaptor.forClass(EccInternalSignRequest.class);
|
||||
Mockito.verify(service).digest(digestCaptor.capture());
|
||||
Mockito.verify(service).getPrivateKeyAccessRight(accessCaptor.capture());
|
||||
Mockito.verify(service).eccInternalSign(signCaptor.capture());
|
||||
Mockito.verify(service).releasePrivateKeyAccessRight(6);
|
||||
Assertions.assertEquals(com.cisd.tms.integration.crypto.pcie.Gm0018AlgorithmIds.SM3, digestCaptor.getValue().getAlgId());
|
||||
Assertions.assertArrayEquals("plain".getBytes(StandardCharsets.UTF_8), digestCaptor.getValue().getData());
|
||||
Assertions.assertEquals(32, digestCaptor.getValue().getOutBufferSize());
|
||||
Assertions.assertEquals(6, accessCaptor.getValue().getKeyIndex());
|
||||
Assertions.assertArrayEquals("88888888".getBytes(StandardCharsets.UTF_8), accessCaptor.getValue().getPassword());
|
||||
Assertions.assertEquals(6, signCaptor.getValue().getKeyIndex());
|
||||
Assertions.assertArrayEquals(new byte[] {0x01, 0x02, 0x03}, signCaptor.getValue().getData());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldVerifyViaHighLevelUserKeyVerifyWithSm3() {
|
||||
PcieSessionTemplate sessionTemplate = Mockito.mock(PcieSessionTemplate.class);
|
||||
CryptoCardProperties properties = new CryptoCardProperties();
|
||||
JnaPcieCryptoService service = Mockito.spy(new JnaPcieCryptoService(sessionTemplate, properties));
|
||||
BackupDataResult digest = new BackupDataResult();
|
||||
digest.setData(new byte[] {0x21, 0x22, 0x23});
|
||||
digest.setLength(3);
|
||||
Mockito.doReturn(digest).when(service).digest(Mockito.any(DigestRequest.class));
|
||||
Mockito.doNothing().when(service).eccInternalVerify(Mockito.any(EccInternalVerifyRequest.class));
|
||||
|
||||
UserKeyVerifyRequest request = new UserKeyVerifyRequest();
|
||||
request.setKeyIndex(7);
|
||||
request.setData("verify".getBytes(StandardCharsets.UTF_8));
|
||||
request.setSignature(new byte[] {0x31, 0x32});
|
||||
|
||||
service.userKeyVerifyWithSm3(request);
|
||||
|
||||
ArgumentCaptor<DigestRequest> digestCaptor = ArgumentCaptor.forClass(DigestRequest.class);
|
||||
ArgumentCaptor<EccInternalVerifyRequest> verifyCaptor = ArgumentCaptor.forClass(EccInternalVerifyRequest.class);
|
||||
Mockito.verify(service).digest(digestCaptor.capture());
|
||||
Mockito.verify(service).eccInternalVerify(verifyCaptor.capture());
|
||||
Assertions.assertEquals(com.cisd.tms.integration.crypto.pcie.Gm0018AlgorithmIds.SM3, digestCaptor.getValue().getAlgId());
|
||||
Assertions.assertArrayEquals("verify".getBytes(StandardCharsets.UTF_8), digestCaptor.getValue().getData());
|
||||
Assertions.assertEquals(32, digestCaptor.getValue().getOutBufferSize());
|
||||
Assertions.assertEquals(7, verifyCaptor.getValue().getKeyIndex());
|
||||
Assertions.assertArrayEquals(new byte[] {0x21, 0x22, 0x23}, verifyCaptor.getValue().getData());
|
||||
Assertions.assertArrayEquals(new byte[] {0x31, 0x32}, verifyCaptor.getValue().getSignature());
|
||||
}
|
||||
}
|
||||
|
||||
+237
-5
@@ -1,11 +1,22 @@
|
||||
package com.cisd.tms.modules.device.controller;
|
||||
|
||||
import com.cisd.tms.common.exception.GlobalExceptionHandler;
|
||||
import com.cisd.tms.integration.crypto.pcie.Gm0018AlgorithmIds;
|
||||
import com.cisd.tms.integration.crypto.pcie.model.BackupDataResult;
|
||||
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.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.GenerateKeyPairRequest;
|
||||
import com.cisd.tms.integration.crypto.pcie.model.KeyStatusResult;
|
||||
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.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.PcieCryptoService;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -252,20 +263,241 @@ class CryptoCardControllerTest {
|
||||
inOrder.verify(pcieCryptoService).backupUserKey(1, 0, 120);
|
||||
inOrder.verify(pcieCryptoService).deleteUserKey(1);
|
||||
inOrder.verify(pcieCryptoService).statusUserKeyEcc(1, 0);
|
||||
inOrder.verify(pcieCryptoService).generateKeyPairEcc(generateCaptor.capture());
|
||||
inOrder.verify(pcieCryptoService).recoverUserKey(recoverCaptor.capture());
|
||||
inOrder.verify(pcieCryptoService).statusUserKeyEcc(1, 0);
|
||||
|
||||
assertEquals(2, generateCaptor.getAllValues().size());
|
||||
assertEquals(1, generateCaptor.getAllValues().size());
|
||||
assertEquals(256, generateCaptor.getAllValues().get(0).getKeyBits());
|
||||
assertEquals(1, generateCaptor.getAllValues().get(0).getKeyIndex());
|
||||
assertEquals(0, generateCaptor.getAllValues().get(0).getKeyType());
|
||||
assertEquals(256, generateCaptor.getAllValues().get(1).getKeyBits());
|
||||
assertEquals(1, generateCaptor.getAllValues().get(1).getKeyIndex());
|
||||
assertEquals(0, generateCaptor.getAllValues().get(1).getKeyType());
|
||||
assertEquals(1, recoverCaptor.getValue().getKeyIndex());
|
||||
assertEquals(0, recoverCaptor.getValue().getKeyType());
|
||||
assertEquals(1, recoverCaptor.getValue().getStoreFlag());
|
||||
assertArrayEquals(new byte[] {0x01, 0x23, 0x45, 0x67}, recoverCaptor.getValue().getEncryptedKey());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldEncryptUserKeyViaHighLevelEndpoint() throws Exception {
|
||||
PcieCryptoService pcieCryptoService = Mockito.mock(PcieCryptoService.class);
|
||||
BackupDataResult result = new BackupDataResult();
|
||||
result.setLength(3);
|
||||
result.setData(new byte[] {0x21, 0x43, 0x65});
|
||||
Mockito.when(pcieCryptoService.userKeyEncrypt(Mockito.any())).thenReturn(result);
|
||||
|
||||
MockMvc mockMvc = MockMvcBuilders.standaloneSetup(new CryptoCardController(pcieCryptoService))
|
||||
.setControllerAdvice(new GlobalExceptionHandler())
|
||||
.build();
|
||||
|
||||
mockMvc.perform(post("/api/v1/device/crypto/user-key/encrypt")
|
||||
.contentType("application/json")
|
||||
.content("""
|
||||
{
|
||||
"keyIndex": 7,
|
||||
"dataBase64": "aGVsbG8="
|
||||
}
|
||||
"""))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string(containsString("\"length\":3")))
|
||||
.andExpect(content().string(containsString("\"cipherBase64\":\"IUNl\"")));
|
||||
|
||||
ArgumentCaptor<UserKeyEncryptRequest> captor = ArgumentCaptor.forClass(UserKeyEncryptRequest.class);
|
||||
Mockito.verify(pcieCryptoService).userKeyEncrypt(captor.capture());
|
||||
assertEquals(7, captor.getValue().getKeyIndex());
|
||||
assertArrayEquals("hello".getBytes(java.nio.charset.StandardCharsets.UTF_8), captor.getValue().getData());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldDecryptUserKeyViaHighLevelEndpoint() throws Exception {
|
||||
PcieCryptoService pcieCryptoService = Mockito.mock(PcieCryptoService.class);
|
||||
BackupDataResult result = new BackupDataResult();
|
||||
result.setLength(5);
|
||||
result.setData("hello".getBytes(java.nio.charset.StandardCharsets.UTF_8));
|
||||
Mockito.when(pcieCryptoService.userKeyDecrypt(Mockito.any())).thenReturn(result);
|
||||
|
||||
MockMvc mockMvc = MockMvcBuilders.standaloneSetup(new CryptoCardController(pcieCryptoService))
|
||||
.setControllerAdvice(new GlobalExceptionHandler())
|
||||
.build();
|
||||
|
||||
mockMvc.perform(post("/api/v1/device/crypto/user-key/decrypt")
|
||||
.contentType("application/json")
|
||||
.content("""
|
||||
{
|
||||
"keyIndex": 7,
|
||||
"cipherBase64": "IUNl"
|
||||
}
|
||||
"""))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string(containsString("\"length\":5")))
|
||||
.andExpect(content().string(containsString("\"dataBase64\":\"aGVsbG8=\"")));
|
||||
|
||||
ArgumentCaptor<UserKeyDecryptRequest> captor = ArgumentCaptor.forClass(UserKeyDecryptRequest.class);
|
||||
Mockito.verify(pcieCryptoService).userKeyDecrypt(captor.capture());
|
||||
assertEquals(7, captor.getValue().getKeyIndex());
|
||||
assertArrayEquals(new byte[] {0x21, 0x43, 0x65}, captor.getValue().getCipherBlob());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldSignUserKeyViaHighLevelEndpoint() throws Exception {
|
||||
PcieCryptoService pcieCryptoService = Mockito.mock(PcieCryptoService.class);
|
||||
BackupDataResult result = new BackupDataResult();
|
||||
result.setLength(4);
|
||||
result.setData(new byte[] {0x11, 0x22, 0x33, 0x44});
|
||||
Mockito.when(pcieCryptoService.userKeySignWithSm3(Mockito.any())).thenReturn(result);
|
||||
|
||||
MockMvc mockMvc = MockMvcBuilders.standaloneSetup(new CryptoCardController(pcieCryptoService))
|
||||
.setControllerAdvice(new GlobalExceptionHandler())
|
||||
.build();
|
||||
|
||||
mockMvc.perform(post("/api/v1/device/crypto/user-key/sign")
|
||||
.contentType("application/json")
|
||||
.content("""
|
||||
{
|
||||
"keyIndex": 7,
|
||||
"dataBase64": "c2lnbg=="
|
||||
}
|
||||
"""))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string(containsString("\"length\":4")))
|
||||
.andExpect(content().string(containsString("\"signatureBase64\":\"ESIzRA==\"")));
|
||||
|
||||
ArgumentCaptor<UserKeySignRequest> captor = ArgumentCaptor.forClass(UserKeySignRequest.class);
|
||||
Mockito.verify(pcieCryptoService).userKeySignWithSm3(captor.capture());
|
||||
assertEquals(7, captor.getValue().getKeyIndex());
|
||||
assertArrayEquals("sign".getBytes(java.nio.charset.StandardCharsets.UTF_8), captor.getValue().getData());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldVerifyUserKeyViaHighLevelEndpoint() throws Exception {
|
||||
PcieCryptoService pcieCryptoService = Mockito.mock(PcieCryptoService.class);
|
||||
|
||||
MockMvc mockMvc = MockMvcBuilders.standaloneSetup(new CryptoCardController(pcieCryptoService))
|
||||
.setControllerAdvice(new GlobalExceptionHandler())
|
||||
.build();
|
||||
|
||||
mockMvc.perform(post("/api/v1/device/crypto/user-key/verify")
|
||||
.contentType("application/json")
|
||||
.content("""
|
||||
{
|
||||
"keyIndex": 7,
|
||||
"dataBase64": "c2lnbg==",
|
||||
"signatureBase64": "ESIzRA=="
|
||||
}
|
||||
"""))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string(containsString("\"passed\":true")));
|
||||
|
||||
ArgumentCaptor<UserKeyVerifyRequest> captor = ArgumentCaptor.forClass(UserKeyVerifyRequest.class);
|
||||
Mockito.verify(pcieCryptoService).userKeyVerifyWithSm3(captor.capture());
|
||||
assertEquals(7, captor.getValue().getKeyIndex());
|
||||
assertArrayEquals("sign".getBytes(java.nio.charset.StandardCharsets.UTF_8), captor.getValue().getData());
|
||||
assertArrayEquals(new byte[] {0x11, 0x22, 0x33, 0x44}, captor.getValue().getSignature());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldRunUserKeyCryptoSelfTestFlow() throws Exception {
|
||||
PcieCryptoService pcieCryptoService = Mockito.mock(PcieCryptoService.class);
|
||||
BackupDataResult cipher = new BackupDataResult();
|
||||
cipher.setLength(3);
|
||||
cipher.setData(new byte[] {0x21, 0x43, 0x65});
|
||||
BackupDataResult decrypt = new BackupDataResult();
|
||||
decrypt.setLength(5);
|
||||
decrypt.setData("hello".getBytes(java.nio.charset.StandardCharsets.UTF_8));
|
||||
BackupDataResult signature = new BackupDataResult();
|
||||
signature.setLength(4);
|
||||
signature.setData(new byte[] {0x11, 0x22, 0x33, 0x44});
|
||||
BackupDataResult digest = new BackupDataResult();
|
||||
digest.setLength(32);
|
||||
digest.setData(new byte[] {
|
||||
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
|
||||
0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
|
||||
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
|
||||
0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20
|
||||
});
|
||||
KeyStatusResult deleted = new KeyStatusResult();
|
||||
deleted.setKeyState(0);
|
||||
deleted.setKeyStateName("FREE");
|
||||
Mockito.when(pcieCryptoService.sdfeInternalEncryptEcc(Mockito.any())).thenReturn(cipher);
|
||||
Mockito.when(pcieCryptoService.sdfeInternalDecryptEcc(Mockito.any())).thenReturn(decrypt);
|
||||
Mockito.when(pcieCryptoService.digest(Mockito.any())).thenReturn(digest);
|
||||
Mockito.when(pcieCryptoService.eccInternalSign(Mockito.any())).thenReturn(signature);
|
||||
Mockito.when(pcieCryptoService.statusUserKeyEcc(7, 0)).thenReturn(deleted);
|
||||
Mockito.when(pcieCryptoService.statusUserKeyEcc(7, 1)).thenReturn(deleted);
|
||||
|
||||
MockMvc mockMvc = MockMvcBuilders.standaloneSetup(new CryptoCardController(pcieCryptoService))
|
||||
.setControllerAdvice(new GlobalExceptionHandler())
|
||||
.build();
|
||||
|
||||
mockMvc.perform(post("/api/v1/device/crypto/user-key/crypto-self-test")
|
||||
.contentType("application/json")
|
||||
.content("""
|
||||
{
|
||||
"keyIndex": 7,
|
||||
"encryptPlainBase64": "aGVsbG8=",
|
||||
"signDataBase64": "c2lnbg=="
|
||||
}
|
||||
"""))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string(containsString("\"keyIndex\":7")))
|
||||
.andExpect(content().string(containsString("\"encryptPlainBase64\":\"aGVsbG8=\"")))
|
||||
.andExpect(content().string(containsString("\"cipherLength\":3")))
|
||||
.andExpect(content().string(containsString("\"cipherBase64\":\"IUNl\"")))
|
||||
.andExpect(content().string(containsString("\"decryptLength\":5")))
|
||||
.andExpect(content().string(containsString("\"decryptBase64\":\"aGVsbG8=\"")))
|
||||
.andExpect(content().string(containsString("\"decryptMatched\":true")))
|
||||
.andExpect(content().string(containsString("\"signatureLength\":4")))
|
||||
.andExpect(content().string(containsString("\"signatureBase64\":\"ESIzRA==\"")))
|
||||
.andExpect(content().string(containsString("\"signDigestBase64\":\"AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyA=\"")))
|
||||
.andExpect(content().string(containsString("\"verifyPassed\":true")))
|
||||
.andExpect(content().string(containsString("\"signDeleteStatus\":{\"keyState\":0,\"keyStateName\":\"FREE\"}")))
|
||||
.andExpect(content().string(containsString("\"encDeleteStatus\":{\"keyState\":0,\"keyStateName\":\"FREE\"}")));
|
||||
|
||||
ArgumentCaptor<GenerateKeyPairRequest> generateCaptor = ArgumentCaptor.forClass(GenerateKeyPairRequest.class);
|
||||
ArgumentCaptor<DigestRequest> digestCaptor = ArgumentCaptor.forClass(DigestRequest.class);
|
||||
ArgumentCaptor<EccInternalEncryptRequest> encryptCaptor = ArgumentCaptor.forClass(EccInternalEncryptRequest.class);
|
||||
ArgumentCaptor<EccInternalDecryptRequest> decryptCaptor = ArgumentCaptor.forClass(EccInternalDecryptRequest.class);
|
||||
ArgumentCaptor<EccInternalSignRequest> signCaptor = ArgumentCaptor.forClass(EccInternalSignRequest.class);
|
||||
ArgumentCaptor<EccInternalVerifyRequest> verifyCaptor = ArgumentCaptor.forClass(EccInternalVerifyRequest.class);
|
||||
ArgumentCaptor<PrivateKeyAccessRequest> accessCaptor = ArgumentCaptor.forClass(PrivateKeyAccessRequest.class);
|
||||
InOrder inOrder = Mockito.inOrder(pcieCryptoService);
|
||||
inOrder.verify(pcieCryptoService).generateKeyPairEcc(generateCaptor.capture());
|
||||
inOrder.verify(pcieCryptoService).sdfeInternalEncryptEcc(encryptCaptor.capture());
|
||||
inOrder.verify(pcieCryptoService).getPrivateKeyAccessRight(accessCaptor.capture());
|
||||
inOrder.verify(pcieCryptoService).sdfeInternalDecryptEcc(decryptCaptor.capture());
|
||||
inOrder.verify(pcieCryptoService).releasePrivateKeyAccessRight(7);
|
||||
inOrder.verify(pcieCryptoService).deleteUserKey(7);
|
||||
inOrder.verify(pcieCryptoService).statusUserKeyEcc(7, 1);
|
||||
inOrder.verify(pcieCryptoService).generateKeyPairEcc(generateCaptor.capture());
|
||||
inOrder.verify(pcieCryptoService).digest(digestCaptor.capture());
|
||||
inOrder.verify(pcieCryptoService).getPrivateKeyAccessRight(accessCaptor.capture());
|
||||
inOrder.verify(pcieCryptoService).eccInternalSign(signCaptor.capture());
|
||||
inOrder.verify(pcieCryptoService).releasePrivateKeyAccessRight(7);
|
||||
inOrder.verify(pcieCryptoService).eccInternalVerify(verifyCaptor.capture());
|
||||
inOrder.verify(pcieCryptoService).deleteUserKey(7);
|
||||
inOrder.verify(pcieCryptoService).statusUserKeyEcc(7, 0);
|
||||
|
||||
assertEquals(2, generateCaptor.getAllValues().size());
|
||||
assertEquals(256, generateCaptor.getAllValues().get(0).getKeyBits());
|
||||
assertEquals(7, generateCaptor.getAllValues().get(0).getKeyIndex());
|
||||
assertEquals(1, generateCaptor.getAllValues().get(0).getKeyType());
|
||||
assertEquals(256, generateCaptor.getAllValues().get(1).getKeyBits());
|
||||
assertEquals(7, generateCaptor.getAllValues().get(1).getKeyIndex());
|
||||
assertEquals(0, generateCaptor.getAllValues().get(1).getKeyType());
|
||||
assertEquals(7, encryptCaptor.getValue().getKeyIndex());
|
||||
assertArrayEquals("hello".getBytes(java.nio.charset.StandardCharsets.UTF_8), encryptCaptor.getValue().getData());
|
||||
assertEquals(7, decryptCaptor.getValue().getKeyIndex());
|
||||
assertArrayEquals(new byte[] {0x21, 0x43, 0x65}, decryptCaptor.getValue().getCipherBlob());
|
||||
assertEquals(5, decryptCaptor.getValue().getOutBufferSize());
|
||||
assertEquals(Gm0018AlgorithmIds.SM3, digestCaptor.getValue().getAlgId());
|
||||
assertArrayEquals("sign".getBytes(java.nio.charset.StandardCharsets.UTF_8), digestCaptor.getValue().getData());
|
||||
assertEquals(2, accessCaptor.getAllValues().size());
|
||||
assertEquals(7, accessCaptor.getAllValues().get(0).getKeyIndex());
|
||||
assertArrayEquals("88888888".getBytes(java.nio.charset.StandardCharsets.UTF_8), accessCaptor.getAllValues().get(0).getPassword());
|
||||
assertEquals(7, accessCaptor.getAllValues().get(1).getKeyIndex());
|
||||
assertArrayEquals("88888888".getBytes(java.nio.charset.StandardCharsets.UTF_8), accessCaptor.getAllValues().get(1).getPassword());
|
||||
assertEquals(7, signCaptor.getValue().getKeyIndex());
|
||||
assertArrayEquals(digest.getData(), signCaptor.getValue().getData());
|
||||
assertEquals(7, verifyCaptor.getValue().getKeyIndex());
|
||||
assertArrayEquals(digest.getData(), verifyCaptor.getValue().getData());
|
||||
assertArrayEquals(new byte[] {0x11, 0x22, 0x33, 0x44}, verifyCaptor.getValue().getSignature());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.cisd.tms.modules.device.controller;
|
||||
|
||||
import com.cisd.tms.common.enums.ErrorCode;
|
||||
import com.cisd.tms.common.exception.GlobalExceptionHandler;
|
||||
import com.cisd.tms.modules.device.service.NetworkConfigService;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mockito;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
class NetworkConfigControllerTest {
|
||||
|
||||
@Test
|
||||
void shouldReturnBadRequestWhenBondModeDoesNotExist() throws Exception {
|
||||
NetworkConfigService networkConfigService = Mockito.mock(NetworkConfigService.class);
|
||||
Mockito.when(networkConfigService.getBondMode("bond0")).thenReturn(null);
|
||||
|
||||
MockMvc mockMvc = MockMvcBuilders.standaloneSetup(new NetworkConfigController(networkConfigService))
|
||||
.setControllerAdvice(new GlobalExceptionHandler())
|
||||
.build();
|
||||
|
||||
mockMvc.perform(get("/api/v1/device/network-config/bond/mode/bond0"))
|
||||
.andExpect(status().isBadRequest())
|
||||
.andExpect(jsonPath("$.code").value(ErrorCode.BAD_REQUEST.getCode()))
|
||||
.andExpect(jsonPath("$.msg").value("未找到该连接的 Bond 模式"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package com.cisd.tms.security.internal;
|
||||
|
||||
import com.cisd.tms.common.config.properties.TmsSecurityProperties;
|
||||
import com.cisd.tms.common.enums.ErrorCode;
|
||||
import com.cisd.tms.modules.auth.entity.AuthSessionEntity;
|
||||
import com.cisd.tms.modules.auth.repository.AuthSessionRepository;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import java.time.Clock;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
import java.util.Optional;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mockito;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
|
||||
class InternalApiAuthInterceptorTest {
|
||||
|
||||
private static final Clock FIXED_CLOCK = Clock.fixed(Instant.parse("2026-04-17T08:30:00Z"), ZoneOffset.UTC);
|
||||
|
||||
@Test
|
||||
void shouldReturnSessionInvalidWhenSessionTokenIsMissing() throws Exception {
|
||||
AuthSessionRepository authSessionRepository = Mockito.mock(AuthSessionRepository.class);
|
||||
InternalApiAuthInterceptor interceptor = new InternalApiAuthInterceptor(
|
||||
authSessionRepository,
|
||||
enabledSecurityProperties(),
|
||||
new ObjectMapper(),
|
||||
FIXED_CLOCK
|
||||
);
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/api/v1/auth/me");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
boolean allowed = interceptor.preHandle(request, response, new Object());
|
||||
|
||||
Assertions.assertFalse(allowed);
|
||||
Assertions.assertEquals(401, response.getStatus());
|
||||
Assertions.assertTrue(response.getContentAsString().contains("\"code\":" + ErrorCode.SESSION_INVALID.getCode()));
|
||||
Assertions.assertTrue(response.getContentAsString().contains("session token missing"));
|
||||
Mockito.verifyNoInteractions(authSessionRepository);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldReturnSessionInvalidWhenSessionIsExpired() throws Exception {
|
||||
AuthSessionRepository authSessionRepository = Mockito.mock(AuthSessionRepository.class);
|
||||
AuthSessionEntity expired = new AuthSessionEntity();
|
||||
expired.setSessionToken("token-expired-001");
|
||||
expired.setRoleCode("AUDIT_ADMIN");
|
||||
expired.setAuthLevel("LIMITED");
|
||||
expired.setExpiresAt(LocalDateTime.ofInstant(FIXED_CLOCK.instant(), ZoneOffset.UTC).minusMinutes(1));
|
||||
Mockito.when(authSessionRepository.findBySessionToken("token-expired-001")).thenReturn(Optional.of(expired));
|
||||
|
||||
InternalApiAuthInterceptor interceptor = new InternalApiAuthInterceptor(
|
||||
authSessionRepository,
|
||||
enabledSecurityProperties(),
|
||||
new ObjectMapper(),
|
||||
FIXED_CLOCK
|
||||
);
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/api/v1/auth/me");
|
||||
request.addHeader("X-Session-Token", "token-expired-001");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
boolean allowed = interceptor.preHandle(request, response, new Object());
|
||||
|
||||
Assertions.assertFalse(allowed);
|
||||
Assertions.assertEquals(401, response.getStatus());
|
||||
Assertions.assertTrue(response.getContentAsString().contains("\"code\":" + ErrorCode.SESSION_INVALID.getCode()));
|
||||
Assertions.assertTrue(response.getContentAsString().contains("session expired"));
|
||||
}
|
||||
|
||||
private static TmsSecurityProperties enabledSecurityProperties() {
|
||||
TmsSecurityProperties properties = new TmsSecurityProperties();
|
||||
properties.getInternalAuth().setEnabled(true);
|
||||
return properties;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user