You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
digital-rmb-backend/src/main/java/com/yau/digitalrmb/institutionidentity/application/InstitutionApplicationVerif...

103 lines
5.7 KiB
Java

package com.yau.digitalrmb.institutionidentity.application;
import com.yau.digitalrmb.institutionidentity.domain.InstitutionIdentifierApplication;
import com.yau.digitalrmb.institutionidentity.domain.InstitutionIdentifierRepository;
import com.yau.digitalrmb.institutionidentity.domain.InstitutionIdentityCryptography;
import com.yau.digitalrmb.shared.api.ErrorCode;
import com.yau.digitalrmb.shared.exception.BusinessException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
@Service
public class InstitutionApplicationVerificationService {
@Resource
private InstitutionIdentityCryptography cryptography;
@Resource
private InstitutionKeyService keyService;
@Resource
private InstitutionIdentifierRepository repository;
@Resource
private InstitutionTrainingErrorRecorder errorRecorder;
@Transactional
public InstitutionApplicationVerificationResult verify(long applicationId, String verificationKeyId,
InstitutionKeySubject subject, String operator) {
InstitutionIdentifierApplication application = requireApplication(applicationId);
if (!InstitutionKeyService.BANK_SECOND_KEY.equals(verificationKeyId)) {
recordAndThrow(application, "WRONG_KEY", "VERIFY", verificationKeyId,
"验证必须选择商业银行第二密钥的公钥", operator);
}
requireStatus(application, InstitutionIdentifierApplication.Status.PACKAGED,
"当前步骤不是央行验证,不能操作", operator);
InstitutionIdentifierApplication.Status expectedStatus = application.getStatus();
String originalText = application.getBankCode() + "|" + application.getTimestamp();
String recalculatedDigest = cryptography.sm3(originalText);
boolean signatureValid = keyService.verifyCommercialBank(subject, application.getDigest(),
application.getBankSignature());
boolean digestMatches = recalculatedDigest.equalsIgnoreCase(application.getDigest());
invokeDomain(() -> application.recordVerification(verificationKeyId, signatureValid, digestMatches));
repository.update(application, expectedStatus, "VERIFY",
signatureValid && digestMatches ? "SM2身份验证和SM3完整性验证通过" : "申请验证失败",
operator);
return new InstitutionApplicationVerificationResult(applicationId, application.getStatus().name(),
"SM2_WITH_SM3_VERIFY_AND_SM3_RECALCULATE", verificationKeyId, originalText,
application.getDigest(), recalculatedDigest, signatureValid, digestMatches);
}
@Transactional
public InstitutionIdentifierConfirmationResult confirm(long applicationId, String signingKeyId,
InstitutionKeySubject subject, String operator) {
InstitutionIdentifierApplication application = requireApplication(applicationId);
if (!InstitutionKeyService.CENTRAL_FIRST_KEY.equals(signingKeyId)) {
recordAndThrow(application, "WRONG_KEY", "CONFIRM", signingKeyId,
"签名确权必须选择中央银行第一密钥", operator);
}
requireStatus(application, InstitutionIdentifierApplication.Status.VERIFIED,
"申请尚未验证通过,不能进行央行签名确权", operator);
InstitutionIdentifierApplication.Status expectedStatus = application.getStatus();
String digest = application.getDigest();
String identifier = "ORG_" + digest.substring(0, 12);
String centralBankSignature = keyService.signCentralBank(subject, digest);
invokeDomain(() -> application.issue(signingKeyId, identifier, centralBankSignature));
repository.update(application, expectedStatus, "CONFIRM",
"中央银行第一私钥完成SM2签名确权并签发机构标识", operator);
return new InstitutionIdentifierConfirmationResult(applicationId, application.getStatus().name(),
signingKeyId, centralBankSignature, identifier, digest);
}
private InstitutionIdentifierApplication requireApplication(long applicationId) {
return repository.findById(applicationId).orElseThrow(() ->
new BusinessException(ErrorCode.RESOURCE_NOT_FOUND, "机构标识申请不存在"));
}
private void requireStatus(InstitutionIdentifierApplication application,
InstitutionIdentifierApplication.Status expectedStatus,
String message, String operator) {
if (application.getStatus() != expectedStatus) {
recordAndThrow(application, "INVALID_STEP", expectedStatus.name(), null,
message + ",当前状态:" + application.getStatus().name(), operator);
}
}
private void recordAndThrow(InstitutionIdentifierApplication application, String errorType, String operationStep,
String providedKeyId, String message, String operator) {
int errorSequence = errorRecorder.record(application.getId(), errorType, operationStep, providedKeyId,
message, operator);
throw new BusinessException(ErrorCode.VALIDATION_ERROR,
message + ",本次实训第" + errorSequence + "次错误");
}
private static void invokeDomain(Runnable operation) {
try {
operation.run();
} catch (IllegalArgumentException | IllegalStateException exception) {
throw new BusinessException(ErrorCode.VALIDATION_ERROR, exception.getMessage());
}
}
}