This commit is contained in:
liulu 2024-12-12 15:11:21 +08:00
parent 44161e70bb
commit 36bf16353e
9 changed files with 609 additions and 18 deletions

View File

@ -2,7 +2,9 @@ package com.sunyard.chsm.sdf;
import com.sunyard.chsm.sdf.context.AlgId;
import com.sunyard.chsm.sdf.model.EccCipher;
import com.sunyard.chsm.sdf.model.EccKey;
import com.sunyard.chsm.sdf.model.EccSignature;
/**
@ -70,6 +72,50 @@ public interface SdfApiService {
*/
EccKey genKeyPairEcc();
/**
* 外部密钥ECC签名
*
* @param privateKey ECC私钥
* @param pucData 缓冲区指针用于存放外部输入的数据
* @param userId 签名者id
* @return pucSignature 返回签名值数据
*/
EccSignature externalSignWithId(byte[] privateKey, byte[] pucData, byte[] userId);
EccSignature externalSign(byte[] privateKey, byte[] pucData);
/**
* 外部密钥ECC验证
*
* @param publicKey ECC公钥
* @param pubData 原文
* @param userId 签名者id
* @param signData 外部签名数据
* @return 0 成功; 非0 失败,返回错误代码
*/
boolean externalVerifyWithId(byte[] publicKey, byte[] pubData, byte[] signData, byte[] userId);
boolean externalVerify(byte[] publicKey, byte[] pubData, byte[] signData);
/**
* 外部密钥ECC公钥加密
*
* @param publicKey 外部ECC公钥结构
* @param pucData 缓冲区指针用于存放外部输入的数据
* @return pucEncData 返回数据密文
*/
EccCipher externalEncrypt(byte[] publicKey, byte[] pucData);
/**
* 外部密钥ECC私钥解密
*
* @param privateKey 外部ECC私钥结构
* @param encData 缓冲区指针用于存放输入的数据密文
* @return pucData 返回数据明文
*/
byte[] externalDecrypt(byte[] privateKey, byte[] encData);
/**
* 计算MAC
*

View File

@ -4,16 +4,21 @@ 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.EccPriKey;
import com.sunyard.chsm.sdf.model.EccPubKey;
import com.sunyard.chsm.sdf.model.EccSignature;
import com.sunyard.chsm.sdf.util.LangUtils;
import com.sunyard.chsm.utils.gm.BCECUtils;
import com.sunyard.chsm.utils.gm.BCSM2Utils;
import com.sunyard.chsm.utils.gm.BCSM4Utils;
import lombok.SneakyThrows;
import org.bouncycastle.crypto.CryptoException;
import org.bouncycastle.crypto.InvalidCipherTextException;
import org.bouncycastle.crypto.digests.NullDigest;
import org.bouncycastle.crypto.digests.SM3Digest;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.signers.SM2Signer;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
import org.bouncycastle.math.ec.ECPoint;
@ -130,6 +135,52 @@ public class BcSdfApiAdaptor implements SdfApiAdapter {
}
}
@Override
public EccSignature externalSignECC(String sessionHandle, EccPriKey privateKey, byte[] pucData) {
ECPrivateKeyParameters pri = BCECUtils.createECPrivateKeyParameters(getD());
try {
SM2Signer signer = new SM2Signer(new NullDigest());
signer.init(true, pri);
signer.update(pucData, 0, pucData.length);
byte[] signature = signer.generateSignature();
return EccSignature.fromBytes(signature);
} catch (CryptoException e) {
throw new IllegalArgumentException(e);
}
}
@Override
public boolean externalVerifyECC(String sessionHandle, EccPubKey publicKey, byte[] pucData, EccSignature pucSignature) {
ECPublicKeyParameters pub = BCECUtils.createECPublicKeyParameters(publicKey.getX(), publicKey.getY());
SM2Signer verifier = new SM2Signer(new NullDigest());
verifier.init(false, pub);
// 验证数据
verifier.update(pucData, 0, pucData.length);
return verifier.verifySignature(pucSignature.getRawSignBytes());
}
@Override
public EccCipher externalEncryptECC(String sessionHandle, EccPubKey pubKey, byte[] pucData) {
ECPublicKeyParameters pub = BCECUtils.createECPublicKeyParameters(pubKey.getX(), pubKey.getY());
try {
byte[] encrypt = BCSM2Utils.encrypt(pub, pucData);
return EccCipher.fromBytes(encrypt);
} catch (InvalidCipherTextException e) {
throw new IllegalArgumentException(e);
}
}
@Override
public byte[] externalDecryptECC(String sessionHandle, EccPriKey pucPrivateKeyEcc, EccCipher pucEncData) {
ECPrivateKeyParameters pri = BCECUtils.createECPrivateKeyParameters(getD());
try {
return BCSM2Utils.decrypt(pri, LangUtils.merge(new byte[]{0x04}, pucEncData.getC1C3C2Bytes()));
} catch (InvalidCipherTextException e) {
throw new IllegalArgumentException(e);
}
}
@Override
public String importKeyWithISKECC(String sessionHandle, int uiIskIndex, EccCipher eccCipher) {
ECPrivateKeyParameters pri = BCECUtils.createECPrivateKeyParameters(getD());
@ -159,19 +210,6 @@ public class BcSdfApiAdaptor implements SdfApiAdapter {
return 0;
}
@Override
public EccCipher externalEncryptECC(String sessionHandle, EccPubKey pubKey, byte[] pucData) {
ECPublicKeyParameters pub = BCECUtils.createECPublicKeyParameters(pubKey.getX(), pubKey.getY());
try {
byte[] encrypt = BCSM2Utils.encrypt(pub, pucData);
return EccCipher.fromBytes(encrypt);
} catch (InvalidCipherTextException e) {
throw new IllegalArgumentException(e);
}
}
@Override
@SneakyThrows
public byte[] symEncrypt(String sessionHandle, String keyHandle, AlgId alg, byte[] pucIv, byte[] pucData) {

View File

@ -4,12 +4,14 @@ 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.context.SdrCode;
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.EccSignature;
import com.sunyard.chsm.sdf.model.SDF_DeviceInfo;
import com.sunyard.chsm.sdf.util.LangUtils;
import lombok.RequiredArgsConstructor;
@ -17,6 +19,7 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.util.Assert;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
@ -169,10 +172,11 @@ public abstract class JnaSdfAdaptor implements SdfApiAdapter {
@Override
public int destroyKey(String sessionHandle, String hKeyHandle) {
return 0;
Pointer hSessionHandle = getSessionHandle(sessionHandle);
Pointer keyHandle = KEY_HANDLE_CONTEXT.remove(hKeyHandle);
return sdfLibrary.SDF_DestroyKey(hSessionHandle, keyHandle);
}
@Override
public EccCipher exchangeDigitEnvelopeBaseOnECC(String sessionHandle, int uiKeyIndex, EccPubKey pubKey, EccCipher pucEncDateIn) {
Pointer hSessionHandle = getSessionHandle(sessionHandle);
@ -183,6 +187,25 @@ public abstract class JnaSdfAdaptor implements SdfApiAdapter {
return EccCipher.fromBytes(pucEncDateOut);
}
@Override
public EccSignature externalSignECC(String sessionHandle, EccPriKey privateKey, byte[] pucData) {
byte[] eccSignature = new byte[128];
int uiDataLength = pucData.length;
Pointer hSessionHandle = getSessionHandle(sessionHandle);
sdfLibrary.SDF_ExternalSign_ECC(hSessionHandle, getAlgId(AlgId.SGD_SM2_1), privateKey.toSdfData(),
pucData, uiDataLength, eccSignature);
return EccSignature.fromBytes(eccSignature);
}
@Override
public boolean externalVerifyECC(String sessionHandle, EccPubKey publicKey, byte[] pucData, EccSignature pucSignature) {
int uiDataLength = pucData.length;
Pointer hSessionHandle = getSessionHandle(sessionHandle);
int result = sdfLibrary.SDF_ExternalVerify_ECC(hSessionHandle, getAlgId(AlgId.SGD_SM2_1), publicKey.toSdfData(),
pucData, uiDataLength, pucSignature.toSdfData());
return Objects.equals(result, SdrCode.SDR_OK.getCode());
}
@Override
public EccCipher externalEncryptECC(String sessionHandle, EccPubKey pubKey, byte[] pucData) {
byte[] encData = new byte[128 + 32 + 4 + pucData.length];
@ -191,6 +214,15 @@ public abstract class JnaSdfAdaptor implements SdfApiAdapter {
return EccCipher.fromBytes(encData);
}
@Override
public byte[] externalDecryptECC(String sessionHandle, EccPriKey priKey, EccCipher pucEncData) {
Pointer hSessionHandle = getSessionHandle(sessionHandle);
byte[] pucData = new byte[pucEncData.getL()];
IntByReference puiLength = new IntByReference();
sdfLibrary.SDF_ExternalDecrypt_ECC(hSessionHandle, getAlgId(AlgId.SGD_SM2_3), priKey.toSdfData(), pucEncData.toSdfData(), pucData, puiLength);
return pucData;
}
@Override
public byte[] symEncrypt(String sessionHandle, String keyHandle, AlgId alg, byte[] pucIv, byte[] pucData) {
@ -225,7 +257,7 @@ public abstract class JnaSdfAdaptor implements SdfApiAdapter {
Pointer hKeyHandle = getKeyHandle(keyHandle);
int uiMacLength = pucData.length;
byte[] pucMac = new byte[uiMacLength];
byte[] pucMac = new byte[16];
IntByReference puiLength = new IntByReference();
sdfLibrary.SDF_CalculateMAC(hSessionHandle, hKeyHandle, getAlgId(uiAlg), pucIv, pucData, uiMacLength, pucMac, puiLength);

View File

@ -4,7 +4,9 @@ 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.EccPriKey;
import com.sunyard.chsm.sdf.model.EccPubKey;
import com.sunyard.chsm.sdf.model.EccSignature;
/**
* @author liulu
@ -96,9 +98,27 @@ public interface SdfApiAdapter {
*/
int destroyKey(String sessionHandle, String hKeyHandle);
EccCipher exchangeDigitEnvelopeBaseOnECC(String sessionHandle, int uiKeyIndex, EccPubKey pubKey, EccCipher pucEncDateIn);
/**
* 外部密钥ECC签名
*
* @param privateKey ECC私钥
* @param pucData 缓冲区指针用于存放外部输入的数据
* @return pucSignature 返回签名值数据
*/
EccSignature externalSignECC(String sessionHandle, EccPriKey privateKey, byte[] pucData);
/**
* 外部密钥ECC验证
*
* @param publicKey ECC公钥
* @param pucData 缓冲区指针用于存放外部输入的数据
* @param pucSignature 缓冲区指针用于存放输入的签名值数据
* @return 0 成功; 非0 失败,返回错误代码
*/
boolean externalVerifyECC(String sessionHandle, EccPubKey publicKey, byte[] pucData, EccSignature pucSignature);
/**
* 外部密钥ECC公钥加密
*
@ -108,6 +128,15 @@ public interface SdfApiAdapter {
*/
EccCipher externalEncryptECC(String sessionHandle, EccPubKey pubKey, byte[] pucData);
/**
* 外部密钥ECC私钥解密
*
* @param pucPrivateKeyEcc 外部ECC私钥结构
* @param pucEncData 缓冲区指针用于存放输入的数据密文
* @return pucData 返回数据明文
*/
byte[] externalDecryptECC(String sessionHandle, EccPriKey pucPrivateKeyEcc, EccCipher pucEncData);
/**
* 对称加密
*

View File

@ -3,6 +3,7 @@ package com.sunyard.chsm.sdf.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.bouncycastle.util.encoders.Hex;
import org.springframework.util.Assert;
import java.util.Arrays;
@ -22,8 +23,15 @@ public class EccPriKey {
//
private byte[] D;
public byte[] toSdfData() {
byte[] sdf = new byte[68];
System.arraycopy(Hex.decode("00010000"), 0, sdf, 0, 4);
System.arraycopy(D, 0, sdf, 36, 32);
return sdf;
}
public static EccPriKey fromBytes(byte[] priKey) {
Assert.notNull(priKey, "公钥数据不能为null");
Assert.notNull(priKey, "钥数据不能为null");
if (Objects.equals(priKey.length, 68)) {
// 00010000
priKey = Arrays.copyOfRange(priKey, 4, priKey.length);

View File

@ -4,6 +4,8 @@ import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Arrays;
/**
* @author liulu
* @version V1.0
@ -27,5 +29,28 @@ public class EccSignature {
return signData;
}
public byte[] toSdfData() {
byte[] res = new byte[128];
System.arraycopy(r, 0, res, 32, 32);
System.arraycopy(s, 0, res, 96, 32);
return res;
}
public static EccSignature fromBytes(byte[] sign) {
if (sign == null || sign.length == 0) {
return null;
}
if (sign.length == 64) {
byte[] r = Arrays.copyOfRange(sign, 0, 32);
byte[] s = Arrays.copyOfRange(sign, 32, 64);
return new EccSignature(r, s);
} else if (sign.length == 128) {
byte[] r = Arrays.copyOfRange(sign, 32, 64);
byte[] s = Arrays.copyOfRange(sign, 96, 128);
return new EccSignature(r, s);
} else {
throw new IllegalArgumentException("ECC签名数据格式错误");
}
}
}

View File

@ -0,0 +1,294 @@
package com.sunyard.chsm.utils.gm;
import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.ASN1Encoding;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.CryptoException;
import org.bouncycastle.crypto.CryptoServicesRegistrar;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.digests.SM3Digest;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECKeyParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.params.ParametersWithID;
import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.crypto.signers.DSAKCalculator;
import org.bouncycastle.crypto.signers.RandomDSAKCalculator;
import org.bouncycastle.math.ec.ECAlgorithms;
import org.bouncycastle.math.ec.ECConstants;
import org.bouncycastle.math.ec.ECFieldElement;
import org.bouncycastle.math.ec.ECMultiplier;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.math.ec.FixedPointCombMultiplier;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.encoders.Hex;
import java.io.IOException;
import java.math.BigInteger;
/**
* 有的国密需求是用户可以自己做预处理签名验签只是对预处理的结果进行签名和验签
*/
public class SM2PreprocessSigner implements ECConstants {
private static final int DIGEST_LENGTH = 32; // bytes
private final DSAKCalculator kCalculator = new RandomDSAKCalculator();
private Digest digest = null;
private ECDomainParameters ecParams;
private ECPoint pubPoint;
private ECKeyParameters ecKey;
private byte[] userID;
/**
* 初始化
*
* @param forSigning true表示用于签名false表示用于验签
* @param param
*/
public void init(boolean forSigning, CipherParameters param) {
init(forSigning, new SM3Digest(), param);
}
/**
* 初始化
*
* @param forSigning true表示用于签名false表示用于验签
* @param digest SM2算法的话一般是采用SM3摘要算法
* @param param
* @throws RuntimeException
*/
public void init(boolean forSigning, Digest digest, CipherParameters param) throws RuntimeException {
CipherParameters baseParam;
if (digest.getDigestSize() != DIGEST_LENGTH) {
throw new RuntimeException("Digest size must be " + DIGEST_LENGTH);
}
this.digest = digest;
if (param instanceof ParametersWithID) {
baseParam = ((ParametersWithID) param).getParameters();
userID = ((ParametersWithID) param).getID();
} else {
baseParam = param;
userID = Hex.decode("31323334353637383132333435363738"); // the default value
}
if (forSigning) {
if (baseParam instanceof ParametersWithRandom) {
ParametersWithRandom rParam = (ParametersWithRandom) baseParam;
ecKey = (ECKeyParameters) rParam.getParameters();
ecParams = ecKey.getParameters();
kCalculator.init(ecParams.getN(), rParam.getRandom());
} else {
ecKey = (ECKeyParameters) baseParam;
ecParams = ecKey.getParameters();
kCalculator.init(ecParams.getN(), CryptoServicesRegistrar.getSecureRandom());
}
pubPoint = createBasePointMultiplier().multiply(ecParams.getG(), ((ECPrivateKeyParameters) ecKey).getD()).normalize();
} else {
ecKey = (ECKeyParameters) baseParam;
ecParams = ecKey.getParameters();
pubPoint = ((ECPublicKeyParameters) ecKey).getQ();
}
}
/**
* 预处理辅助方法
* ZA=H256(ENT LA IDA a b xG yG xA yA)
* M=ZA M
* e = Hv(M)
*
* @return
*/
public byte[] preprocess(byte[] m) {
return preprocess(m, 0, m.length);
}
public byte[] preprocess(byte[] m, int off, int len) {
byte[] z = getZ(userID);
digest.update(z, 0, z.length);
digest.update(m, off, len);
byte[] eHash = new byte[DIGEST_LENGTH];
digest.doFinal(eHash, 0);
return eHash;
}
public boolean verifySignature(byte[] eHash, byte[] signature) {
try {
BigInteger[] rs = derDecode(signature);
if (rs != null) {
return verifySignature(eHash, rs[0], rs[1]);
}
} catch (IOException e) {
}
return false;
}
public void reset() {
digest.reset();
}
public byte[] generateSignature(byte[] eHash) throws CryptoException {
BigInteger n = ecParams.getN();
BigInteger e = calculateE(eHash);
BigInteger d = ((ECPrivateKeyParameters) ecKey).getD();
BigInteger r, s;
ECMultiplier basePointMultiplier = createBasePointMultiplier();
// 5.2.1 Draft RFC: SM2 Public Key Algorithms
do // generate s
{
BigInteger k;
do // generate r
{
// A3
k = kCalculator.nextK();
// A4
ECPoint p = basePointMultiplier.multiply(ecParams.getG(), k).normalize();
// A5
r = e.add(p.getAffineXCoord().toBigInteger()).mod(n);
}
while (r.equals(ZERO) || r.add(k).equals(n));
// A6
BigInteger dPlus1ModN = d.add(ONE).modInverse(n);
s = k.subtract(r.multiply(d)).mod(n);
s = dPlus1ModN.multiply(s).mod(n);
}
while (s.equals(ZERO));
// A7
try {
return derEncode(r, s);
} catch (IOException ex) {
throw new CryptoException("unable to encode signature: " + ex.getMessage(), ex);
}
}
private boolean verifySignature(byte[] eHash, BigInteger r, BigInteger s) {
BigInteger n = ecParams.getN();
// 5.3.1 Draft RFC: SM2 Public Key Algorithms
// B1
if (r.compareTo(ONE) < 0 || r.compareTo(n) >= 0) {
return false;
}
// B2
if (s.compareTo(ONE) < 0 || s.compareTo(n) >= 0) {
return false;
}
// B3 eHash
// B4
BigInteger e = calculateE(eHash);
// B5
BigInteger t = r.add(s).mod(n);
if (t.equals(ZERO)) {
return false;
}
// B6
ECPoint q = ((ECPublicKeyParameters) ecKey).getQ();
ECPoint x1y1 = ECAlgorithms.sumOfTwoMultiplies(ecParams.getG(), s, q, t).normalize();
if (x1y1.isInfinity()) {
return false;
}
// B7
BigInteger expectedR = e.add(x1y1.getAffineXCoord().toBigInteger()).mod(n);
return expectedR.equals(r);
}
private byte[] digestDoFinal() {
byte[] result = new byte[digest.getDigestSize()];
digest.doFinal(result, 0);
reset();
return result;
}
private byte[] getZ(byte[] userID) {
digest.reset();
addUserID(digest, userID);
addFieldElement(digest, ecParams.getCurve().getA());
addFieldElement(digest, ecParams.getCurve().getB());
addFieldElement(digest, ecParams.getG().getAffineXCoord());
addFieldElement(digest, ecParams.getG().getAffineYCoord());
addFieldElement(digest, pubPoint.getAffineXCoord());
addFieldElement(digest, pubPoint.getAffineYCoord());
byte[] result = new byte[digest.getDigestSize()];
digest.doFinal(result, 0);
return result;
}
private void addUserID(Digest digest, byte[] userID) {
int len = userID.length * 8;
digest.update((byte) (len >> 8 & 0xFF));
digest.update((byte) (len & 0xFF));
digest.update(userID, 0, userID.length);
}
private void addFieldElement(Digest digest, ECFieldElement v) {
byte[] p = v.getEncoded();
digest.update(p, 0, p.length);
}
protected ECMultiplier createBasePointMultiplier() {
return new FixedPointCombMultiplier();
}
protected BigInteger calculateE(byte[] message) {
return new BigInteger(1, message);
}
protected BigInteger[] derDecode(byte[] encoding)
throws IOException {
ASN1Sequence seq = ASN1Sequence.getInstance(ASN1Primitive.fromByteArray(encoding));
if (seq.size() != 2) {
return null;
}
BigInteger r = ASN1Integer.getInstance(seq.getObjectAt(0)).getValue();
BigInteger s = ASN1Integer.getInstance(seq.getObjectAt(1)).getValue();
byte[] expectedEncoding = derEncode(r, s);
if (!Arrays.constantTimeAreEqual(expectedEncoding, encoding)) {
return null;
}
return new BigInteger[]{r, s};
}
protected byte[] derEncode(BigInteger r, BigInteger s)
throws IOException {
ASN1EncodableVector v = new ASN1EncodableVector();
v.add(new ASN1Integer(r));
v.add(new ASN1Integer(s));
return new DERSequence(v).getEncoded(ASN1Encoding.DER);
}
}

View File

@ -11,11 +11,18 @@ 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.EccPriKey;
import com.sunyard.chsm.sdf.model.EccPubKey;
import com.sunyard.chsm.sdf.model.EccSignature;
import com.sunyard.chsm.sdf.util.PaddingUtil;
import com.sunyard.chsm.service.TmkService;
import com.sunyard.chsm.utils.gm.BCECUtils;
import com.sunyard.chsm.utils.gm.BCSM3Utils;
import com.sunyard.chsm.utils.gm.SM2PreprocessSigner;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.params.ParametersWithID;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
@ -80,6 +87,57 @@ public class SingleSdfApiService implements SdfApiService, InitializingBean {
return sdfApiAdapter.generateKeyPairECC(sessionHandle, AlgId.SGD_SM2_1);
}
@Override
public EccSignature externalSign(byte[] privateKey, byte[] pucData) {
return externalSignWithId(privateKey, pucData, new byte[0]);
}
@Override
public EccSignature externalSignWithId(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 sdfApiAdapter.externalSignECC(sessionHandle, sdfEccPrivateKey, preHash);
}
@Override
public boolean externalVerifyWithId(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 sdfApiAdapter.externalVerifyECC(sessionHandle, eccPublicKey, preHash, eccSignature);
}
@Override
public boolean externalVerify(byte[] publicKey, byte[] pubData, byte[] signData) {
return externalVerifyWithId(publicKey, pubData, signData, new byte[0]);
}
@Override
public EccCipher externalEncrypt(byte[] publicKey, byte[] pucData) {
EccPubKey eccPublicKey = EccPubKey.fromBytes(publicKey);
return sdfApiAdapter.externalEncryptECC(sessionHandle, eccPublicKey, pucData);
}
@Override
public byte[] externalDecrypt(byte[] privateKey, byte[] encData) {
EccPriKey sdfEccPrivateKey = EccPriKey.fromBytes(privateKey);
EccCipher eccCipher = EccCipher.fromBytes(encData);
return sdfApiAdapter.externalDecryptECC(sessionHandle, sdfEccPrivateKey, eccCipher);
}
@Override
public byte[] calculateMAC(byte[] symKey, byte[] pucIv, byte[] pucData) {
checkStatus();

View File

@ -2,10 +2,18 @@ package com.sunyard.chsm.pool;
import com.sunyard.chsm.sdf.SdfApiService;
import com.sunyard.chsm.sdf.context.AlgId;
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.EccSignature;
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 javax.annotation.Resource;
@ -63,6 +71,59 @@ public class LoadBalancedSdfApiService implements SdfApiService {
return apply(s -> s.getSdfApiAdapter().generateKeyPairECC(s.getSessionHandle(), AlgId.SGD_SM2_1));
}
@Override
public EccSignature externalSign(byte[] privateKey, byte[] pucData) {
return externalSignWithId(privateKey, pucData, new byte[0]);
}
@Override
public EccSignature externalSignWithId(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 externalVerifyWithId(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 externalVerify(byte[] publicKey, byte[] pubData, byte[] signData) {
return externalVerifyWithId(publicKey, pubData, signData, new byte[0]);
}
@Override
public EccCipher externalEncrypt(byte[] publicKey, byte[] pucData) {
EccPubKey eccPublicKey = EccPubKey.fromBytes(publicKey);
return apply(s -> s.getSdfApiAdapter().externalEncryptECC(s.getSessionHandle(), eccPublicKey, pucData));
}
@Override
public byte[] externalDecrypt(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(byte[] symKey, byte[] pucIv, byte[] pucData) {
return apply(s -> {