From a452376d8d10909e3662a2a9bb2928369a23da50 Mon Sep 17 00:00:00 2001 From: cheney Date: Wed, 3 Jun 2026 16:34:41 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B0=8F=E4=BA=8E=204M=20=E5=8F=AF=E4=BB=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/sunyard/SydApiException.java | 3 + src/main/java/com/sunyard/util/BytesUtil.java | 174 ++++++++++++++++++ .../java/racal/sunyard/main/SydApi4j.java | 4 +- src/test/java/cmbpoc/FunctionTest.java | 34 +++- 4 files changed, 211 insertions(+), 4 deletions(-) create mode 100644 src/main/java/com/sunyard/util/BytesUtil.java diff --git a/src/main/java/com/sunyard/SydApiException.java b/src/main/java/com/sunyard/SydApiException.java index 51cd224..1f95e2b 100644 --- a/src/main/java/com/sunyard/SydApiException.java +++ b/src/main/java/com/sunyard/SydApiException.java @@ -45,6 +45,9 @@ public class SydApiException extends RuntimeException{ case 4: msg = "DER 编码格式错误(公钥) "; break; + case 31: + msg = "缓冲区索引错误"; + break; case 0xd: msg = "公钥加密错误"; break; diff --git a/src/main/java/com/sunyard/util/BytesUtil.java b/src/main/java/com/sunyard/util/BytesUtil.java new file mode 100644 index 0000000..06233b7 --- /dev/null +++ b/src/main/java/com/sunyard/util/BytesUtil.java @@ -0,0 +1,174 @@ +package com.sunyard.util; + +import java.nio.ByteOrder; + +/** + * 字节数组转换工具类,提供常见的基本类型与字节数组之间的互转功能。 + * 默认采用大端字节序(高位在前),也支持通过参数指定字节序。 + * + * @author YourName + */ +public final class BytesUtil { + + private BytesUtil() { + // 私有构造方法,防止实例化 + } + + // ==================== 无符号 short 转字节数组 ==================== + + /** + * 将无符号 short 值(以 int 形式传入,范围 0 ~ 65535)转换为大端字节序的字节数组(2字节)。 + * + * @param value 无符号 short 值(0 到 65535) + * @return 长度为 2 的字节数组,高位在前 + * @throws IllegalArgumentException 如果 value 超出 0~65535 范围 + */ + public static byte[] unsignedShortToBytes(int value) { + if (value < 0 || value > 0xFFFF) { + throw new IllegalArgumentException("Value out of range for unsigned short: " + value); + } + return new byte[]{ + (byte) ((value >> 8) & 0xFF), + (byte) (value & 0xFF) + }; + } + + /** + * 将无符号 short 值(以 short 类型传入,自动按无符号处理)转换为大端字节序的字节数组(2字节)。 + * 例如,传入 (short) 0x8001 会得到 { (byte)0x80, (byte)0x01 }。 + * + * @param value short 类型,将按其二进制补码表示直接作为无符号值处理 + * @return 长度为 2 的字节数组,高位在前 + */ + public static byte[] unsignedShortToBytes(short value) { + // 将 short 转为无符号 int + int unsignedValue = value & 0xFFFF; + return unsignedShortToBytes(unsignedValue); + } + + /** + * 将无符号 short 值(int 类型)转换为指定字节序的字节数组(2字节)。 + * + * @param value 无符号 short 值(0 到 65535) + * @param byteOrder 字节序,ByteOrder.BIG_ENDIAN 或 ByteOrder.LITTLE_ENDIAN + * @return 长度为 2 的字节数组 + * @throws IllegalArgumentException 如果 value 超出范围或 byteOrder 为 null + */ + public static byte[] unsignedShortToBytes(int value, ByteOrder byteOrder) { + if (byteOrder == null) { + throw new IllegalArgumentException("ByteOrder must not be null"); + } + byte[] bytes = unsignedShortToBytes(value); + if (byteOrder == ByteOrder.LITTLE_ENDIAN) { + // 交换高低位 + byte tmp = bytes[0]; + bytes[0] = bytes[1]; + bytes[1] = tmp; + } + return bytes; + } + + /** + * 将无符号 short 值(short 类型)转换为指定字节序的字节数组(2字节)。 + * + * @param value short 类型,按无符号处理 + * @param byteOrder 字节序 + * @return 长度为 2 的字节数组 + */ + public static byte[] unsignedShortToBytes(short value, ByteOrder byteOrder) { + return unsignedShortToBytes(value & 0xFFFF, byteOrder); + } + + // ==================== 字节数组转无符号 short ==================== + + /** + * 从字节数组的起始位置读取 2 字节,按大端序转换为无符号 short 值(返回 int 类型)。 + * + * @param bytes 字节数组 + * @param offset 起始偏移量 + * @return 无符号 short 值(0 ~ 65535) + * @throws IllegalArgumentException 如果 bytes 为 null 或长度不足 + */ + public static int bytesToUnsignedShort(byte[] bytes, int offset) { + if (bytes == null || offset + 2 > bytes.length) { + throw new IllegalArgumentException("Invalid byte array or offset"); + } + return ((bytes[offset] & 0xFF) << 8) | (bytes[offset + 1] & 0xFF); + } + + /** + * 从字节数组的起始位置读取 2 字节,按指定字节序转换为无符号 short 值。 + * + * @param bytes 字节数组 + * @param offset 起始偏移量 + * @param byteOrder 字节序 + * @return 无符号 short 值 + */ + public static int bytesToUnsignedShort(byte[] bytes, int offset, ByteOrder byteOrder) { + if (byteOrder == ByteOrder.LITTLE_ENDIAN) { + return ((bytes[offset + 1] & 0xFF) << 8) | (bytes[offset] & 0xFF); + } else { + return bytesToUnsignedShort(bytes, offset); + } + } + + // ==================== 其他常见转换(扩展) ==================== + + /** + * 将 int 值转换为大端序的 4 字节数组。 + */ + public static byte[] intToBytes(int value) { + return new byte[]{ + (byte) ((value >> 24) & 0xFF), + (byte) ((value >> 16) & 0xFF), + (byte) ((value >> 8) & 0xFF), + (byte) (value & 0xFF) + }; + } + + /** + * 将大端序的 4 字节数组转换为 int 值。 + */ + public static int bytesToInt(byte[] bytes, int offset) { + if (bytes == null || offset + 4 > bytes.length) { + throw new IllegalArgumentException("Invalid byte array or offset"); + } + return ((bytes[offset] & 0xFF) << 24) + | ((bytes[offset + 1] & 0xFF) << 16) + | ((bytes[offset + 2] & 0xFF) << 8) + | (bytes[offset + 3] & 0xFF); + } + + /** + * 将 long 值转换为大端序的 8 字节数组。 + */ + public static byte[] longToBytes(long value) { + return new byte[]{ + (byte) ((value >> 56) & 0xFF), + (byte) ((value >> 48) & 0xFF), + (byte) ((value >> 40) & 0xFF), + (byte) ((value >> 32) & 0xFF), + (byte) ((value >> 24) & 0xFF), + (byte) ((value >> 16) & 0xFF), + (byte) ((value >> 8) & 0xFF), + (byte) (value & 0xFF) + }; + } + + /** + * 将大端序的 8 字节数组转换为 long 值。 + */ + public static long bytesToLong(byte[] bytes, int offset) { + if (bytes == null || offset + 8 > bytes.length) { + throw new IllegalArgumentException("Invalid byte array or offset"); + } + return ((long) (bytes[offset] & 0xFF) << 56) + | ((long) (bytes[offset + 1] & 0xFF) << 48) + | ((long) (bytes[offset + 2] & 0xFF) << 40) + | ((long) (bytes[offset + 3] & 0xFF) << 32) + | ((long) (bytes[offset + 4] & 0xFF) << 24) + | ((long) (bytes[offset + 5] & 0xFF) << 16) + | ((long) (bytes[offset + 6] & 0xFF) << 8) + | ((long) (bytes[offset + 7] & 0xFF)); + } +} diff --git a/src/main/java/racal/sunyard/main/SydApi4j.java b/src/main/java/racal/sunyard/main/SydApi4j.java index 8212e56..d2d9dad 100644 --- a/src/main/java/racal/sunyard/main/SydApi4j.java +++ b/src/main/java/racal/sunyard/main/SydApi4j.java @@ -6966,7 +6966,7 @@ public class SydApi4j implements SydApi { int isLast = bb.get(); byte[] dataLenArr = new byte[2]; bb.get(dataLenArr); - int dataLen = ByteUtil.bytesToInt(dataLenArr, ByteOrder.BIG_ENDIAN); + int dataLen = ByteUtil.bytesToShort(dataLenArr, ByteOrder.BIG_ENDIAN); // byte[] data = new byte[dataLen]; // bb.get(data); ByteBuffer slice = ByteBufferUtil.sliceAndConsume(bb, dataLen); @@ -7097,7 +7097,7 @@ public class SydApi4j implements SydApi { int isLast = bb.get(); byte[] dataLenArr = new byte[2]; bb.get(dataLenArr); - int dataLen = ByteUtil.bytesToInt(dataLenArr, ByteOrder.BIG_ENDIAN); + int dataLen = ByteUtil.bytesToShort(dataLenArr, ByteOrder.BIG_ENDIAN); ByteBuffer slice = ByteBufferUtil.sliceAndConsume(bb, dataLen); return new MutiReturn7(retCode, isLast, slice); } else { diff --git a/src/test/java/cmbpoc/FunctionTest.java b/src/test/java/cmbpoc/FunctionTest.java index 703be55..026024d 100644 --- a/src/test/java/cmbpoc/FunctionTest.java +++ b/src/test/java/cmbpoc/FunctionTest.java @@ -16,7 +16,10 @@ public class FunctionTest { private byte[] publicKey4Sign; private byte[] privateKey4Ende; private byte[] publicKey4Ende; - private byte[] orgData = new byte[15]; + private byte[] orgData = new byte[1024]; + private byte[] orgData2K = new byte[ 2 * 1024 ]; + private byte[] orgData2M = new byte[ 2 * 1024 * 1024 ]; + private byte[] orgData10M = new byte[ 4 * 1024 * 1024 - 1024]; private String sign; @Before @@ -26,7 +29,7 @@ public class FunctionTest { System.setProperty("com.sunyard.sydapi4j.debug", "true"); // 建立链接(单台) - this.api = (SydApi4j) new SydApi4j().connect("192.168.100.145", 8889, null, 5000); + this.api = (SydApi4j) new SydApi4j().connect("192.168.100.145", 8889, null, 30000); // RetWrap keypair = this.getPrivateKeyAndPublickKey(keypairIndex4Sign); // this.publicKey4Sign = Util.hexString2Bytes( keypair.get("pk").toString() ); @@ -103,6 +106,33 @@ public class FunctionTest { byte[] deData = this.api.SYD_SM2Decrypt(privateKey4Ende, enData); Assert.assertArrayEquals(orgData, deData); } + + + @Test + public void SYD_SM2_Encrypt_2K(){ + byte[] enData = this.api.SYD_SM2Encrypt(publicKey4Ende, orgData2K); + System.out.println("密文=" + Util.bytes2HexString(enData)); + byte[] deData = this.api.SYD_SM2Decrypt(privateKey4Ende, enData); + Assert.assertArrayEquals(orgData2K, deData); + } + + + @Test + public void SYD_SM2_Encrypt_2M(){ + byte[] enData = this.api.SYD_SM2Encrypt(publicKey4Ende, orgData2M); + System.out.println("密文=" + Util.bytes2HexString(enData)); + byte[] deData = this.api.SYD_SM2Decrypt(privateKey4Ende, enData); + Assert.assertArrayEquals(orgData2M, deData); + } + + + @Test + public void SYD_SM2_Encrypt_10M(){ + byte[] enData = this.api.SYD_SM2Encrypt(publicKey4Ende, orgData10M); + System.out.println("密文=" + Util.bytes2HexString(enData)); + byte[] deData = this.api.SYD_SM2Decrypt(privateKey4Ende, enData); + Assert.assertArrayEquals(orgData10M, deData); + } }