fix 长度问题
This commit is contained in:
parent
914ba8eee5
commit
d1c8201f98
@ -91,7 +91,7 @@ public final class ParamChecker {
|
||||
* @throws IllegalArgumentException 如果 str 为 null 或仅包含空白字符
|
||||
*/
|
||||
public static String checkNotBlank(String str, String paramName) {
|
||||
if (str == null || str.isBlank()) {
|
||||
if (str == null || !str.trim().isEmpty()) {
|
||||
throw new IllegalArgumentException("参数 '" + paramName + "' 不能为 null、空字符串或仅包含空白字符");
|
||||
}
|
||||
return str;
|
||||
|
||||
@ -6791,6 +6791,8 @@ public class SydApi4j implements SydApi {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String SM2EncryptOrder(byte[] publicKey, byte[] pOrgData) {
|
||||
Proto77 proto = new Proto77();
|
||||
@ -6917,10 +6919,8 @@ public class SydApi4j implements SydApi {
|
||||
// 重新计算长度
|
||||
int len = bb.position();
|
||||
len -= 2;
|
||||
byte[] lenArray = new byte[2];
|
||||
lenArray[0] = (byte) ((len >> 8) & 0xFF);
|
||||
lenArray[1] = (byte) (len & 0xFF);
|
||||
bb.put(lenArray);
|
||||
bb.put(0, (byte) ((len >> 8) & 0xFF)); // 覆盖开头的两个占位字节
|
||||
bb.put(1, (byte) (len & 0xFF)); // 覆盖开头的两个占位字节
|
||||
|
||||
// 通信
|
||||
synchronized (this) {
|
||||
@ -6955,6 +6955,133 @@ public class SydApi4j implements SydApi {
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* SM2 解密(支持大包分段)
|
||||
* @param privateKey 私钥字节数组
|
||||
* @param pCipherData 密文数据
|
||||
* @return 解密后的明文
|
||||
*/
|
||||
public byte[] SYD_SM2Decrypt(byte[] privateKey, byte[] pCipherData) {
|
||||
ParamChecker.checkNotNull(privateKey, "privateKey");
|
||||
ParamChecker.checkNotNull(pCipherData, "pCipherData");
|
||||
|
||||
final int CHUNK_SIZE = 63 * 1024; // 63 KB,与加密保持一致
|
||||
int dataLen = pCipherData.length;
|
||||
int offset = 0;
|
||||
|
||||
// 1. 分块传入密文
|
||||
while (offset < dataLen) {
|
||||
int len = Math.min(CHUNK_SIZE, dataLen - offset);
|
||||
SYD_SM2Decrypt(1, privateKey, ByteBuffer.wrap(pCipherData, offset, len), offset);
|
||||
offset += len;
|
||||
}
|
||||
|
||||
// 2. 传入私钥,触发解密处理
|
||||
SYD_SM2Decrypt(2, privateKey, null, 0);
|
||||
|
||||
// 3. 分块取回明文
|
||||
int idx = 0;
|
||||
List<ByteBuffer> chunks = new ArrayList<>();
|
||||
int totalLen = 0;
|
||||
int isLast = 0;
|
||||
|
||||
while (isLast != 1) {
|
||||
MutiReturn7 ret = SYD_SM2Decrypt(3, null, null, idx);
|
||||
ByteBuffer bb = ret.getData();
|
||||
isLast = ret.getIsLast();
|
||||
|
||||
if (bb != null && bb.remaining() > 0) {
|
||||
chunks.add(bb);
|
||||
totalLen += bb.remaining();
|
||||
idx += bb.remaining();
|
||||
} else if (isLast != 1) {
|
||||
throw new RuntimeException("Empty plain chunk with isLast=0");
|
||||
}
|
||||
}
|
||||
|
||||
// 合并明文分片
|
||||
byte[] result = new byte[totalLen];
|
||||
int offset2 = 0;
|
||||
for (ByteBuffer chunk : chunks) {
|
||||
int len = chunk.remaining();
|
||||
chunk.get(result, offset2, len);
|
||||
offset2 += len;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 底层解密通信(与加密结构对称,魔法数改为 "7G")
|
||||
* @param dataType 1-传入密文块,2-传入私钥,3-取明文块
|
||||
* @param privateKey 私钥(dataType=2时使用)
|
||||
* @param pCipherData 密文块(dataType=1时使用)
|
||||
* @param idx 偏移量索引
|
||||
* @return MutiReturn7 包含返回码、isLast标志及数据片
|
||||
*/
|
||||
private MutiReturn7 SYD_SM2Decrypt(int dataType, byte[] privateKey, ByteBuffer pCipherData, int idx) {
|
||||
ParamChecker.checkInRange(dataType, "dataType", 1, 3);
|
||||
|
||||
// 估算缓存大小
|
||||
int buffLen = 4096;
|
||||
if (dataType == 1) {
|
||||
buffLen = pCipherData.limit() > 4096 ? 64 * 1024 : 5 * 1024;
|
||||
}
|
||||
|
||||
ByteBuffer bb = ByteBuffer.allocate(buffLen);
|
||||
PacketSN sn = PacketSN.gen();
|
||||
bb.put(new byte[2]); // 占位,后续填总长度
|
||||
bb.put(sn.getSn().array());
|
||||
bb.put("7G".getBytes()); // 魔法数改为 "7G"
|
||||
bb.put((byte) dataType);
|
||||
|
||||
if (dataType == 2) { // 私钥
|
||||
bb.put(ByteUtil.shortToBytes((short) privateKey.length));
|
||||
bb.put(privateKey);
|
||||
}
|
||||
if (dataType == 1) { // 密文块
|
||||
bb.put(ByteUtil.shortToBytes((short) pCipherData.limit()));
|
||||
bb.put(pCipherData);
|
||||
bb.put(ByteUtil.shortToBytes((short) idx));
|
||||
}
|
||||
if (dataType == 3) { // 请求明文块
|
||||
bb.put(ByteUtil.shortToBytes((short) (63 * 1024)));
|
||||
bb.put(ByteUtil.shortToBytes((short) idx));
|
||||
}
|
||||
|
||||
// 填写总长度(长度字段本身不包含在内)
|
||||
int len = bb.position() - 2;
|
||||
bb.put(0, (byte) ((len >> 8) & 0xFF)); // 覆盖开头的两个占位字节
|
||||
bb.put(1, (byte) (len & 0xFF)); // 覆盖开头的两个占位字节
|
||||
|
||||
// 通信
|
||||
synchronized (this) {
|
||||
bb = syncRead(syncSend(bb));
|
||||
}
|
||||
|
||||
bb.flip();
|
||||
bb.position(12); // 跳过前12字节(头部固定)
|
||||
byte[] code = new byte[2];
|
||||
bb.get(code);
|
||||
int retCode = Integer.parseInt(new String(code));
|
||||
if (retCode != 0) {
|
||||
throw new SydApiException(retCode);
|
||||
}
|
||||
|
||||
// 仅 dataType=3 时有数据返回
|
||||
if (dataType == 3) {
|
||||
int isLast = bb.get();
|
||||
byte[] dataLenArr = new byte[2];
|
||||
bb.get(dataLenArr);
|
||||
int dataLen = ByteUtil.bytesToInt(dataLenArr);
|
||||
ByteBuffer slice = ByteBufferUtil.sliceAndConsume(bb, dataLen);
|
||||
return new MutiReturn7(retCode, isLast, slice);
|
||||
} else {
|
||||
return new MutiReturn7(retCode, 0, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String SM2Encrypt(byte[] publicKey, byte[] pOrgData) {
|
||||
Proto77 proto = new Proto77();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user