chsm-server/chsm-web-server/src/main/java/com/sunyard/chsm/pool/LoadBalancedSdfApiService.java
2024-12-30 09:06:11 +08:00

191 lines
8.0 KiB
Java

package com.sunyard.chsm.pool;
import com.sunyard.chsm.constant.CryptoConst;
import com.sunyard.chsm.enums.AlgMode;
import com.sunyard.chsm.enums.Padding;
import com.sunyard.chsm.sdf.SdfApiService;
import com.sunyard.chsm.sdf.context.AlgId;
import com.sunyard.chsm.sdf.model.*;
import com.sunyard.chsm.sdf.util.PaddingUtil;
import com.sunyard.chsm.utils.gm.BCECUtils;
import com.sunyard.chsm.utils.gm.BCSM3Utils;
import com.sunyard.chsm.utils.gm.SM2PreprocessSigner;
import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.params.ParametersWithID;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import javax.annotation.Resource;
import java.util.Objects;
import java.util.function.Function;
/**
* @author liulu
* @since 2024/12/10
*/
@Slf4j
@Service
public class LoadBalancedSdfApiService implements SdfApiService {
@Resource
private DeviceManager deviceManager;
private <T> T apply(Function<TMKContext, T> fun) {
TMKContext context = deviceManager.chooseOne();
try {
return fun.apply(context);
} finally {
deviceManager.returnContextToPool(context);
}
}
@Override
public byte[] generateRandom(int len) {
return apply(s -> s.getSdfApiAdapter().generateRandom(s.getSessionHandle(), len));
}
@Override
public byte[] symEncrypt(AlgId alg, Padding padding, byte[] key, byte[] iv, byte[] data) {
if (alg.name().contains(AlgMode.CBC.getCode())) {
Assert.notNull(iv, "CBC模式下, iv不能为空");
Assert.isTrue(iv.length >= key.length, "CBC模式下, iv长度不能低于key的长度");
}
byte[] paddingData = PaddingUtil.padding(padding, data);
return apply(s -> {
String keyHandle = s.getSdfApiAdapter().importKey(s.getSessionHandle(), key);
byte[] encrypt = s.getSdfApiAdapter().symEncrypt(s.getSessionHandle(), keyHandle, alg, iv, paddingData);
s.getSdfApiAdapter().destroyKey(s.getSessionHandle(), keyHandle);
return encrypt;
});
}
@Override
public byte[] symDecrypt(AlgId alg, Padding padding, byte[] key, byte[] iv, byte[] data) {
if (alg.name().contains(AlgMode.CBC.getCode())) {
Assert.notNull(iv, "CBC模式下, iv不能为空");
Assert.isTrue(iv.length >= key.length, "CBC模式下, iv长度不能低于key的长度");
}
byte[] decrypt = apply(s -> {
String keyHandle = s.getSdfApiAdapter().importKey(s.getSessionHandle(), key);
byte[] d = s.getSdfApiAdapter().symDecrypt(s.getSessionHandle(), keyHandle, alg, iv, data);
s.getSdfApiAdapter().destroyKey(s.getSessionHandle(), keyHandle);
return d;
});
return PaddingUtil.unpadding(padding, decrypt);
}
@Override
public EccKey genKeyPairEcc() {
return apply(s -> s.getSdfApiAdapter().generateKeyPairECC(s.getSessionHandle(), AlgId.SGD_SM2_1));
}
@Override
public EccSignature externalSignECC(byte[] privateKey, byte[] pucData) {
Assert.notNull(pucData, "待签名数据不能为空");
Assert.isTrue(pucData.length == 32, "待签名数据长度必须为32字节");
EccPriKey priKey = EccPriKey.fromBytes(privateKey);
return apply(s -> s.getSdfApiAdapter().externalSignECC(s.getSessionHandle(), priKey, pucData));
}
@Override
public EccSignature externalSignWithIdECC(byte[] privateKey, byte[] pucData, byte[] userId) {
EccPriKey sdfEccPrivateKey = EccPriKey.fromBytes(privateKey);
SM2PreprocessSigner signer = new SM2PreprocessSigner();
CipherParameters keyParameters = BCECUtils.createECPrivateKeyParameters(sdfEccPrivateKey.getD());
if (userId != null && userId.length > 0) {
keyParameters = new ParametersWithID(keyParameters, userId);
}
signer.init(true, keyParameters);
byte[] preHash = signer.preprocess(pucData);
return apply(s -> s.getSdfApiAdapter().externalSignECC(s.getSessionHandle(), sdfEccPrivateKey, preHash));
}
@Override
public boolean externalVerifyWithIdECC(byte[] publicKey, byte[] pubData, byte[] signData, byte[] userId) {
EccPubKey eccPublicKey = EccPubKey.fromBytes(publicKey);
CipherParameters parameters = BCECUtils.createECPublicKeyParameters(eccPublicKey.getX(), eccPublicKey.getY());
if (userId != null && userId.length > 0) {
parameters = new ParametersWithID(parameters, userId);
}
SM2PreprocessSigner signer = new SM2PreprocessSigner();
signer.init(false, parameters);
byte[] preHash = signer.preprocess(pubData);
EccSignature eccSignature = EccSignature.fromBytes(signData);
return apply(s -> s.getSdfApiAdapter().externalVerifyECC(s.getSessionHandle(),
eccPublicKey, preHash, eccSignature));
}
@Override
public boolean externalVerifyECC(byte[] publicKey, byte[] pubData, byte[] signData) {
Assert.notNull(pubData, "验签原文数据不能为空");
Assert.isTrue(pubData.length == 32, "验签原文数据长度必须为32字节");
EccPubKey eccPublicKey = EccPubKey.fromBytes(publicKey);
EccSignature eccSignature = EccSignature.fromBytes(signData);
return apply(s -> s.getSdfApiAdapter().externalVerifyECC(s.getSessionHandle(), eccPublicKey, pubData, eccSignature));
}
@Override
public EccCipher externalEncryptECC(byte[] publicKey, byte[] pucData) {
EccPubKey eccPublicKey = EccPubKey.fromBytes(publicKey);
return apply(s -> s.getSdfApiAdapter().externalEncryptECC(s.getSessionHandle(), eccPublicKey, pucData));
}
@Override
public byte[] externalDecryptECC(byte[] privateKey, byte[] encData) {
EccPriKey sdfEccPrivateKey = EccPriKey.fromBytes(privateKey);
EccCipher eccCipher = EccCipher.fromBytes(encData);
return apply(s -> s.getSdfApiAdapter().externalDecryptECC(s.getSessionHandle(), sdfEccPrivateKey, eccCipher));
}
@Override
public byte[] calculateMAC(AlgId algId, Padding padding, byte[] symKey, byte[] pucIv, byte[] pucData) {
byte[] pad = PaddingUtil.padding(padding, pucData);
return apply(s -> {
String keyHandle = s.getSdfApiAdapter().importKey(s.getSessionHandle(), symKey);
byte[] mac = s.getSdfApiAdapter().calculateMAC(s.getSessionHandle(), keyHandle, algId, pucIv, pad);
s.getSdfApiAdapter().destroyKey(s.getSessionHandle(), keyHandle);
return mac;
});
}
@Override
public byte[] hmac(byte[] key, byte[] srcData) {
return BCSM3Utils.hmac(key, srcData);
}
@Override
public byte[] hash(byte[] pucData, byte[] pubKey, byte[] userId) {
EccPubKey eccPubKey = pubKey == null || pubKey.length == 0 ? null : EccPubKey.fromBytes(pubKey);
byte[] finalUserId = Objects.nonNull(pubKey) && Objects.isNull(userId) ? CryptoConst.USER_ID : userId;
return apply(s -> {
String newSession = s.getSdfApiAdapter().openSession(s.getDeviceHandle());
s.getSdfApiAdapter().hashInit(newSession, AlgId.SGD_SM3, eccPubKey, finalUserId);
s.getSdfApiAdapter().hashUpdate(newSession, pucData);
byte[] hash = s.getSdfApiAdapter().hashFinish(newSession);
s.getSdfApiAdapter().closeSession(newSession);
return hash;
});
}
@Override
public byte[] hash(byte[] pucData) {
return hash(pucData, null, null);
}
@Override
public byte[] encryptByTMK(byte[] data) {
byte[] pad = PaddingUtil.PKCS7Padding(data);
return apply(s -> s.getSdfApiAdapter().symEncrypt(s.getSessionHandle(), s.getKeyHandle(), AlgId.SGD_SM4_CBC, CryptoConst.iv(), pad));
}
@Override
public byte[] decryptByTMK(byte[] data) {
byte[] decrypt = apply(s -> s.getSdfApiAdapter().symDecrypt(s.getSessionHandle(), s.getKeyHandle(), AlgId.SGD_SM4_CBC, CryptoConst.iv(), data));
return PaddingUtil.PKCS7Unpadding(decrypt);
}
}