This commit is contained in:
liulu
2024-12-05 16:49:32 +08:00
parent b87165b850
commit 0f61f4be5b
8 changed files with 318 additions and 26 deletions
@@ -1,7 +1,10 @@
package com.sunyard.chsm.sdf.adapter;
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.sdf.model.EccPubKey;
import com.sunyard.chsm.sdf.util.LangUtils;
import com.sunyard.chsm.utils.gm.BCECUtils;
import com.sunyard.chsm.utils.gm.BCSM2Utils;
@@ -11,7 +14,6 @@ import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.BigIntegers;
import java.math.BigInteger;
@@ -72,10 +74,10 @@ public class BcSdfApiAdaptor implements SdfApiAdapter {
}
@Override
public byte[] exportEncPublicKeyECC(String sessionHandle, int uiKeyIndex) {
public EccPubKey exportEncPublicKeyECC(String sessionHandle, int uiKeyIndex) {
BigInteger d = new BigInteger(1, getD());
ECPoint q = BCSM2Utils.G_POINT.multiply(d).normalize();
return LangUtils.merge(q.getXCoord().getEncoded(), q.getYCoord().getEncoded());
return new EccPubKey(256, q.getXCoord().getEncoded(), q.getYCoord().getEncoded());
}
private byte[] getD() {
@@ -99,26 +101,53 @@ public class BcSdfApiAdaptor implements SdfApiAdapter {
}
@Override
public byte[] exchangeDigitEnvelopeBaseOnECC(String sessionHandle, int uiKeyIndex, byte[] pubKey, byte[] pucEncDateIn) {
return new byte[0];
public boolean getPrivateKeyAccessRight(String hSessionHandle, int uiKeyIndex, byte[] pucPassword) {
return false;
}
@Override
public byte[] externalEncryptECC(String sessionHandle, byte[] pubKey, byte[] pucData) {
if (pubKey[0] == 4) {
pubKey = Arrays.copyOfRange(pubKey, 1, 65);
}
public EccCipher exchangeDigitEnvelopeBaseOnECC(String sessionHandle, int uiKeyIndex, EccPubKey pubKey, EccCipher pucEncDateIn) {
return null;
}
@Override
public String importKeyWithISKECC(String sessionHandle, int uiIskIndex, EccCipher eccCipher) {
return "";
}
@Override
public String importKey(String sessionHandle, byte[] pucKey) {
return "";
}
@Override
public int destroyKey(String sessionHandle, String hKeyHandle) {
return 0;
}
@Override
public EccCipher externalEncryptECC(String sessionHandle, EccPubKey pubKey, byte[] pucData) {
ECPublicKeyParameters parameters = BCECUtils.createECPublicKeyParameters(
Arrays.copyOfRange(pubKey, 0, 32),
Arrays.copyOfRange(pubKey, 32, 64)
pubKey.getX(),
pubKey.getY()
);
try {
byte[] encrypt = BCSM2Utils.encrypt(parameters, pucData);
return Arrays.copyOfRange(encrypt, 1, encrypt.length);
return EccCipher.fromBytes(encrypt);
} catch (InvalidCipherTextException e) {
throw new IllegalArgumentException(e);
}
}
@Override
public byte[] symEncrypt(String sessionHandle, String keyHandle, AlgId alg, byte[] pucIv, byte[] pucData) {
return new byte[0];
}
@Override
public byte[] symDecrypt(String sessionHandle, String keyHandle, AlgId alg, byte[] pucIv, byte[] pucEncData) {
return new byte[0];
}
}
@@ -1,18 +1,21 @@
package com.sunyard.chsm.sdf.adapter;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.ptr.PointerByReference;
import com.sunyard.chsm.sdf.context.AlgId;
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.EccPubKey;
import com.sunyard.chsm.sdf.model.SDF_DeviceInfo;
import com.sunyard.chsm.sdf.util.LangUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.util.encoders.Hex;
import org.springframework.util.Assert;
import java.util.Arrays;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
@@ -98,9 +101,9 @@ public abstract class JnaSdfAdaptor implements SdfApiAdapter {
sdfLibrary.SDF_GetDeviceInfo(getSessionHandle(sessionHandle), sdfInfo);
DeviceInfo deviceInfo = new DeviceInfo();
deviceInfo.setIssuerName(new String(sdfInfo.IssuerName));
deviceInfo.setDeviceName(new String(sdfInfo.DeviceName));
deviceInfo.setDeviceSerial(new String(sdfInfo.DeviceSerial));
deviceInfo.setIssuerName(new String(LangUtils.removeLastZero(sdfInfo.IssuerName)));
deviceInfo.setDeviceName(new String(LangUtils.removeLastZero(sdfInfo.DeviceName)));
deviceInfo.setDeviceSerial(new String(LangUtils.removeLastZero(sdfInfo.DeviceSerial)));
deviceInfo.setDeviceVersion(sdfInfo.DeviceVersion);
deviceInfo.setStandardVersion(sdfInfo.StandardVersion);
deviceInfo.setAsymAlgAbility(new long[]{sdfInfo.AsymAlgAbility[0], sdfInfo.AsymAlgAbility[1]});
@@ -119,11 +122,12 @@ public abstract class JnaSdfAdaptor implements SdfApiAdapter {
}
@Override
public byte[] exportEncPublicKeyECC(String sessionHandle, int uiKeyIndex) {
public EccPubKey exportEncPublicKeyECC(String sessionHandle, int uiKeyIndex) {
byte[] pubKey = new byte[132];
Pointer hSessionHandle = getSessionHandle(sessionHandle);
sdfLibrary.SDF_ExportEncPublicKey_ECC(hSessionHandle, uiKeyIndex, pubKey);
return LangUtils.merge(Arrays.copyOfRange(pubKey, 36, 68), Arrays.copyOfRange(pubKey, 100, 132));
log.info("sdf pubkey: {}", Hex.toHexString(pubKey));
return EccPubKey.fromBytes(pubKey);
}
@Override
@@ -132,15 +136,86 @@ public abstract class JnaSdfAdaptor implements SdfApiAdapter {
}
@Override
public byte[] exchangeDigitEnvelopeBaseOnECC(String sessionHandle, int uiKeyIndex, byte[] pubKey, byte[] pucEncDateIn) {
return new byte[0];
public boolean getPrivateKeyAccessRight(String sessionHandle, int uiKeyIndex, byte[] pucPassword) {
Pointer hSessionHandle = getSessionHandle(sessionHandle);
int res = sdfLibrary.SDF_GetPrivateKeyAccessRight(hSessionHandle, uiKeyIndex, pucPassword, pucPassword.length);
log.info("SDF_GetPrivateKeyAccessRight: {}, {}", res, Integer.toHexString(res));
return res == 0;
}
@Override
public byte[] externalEncryptECC(String sessionHandle, byte[] pubKey, byte[] pucData) {
public String importKeyWithISKECC(String sessionHandle, int uiIskIndex, EccCipher eccCipher) {
Pointer hSessionHandle = getSessionHandle(sessionHandle);
PointerByReference phKeyHandle = new PointerByReference();
int res = sdfLibrary.SDF_ImportKeyWithISK_ECC(hSessionHandle, uiIskIndex, eccCipher.toSdfData(), phKeyHandle);
log.info("SDF_ImportKeyWithISK_ECC: {}, {}", res, Integer.toHexString(res));
String key = UUID.randomUUID().toString();
KEY_HANDLE_CONTEXT.put(key, phKeyHandle.getValue());
return key;
}
@Override
public String importKey(String sessionHandle, byte[] pucKey) {
Pointer hSessionHandle = getSessionHandle(sessionHandle);
PointerByReference phKeyHandle = new PointerByReference();
sdfLibrary.SDF_ImportKey(hSessionHandle, pucKey, pucKey.length, phKeyHandle);
String key = UUID.randomUUID().toString();
KEY_HANDLE_CONTEXT.put(key, phKeyHandle.getValue());
return key;
}
@Override
public int destroyKey(String sessionHandle, String hKeyHandle) {
return 0;
}
@Override
public EccCipher exchangeDigitEnvelopeBaseOnECC(String sessionHandle, int uiKeyIndex, EccPubKey pubKey, EccCipher pucEncDateIn) {
Pointer hSessionHandle = getSessionHandle(sessionHandle);
byte[] pucEncDateOut = new byte[164 + pucEncDateIn.getL()];
int res = sdfLibrary.SDF_ExchangeDigitEnvelopeBaseOnECC(hSessionHandle, uiKeyIndex, getAlgId(AlgId.SGD_SM2_1),
pubKey.toSdfData(), pucEncDateIn.toSdfData(), pucEncDateOut);
log.info("SDF_ExchangeDigitEnvelopeBaseOnECC: {}, {}", res, Integer.toHexString(res));
return EccCipher.fromBytes(pucEncDateOut);
}
@Override
public EccCipher externalEncryptECC(String sessionHandle, EccPubKey pubKey, byte[] pucData) {
byte[] encData = new byte[128 + 32 + 4 + pucData.length];
Pointer hSessionHandle = getSessionHandle(sessionHandle);
sdfLibrary.SDF_ExternalEncrypt_ECC(hSessionHandle, getAlgId(AlgId.SGD_SM2_3), pubKey, pucData, pucData.length, encData);
return encData;
sdfLibrary.SDF_ExternalEncrypt_ECC(hSessionHandle, getAlgId(AlgId.SGD_SM2_3), pubKey.toSdfData(), pucData, pucData.length, encData);
log.info("sdfEncryptECC: {}", Hex.toHexString(encData));
return EccCipher.fromBytes(encData);
}
@Override
public byte[] symEncrypt(String sessionHandle, String keyHandle, AlgId alg, byte[] pucIv, byte[] pucData) {
Pointer hSessionHandle = getSessionHandle(sessionHandle);
Pointer hKeyHandle = getKeyHandle(keyHandle);
int uiDataLength = pucData.length;
byte[] pucEncData = new byte[uiDataLength];
IntByReference puiLength = new IntByReference();
//加密
sdfLibrary.SDF_Encrypt(hSessionHandle, hKeyHandle, getAlgId(alg),
pucIv, pucData, uiDataLength, pucEncData, puiLength);
return pucEncData;
}
@Override
public byte[] symDecrypt(String sessionHandle, String keyHandle, AlgId alg, byte[] pucIv, byte[] pucEncData) {
Pointer hSessionHandle = getSessionHandle(sessionHandle);
Pointer hKeyHandle = getKeyHandle(keyHandle);
int uiEncDataLength = pucEncData.length;
byte[] pucData = new byte[uiEncDataLength];
//解密
IntByReference puiLength = new IntByReference();
sdfLibrary.SDF_Decrypt(hSessionHandle, hKeyHandle, getAlgId(alg),
pucIv, pucEncData, uiEncDataLength, pucData, puiLength);
return pucData;
}
}
@@ -1,7 +1,10 @@
package com.sunyard.chsm.sdf.adapter;
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.sdf.model.EccPubKey;
/**
* @author liulu
@@ -55,7 +58,7 @@ public interface SdfApiAdapter {
* @param uiKeyIndex 密码设备存储的ECC密钥对索引值
* @return pucPublicKeyEcc 返回ECC加密公钥x+y
*/
byte[] exportEncPublicKeyECC(String sessionHandle, int uiKeyIndex);
EccPubKey exportEncPublicKeyECC(String sessionHandle, int uiKeyIndex);
/**
* 产生ECC密钥对并输出
@@ -66,11 +69,68 @@ public interface SdfApiAdapter {
*/
EccKey generateKeyPairECC(String sessionHandle, String alg, int uiKeyBits);
boolean getPrivateKeyAccessRight(String hSessionHandle, int uiKeyIndex, byte[] pucPassword);
byte[] exchangeDigitEnvelopeBaseOnECC(String sessionHandle, int uiKeyIndex, byte[] pubKey, byte[] pucEncDateIn);
/**
* 导入会话密钥并用内部ECC私钥解密
*
* @param uiIskIndex 密码设备内部存储加密私钥的索引值,对应于加密时的公钥
* @param eccCipher 缓冲区指针,用于存放返回的密钥密文
* @return phKeyHandle 返回密钥句柄
*/
String importKeyWithISKECC(String sessionHandle, int uiIskIndex, EccCipher eccCipher);
/**
* 导入明文会话密钥
*
* @param sessionHandle 与设备建立的会话句柄
* @param pucKey 缓冲区指针,用于存放输入的密钥密文
* @return phKeyHandle 返回密钥句柄
*/
String importKey(String sessionHandle, byte[] pucKey);
/**
* 销毁会话密钥
*
* @param hKeyHandle 密钥句柄
* @return 0 成功; 非0 失败,返回错误代码
*/
int destroyKey(String sessionHandle, String hKeyHandle);
byte[] externalEncryptECC(String sessionHandle, byte[] pubKey, byte[] pucData);
EccCipher exchangeDigitEnvelopeBaseOnECC(String sessionHandle, int uiKeyIndex, EccPubKey pubKey, EccCipher pucEncDateIn);
/**
* 外部密钥ECC公钥加密
*
* @param pubKey 外部ECC公钥结构
* @param pucData 缓冲区指针,用于存放外部输入的数据
* @return pucEncData 返回数据密文
*/
EccCipher externalEncryptECC(String sessionHandle, EccPubKey pubKey, byte[] pucData);
/**
* 对称加密
*
* @param sessionHandle 与设备建立的会话句柄
* @param keyHandle 指定的密钥句柄
* @param alg 算法标识,指定对称加密算法 SGD_SMS4_ECB
* @param pucIv IV数据
* @param pucData 数据明文
* @return 数据密文
*/
byte[] symEncrypt(String sessionHandle, String keyHandle, AlgId alg, byte[] pucIv, byte[] pucData);
/**
* 对称解密
*
* @param sessionHandle 与设备建立的会话句柄
* @param keyHandle 指定的密钥句柄
* @param alg 算法标识,指定对称加密算法 SGD_SMS4_ECB
* @param pucIv IV数据
* @param pucEncData 数据密文
* @return 数据明文
*/
byte[] symDecrypt(String sessionHandle, String keyHandle, AlgId alg, byte[] pucIv, byte[] pucEncData);
}
@@ -24,6 +24,10 @@ public class SunyardJnaSdfAdaptor extends JnaSdfAdaptor {
private final Integer connTimeout;
private final Integer dealTimeout;
public SunyardJnaSdfAdaptor(String ip) {
this(ip, 8889, "sdf");
}
public SunyardJnaSdfAdaptor(String ip, int port) {
this(ip, port, "sdf");
}