From 0f61f4be5bea87077059c6f56ef18bebd87b7904 Mon Sep 17 00:00:00 2001 From: liulu Date: Thu, 5 Dec 2024 16:49:06 +0800 Subject: [PATCH] sdf --- .../chsm/sdf/adapter/BcSdfApiAdaptor.java | 53 +++++++--- .../chsm/sdf/adapter/JnaSdfAdaptor.java | 97 ++++++++++++++++--- .../chsm/sdf/adapter/SdfApiAdapter.java | 66 ++++++++++++- .../sdf/adapter/SunyardJnaSdfAdaptor.java | 4 + .../com/sunyard/chsm/sdf/lib/SdfLibrary.java | 21 ++++ .../com/sunyard/chsm/sdf/model/EccCipher.java | 41 ++++++++ .../com/sunyard/chsm/sdf/model/EccPubKey.java | 48 +++++++++ .../com/sunyard/chsm/sdf/util/LangUtils.java | 14 +++ 8 files changed, 318 insertions(+), 26 deletions(-) diff --git a/chsm-common/src/main/java/com/sunyard/chsm/sdf/adapter/BcSdfApiAdaptor.java b/chsm-common/src/main/java/com/sunyard/chsm/sdf/adapter/BcSdfApiAdaptor.java index 27c5983..67153e1 100644 --- a/chsm-common/src/main/java/com/sunyard/chsm/sdf/adapter/BcSdfApiAdaptor.java +++ b/chsm-common/src/main/java/com/sunyard/chsm/sdf/adapter/BcSdfApiAdaptor.java @@ -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]; + } } diff --git a/chsm-common/src/main/java/com/sunyard/chsm/sdf/adapter/JnaSdfAdaptor.java b/chsm-common/src/main/java/com/sunyard/chsm/sdf/adapter/JnaSdfAdaptor.java index 7bcc0f1..7223526 100644 --- a/chsm-common/src/main/java/com/sunyard/chsm/sdf/adapter/JnaSdfAdaptor.java +++ b/chsm-common/src/main/java/com/sunyard/chsm/sdf/adapter/JnaSdfAdaptor.java @@ -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; } } diff --git a/chsm-common/src/main/java/com/sunyard/chsm/sdf/adapter/SdfApiAdapter.java b/chsm-common/src/main/java/com/sunyard/chsm/sdf/adapter/SdfApiAdapter.java index 423acc2..4ab5ee4 100644 --- a/chsm-common/src/main/java/com/sunyard/chsm/sdf/adapter/SdfApiAdapter.java +++ b/chsm-common/src/main/java/com/sunyard/chsm/sdf/adapter/SdfApiAdapter.java @@ -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); } diff --git a/chsm-common/src/main/java/com/sunyard/chsm/sdf/adapter/SunyardJnaSdfAdaptor.java b/chsm-common/src/main/java/com/sunyard/chsm/sdf/adapter/SunyardJnaSdfAdaptor.java index e7152bf..7f6bc04 100644 --- a/chsm-common/src/main/java/com/sunyard/chsm/sdf/adapter/SunyardJnaSdfAdaptor.java +++ b/chsm-common/src/main/java/com/sunyard/chsm/sdf/adapter/SunyardJnaSdfAdaptor.java @@ -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"); } diff --git a/chsm-common/src/main/java/com/sunyard/chsm/sdf/lib/SdfLibrary.java b/chsm-common/src/main/java/com/sunyard/chsm/sdf/lib/SdfLibrary.java index 51ce618..e89fcc9 100644 --- a/chsm-common/src/main/java/com/sunyard/chsm/sdf/lib/SdfLibrary.java +++ b/chsm-common/src/main/java/com/sunyard/chsm/sdf/lib/SdfLibrary.java @@ -179,6 +179,27 @@ public interface SdfLibrary extends Library { */ int SDF_ExchangeDigitEnvelopeBaseOnECC(Pointer hSessionHandle, int uiKeyIndex, int uiAlgID, byte[] pucPublicKey, byte[] pucEncDateIn, byte[] pucEncDateOut); + /** + * + * @param hSessionHandle 与设备建立的会话句柄 + * @param pucKey 缓冲区指针,用于存放输入的密钥密文 + * @param puiKeyLength 返回的密钥明文长度 + * @param phKeyHandle 返回的密钥句柄 + * @return 0 成功; 非0 失败,返回错误代码 + */ + int SDF_ImportKey(Pointer hSessionHandle, byte[] pucKey, int puiKeyLength, PointerByReference phKeyHandle); + + /** + * 获取私钥使用权限 + * + * @param hSessionHandle 与设备建立的会话句柄 + * @param uiKeyIndex 密码设备存储私钥的索引值 + * @param pucPassword 使用私钥权限的标识码 + * @param uiPwdLength 私钥访问控制码长度,不少于8字节 + * @return 0 成功; 非0 失败,返回错误代码 + */ + int SDF_GetPrivateKeyAccessRight(Pointer hSessionHandle, int uiKeyIndex, byte[] pucPassword, int uiPwdLength); + /** * 导入会话密钥并用内部ECC私钥解密 * diff --git a/chsm-common/src/main/java/com/sunyard/chsm/sdf/model/EccCipher.java b/chsm-common/src/main/java/com/sunyard/chsm/sdf/model/EccCipher.java index 2bb4ac2..346909e 100644 --- a/chsm-common/src/main/java/com/sunyard/chsm/sdf/model/EccCipher.java +++ b/chsm-common/src/main/java/com/sunyard/chsm/sdf/model/EccCipher.java @@ -3,6 +3,11 @@ package com.sunyard.chsm.sdf.model; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; +import org.springframework.util.Assert; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.Arrays; /** * @author liulu @@ -41,4 +46,40 @@ public class EccCipher { return rawData; } + public byte[] toSdfData() { + byte[] d = new byte[164 + L]; + byte[] l = ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).putInt(L).array(); + System.arraycopy(x, 0, d, 32, 32); + System.arraycopy(y, 0, d, 96, 32); + System.arraycopy(M, 0, d, 128, 32); + System.arraycopy(l, 0, d, 160, 4); + System.arraycopy(C, 0, d, 164, L); + return d; + } + + public static EccCipher fromBytes(byte[] cipher) { + Assert.notNull(cipher, "Ecc密文数据不能为null"); + if (cipher[0] == 0x04) { + cipher = Arrays.copyOfRange(cipher, 1, cipher.length); + } + Assert.isTrue(cipher.length > 96, "Ecc加密数据格式错误"); + if (cipher.length > 164 + && Arrays.equals(Arrays.copyOf(cipher, 32), new byte[32]) + && Arrays.equals(Arrays.copyOfRange(cipher, 64, 96), new byte[32])) { + int L = cipher.length - 164; + byte[] x = Arrays.copyOfRange(cipher, 32, 64); + byte[] y = Arrays.copyOfRange(cipher, 96, 128); + byte[] m = Arrays.copyOfRange(cipher, 128, 160); + byte[] c = Arrays.copyOfRange(cipher, 164, cipher.length); + return new EccCipher(x, y, m, L, c); + } + + int L = cipher.length - 96; + byte[] x = Arrays.copyOfRange(cipher, 0, 32); + byte[] y = Arrays.copyOfRange(cipher, 32, 64); + byte[] m = Arrays.copyOfRange(cipher, 64, 96); + byte[] c = Arrays.copyOfRange(cipher, 96, cipher.length); + return new EccCipher(x, y, m, L, c); + } + } diff --git a/chsm-common/src/main/java/com/sunyard/chsm/sdf/model/EccPubKey.java b/chsm-common/src/main/java/com/sunyard/chsm/sdf/model/EccPubKey.java index 86b1952..e6f1f08 100644 --- a/chsm-common/src/main/java/com/sunyard/chsm/sdf/model/EccPubKey.java +++ b/chsm-common/src/main/java/com/sunyard/chsm/sdf/model/EccPubKey.java @@ -3,6 +3,12 @@ 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.nio.ByteBuffer; +import java.util.Arrays; +import java.util.Objects; /** * @author liulu @@ -20,6 +26,9 @@ public class EccPubKey { // 公 钥 y 坐 标 private byte[] y; + public String getPubKeyHex() { + return Hex.toHexString(getPubKeyBytes()); + } public byte[] getPubKeyBytes() { byte[] rawKey = new byte[x.length + y.length]; @@ -28,4 +37,43 @@ public class EccPubKey { return rawKey; } + public byte[] toSdfData() { + byte[] sdf = new byte[132]; + System.arraycopy(Hex.decode("00010000"), 0, sdf, 0, 4); + System.arraycopy(x, 0, sdf, 36, 32); + System.arraycopy(y, 0, sdf, 100, 32); + return sdf; + } + + public static EccPubKey fromHex(String pubKeyHex) { + return fromBytes(Hex.decode(pubKeyHex)); + } + + public static EccPubKey fromBytes(byte[] pubKey) { + Assert.notNull(pubKey, "公钥数据不能为null"); + if (Objects.equals(pubKey.length, 65)) { + Assert.isTrue(Objects.equals(pubKey[0], 0x04), "Ecc公钥数据格式错误,必须04开头"); + pubKey = Arrays.copyOfRange(pubKey, 1, pubKey.length); + } else if (Objects.equals(pubKey.length, 132)) { + // 00010000 + byte[] bytes = Arrays.copyOf(pubKey, 4); + System.out.println(Hex.toHexString(bytes)); + int anInt = ByteBuffer.wrap(bytes).getInt(); + System.out.println(anInt); + + pubKey = Arrays.copyOfRange(pubKey, 4, pubKey.length); + } + Assert.isTrue(Objects.equals(pubKey.length, 64) || Objects.equals(pubKey.length, 128), "Ecc公钥数据格式错误"); + byte[] x = new byte[32]; + byte[] y = new byte[32]; + if (Objects.equals(pubKey.length, 64)) { + System.arraycopy(pubKey, 0, x, 0, 32); + System.arraycopy(pubKey, 32, y, 0, 32); + } else if (Objects.equals(pubKey.length, 128)) { + System.arraycopy(pubKey, 32, x, 0, 32); + System.arraycopy(pubKey, 96, y, 0, 32); + } + return new EccPubKey(256, x, y); + } + } diff --git a/chsm-common/src/main/java/com/sunyard/chsm/sdf/util/LangUtils.java b/chsm-common/src/main/java/com/sunyard/chsm/sdf/util/LangUtils.java index bfcf9ff..327f312 100644 --- a/chsm-common/src/main/java/com/sunyard/chsm/sdf/util/LangUtils.java +++ b/chsm-common/src/main/java/com/sunyard/chsm/sdf/util/LangUtils.java @@ -10,6 +10,20 @@ import java.util.Arrays; */ public abstract class LangUtils { + + public static byte[] removeLastZero(byte[] bytes) { + if (bytes == null) { + return bytes; + } + int len = bytes.length; + for (int i = len - 1; i >= 0; i--) { + if (bytes[i] != 0) { + return Arrays.copyOfRange(bytes, 0, i + 1); + } + } + return bytes; + } + public static byte[] merge(byte[]... bytes) { int newLen = Arrays.stream(bytes).mapToInt(it -> it.length).sum(); byte[] res = new byte[newLen];