sdf api
This commit is contained in:
parent
3dc061907f
commit
2250a6234b
@ -1,186 +1,186 @@
|
||||
package com.sunyard.chsm.sdf;
|
||||
|
||||
|
||||
import com.sunyard.chsm.enums.AlgMode;
|
||||
import com.sunyard.chsm.enums.KeyAlg;
|
||||
import com.sunyard.chsm.enums.KeyCategory;
|
||||
import com.sunyard.chsm.enums.Padding;
|
||||
import com.sunyard.chsm.sdf.context.AlgId;
|
||||
import com.sunyard.chsm.sdf.model.EccKey;
|
||||
import com.sunyard.chsm.sdf.util.LangUtils;
|
||||
import com.sunyard.chsm.utils.gm.BCSM2Utils;
|
||||
import com.sunyard.chsm.utils.gm.BCSM3Utils;
|
||||
import com.sunyard.chsm.utils.gm.BCSM4Utils;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
|
||||
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
|
||||
import org.bouncycastle.util.BigIntegers;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.KeyPair;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.NoSuchProviderException;
|
||||
import java.security.SecureRandom;
|
||||
|
||||
|
||||
/**
|
||||
* 基于 BC 库的国密软算法实现
|
||||
* 当前实现类的接口返回的对称密钥和私钥认为是明文,在上层 Service 进行使用和存储时的加密和解密运算。
|
||||
* <p>
|
||||
* 主密钥:
|
||||
* - 生成。 软随机数。项目启动时不存在则自动生成。
|
||||
* - 存储。 存储在 SC_PARAM_CONF 表, KEY 为 mk 的字段,值为固定的 48 字节,以 HEX 格式 96 字节存储。
|
||||
* 前 16 字节为主密钥值,后 32 字节为主密钥值使用 SM3 计算的校验值。
|
||||
* - 同步。基于数据库进行导入、导出、和备份、恢复。多台应用服务器连接同一个数据库,无需同步。
|
||||
* - 使用。顶层密钥,用于保护其他存于数据的密钥。
|
||||
*
|
||||
* @author liulu 、Cheney
|
||||
* @since 2024/10/23
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class BCSdfApiService extends AbstractSdfApiService {
|
||||
|
||||
public BCSdfApiService() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] generateRandom(int len) {
|
||||
byte[] res = new byte[len];
|
||||
new SecureRandom().nextBytes(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 生成对称算法密钥
|
||||
*
|
||||
* @param alg 算法,只支持对称算法
|
||||
* @param keyLen 密钥长度(bit),只针对密钥长度可变的算法。
|
||||
* 禁止传 null
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public byte[] genSymKey(KeyAlg alg, Integer keyLen) {
|
||||
switch (alg) {
|
||||
case SM4: {
|
||||
if (null == keyLen || keyLen != BCSM4Utils.DEFAULT_KEY_SIZE) {
|
||||
throw new IllegalArgumentException("Invalid key length: " + keyLen);
|
||||
}
|
||||
try {
|
||||
return BCSM4Utils.generateKey();
|
||||
} catch (NoSuchAlgorithmException | NoSuchProviderException e) {
|
||||
throw new RuntimeException("算法实现错误", e);
|
||||
}
|
||||
}
|
||||
default: {
|
||||
throw new IllegalArgumentException("Unsupported algorithm: " + alg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] symEncrypt(KeyAlg alg, AlgMode mode, Padding padding, byte[] key, byte[] data) {
|
||||
return symCalc(Cipher.ENCRYPT_MODE, alg, mode, padding, key, data);
|
||||
}
|
||||
|
||||
@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 symCalc(Cipher.DECRYPT_MODE, alg, mode, padding, key, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] symDecrypt(AlgId alg, byte[] key, byte[] iv, byte[] data) {
|
||||
return new byte[0];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 对称加解密的统一实现
|
||||
*
|
||||
* @param alg 算法,只支持对称算法
|
||||
* @param key 密钥值,明文
|
||||
* @param data 加密时明文数据,解密时为密文数据
|
||||
*/
|
||||
private byte[] symCalc(int cipherMode, KeyAlg alg, AlgMode mode, Padding padding, byte[] key, byte[] data) {
|
||||
if (alg.getCategory() != KeyCategory.SYM_KEY) {
|
||||
throw new IllegalArgumentException("Must SYM_KEY, unsupported algorithm: " + alg);
|
||||
}
|
||||
|
||||
// 算法
|
||||
String algName = null;
|
||||
if (alg == KeyAlg.SM4) {
|
||||
algName = "SM4/";
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unsupported algorithm: " + alg);
|
||||
}
|
||||
|
||||
// 算法轮模式
|
||||
algName += mode.getCode() + "/";
|
||||
|
||||
// 填充模式
|
||||
algName += padding.getCode();
|
||||
|
||||
|
||||
Cipher cipher = null;
|
||||
try {
|
||||
cipher = BCSM4Utils.generateECBCipher(algName, cipherMode, key);
|
||||
return cipher.doFinal(data);
|
||||
} catch (IllegalBlockSizeException | BadPaddingException | NoSuchAlgorithmException | NoSuchProviderException | NoSuchPaddingException | InvalidKeyException e) {
|
||||
throw new RuntimeException("算法执行错误", e);
|
||||
}
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
@Override
|
||||
public EccKey genKeyPairEcc() {
|
||||
// 生成密钥对
|
||||
KeyPair keyPair = BCSM2Utils.generateKeyPair();
|
||||
BCECPublicKey pubKey = (BCECPublicKey) keyPair.getPublic();
|
||||
BCECPrivateKey priKey = (BCECPrivateKey) keyPair.getPrivate();
|
||||
byte[] x = pubKey.getQ().getXCoord().getEncoded();
|
||||
byte[] y = pubKey.getQ().getYCoord().getEncoded();
|
||||
byte[] d = BigIntegers.asUnsignedByteArray(32, priKey.getD());
|
||||
return new EccKey(LangUtils.merge(x, y), d);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public byte[] calculateMAC(byte[] symKey, byte[] pucIv, byte[] pucData) {
|
||||
return new byte[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] hmac(byte[] key, byte[] srcData) {
|
||||
return BCSM3Utils.hmac(key, srcData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] hash(byte[] pucData) {
|
||||
return BCSM3Utils.hash(pucData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] encryptByTMK(byte[] data) {
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] decryptByTMK(byte[] data) {
|
||||
return data;
|
||||
}
|
||||
|
||||
}
|
||||
//package com.sunyard.chsm.sdf;
|
||||
//
|
||||
//
|
||||
//import com.sunyard.chsm.enums.AlgMode;
|
||||
//import com.sunyard.chsm.enums.KeyAlg;
|
||||
//import com.sunyard.chsm.enums.KeyCategory;
|
||||
//import com.sunyard.chsm.enums.Padding;
|
||||
//import com.sunyard.chsm.sdf.context.AlgId;
|
||||
//import com.sunyard.chsm.sdf.model.EccKey;
|
||||
//import com.sunyard.chsm.sdf.util.LangUtils;
|
||||
//import com.sunyard.chsm.utils.gm.BCSM2Utils;
|
||||
//import com.sunyard.chsm.utils.gm.BCSM3Utils;
|
||||
//import com.sunyard.chsm.utils.gm.BCSM4Utils;
|
||||
//import lombok.SneakyThrows;
|
||||
//import lombok.extern.slf4j.Slf4j;
|
||||
//import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
|
||||
//import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
|
||||
//import org.bouncycastle.util.BigIntegers;
|
||||
//import org.springframework.stereotype.Service;
|
||||
//
|
||||
//import javax.crypto.BadPaddingException;
|
||||
//import javax.crypto.Cipher;
|
||||
//import javax.crypto.IllegalBlockSizeException;
|
||||
//import javax.crypto.NoSuchPaddingException;
|
||||
//import java.security.InvalidKeyException;
|
||||
//import java.security.KeyPair;
|
||||
//import java.security.NoSuchAlgorithmException;
|
||||
//import java.security.NoSuchProviderException;
|
||||
//import java.security.SecureRandom;
|
||||
//
|
||||
//
|
||||
///**
|
||||
// * 基于 BC 库的国密软算法实现
|
||||
// * 当前实现类的接口返回的对称密钥和私钥认为是明文,在上层 Service 进行使用和存储时的加密和解密运算。
|
||||
// * <p>
|
||||
// * 主密钥:
|
||||
// * - 生成。 软随机数。项目启动时不存在则自动生成。
|
||||
// * - 存储。 存储在 SC_PARAM_CONF 表, KEY 为 mk 的字段,值为固定的 48 字节,以 HEX 格式 96 字节存储。
|
||||
// * 前 16 字节为主密钥值,后 32 字节为主密钥值使用 SM3 计算的校验值。
|
||||
// * - 同步。基于数据库进行导入、导出、和备份、恢复。多台应用服务器连接同一个数据库,无需同步。
|
||||
// * - 使用。顶层密钥,用于保护其他存于数据的密钥。
|
||||
// *
|
||||
// * @author liulu 、Cheney
|
||||
// * @since 2024/10/23
|
||||
// */
|
||||
//@Slf4j
|
||||
//@Service
|
||||
//public class BCSdfApiService extends AbstractSdfApiService {
|
||||
//
|
||||
// public BCSdfApiService() {
|
||||
// super();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public byte[] generateRandom(int len) {
|
||||
// byte[] res = new byte[len];
|
||||
// new SecureRandom().nextBytes(res);
|
||||
// return res;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// /**
|
||||
// * 生成对称算法密钥
|
||||
// *
|
||||
// * @param alg 算法,只支持对称算法
|
||||
// * @param keyLen 密钥长度(bit),只针对密钥长度可变的算法。
|
||||
// * 禁止传 null
|
||||
// * @return
|
||||
// */
|
||||
// @Override
|
||||
// public byte[] genSymKey(KeyAlg alg, Integer keyLen) {
|
||||
// switch (alg) {
|
||||
// case SM4: {
|
||||
// if (null == keyLen || keyLen != BCSM4Utils.DEFAULT_KEY_SIZE) {
|
||||
// throw new IllegalArgumentException("Invalid key length: " + keyLen);
|
||||
// }
|
||||
// try {
|
||||
// return BCSM4Utils.generateKey();
|
||||
// } catch (NoSuchAlgorithmException | NoSuchProviderException e) {
|
||||
// throw new RuntimeException("算法实现错误", e);
|
||||
// }
|
||||
// }
|
||||
// default: {
|
||||
// throw new IllegalArgumentException("Unsupported algorithm: " + alg);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public byte[] symEncrypt(KeyAlg alg, AlgMode mode, Padding padding, byte[] key, byte[] data) {
|
||||
// return symCalc(Cipher.ENCRYPT_MODE, alg, mode, padding, key, data);
|
||||
// }
|
||||
//
|
||||
// @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 symCalc(Cipher.DECRYPT_MODE, alg, mode, padding, key, data);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public byte[] symDecrypt(AlgId alg, byte[] key, byte[] iv, byte[] data) {
|
||||
// return new byte[0];
|
||||
// }
|
||||
//
|
||||
//
|
||||
// /**
|
||||
// * 对称加解密的统一实现
|
||||
// *
|
||||
// * @param alg 算法,只支持对称算法
|
||||
// * @param key 密钥值,明文
|
||||
// * @param data 加密时明文数据,解密时为密文数据
|
||||
// */
|
||||
// private byte[] symCalc(int cipherMode, KeyAlg alg, AlgMode mode, Padding padding, byte[] key, byte[] data) {
|
||||
// if (alg.getCategory() != KeyCategory.SYM_KEY) {
|
||||
// throw new IllegalArgumentException("Must SYM_KEY, unsupported algorithm: " + alg);
|
||||
// }
|
||||
//
|
||||
// // 算法
|
||||
// String algName = null;
|
||||
// if (alg == KeyAlg.SM4) {
|
||||
// algName = "SM4/";
|
||||
// } else {
|
||||
// throw new IllegalArgumentException("Unsupported algorithm: " + alg);
|
||||
// }
|
||||
//
|
||||
// // 算法轮模式
|
||||
// algName += mode.getCode() + "/";
|
||||
//
|
||||
// // 填充模式
|
||||
// algName += padding.getCode();
|
||||
//
|
||||
//
|
||||
// Cipher cipher = null;
|
||||
// try {
|
||||
// cipher = BCSM4Utils.generateECBCipher(algName, cipherMode, key);
|
||||
// return cipher.doFinal(data);
|
||||
// } catch (IllegalBlockSizeException | BadPaddingException | NoSuchAlgorithmException | NoSuchProviderException | NoSuchPaddingException | InvalidKeyException e) {
|
||||
// throw new RuntimeException("算法执行错误", e);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @SneakyThrows
|
||||
// @Override
|
||||
// public EccKey genKeyPairEcc() {
|
||||
// // 生成密钥对
|
||||
// KeyPair keyPair = BCSM2Utils.generateKeyPair();
|
||||
// BCECPublicKey pubKey = (BCECPublicKey) keyPair.getPublic();
|
||||
// BCECPrivateKey priKey = (BCECPrivateKey) keyPair.getPrivate();
|
||||
// byte[] x = pubKey.getQ().getXCoord().getEncoded();
|
||||
// byte[] y = pubKey.getQ().getYCoord().getEncoded();
|
||||
// byte[] d = BigIntegers.asUnsignedByteArray(32, priKey.getD());
|
||||
// return new EccKey(LangUtils.merge(x, y), d);
|
||||
// }
|
||||
//
|
||||
//
|
||||
// @Override
|
||||
// public byte[] calculateMAC(byte[] symKey, byte[] pucIv, byte[] pucData) {
|
||||
// return new byte[0];
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public byte[] hmac(byte[] key, byte[] srcData) {
|
||||
// return BCSM3Utils.hmac(key, srcData);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public byte[] hash(byte[] pucData) {
|
||||
// return BCSM3Utils.hash(pucData);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public byte[] encryptByTMK(byte[] data) {
|
||||
// return data;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public byte[] decryptByTMK(byte[] data) {
|
||||
// return data;
|
||||
// }
|
||||
//
|
||||
//}
|
||||
|
@ -213,4 +213,34 @@ public class BcSdfApiAdaptor implements SdfApiAdapter {
|
||||
Assert.notNull(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);
|
||||
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[] 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的长度
|
||||
* @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) {
|
||||
Assert.notNull(priKey, "公钥数据不能为null");
|
||||
if (Objects.equals(priKey.length, 132)) {
|
||||
if (Objects.equals(priKey.length, 68)) {
|
||||
// 00010000
|
||||
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.model.EccKey;
|
||||
import com.sunyard.chsm.sdf.util.PaddingUtil;
|
||||
import com.sunyard.chsm.utils.gm.BCSM3Utils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.function.Function;
|
||||
@ -17,9 +19,9 @@ import java.util.function.Function;
|
||||
* @since 2024/12/10
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class LoadBalancedSdfApiService implements SdfApiService {
|
||||
|
||||
|
||||
@Resource
|
||||
private DeviceManager deviceManager;
|
||||
|
||||
@ -100,26 +102,28 @@ public class LoadBalancedSdfApiService implements SdfApiService {
|
||||
|
||||
@Override
|
||||
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
|
||||
public byte[] hmac(byte[] key, byte[] srcData) {
|
||||
return new byte[0];
|
||||
return BCSM3Utils.hmac(key, srcData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] hash(byte[] pucData) {
|
||||
return new byte[0];
|
||||
return apply(s -> s.getSdfApiAdapter().hashOperation(s.getSessionHandle(), AlgId.SGD_SM3, null, null, pucData));
|
||||
}
|
||||
|
||||
@Override
|
||||
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
|
||||
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