sdf api
This commit is contained in:
parent
3dc061907f
commit
2250a6234b
@ -1,186 +1,186 @@
|
|||||||
package com.sunyard.chsm.sdf;
|
//package com.sunyard.chsm.sdf;
|
||||||
|
//
|
||||||
|
//
|
||||||
import com.sunyard.chsm.enums.AlgMode;
|
//import com.sunyard.chsm.enums.AlgMode;
|
||||||
import com.sunyard.chsm.enums.KeyAlg;
|
//import com.sunyard.chsm.enums.KeyAlg;
|
||||||
import com.sunyard.chsm.enums.KeyCategory;
|
//import com.sunyard.chsm.enums.KeyCategory;
|
||||||
import com.sunyard.chsm.enums.Padding;
|
//import com.sunyard.chsm.enums.Padding;
|
||||||
import com.sunyard.chsm.sdf.context.AlgId;
|
//import com.sunyard.chsm.sdf.context.AlgId;
|
||||||
import com.sunyard.chsm.sdf.model.EccKey;
|
//import com.sunyard.chsm.sdf.model.EccKey;
|
||||||
import com.sunyard.chsm.sdf.util.LangUtils;
|
//import com.sunyard.chsm.sdf.util.LangUtils;
|
||||||
import com.sunyard.chsm.utils.gm.BCSM2Utils;
|
//import com.sunyard.chsm.utils.gm.BCSM2Utils;
|
||||||
import com.sunyard.chsm.utils.gm.BCSM3Utils;
|
//import com.sunyard.chsm.utils.gm.BCSM3Utils;
|
||||||
import com.sunyard.chsm.utils.gm.BCSM4Utils;
|
//import com.sunyard.chsm.utils.gm.BCSM4Utils;
|
||||||
import lombok.SneakyThrows;
|
//import lombok.SneakyThrows;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
//import lombok.extern.slf4j.Slf4j;
|
||||||
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
|
//import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
|
||||||
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
|
//import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
|
||||||
import org.bouncycastle.util.BigIntegers;
|
//import org.bouncycastle.util.BigIntegers;
|
||||||
import org.springframework.stereotype.Service;
|
//import org.springframework.stereotype.Service;
|
||||||
|
//
|
||||||
import javax.crypto.BadPaddingException;
|
//import javax.crypto.BadPaddingException;
|
||||||
import javax.crypto.Cipher;
|
//import javax.crypto.Cipher;
|
||||||
import javax.crypto.IllegalBlockSizeException;
|
//import javax.crypto.IllegalBlockSizeException;
|
||||||
import javax.crypto.NoSuchPaddingException;
|
//import javax.crypto.NoSuchPaddingException;
|
||||||
import java.security.InvalidKeyException;
|
//import java.security.InvalidKeyException;
|
||||||
import java.security.KeyPair;
|
//import java.security.KeyPair;
|
||||||
import java.security.NoSuchAlgorithmException;
|
//import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.NoSuchProviderException;
|
//import java.security.NoSuchProviderException;
|
||||||
import java.security.SecureRandom;
|
//import java.security.SecureRandom;
|
||||||
|
//
|
||||||
|
//
|
||||||
/**
|
///**
|
||||||
* 基于 BC 库的国密软算法实现
|
// * 基于 BC 库的国密软算法实现
|
||||||
* 当前实现类的接口返回的对称密钥和私钥认为是明文,在上层 Service 进行使用和存储时的加密和解密运算。
|
// * 当前实现类的接口返回的对称密钥和私钥认为是明文,在上层 Service 进行使用和存储时的加密和解密运算。
|
||||||
* <p>
|
// * <p>
|
||||||
* 主密钥:
|
// * 主密钥:
|
||||||
* - 生成。 软随机数。项目启动时不存在则自动生成。
|
// * - 生成。 软随机数。项目启动时不存在则自动生成。
|
||||||
* - 存储。 存储在 SC_PARAM_CONF 表, KEY 为 mk 的字段,值为固定的 48 字节,以 HEX 格式 96 字节存储。
|
// * - 存储。 存储在 SC_PARAM_CONF 表, KEY 为 mk 的字段,值为固定的 48 字节,以 HEX 格式 96 字节存储。
|
||||||
* 前 16 字节为主密钥值,后 32 字节为主密钥值使用 SM3 计算的校验值。
|
// * 前 16 字节为主密钥值,后 32 字节为主密钥值使用 SM3 计算的校验值。
|
||||||
* - 同步。基于数据库进行导入、导出、和备份、恢复。多台应用服务器连接同一个数据库,无需同步。
|
// * - 同步。基于数据库进行导入、导出、和备份、恢复。多台应用服务器连接同一个数据库,无需同步。
|
||||||
* - 使用。顶层密钥,用于保护其他存于数据的密钥。
|
// * - 使用。顶层密钥,用于保护其他存于数据的密钥。
|
||||||
*
|
// *
|
||||||
* @author liulu 、Cheney
|
// * @author liulu 、Cheney
|
||||||
* @since 2024/10/23
|
// * @since 2024/10/23
|
||||||
*/
|
// */
|
||||||
@Slf4j
|
//@Slf4j
|
||||||
@Service
|
//@Service
|
||||||
public class BCSdfApiService extends AbstractSdfApiService {
|
//public class BCSdfApiService extends AbstractSdfApiService {
|
||||||
|
//
|
||||||
public BCSdfApiService() {
|
// public BCSdfApiService() {
|
||||||
super();
|
// super();
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@Override
|
// @Override
|
||||||
public byte[] generateRandom(int len) {
|
// public byte[] generateRandom(int len) {
|
||||||
byte[] res = new byte[len];
|
// byte[] res = new byte[len];
|
||||||
new SecureRandom().nextBytes(res);
|
// new SecureRandom().nextBytes(res);
|
||||||
return res;
|
// return res;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
/**
|
// /**
|
||||||
* 生成对称算法密钥
|
// * 生成对称算法密钥
|
||||||
*
|
// *
|
||||||
* @param alg 算法,只支持对称算法
|
// * @param alg 算法,只支持对称算法
|
||||||
* @param keyLen 密钥长度(bit),只针对密钥长度可变的算法。
|
// * @param keyLen 密钥长度(bit),只针对密钥长度可变的算法。
|
||||||
* 禁止传 null
|
// * 禁止传 null
|
||||||
* @return
|
// * @return
|
||||||
*/
|
// */
|
||||||
@Override
|
// @Override
|
||||||
public byte[] genSymKey(KeyAlg alg, Integer keyLen) {
|
// public byte[] genSymKey(KeyAlg alg, Integer keyLen) {
|
||||||
switch (alg) {
|
// switch (alg) {
|
||||||
case SM4: {
|
// case SM4: {
|
||||||
if (null == keyLen || keyLen != BCSM4Utils.DEFAULT_KEY_SIZE) {
|
// if (null == keyLen || keyLen != BCSM4Utils.DEFAULT_KEY_SIZE) {
|
||||||
throw new IllegalArgumentException("Invalid key length: " + keyLen);
|
// throw new IllegalArgumentException("Invalid key length: " + keyLen);
|
||||||
}
|
// }
|
||||||
try {
|
// try {
|
||||||
return BCSM4Utils.generateKey();
|
// return BCSM4Utils.generateKey();
|
||||||
} catch (NoSuchAlgorithmException | NoSuchProviderException e) {
|
// } catch (NoSuchAlgorithmException | NoSuchProviderException e) {
|
||||||
throw new RuntimeException("算法实现错误", e);
|
// throw new RuntimeException("算法实现错误", e);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
default: {
|
// default: {
|
||||||
throw new IllegalArgumentException("Unsupported algorithm: " + alg);
|
// throw new IllegalArgumentException("Unsupported algorithm: " + alg);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@Override
|
// @Override
|
||||||
public byte[] symEncrypt(KeyAlg alg, AlgMode mode, Padding padding, byte[] key, byte[] data) {
|
// public byte[] symEncrypt(KeyAlg alg, AlgMode mode, Padding padding, byte[] key, byte[] data) {
|
||||||
return symCalc(Cipher.ENCRYPT_MODE, alg, mode, padding, key, data);
|
// return symCalc(Cipher.ENCRYPT_MODE, alg, mode, padding, key, data);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@Override
|
// @Override
|
||||||
public byte[] symEncrypt(AlgId alg, byte[] key, byte[] iv, byte[] data) {
|
// public byte[] symEncrypt(AlgId alg, byte[] key, byte[] iv, byte[] data) {
|
||||||
return new byte[0];
|
// return new byte[0];
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
@Override
|
// @Override
|
||||||
public byte[] symDecrypt(KeyAlg alg, AlgMode mode, Padding padding, byte[] key, byte[] data) {
|
// public byte[] symDecrypt(KeyAlg alg, AlgMode mode, Padding padding, byte[] key, byte[] data) {
|
||||||
return symCalc(Cipher.DECRYPT_MODE, alg, mode, padding, key, data);
|
// return symCalc(Cipher.DECRYPT_MODE, alg, mode, padding, key, data);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@Override
|
// @Override
|
||||||
public byte[] symDecrypt(AlgId alg, byte[] key, byte[] iv, byte[] data) {
|
// public byte[] symDecrypt(AlgId alg, byte[] key, byte[] iv, byte[] data) {
|
||||||
return new byte[0];
|
// return new byte[0];
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
/**
|
// /**
|
||||||
* 对称加解密的统一实现
|
// * 对称加解密的统一实现
|
||||||
*
|
// *
|
||||||
* @param alg 算法,只支持对称算法
|
// * @param alg 算法,只支持对称算法
|
||||||
* @param key 密钥值,明文
|
// * @param key 密钥值,明文
|
||||||
* @param data 加密时明文数据,解密时为密文数据
|
// * @param data 加密时明文数据,解密时为密文数据
|
||||||
*/
|
// */
|
||||||
private byte[] symCalc(int cipherMode, KeyAlg alg, AlgMode mode, Padding padding, byte[] key, byte[] data) {
|
// private byte[] symCalc(int cipherMode, KeyAlg alg, AlgMode mode, Padding padding, byte[] key, byte[] data) {
|
||||||
if (alg.getCategory() != KeyCategory.SYM_KEY) {
|
// if (alg.getCategory() != KeyCategory.SYM_KEY) {
|
||||||
throw new IllegalArgumentException("Must SYM_KEY, unsupported algorithm: " + alg);
|
// throw new IllegalArgumentException("Must SYM_KEY, unsupported algorithm: " + alg);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
// 算法
|
// // 算法
|
||||||
String algName = null;
|
// String algName = null;
|
||||||
if (alg == KeyAlg.SM4) {
|
// if (alg == KeyAlg.SM4) {
|
||||||
algName = "SM4/";
|
// algName = "SM4/";
|
||||||
} else {
|
// } else {
|
||||||
throw new IllegalArgumentException("Unsupported algorithm: " + alg);
|
// throw new IllegalArgumentException("Unsupported algorithm: " + alg);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
// 算法轮模式
|
// // 算法轮模式
|
||||||
algName += mode.getCode() + "/";
|
// algName += mode.getCode() + "/";
|
||||||
|
//
|
||||||
// 填充模式
|
// // 填充模式
|
||||||
algName += padding.getCode();
|
// algName += padding.getCode();
|
||||||
|
//
|
||||||
|
//
|
||||||
Cipher cipher = null;
|
// Cipher cipher = null;
|
||||||
try {
|
// try {
|
||||||
cipher = BCSM4Utils.generateECBCipher(algName, cipherMode, key);
|
// cipher = BCSM4Utils.generateECBCipher(algName, cipherMode, key);
|
||||||
return cipher.doFinal(data);
|
// return cipher.doFinal(data);
|
||||||
} catch (IllegalBlockSizeException | BadPaddingException | NoSuchAlgorithmException | NoSuchProviderException | NoSuchPaddingException | InvalidKeyException e) {
|
// } catch (IllegalBlockSizeException | BadPaddingException | NoSuchAlgorithmException | NoSuchProviderException | NoSuchPaddingException | InvalidKeyException e) {
|
||||||
throw new RuntimeException("算法执行错误", e);
|
// throw new RuntimeException("算法执行错误", e);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@SneakyThrows
|
// @SneakyThrows
|
||||||
@Override
|
// @Override
|
||||||
public EccKey genKeyPairEcc() {
|
// public EccKey genKeyPairEcc() {
|
||||||
// 生成密钥对
|
// // 生成密钥对
|
||||||
KeyPair keyPair = BCSM2Utils.generateKeyPair();
|
// KeyPair keyPair = BCSM2Utils.generateKeyPair();
|
||||||
BCECPublicKey pubKey = (BCECPublicKey) keyPair.getPublic();
|
// BCECPublicKey pubKey = (BCECPublicKey) keyPair.getPublic();
|
||||||
BCECPrivateKey priKey = (BCECPrivateKey) keyPair.getPrivate();
|
// BCECPrivateKey priKey = (BCECPrivateKey) keyPair.getPrivate();
|
||||||
byte[] x = pubKey.getQ().getXCoord().getEncoded();
|
// byte[] x = pubKey.getQ().getXCoord().getEncoded();
|
||||||
byte[] y = pubKey.getQ().getYCoord().getEncoded();
|
// byte[] y = pubKey.getQ().getYCoord().getEncoded();
|
||||||
byte[] d = BigIntegers.asUnsignedByteArray(32, priKey.getD());
|
// byte[] d = BigIntegers.asUnsignedByteArray(32, priKey.getD());
|
||||||
return new EccKey(LangUtils.merge(x, y), d);
|
// return new EccKey(LangUtils.merge(x, y), d);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
@Override
|
// @Override
|
||||||
public byte[] calculateMAC(byte[] symKey, byte[] pucIv, byte[] pucData) {
|
// public byte[] calculateMAC(byte[] symKey, byte[] pucIv, byte[] pucData) {
|
||||||
return new byte[0];
|
// return new byte[0];
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@Override
|
// @Override
|
||||||
public byte[] hmac(byte[] key, byte[] srcData) {
|
// public byte[] hmac(byte[] key, byte[] srcData) {
|
||||||
return BCSM3Utils.hmac(key, srcData);
|
// return BCSM3Utils.hmac(key, srcData);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@Override
|
// @Override
|
||||||
public byte[] hash(byte[] pucData) {
|
// public byte[] hash(byte[] pucData) {
|
||||||
return BCSM3Utils.hash(pucData);
|
// return BCSM3Utils.hash(pucData);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@Override
|
// @Override
|
||||||
public byte[] encryptByTMK(byte[] data) {
|
// public byte[] encryptByTMK(byte[] data) {
|
||||||
return data;
|
// return data;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@Override
|
// @Override
|
||||||
public byte[] decryptByTMK(byte[] data) {
|
// public byte[] decryptByTMK(byte[] data) {
|
||||||
return data;
|
// return data;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
}
|
//}
|
||||||
|
@ -213,4 +213,34 @@ public class BcSdfApiAdaptor implements SdfApiAdapter {
|
|||||||
Assert.notNull(key, "密钥句柄不存在");
|
Assert.notNull(key, "密钥句柄不存在");
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] calculateMAC(String sessionHandle, String keyHandle, AlgId uiAlg, byte[] pucIv, byte[] pucData) {
|
||||||
|
return new byte[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] calculateMAC(String sessionHandle, byte[] symKey, AlgId uiAlg, byte[] pucIv, byte[] pucData) {
|
||||||
|
return new byte[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashInit(String sessionHandle, AlgId alg, EccPubKey pucPublicKey, byte[] pucID) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashUpdate(String sessionHandle, byte[] pucData) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] hashFinish(String sessionHandle) {
|
||||||
|
return new byte[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] hashOperation(String sessionHandle, AlgId alg, EccPubKey pucPublicKey, byte[] pucID, byte[] pucData) {
|
||||||
|
return new byte[0];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -257,4 +257,70 @@ public abstract class JnaSdfAdaptor implements SdfApiAdapter {
|
|||||||
sdfLibrary.SDF_DestroyKey(hSessionHandle, hKeyHandle);
|
sdfLibrary.SDF_DestroyKey(hSessionHandle, hKeyHandle);
|
||||||
return pucData;
|
return pucData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] calculateMAC(String sessionHandle, String keyHandle, AlgId uiAlg, byte[] pucIv, byte[] pucData) {
|
||||||
|
Pointer hSessionHandle = getSessionHandle(sessionHandle);
|
||||||
|
Pointer hKeyHandle = getKeyHandle(keyHandle);
|
||||||
|
|
||||||
|
int uiMacLength = pucData.length;
|
||||||
|
byte[] pucMac = new byte[uiMacLength];
|
||||||
|
|
||||||
|
IntByReference puiLength = new IntByReference();
|
||||||
|
sdfLibrary.SDF_CalculateMAC(hSessionHandle, hKeyHandle, getAlgId(uiAlg), pucIv, pucData, uiMacLength, pucMac, puiLength);
|
||||||
|
|
||||||
|
return pucMac;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] calculateMAC(String sessionHandle, byte[] symKey, AlgId uiAlg, byte[] pucIv, byte[] pucData) {
|
||||||
|
PointerByReference phKeyHandle = new PointerByReference();
|
||||||
|
Pointer hSessionHandle = getSessionHandle(sessionHandle);
|
||||||
|
int length = symKey.length;
|
||||||
|
// 导入会话密钥
|
||||||
|
sdfLibrary.SDF_ImportKey(hSessionHandle, symKey, length, phKeyHandle);
|
||||||
|
|
||||||
|
int uiMacLength = pucData.length;
|
||||||
|
byte[] pucMac = new byte[uiMacLength];
|
||||||
|
Pointer hKeyHandle = phKeyHandle.getValue();
|
||||||
|
IntByReference puiLength = new IntByReference();
|
||||||
|
sdfLibrary.SDF_CalculateMAC(hSessionHandle, hKeyHandle, getAlgId(uiAlg), pucIv, pucData, uiMacLength, pucMac, puiLength);
|
||||||
|
// 销毁会话密钥
|
||||||
|
sdfLibrary.SDF_DestroyKey(hSessionHandle, hKeyHandle);
|
||||||
|
return pucMac;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashInit(String sessionHandle, AlgId alg, EccPubKey pucPublicKey, byte[] pucID) {
|
||||||
|
Pointer hSessionHandle = getSessionHandle(sessionHandle);
|
||||||
|
byte[] pubPub = pucPublicKey == null ? null : pucPublicKey.toSdfData();
|
||||||
|
return sdfLibrary.SDF_HashInit(hSessionHandle, getAlgId(AlgId.SGD_SM3), pubPub, pucID, pucID.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashUpdate(String sessionHandle, byte[] pucData) {
|
||||||
|
Pointer hSessionHandle = getSessionHandle(sessionHandle);
|
||||||
|
return sdfLibrary.SDF_HashUpdate(hSessionHandle, pucData, pucData.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] hashFinish(String sessionHandle) {
|
||||||
|
Pointer hSessionHandle = getSessionHandle(sessionHandle);
|
||||||
|
byte[] pucHash = new byte[32];
|
||||||
|
IntByReference puiLength = new IntByReference();
|
||||||
|
sdfLibrary.SDF_HashFinal(hSessionHandle, pucHash, puiLength);
|
||||||
|
return pucHash;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] hashOperation(String sessionHandle, AlgId alg, EccPubKey pucPublicKey, byte[] pucID, byte[] pucData) {
|
||||||
|
Pointer hSessionHandle = getSessionHandle(sessionHandle);
|
||||||
|
byte[] pubPub = pucPublicKey == null ? null : pucPublicKey.toSdfData();
|
||||||
|
sdfLibrary.SDF_HashInit(hSessionHandle, getAlgId(AlgId.SGD_SM3), pubPub, pucID, pucID.length);
|
||||||
|
sdfLibrary.SDF_HashUpdate(hSessionHandle, pucData, pucData.length);
|
||||||
|
byte[] pucHash = new byte[32];
|
||||||
|
IntByReference puiLength = new IntByReference();
|
||||||
|
sdfLibrary.SDF_HashFinal(hSessionHandle, pucHash, puiLength);
|
||||||
|
return pucHash;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -135,4 +135,47 @@ public interface SdfApiAdapter {
|
|||||||
byte[] symDecrypt(String sessionHandle, String keyHandle, AlgId alg, byte[] pucIv, byte[] pucEncData);
|
byte[] symDecrypt(String sessionHandle, String keyHandle, AlgId alg, byte[] pucIv, byte[] pucEncData);
|
||||||
|
|
||||||
byte[] externalSymDecrypt(String sessionHandle, byte[] symKey, AlgId alg, byte[] pucIv, byte[] pucEncData);
|
byte[] externalSymDecrypt(String sessionHandle, byte[] symKey, AlgId alg, byte[] pucIv, byte[] pucEncData);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param sessionHandle 与设备建立的会话句柄
|
||||||
|
* @param keyHandle 指定的密钥句柄
|
||||||
|
* @param uiAlg 算法标识,指定MAC算法 SGD_SMS4_MAC
|
||||||
|
* @param pucIv IV数据
|
||||||
|
* @param pucData 数据明文
|
||||||
|
* @return MAC值
|
||||||
|
*/
|
||||||
|
byte[] calculateMAC(String sessionHandle, String keyHandle, AlgId uiAlg, byte[] pucIv, byte[] pucData);
|
||||||
|
byte[] calculateMAC(String sessionHandle, byte[] symKey, AlgId uiAlg, byte[] pucIv, byte[] pucData);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 杂凑运算初始化
|
||||||
|
*
|
||||||
|
* @param sessionHandle 与设备建立的会话句柄
|
||||||
|
* @param alg 当前杂凑算法标识 SGD_SM3
|
||||||
|
* @param pucPublicKey 签名者公钥,当uiAlgID为SGD_SM3时有效
|
||||||
|
* @param pucID 签名者的ID值,当uiAlgID为SGD_SM3时有效
|
||||||
|
* @return 0 成功; 非0 失败,返回错误代码
|
||||||
|
*/
|
||||||
|
int hashInit(String sessionHandle, AlgId alg, EccPubKey pucPublicKey, byte[] pucID);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 多包杂凑运算
|
||||||
|
*
|
||||||
|
* @param sessionHandle sessionHandle
|
||||||
|
* @param pucData 数据明文
|
||||||
|
* @return 0 成功; 非0 失败,返回错误代码
|
||||||
|
*/
|
||||||
|
int hashUpdate(String sessionHandle, byte[] pucData);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 杂凑运算结束
|
||||||
|
*
|
||||||
|
* @param sessionHandle 与设备建立的会话句柄
|
||||||
|
* @return 杂凑数据
|
||||||
|
*/
|
||||||
|
byte[] hashFinish(String sessionHandle);
|
||||||
|
|
||||||
|
|
||||||
|
byte[] hashOperation(String sessionHandle, AlgId alg, EccPubKey pucPublicKey, byte[] pucID, byte[] pucData);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -283,7 +283,7 @@ public interface SdfLibrary extends Library {
|
|||||||
* @param pucIDlength 签名者ID的长度
|
* @param pucIDlength 签名者ID的长度
|
||||||
* @return int 响应码
|
* @return int 响应码
|
||||||
*/
|
*/
|
||||||
int SDF_HashInit(Pointer phSessionHandle, int uiAlgID, byte[] pucPublicKey, String pucID, int pucIDlength);
|
int SDF_HashInit(Pointer phSessionHandle, int uiAlgID, byte[] pucPublicKey, byte[] pucID, int pucIDlength);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 多包杂凑运算
|
* 多包杂凑运算
|
||||||
|
@ -24,7 +24,7 @@ public class EccPriKey {
|
|||||||
|
|
||||||
public static EccPriKey fromBytes(byte[] priKey) {
|
public static EccPriKey fromBytes(byte[] priKey) {
|
||||||
Assert.notNull(priKey, "公钥数据不能为null");
|
Assert.notNull(priKey, "公钥数据不能为null");
|
||||||
if (Objects.equals(priKey.length, 132)) {
|
if (Objects.equals(priKey.length, 68)) {
|
||||||
// 00010000
|
// 00010000
|
||||||
priKey = Arrays.copyOfRange(priKey, 4, priKey.length);
|
priKey = Arrays.copyOfRange(priKey, 4, priKey.length);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,166 @@
|
|||||||
|
package com.sunyard.chsm.sdf;
|
||||||
|
|
||||||
|
import com.sunyard.chsm.enums.AlgMode;
|
||||||
|
import com.sunyard.chsm.enums.DeviceTmkStatus;
|
||||||
|
import com.sunyard.chsm.enums.KeyAlg;
|
||||||
|
import com.sunyard.chsm.enums.Padding;
|
||||||
|
import com.sunyard.chsm.mapper.SpDeviceMapper;
|
||||||
|
import com.sunyard.chsm.model.dto.DeviceCheckRes;
|
||||||
|
import com.sunyard.chsm.model.entity.Device;
|
||||||
|
import com.sunyard.chsm.sdf.adapter.BcSdfApiAdaptor;
|
||||||
|
import com.sunyard.chsm.sdf.adapter.SdfApiAdapter;
|
||||||
|
import com.sunyard.chsm.sdf.adapter.SdfApiAdapterFactory;
|
||||||
|
import com.sunyard.chsm.sdf.context.AlgId;
|
||||||
|
import com.sunyard.chsm.sdf.model.DeviceInfo;
|
||||||
|
import com.sunyard.chsm.sdf.model.EccCipher;
|
||||||
|
import com.sunyard.chsm.sdf.model.EccKey;
|
||||||
|
import com.sunyard.chsm.service.TmkService;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author liulu
|
||||||
|
* @since 2024/12/11
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class SingleSdfApiService implements SdfApiService, InitializingBean {
|
||||||
|
|
||||||
|
private String tmkHandle;
|
||||||
|
private String sessionHandle;
|
||||||
|
private SdfApiAdapter sdfApiAdapter;
|
||||||
|
private final TmkService tmkService;
|
||||||
|
private final SpDeviceMapper spDeviceMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] generateRandom(int len) {
|
||||||
|
return new byte[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] genSymKey(KeyAlg alg, Integer keyLen) {
|
||||||
|
return new byte[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] genSymKey(KeyAlg alg) {
|
||||||
|
return new byte[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] symEncrypt(KeyAlg alg, AlgMode mode, Padding padding, byte[] key, byte[] data) {
|
||||||
|
return new byte[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] symEncrypt(KeyAlg alg, byte[] key, byte[] data) {
|
||||||
|
return new byte[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] symEncrypt(AlgId alg, byte[] key, byte[] iv, byte[] data) {
|
||||||
|
return new byte[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] symDecrypt(KeyAlg alg, AlgMode mode, Padding padding, byte[] key, byte[] data) {
|
||||||
|
return new byte[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] symDecrypt(KeyAlg alg, byte[] key, byte[] data) {
|
||||||
|
return new byte[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] symDecrypt(AlgId alg, byte[] key, byte[] iv, byte[] data) {
|
||||||
|
return new byte[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EccKey genKeyPairEcc() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] calculateMAC(byte[] symKey, byte[] pucIv, byte[] pucData) {
|
||||||
|
return new byte[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] hmac(byte[] key, byte[] srcData) {
|
||||||
|
return new byte[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] hash(byte[] pucData) {
|
||||||
|
return new byte[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] encryptByTMK(byte[] data) {
|
||||||
|
return new byte[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] decryptByTMK(byte[] data) {
|
||||||
|
return new byte[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
private void changeDevice(boolean tmkInit) {
|
||||||
|
DeviceTmkStatus status = tmkInit ? DeviceTmkStatus.finished : DeviceTmkStatus.available;
|
||||||
|
Device device = spDeviceMapper.selectOneByStatus(status);
|
||||||
|
if (Objects.nonNull(device)) {
|
||||||
|
DeviceCheckRes checkRes = tmkService.checkDevice(device);
|
||||||
|
if (!checkRes.isHasError()) {
|
||||||
|
this.sdfApiAdapter = checkRes.getSdfApiAdapter();
|
||||||
|
String hd = sdfApiAdapter.openDevice();
|
||||||
|
this.sessionHandle = sdfApiAdapter.openSession(hd);
|
||||||
|
if (tmkInit) {
|
||||||
|
sdfApiAdapter.getPrivateKeyAccessRight(sessionHandle, device.getEncKeyIdx(), device.getAccessCredentials().getBytes());
|
||||||
|
this.tmkHandle = sdfApiAdapter.importKeyWithISKECC(sessionHandle, device.getEncKeyIdx(), EccCipher.fromHex(device.getEncTmk()));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (tmkService.isEnableSoftDevice()) {
|
||||||
|
this.sdfApiAdapter = SdfApiAdapterFactory.getBcAdapter();
|
||||||
|
this.sessionHandle = sdfApiAdapter.openSession("");
|
||||||
|
if (tmkInit) {
|
||||||
|
byte[] encTmk = tmkService.getSoftDeviceEncTmk();
|
||||||
|
this.tmkHandle = sdfApiAdapter.importKeyWithISKECC(sessionHandle, device.getEncKeyIdx(), EccCipher.fromBytes(encTmk));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterPropertiesSet() throws Exception {
|
||||||
|
Executors.newSingleThreadScheduledExecutor()
|
||||||
|
.scheduleWithFixedDelay(() -> {
|
||||||
|
boolean tmkInit = tmkService.isTmkInit();
|
||||||
|
if (sdfApiAdapter != null) {
|
||||||
|
if (sdfApiAdapter instanceof BcSdfApiAdaptor) {
|
||||||
|
changeDevice(tmkInit);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (tmkInit && StringUtils.isEmpty(tmkHandle)) {
|
||||||
|
changeDevice(tmkInit);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
DeviceInfo deviceInfo = sdfApiAdapter.getDeviceInfo(sessionHandle);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
changeDevice(tmkInit);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
changeDevice(tmkInit);
|
||||||
|
}
|
||||||
|
}, 0L, 5L, TimeUnit.MINUTES);
|
||||||
|
}
|
||||||
|
}
|
@ -7,7 +7,9 @@ import com.sunyard.chsm.sdf.SdfApiService;
|
|||||||
import com.sunyard.chsm.sdf.context.AlgId;
|
import com.sunyard.chsm.sdf.context.AlgId;
|
||||||
import com.sunyard.chsm.sdf.model.EccKey;
|
import com.sunyard.chsm.sdf.model.EccKey;
|
||||||
import com.sunyard.chsm.sdf.util.PaddingUtil;
|
import com.sunyard.chsm.sdf.util.PaddingUtil;
|
||||||
|
import com.sunyard.chsm.utils.gm.BCSM3Utils;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
@ -17,9 +19,9 @@ import java.util.function.Function;
|
|||||||
* @since 2024/12/10
|
* @since 2024/12/10
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
|
@Service
|
||||||
public class LoadBalancedSdfApiService implements SdfApiService {
|
public class LoadBalancedSdfApiService implements SdfApiService {
|
||||||
|
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private DeviceManager deviceManager;
|
private DeviceManager deviceManager;
|
||||||
|
|
||||||
@ -100,26 +102,28 @@ public class LoadBalancedSdfApiService implements SdfApiService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte[] calculateMAC(byte[] symKey, byte[] pucIv, byte[] pucData) {
|
public byte[] calculateMAC(byte[] symKey, byte[] pucIv, byte[] pucData) {
|
||||||
return new byte[0];
|
return apply(s -> s.getSdfApiAdapter().calculateMAC(s.getSessionHandle(), symKey, AlgId.SGD_SM4_MAC, pucIv, pucData));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte[] hmac(byte[] key, byte[] srcData) {
|
public byte[] hmac(byte[] key, byte[] srcData) {
|
||||||
return new byte[0];
|
return BCSM3Utils.hmac(key, srcData);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte[] hash(byte[] pucData) {
|
public byte[] hash(byte[] pucData) {
|
||||||
return new byte[0];
|
return apply(s -> s.getSdfApiAdapter().hashOperation(s.getSessionHandle(), AlgId.SGD_SM3, null, null, pucData));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte[] encryptByTMK(byte[] data) {
|
public byte[] encryptByTMK(byte[] data) {
|
||||||
return new byte[0];
|
byte[] pad = PaddingUtil.PKCS7Unpadding(data);
|
||||||
|
return apply(s -> s.getSdfApiAdapter().symEncrypt(s.getSessionHandle(), s.getKeyHandle(), AlgId.SGD_SM4_CBC, new byte[8], pad));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte[] decryptByTMK(byte[] data) {
|
public byte[] decryptByTMK(byte[] data) {
|
||||||
return new byte[0];
|
byte[] decrypt = apply(s -> s.getSdfApiAdapter().symDecrypt(s.getSessionHandle(), s.getKeyHandle(), AlgId.SGD_SM4_CBC, new byte[8], data));
|
||||||
|
return PaddingUtil.PKCS7Unpadding(decrypt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user