This commit is contained in:
liulu
2024-12-11 11:49:40 +08:00
parent 63fce073dd
commit 3dc061907f
18 changed files with 264 additions and 104 deletions
@@ -15,6 +15,7 @@ import java.util.Objects;
public enum Padding {
NOPadding("NoPadding", "NoPadding"),
PCKS5Padding( "PKCS5Padding", "PKCS5Padding"),
PCKS7Padding( "PKCS7Padding", "PKCS7Padding"),
;
private final String code;
@@ -5,6 +5,7 @@ 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;
@@ -21,7 +22,11 @@ import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.security.*;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
/**
@@ -86,12 +91,22 @@ public class BCSdfApiService extends AbstractSdfApiService {
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];
}
/**
* 对称加解密的统一实现
@@ -4,6 +4,7 @@ package com.sunyard.chsm.sdf;
import com.sunyard.chsm.enums.AlgMode;
import com.sunyard.chsm.enums.KeyAlg;
import com.sunyard.chsm.enums.Padding;
import com.sunyard.chsm.sdf.context.AlgId;
import com.sunyard.chsm.sdf.model.EccKey;
@@ -23,41 +24,48 @@ public interface SdfApiService {
byte[] generateRandom(int len);
/**
* 生成对称密钥
* @param alg 算法,只支持对称算法
*
* @param alg 算法,只支持对称算法
* @param keyLen 密钥长度(bit),只针对密钥长度可变的算法。
* 禁止传 null
* @return 对称密钥
*/
byte[] genSymKey(KeyAlg alg, Integer keyLen);
byte[] genSymKey(KeyAlg alg);
/**
* 对称加密
* @param alg 算法,只支持对称算法
* @param mode 轮模式
*
* @param alg 算法,只支持对称算法
* @param mode 轮模式
* @param padding 填充模式
* @param key 密钥值,明文
* @param data 原始数据
* @param key 密钥值,明文
* @param data 原始数据
*/
byte[] symEncrypt(KeyAlg alg, AlgMode mode, Padding padding, byte[] key, byte[] data);
byte[] symEncrypt(KeyAlg alg, byte[] key, byte[] data);
byte[] symEncrypt(AlgId alg, byte[] key, byte[] iv, byte[] data);
/**
* 对称解密
* @param alg 算法,只支持对称算法
* @param key 密钥值,明文
* @param mode 轮模式
*
* @param alg 算法,只支持对称算法
* @param key 密钥值,明文
* @param mode 轮模式
* @param padding 填充模式
* @param data 密文数据
* @param data 密文数据
*/
byte[] symDecrypt(KeyAlg alg, AlgMode mode, Padding padding, byte[] key, byte[] data);
byte[] symDecrypt(KeyAlg alg, byte[] key, byte[] data);
byte[] symDecrypt(AlgId alg, byte[] key, byte[] iv, byte[] data);
/**
@@ -98,7 +98,7 @@ public class BcSdfApiAdaptor implements SdfApiAdapter {
@SneakyThrows
@Override
public EccKey generateKeyPairECC(String sessionHandle, String alg, int uiKeyBits) {
public EccKey generateKeyPairECC(String sessionHandle, AlgId alg) {
// 生成密钥对
KeyPair keyPair = BCSM2Utils.generateKeyPair();
BCECPublicKey pubKey = (BCECPublicKey) keyPair.getPublic();
@@ -171,9 +171,14 @@ public class BcSdfApiAdaptor implements SdfApiAdapter {
@Override
@SneakyThrows
public byte[] symEncrypt(String sessionHandle, String keyHandle, AlgId alg, byte[] pucIv, byte[] pucData) {
byte[] symKey = getSymKey(keyHandle);
return externalSymEncrypt(sessionHandle, symKey, alg, pucIv, pucData);
}
@Override
@SneakyThrows
public byte[] externalSymEncrypt(String sessionHandle, byte[] symKey, AlgId alg, byte[] pucIv, byte[] pucData) {
switch (alg) {
case SGD_SM4_ECB:
return BCSM4Utils.encrypt_ECB_NoPadding(symKey, pucData);
@@ -185,9 +190,14 @@ public class BcSdfApiAdaptor implements SdfApiAdapter {
}
@Override
@SneakyThrows
public byte[] symDecrypt(String sessionHandle, String keyHandle, AlgId alg, byte[] pucIv, byte[] pucEncData) {
byte[] symKey = getSymKey(keyHandle);
return externalSymDecrypt(sessionHandle, symKey, alg, pucIv, pucEncData);
}
@Override
@SneakyThrows
public byte[] externalSymDecrypt(String sessionHandle, byte[] symKey, AlgId alg, byte[] pucIv, byte[] pucEncData) {
switch (alg) {
case SGD_SM4_ECB:
return BCSM4Utils.decrypt_ECB_NoPadding(symKey, pucEncData);
@@ -8,6 +8,7 @@ import com.sunyard.chsm.sdf.lib.SdfLibrary;
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.sdf.model.EccPriKey;
import com.sunyard.chsm.sdf.model.EccPubKey;
import com.sunyard.chsm.sdf.model.SDF_DeviceInfo;
import com.sunyard.chsm.sdf.util.LangUtils;
@@ -129,8 +130,13 @@ public abstract class JnaSdfAdaptor implements SdfApiAdapter {
}
@Override
public EccKey generateKeyPairECC(String sessionHandle, String alg, int uiKeyBits) {
return null;
public EccKey generateKeyPairECC(String sessionHandle, AlgId alg) {
byte[] sdfPubKey = new byte[132];
byte[] sdfPriKey = new byte[68];
Pointer hSessionHandle = getSessionHandle(sessionHandle);
sdfLibrary.SDF_GenerateKeyPair_ECC(hSessionHandle, getAlgId(alg), 256, sdfPubKey, sdfPriKey);
return new EccKey(EccPubKey.fromBytes(sdfPubKey).getPubKeyBytes(), EccPriKey.fromBytes(sdfPriKey).getD());
}
@Override
@@ -200,6 +206,25 @@ public abstract class JnaSdfAdaptor implements SdfApiAdapter {
return pucEncData;
}
@Override
public byte[] externalSymEncrypt(String sessionHandle, byte[] symKey, AlgId alg, byte[] pucIv, byte[] pucData) {
int uiDataLength = pucData.length;
byte[] pucEncData = new byte[uiDataLength];
Pointer hSessionHandle = getSessionHandle(sessionHandle);
int length = symKey.length;
PointerByReference phKeyHandle = new PointerByReference();
// 先导入密钥
sdfLibrary.SDF_ImportKey(hSessionHandle, symKey, length, phKeyHandle);
//加密
Pointer hKeyHandle = phKeyHandle.getValue();
IntByReference puiLength = new IntByReference();
sdfLibrary.SDF_Encrypt(hSessionHandle, hKeyHandle, getAlgId(alg),
pucIv, pucData, uiDataLength, pucEncData, puiLength);
// 使用后销毁密钥
sdfLibrary.SDF_DestroyKey(hSessionHandle, hKeyHandle);
return pucEncData;
}
@Override
public byte[] symDecrypt(String sessionHandle, String keyHandle, AlgId alg, byte[] pucIv, byte[] pucEncData) {
Pointer hSessionHandle = getSessionHandle(sessionHandle);
@@ -212,4 +237,24 @@ public abstract class JnaSdfAdaptor implements SdfApiAdapter {
pucIv, pucEncData, uiEncDataLength, pucData, puiLength);
return pucData;
}
@Override
public byte[] externalSymDecrypt(String sessionHandle, byte[] symKey, AlgId alg, byte[] pucIv, byte[] pucEncData) {
int uiEncDataLength = pucEncData.length;
byte[] pucData = new byte[uiEncDataLength];
PointerByReference phKeyHandle = new PointerByReference();
Pointer hSessionHandle = getSessionHandle(sessionHandle);
int length = symKey.length;
// 导入会话密钥
sdfLibrary.SDF_ImportKey(hSessionHandle, symKey, length, phKeyHandle);
// 解密
Pointer hKeyHandle = phKeyHandle.getValue();
IntByReference puiLength = new IntByReference();
sdfLibrary.SDF_Decrypt(hSessionHandle, hKeyHandle, getAlgId(alg),
pucIv, pucEncData, uiEncDataLength, pucData, puiLength);
// 销毁会话密钥
sdfLibrary.SDF_DestroyKey(hSessionHandle, hKeyHandle);
return pucData;
}
}
@@ -51,7 +51,7 @@ public interface SdfApiAdapter {
* @return pucRandom 返回随机数
*/
byte[] generateRandom(String sessionHandle, int uiLength);
/**
* 导出ECC加密公钥
*
@@ -61,13 +61,12 @@ public interface SdfApiAdapter {
EccPubKey exportEncPublicKeyECC(String sessionHandle, int uiKeyIndex);
/**
* 产生ECC密钥对并输出
* 产生ECC密钥对并输出 密钥模长 256
*
* @param alg 指定算法标识 SGD_SM2_1
* @param uiKeyBits 指定密钥模长
* @return pucPublicKeyEcc 返回公钥 | pucPrivateKeyEcc 返回私钥
*/
EccKey generateKeyPairECC(String sessionHandle, String alg, int uiKeyBits);
EccKey generateKeyPairECC(String sessionHandle, AlgId alg);
boolean getPrivateKeyAccessRight(String hSessionHandle, int uiKeyIndex, byte[] pucPassword);
@@ -75,7 +74,7 @@ public interface SdfApiAdapter {
* 导入会话密钥并用内部ECC私钥解密
*
* @param uiIskIndex 密码设备内部存储加密私钥的索引值,对应于加密时的公钥
* @param eccCipher 缓冲区指针,用于存放返回的密钥密文
* @param eccCipher 缓冲区指针,用于存放返回的密钥密文
* @return phKeyHandle 返回密钥句柄
*/
String importKeyWithISKECC(String sessionHandle, int uiIskIndex, EccCipher eccCipher);
@@ -103,8 +102,8 @@ public interface SdfApiAdapter {
/**
* 外部密钥ECC公钥加密
*
* @param pubKey 外部ECC公钥结构
* @param pucData 缓冲区指针,用于存放外部输入的数据
* @param pubKey 外部ECC公钥结构
* @param pucData 缓冲区指针,用于存放外部输入的数据
* @return pucEncData 返回数据密文
*/
EccCipher externalEncryptECC(String sessionHandle, EccPubKey pubKey, byte[] pucData);
@@ -121,6 +120,8 @@ public interface SdfApiAdapter {
*/
byte[] symEncrypt(String sessionHandle, String keyHandle, AlgId alg, byte[] pucIv, byte[] pucData);
byte[] externalSymEncrypt(String sessionHandle, byte[] symKey, AlgId alg, byte[] pucIv, byte[] pucData);
/**
* 对称解密
*
@@ -133,4 +134,5 @@ 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);
}
@@ -13,6 +13,10 @@ import java.util.Objects;
public class SdfApiAdapterFactory {
public static SdfApiAdapter getBcAdapter() {
return BcSdfApiAdaptor.INSTANCE;
}
public static SdfApiAdapter newInstance(String model, String ip, Integer port) {
Assert.hasText(model, "设备型号不能为空");
@@ -31,7 +35,4 @@ public class SdfApiAdapterFactory {
}
}
@@ -221,7 +221,7 @@ public interface SdfLibrary extends Library {
* @param phKeyhandle
* @return
*/
int SDF_DestroyKey(Pointer phSessionHandle, PointerByReference phKeyhandle);
int SDF_DestroyKey(Pointer phSessionHandle, Pointer phKeyhandle);
/**
@@ -3,6 +3,10 @@ package com.sunyard.chsm.sdf.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.util.Assert;
import java.util.Arrays;
import java.util.Objects;
/**
* @author liulu
@@ -18,5 +22,17 @@ public class EccPriKey {
// 私 钥
private byte[] D;
public static EccPriKey fromBytes(byte[] priKey) {
Assert.notNull(priKey, "公钥数据不能为null");
if (Objects.equals(priKey.length, 132)) {
// 00010000
priKey = Arrays.copyOfRange(priKey, 4, priKey.length);
}
Assert.isTrue(Objects.equals(priKey.length, 32) || Objects.equals(priKey.length, 64), "Ecc私钥数据格式错误");
if (Objects.equals(priKey.length, 32)) {
return new EccPriKey(256, priKey);
}
return new EccPriKey(256, Arrays.copyOfRange(priKey, 32, 64));
}
}
@@ -30,7 +30,7 @@ public abstract class PaddingUtil {
}
}
public static byte[] PKCS5Padding(byte[] content) throws Exception {
public static byte[] PKCS5Padding(byte[] content) {
return PKCS7Padding(content, 8);
}
@@ -187,7 +187,7 @@ public class TmkService {
log.warn("data error, no tmk found in system");
return;
}
SdfApiAdapter softAdapter = SdfApiAdapterFactory.newInstance(BouncyCastleProvider.PROVIDER_NAME, "", 0);
SdfApiAdapter softAdapter = SdfApiAdapterFactory.getBcAdapter();
EccPubKey pubKey = softAdapter.exportEncPublicKeyECC("", 1);
SdfApiAdapter tmkAdapter = SdfApiAdapterFactory.newInstance(device.getManufacturerModel(), device.getServiceIp(), device.getServicePort());
@@ -244,7 +244,7 @@ public class TmkService {
}
}
private byte[] getSoftDeviceEncTmk() {
public byte[] getSoftDeviceEncTmk() {
boolean tmkInit = isTmkInit();
Assert.isTrue(tmkInit, "主密钥未初始化");
boolean enabled = isEnableSoftDevice();