diff --git a/DProto/QP.xml b/DProto/QP.xml new file mode 100644 index 0000000..26dc15c --- /dev/null +++ b/DProto/QP.xml @@ -0,0 +1,96 @@ + + + + + + QP + + + + 要导出密钥的索引 + 27位的索引号:16位机构号+3位密钥类型+8位密钥索引号 + + + + + + + + QR + + + + + + + + + + + + + + + + + + + + + + + 私钥的字节长度 + + + + LMK下加密的私钥。 + + + + 可选项。如果显示消息尾域,则该域必须显示。值为 “X’19”。 + 19 + + + + 可选项。最大长度为 32个字符。 + + + + + + + + diff --git a/doc/java接口说明文档.docx b/doc/java接口说明文档.docx index fcb5409..3d9a8fb 100644 Binary files a/doc/java接口说明文档.docx and b/doc/java接口说明文档.docx differ diff --git a/src/main/java/com/sunyard/inf/SydCryptionApi.java b/src/main/java/com/sunyard/inf/SydCryptionApi.java index 2e892f2..965e4f7 100644 --- a/src/main/java/com/sunyard/inf/SydCryptionApi.java +++ b/src/main/java/com/sunyard/inf/SydCryptionApi.java @@ -261,6 +261,60 @@ interface SydSYMApi { */ boolean SYMDecryptDataWithFile(int nAlg, String seesionKey, String inputPath, String outputPath) throws Exception; + /** + * 使用SM4算法进行加密,其中加密模式为CBC, + * Ⅳ使用缺省值0X 00000000000000000000000000000000, + * 补位模式为 PKCS5 PADDING 。 + * @param keyType 密钥类型 0: ZEK,1: TEK + * @param key 密钥 + * @param inType 输入消息类型 0:二进制 1:扩展十六进制 + * @param outType 输出消息类型 0:二进制 1:扩展十六进制 + * @param inFilePath 需要加密的数据文件所在的路径 + * @param outFilePath 加密后的密文数据将要保存的文件路径 + * @return 加密是否成功。false为失败,true为成功 + */ + boolean SM4EncryptFileDataCBC(int keyType, String key, int inType, int outType, String inFilePath, String outFilePath); + + /** + * 使用SM4算法进行加密,其中加密模式为CBC, + * Ⅳ使用缺省值0X 00000000000000000000000000000000, + * 补位模式为 PKCS5 PADDING 。 + * @param keyType 密钥类型 0: ZEK,1: TEK + * @param key 密钥 + * @param inType 输入消息类型 0:二进制 1:扩展十六进制 + * @param outType 输出消息类型 0:二进制 1:扩展十六进制 + * @param msg 消息数据 + * @return 输出的报文密文 + */ + byte[] SM4EncryptDataCBC(int keyType, String key, int inType, int outType, byte[] msg); + + /** + * 使用SM4算法进行解密,其中加密模式为CBC, + * Ⅳ使用缺省值0X 00000000000000000000000000000000, + * 补位模式为 PKCS5 PADDING 。 + * @param keyType 密钥类型 0: ZEK,1: TEK + * @param key 密钥 + * @param inType 输入消息类型 0:二进制 1:扩展十六进制 + * @param outType 输出消息类型 0:二进制 1:扩展十六进制 + * @param inFilePath 加密后的密文数据将要保存的文件路径 + * @param outFilePath 解密后的数据文件所在的路径 + * @return 解密是否成功。false为失败,true为成功 + */ + boolean SM4DecryptFileDataCBC(int keyType, String key, int inType, int outType, String inFilePath, String outFilePath); + + /** + * 使用SM4算法进行解密,其中加密模式为CBC, + * Ⅳ使用缺省值0X 00000000000000000000000000000000, + * 补位模式为 PKCS5 PADDING 。 + * @param keyType 密钥类型 0: ZEK,1: TEK + * @param key 密钥 + * @param inType 输入消息类型 0:二进制 1:扩展十六进制 + * @param outType 输出消息类型 0:二进制 1:扩展十六进制 + * @param msg 加密后的消息数据 + * @return 输出的报文明文 + */ + byte[] SM4DecryptDataCBC(int keyType, String key, int inType, int outType, byte[] msg); + /** * 用输入的会话密钥,对指定报文数据进行加密处理。 * diff --git a/src/main/java/com/sunyard/inf/SydSVApi.java b/src/main/java/com/sunyard/inf/SydSVApi.java index 9abbd27..3602c58 100644 --- a/src/main/java/com/sunyard/inf/SydSVApi.java +++ b/src/main/java/com/sunyard/inf/SydSVApi.java @@ -47,6 +47,19 @@ interface SydNakedSVApi { */ interface SydAttachedSVApi { + /** + * sm2私钥签名 + * 用户id默认为1234567812345678 + * 签名结果R/S序列串先进行der编码,再进行base64编码 + * + * @param flag 私钥标志位,当为1时第二个参数传入存储私钥的索引,当为0时第二个参数传入私钥 + * @param privateKey 当私钥标志位为1时传入存储私钥的索引,当为0时传入私钥 + * @param publicKey 公钥 + * @param orgData 要签名的信息 + * @return 签名结果 + */ + String SM2SignC(int flag, String privateKey, byte[] publicKey, byte[] orgData); + /** * SM2 私钥签名 * @param pUserID 使用者的 ID,最大长度为 16 位数字,右对齐。 @@ -102,6 +115,16 @@ interface SydAttachedSVApi { byte[] orgData, byte[] sign); + /** + * sm2验签 + * 用户id默认为1234567812345678 + * + * @param publicKey 公钥的 DER 编码 + * @param orgData 要签名的信息 + * @param base64Sign 计算的签名,签名结果R/S序列串先进行der编码,再进行base64编码后的结果 + * @return true 验签成功,false 验签失败 + */ + boolean SM2Verify(byte[] publicKey, byte[] orgData, String base64Sign); /** * 采用 SM2 算法,用指定的公钥对指定的原始数据进行数字签名验证。 diff --git a/src/main/java/com/sunyard/util/FileUtil.java b/src/main/java/com/sunyard/util/FileUtil.java new file mode 100644 index 0000000..72ea3a3 --- /dev/null +++ b/src/main/java/com/sunyard/util/FileUtil.java @@ -0,0 +1,86 @@ +package com.sunyard.util; + +import com.sunyard.SydApiException; + +import java.io.*; + +public class FileUtil { + + /** + * 从文件中读取数据 + * @param path + * @return + * @throws SydApiException + */ + public static byte[] getDataFromFile(String path) throws SydApiException { + + File file = new File(path); + if (!file.exists() || !file.isFile()) { + throw new SydApiException("该文件不存在", -27); + } + + BufferedInputStream bis = null; + ByteArrayOutputStream baos = null; + try { + bis = new BufferedInputStream(new FileInputStream(file)); + baos = new ByteArrayOutputStream(1024); + + byte[] buf = new byte[1024]; + + int size = 0; + + while ((size = bis.read(buf)) != -1) { + baos.write(buf, 0, size); + } + + return baos.toByteArray(); + } catch (IOException e) { + e.printStackTrace(); + } finally { + if (bis != null) { + try { + bis.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + if (baos != null) { + try { + baos.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + return null; + } + + + /** + * 将字符串数据存储到文件中 + * 如果文件不存在则自动创建 + * @param path 文件路径 + * @param data 数据 + */ + public static void printDataToFile(String path, String data) { + OutputStreamWriter osw = null; + try { + osw = new OutputStreamWriter(new FileOutputStream(path)); + + osw.write(data); + + } catch (IOException e) { + e.printStackTrace(); + } finally { + if (osw != null) { + try { + osw.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + } +} diff --git a/src/main/java/racal/sunyard/main/SydApi4j.java b/src/main/java/racal/sunyard/main/SydApi4j.java index d41d546..9520ab6 100644 --- a/src/main/java/racal/sunyard/main/SydApi4j.java +++ b/src/main/java/racal/sunyard/main/SydApi4j.java @@ -12,6 +12,7 @@ import com.sunyard.proto.section.SectionValue; import com.sunyard.proto.value.Str; import com.sunyard.trans.PacketSN; import com.sunyard.util.CoderUtil; +import com.sunyard.util.FileUtil; import com.sunyard.util.MyUtil; import com.sunyard.util.SYMUtil; import racal.sunyard.main.dto.*; @@ -2727,6 +2728,49 @@ public class SydApi4j implements SydApi { return Util.bytes2HexString(((PacketSection) ret.get("publicKey")).getBytes()); } + /** + * 通过密钥索引获得 SM2 公钥(DER 编码)。 + * @param privateKeyTag 指示用户密钥存储区的27位地址,27位的索引号:16位机构号+3位密钥类型+8位密钥索引号 + * @return 公钥数据的der编码 + */ + // 测试通过 + public String SM2GetPublicKeyC(String privateKeyTag) { + + ProtoQQ proto = new ProtoQQ(); + HashMap packet = new HashMap(); + HashMap data = new HashMap(); + packet.put("data", data); + PacketSN sn = PacketSN.gen(); + packet.put("header", sn.getSn().array()); + data.put("privateKeyTag", privateKeyTag); + // 渲染发送 + ByteBuffer bb = proto.rend(packet); + //System.out.println(Util.bytes2HexString(Util.toArray(bb))); + synchronized (this) { + // 响应解析 + bb = syncRead(syncSend(bb)); + } + + //ProtocolParser parser = pset.getProtocolResParse(); + Packet p = proto.parse(bb); + Map ret = p.toMap(); + if ( + !Arrays.equals(sn.getSn().array(), ((PacketSection) ret.get("header")).getBytes()) + ) { + throw new SydApiException("包序号不匹配", -4); + } + ret = (Map) ret.get("data"); + PacketSection error = (PacketSection) ret.get("error"); + if (!"00".equals(error.getString())) { + throw new SydApiException(error.getInfo(), error.autoInt()); + } + int len = Integer.parseInt(((PacketSection) ret.get("publicLen")).getString()); + if (len == 128) { + return "03420004" + ((PacketSection) ret.get("publicKey")).getString(); + } + + return ((PacketSection) ret.get("publicKey")).getString(); + } @Override public String SM2GetPublicKeyC(String userId, int nKeyType) { @@ -2768,6 +2812,53 @@ public class SydApi4j implements SydApi { return ((PacketSection) ret.get("publicKey")).getString(); } + /** + * 导出一个SM2私钥。 + * @param privateKeyTag 要导出密钥的索引,27位的索引号:16位机构号+3位密钥类型+8位密钥索引号 + * @return LMK下加密的私钥 + */ + // 测试通过 + public String SM2GetPrivateKeyC(String privateKeyTag) { + + ProtoQP proto = new ProtoQP(); + HashMap packet = new HashMap(); + HashMap data = new HashMap(); + packet.put("data", data); + PacketSN sn = PacketSN.gen(); + packet.put("header", sn.getSn().array()); + data.put("privateKeyTag", privateKeyTag); + // 渲染发送 + ByteBuffer bb = proto.rend(packet); + //System.out.println(Util.bytes2HexString(Util.toArray(bb))); + synchronized (this) { + // 响应解析 + bb = syncRead(syncSend(bb)); + } + + //ProtocolParser parser = pset.getProtocolResParse(); + Packet p = proto.parse(bb); + Map ret = p.toMap(); + if ( + !Arrays.equals(sn.getSn().array(), ((PacketSection) ret.get("header")).getBytes()) + ) { + throw new SydApiException("包序号不匹配", -4); + } + ret = (Map) ret.get("data"); + PacketSection error = (PacketSection) ret.get("error"); + if (!"00".equals(error.getString())) { + throw new SydApiException(error.getInfo(), error.autoInt()); + } + + // 模长 + String mod = "00010000"; + + // 填充 + String fill = "0000000000000000000000000000000000000000000000000000000000000000"; + + return mod + ((PacketSection) ret.get("privateKey")).getString() + fill; + } + + /** * 通过私钥获取公钥 * @@ -2933,6 +3024,120 @@ public class SydApi4j implements SydApi { } + + /** + * sm2私钥签名 + * 用户id默认为1234567812345678 + * 签名结果R/S序列串先进行der编码,再进行base64编码 + * + * @param flag 私钥标志位,当为1时第二个参数传入存储私钥的索引,当为0时第二个参数传入私钥 + * @param privateKey 当私钥标志位为1时传入存储私钥的索引,当为0时传入私钥 + * @param publicKey 公钥 + * @param orgData 要签名的信息 + * @return 签名结果 + */ + // 测试通过 + @Override + public String SM2SignC(int flag, String privateKey, byte[] publicKey, byte[] orgData) { + + Proto74 proto = new Proto74(); + + // 填充数据 + HashMap packet = new HashMap<>(); + HashMap data = new HashMap<>(); + packet.put("data", data); + + PacketSN sn = PacketSN.gen(); + packet.put("header", sn.getSn().array()); + data.put("signatureDataType$option", 1); + data.put("userId", "1234567812345678".getBytes()); + data.put("publicKey", publicKey); + data.put("infoData", orgData); + data.put("privateKeyTag", flag == 1 ? privateKey : "999999999999999999999999999"); + data.put("privateKey", Util.hexString2Bytes(privateKey)); + + // 渲染发送 + ByteBuffer bb = proto.rend(packet); + //System.out.println(Util.bytes2HexString(Util.toArray(bb))); + synchronized (this) { + // 响应解析 + bb = syncRead(syncSend(bb)); + } + + + SectionValue sv = new SectionValue(); + sv.setValue(new byte[]{bb.get(12), bb.get(13)}); + PacketSection error = new PacketSection(sv); + if (0 != error.autoInt()) { + throw new SydApiException(error.getInfo(), error.autoInt()); + } + + bb.position(14); + byte[] v = new byte[4]; + bb.get(v, 0, v.length); + int a = Util.a2i(v, 10); + byte[] s = new byte[a]; + bb.get(s, 0, a); + + return SYMUtil.derSign2Base64Sign(s); + + } + + /** + * sm2验签 + * 用户id默认为1234567812345678 + * + * @param publicKey 公钥的 DER 编码 + * @param orgData 签名信息 + * @param base64Sign 计算的签名,签名结果R/S序列串先进行der编码,再进行base64编码后的结果 + * @return true 验签成功,false 验签失败 + */ + // 测试通过 + @Override + public boolean SM2Verify(byte[] publicKey, byte[] orgData, String base64Sign) { + + Proto75 proto = new Proto75(); //pset.getProtocolReqRender("75"); + + byte[] sign = SYMUtil.base64Sign2DerSign(base64Sign); + + // 填充数据 + HashMap packet = new HashMap(); + HashMap data = new HashMap(); + packet.put("data", data); + PacketSN sn = PacketSN.gen(); + packet.put("header", sn.getSn().array()); + data.put("signatureDataType$option", 1); + data.put("signature", sign); + data.put("userId", "1234567812345678".getBytes()); + data.put("infoData", orgData); + data.put("publicKey", publicKey); + // 渲染发送 + ByteBuffer bb = proto.rend(packet); + + long b = System.currentTimeMillis(); + + synchronized (this) { + // 响应解析 + bb = syncRead(syncSend(bb)); + } + + Packet p = proto.parse(bb); + Map ret = p.toMap(); + + if ( + !Arrays.equals(sn.getSn().array(), ((PacketSection) ret.get("header")).getBytes()) + ) { + throw new SydApiException("包序号不匹配", -4); + } + ret = (Map) ret.get("data"); + PacketSection error = (PacketSection) ret.get("error"); + if (!"00".equals(error.getString())) { + + throw new SydApiException(error.getInfo(), error.autoInt()); + } + return true; + } + // 测试通过 @Override public String SM2SignC(String pUserID, String certNo, int nOrgDataType, byte[] publicKey, byte[] orgData) { @@ -4030,6 +4235,149 @@ public class SydApi4j implements SydApi { return rw; } + /** + * 使用SM4算法进行加密,其中加密模式为CBC, + * Ⅳ使用缺省值0X 00000000000000000000000000000000, + * 补位模式为 PKCS5 PADDING 。 + * @param keyType 密钥类型 0: ZEK,1: TEK + * @param key 密钥 + * @param inType 输入消息类型 0:二进制 1:扩展十六进制 + * @param outType 输出消息类型 0:二进制 1:扩展十六进制 + * @param inFilePath 需要加密的数据文件所在的路径 + * @param outFilePath 加密后的密文数据将要保存的文件路径 + * @return 加密是否成功。false为失败,true为成功 + */ + // 测试通过 + @Override + public boolean SM4EncryptFileDataCBC(int keyType, String key, int inType, int outType, String inFilePath, String outFilePath) { + + byte[] msg = FileUtil.getDataFromFile(inFilePath); + + if (msg == null || msg.length == 0) { + throw new SydApiException("数据为空", -27); + } + + // 调用加密接口将数据加密 + byte[] result = SM4EncryptDataCBC(keyType, key, inType, outType, msg); + String str = Util.bytes2HexString(result); + + FileUtil.printDataToFile(outFilePath, str); + + return true; + } + + /** + * 使用SM4算法进行加密,其中加密模式为CBC, + * Ⅳ使用缺省值0X 00000000000000000000000000000000, + * 补位模式为 PKCS5 PADDING 。 + * @param keyType 密钥类型 0: ZEK,1: TEK + * @param key 密钥 + * @param inType 输入消息类型 0:二进制 1:扩展十六进制 + * @param outType 输出消息类型 0:二进制 1:扩展十六进制 + * @param msg 消息数据 + * @return 输出的报文密文 + */ + // 测试通过 + @Override + public byte[] SM4EncryptDataCBC(int keyType, String key, int inType, int outType, byte[] msg) { + + // 填充数据 + HashMap packet = new HashMap(); + HashMap data = new HashMap(); + byte[] iv = new byte[32]; + Arrays.fill(iv, (byte) 0x30); + + data.put("alg$option", 0x8); + data.put("roundModel$option", 1); + data.put("iv", iv); + data.put("keyType$option", keyType); + data.put("key", key.getBytes()); + data.put("inType$option", inType); + data.put("outType$option", outType); + data.put("fullMode$option", 1); + data.put("fullChar$option", 0); + data.put("fullType$option", 2); + data.put("msg", msg); + + packet.put("data", data); + + return repackEncrypt(packet); + } + + /** + * 使用SM4算法进行解密,其中加密模式为CBC, + * Ⅳ使用缺省值0X 00000000000000000000000000000000, + * 补位模式为 PKCS5 PADDING 。 + * @param keyType 密钥类型 0: ZEK,1: TEK + * @param key 密钥 + * @param inType 输入消息类型 0:二进制 1:扩展十六进制 + * @param outType 输出消息类型 0:二进制 1:扩展十六进制 + * @param inFilePath 加密后的密文数据将要保存的文件路径 + * @param outFilePath 解密后的数据文件所在的路径 + * @return 解密是否成功。false为失败,true为成功 + */ + // 测试通过 + @Override + public boolean SM4DecryptFileDataCBC(int keyType, String key, int inType, int outType, String inFilePath, String outFilePath) { + + byte[] msg = FileUtil.getDataFromFile(inFilePath); + + if (msg == null || msg.length == 0) { + throw new SydApiException("数据为空", -27); + } + + // 调用加密接口将数据加密 + byte[] result = SM4DecryptDataCBC(keyType, key, inType, outType, Util.hexString2Bytes(new String(msg))); + + String str = new String(Util.hexString2Bytes(Util.bytes2HexString(result))); + + FileUtil.printDataToFile(outFilePath, str); + + return true; + } + + /** + * 使用SM4算法进行解密,其中加密模式为CBC, + * Ⅳ使用缺省值0X 00000000000000000000000000000000, + * 补位模式为 PKCS5 PADDING 。 + * @param keyType 密钥类型 0: ZEK,1: TEK + * @param key 密钥 + * @param inType 输入消息类型 0:二进制 1:扩展十六进制 + * @param outType 输出消息类型 0:二进制 1:扩展十六进制 + * @param msg 加密后的消息数据 + * @return 输出的报文明文 + */ + // 测试通过 + @Override + public byte[] SM4DecryptDataCBC(int keyType, String key, int inType, int outType, byte[] msg) { + + byte[] iv = new byte[32]; + Arrays.fill(iv, (byte) 0x30); + + // 填充数据 + PacketSN sn = PacketSN.gen(); + HashMap packet = new HashMap(); + packet.put("header", sn.getSn().array()); + HashMap data = new HashMap(); + + data.put("alg$option", 0x9); + + data.put("roundModel$option", 1); + data.put("iv", iv); + data.put("keyType$option", keyType); + data.put("key", key.getBytes()); + data.put("inType$option", inType); + data.put("outType$option", outType); + data.put("fullMode$option", 1); + data.put("fullChar$option", 0); + data.put("fullType$option", 2); + data.put("msg", msg); + + packet.put("data", data); + + return repackEncrypt(packet); + } + @Override public byte[] SYMEncryptDataCBC(int nAlg, String seesionKey, byte[] pInData) { return SYMEncryptDataCBC(nAlg, seesionKey, 1, pInData); @@ -6188,6 +6536,7 @@ public class SydApi4j implements SydApi { * @return DK: LMK14-15 加密下的密钥 * keyCheck: 密钥校验值 */ + // 测试通过 public RetWrap getTransmissionKey() { // 获取协议 Proto60 proto = new Proto60(); diff --git a/src/test/java/com/sunyard/sydapi/example/ABCNorthBranch.java b/src/test/java/com/sunyard/sydapi/example/ABCNorthBranch.java new file mode 100644 index 0000000..0da81fc --- /dev/null +++ b/src/test/java/com/sunyard/sydapi/example/ABCNorthBranch.java @@ -0,0 +1,179 @@ +package com.sunyard.sydapi.example; + +import com.sunyard.RetWrap; +import com.sunyard.proto.Util; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import racal.sunyard.main.SydApi4j; + +import static com.sunyard.sydapi.util.PrintUtil.printByteArray; +import static com.sunyard.sydapi.util.PrintUtil.printRetWrap; + +/** + * 农行北分海淀支行-军队资金集中收付系统 + */ +public class ABCNorthBranch { + + SydApi4j api; + + // SM2密钥索引 + String SM2PrivateKeyTag = "111111111111111800000000001"; + // SM2公钥 + String SM2PublicKey = null; + // SM2私钥 + String SM2PrivateKey = null; + + // SM4密钥索引 + String SM4PrivateKeyTag = "333333333333333300A00000001"; + // SM4密钥 + String SM4Key = null; + + + @Before + public void before() { + System.setProperty("com.sunyard.sydapi4j.debug", "true"); + api = (SydApi4j) new SydApi4j().connect("192.168.1.7", 8889, null, 5000); + + SM2PublicKey = api.SM2GetPublicKeyC(SM2PrivateKeyTag); + SM2PrivateKey = api.SM2GetPrivateKeyC(SM2PrivateKeyTag); + SM4Key = new String(Util.hexString2Bytes(Util.bytes2HexString((byte[]) api.readKey(SM4PrivateKeyTag).get("key")))); + + + System.out.println("=========================================密钥获取完成========================================="); + } + + @After + public void after() { + try { + this.api.disconnect(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + // A4 + @Test + public void testComposeKey() { + String[] strs = {"583034303438393445374238444531323942344646344546393838394535364132", "583934443335443836454631463332313344353543343738323246383744333835"}; + RetWrap rw = api.composeKey("000", strs); + + printRetWrap(rw); + } + + + // 测试通过 + // 74 + @Test + public void testSM2SignC2() { + String thisOrgData = "FFFFFFFFFFFFFFFF"; + + String s = api.SM2SignC(1, SM2PrivateKeyTag, Util.hexString2Bytes(SM2PublicKey), thisOrgData.getBytes()); + System.out.println(s); + } + + // 测试通过 + // 74 + @Test + public void testSM2SignC3() { + String thisOrgData = "FFFFFFFFFFFFFFFF"; + + String s = api.SM2SignC(0, SM2PrivateKey, Util.hexString2Bytes(SM2PublicKey), thisOrgData.getBytes()); + System.out.println(s); + } + + // 测试通过 + // 75 + @Test + public void testSM2Verify2() { + String thisOrgData = "FFFFFFFFFFFFFFFF"; + + String s = api.SM2SignC(0, SM2PrivateKey, Util.hexString2Bytes(SM2PublicKey), thisOrgData.getBytes()); + + System.out.println(s); + boolean b = api.SM2Verify( Util.hexString2Bytes(SM2PublicKey), thisOrgData.getBytes(), s); + System.out.println(b); + } + + // 测试通过 + // 75 + @Test + public void testSM2Verify3() { + + String thisOrgData = "FFFFFFFFFFFFFFFF"; + + String s = api.SM2SignC(1, SM2PrivateKeyTag, Util.hexString2Bytes(SM2PublicKey), thisOrgData.getBytes()); + + System.out.println(s); + boolean b = api.SM2Verify( Util.hexString2Bytes(SM2PublicKey), thisOrgData.getBytes(), s); + System.out.println(b); + } + + // 测试通过 + // E0 + @Test + public void testSM4EncryptDataCBC() { + String msg = "1111111111111111111111"; + byte[] bytes = api.SM4EncryptDataCBC(0, SM4Key, 0, 0 , msg.getBytes()); + printByteArray(bytes); + + } + + // 测试通过 + // E0 + @Test + public void testSM4DecryptDataCBC() { + String msg = "11111111111"; + byte[] bytes = api.SM4EncryptDataCBC(0, SM4Key, 0, 0 , msg.getBytes()); + + byte[] bytes1 = api.SM4DecryptDataCBC(0, SM4Key, 0, 0, bytes); + + printByteArray(bytes1, false); + } + + // 测试通过 + // E0 + @Test + public void testSM4EncryptFileDataCBC() { + + String inFilePath = "C:\\Users\\edgar\\Desktop\\fsdownload\\test\\in1.txt"; + String outFilePath = "C:\\Users\\edgar\\Desktop\\fsdownload\\test\\in2.txt"; + boolean b = api.SM4EncryptFileDataCBC(0, SM4Key, 0, 0, inFilePath, outFilePath); + System.out.println(b); + } + + + // 测试通过 + // E0 + @Test + public void testSM4DecryptFileDataCBC() { + + String outFilePath = "C:\\Users\\edgar\\Desktop\\fsdownload\\test\\in2.txt"; + String outFilePath2 = "C:\\Users\\edgar\\Desktop\\fsdownload\\test\\out1.txt"; + boolean b = api.SM4DecryptFileDataCBC(0, SM4Key, 0, 0, outFilePath, outFilePath2); + System.out.println(b); + } + + // LF + @Test + public void testReadKey() { + RetWrap retWrap = api.readKey(SM4PrivateKeyTag); + printRetWrap(retWrap); + } + + // QQ + @Test + public void testSM2GetPublicKeyC3() { + + String s = api.SM2GetPublicKeyC(SM2PrivateKeyTag); + System.out.println(s); + } + + // QP + @Test + public void testSM2GetPrivateKeyC() { + String s = api.SM2GetPrivateKeyC(SM2PrivateKeyTag); + System.out.println(s); + } + +} diff --git a/src/test/java/com/sunyard/sydapi/test/TestAllMethods.java b/src/test/java/com/sunyard/sydapi/test/TestAllMethods.java index 97a91f6..fd98fea 100644 --- a/src/test/java/com/sunyard/sydapi/test/TestAllMethods.java +++ b/src/test/java/com/sunyard/sydapi/test/TestAllMethods.java @@ -4,6 +4,7 @@ import com.sunyard.RetWrap; import com.sunyard.SydApi; import com.sunyard.cert.X509; import com.sunyard.proto.Util; +import com.sunyard.sydapi.util.PrintUtil; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -11,6 +12,9 @@ import racal.sunyard.main.SydApi4j; import java.io.*; +import static com.sunyard.sydapi.util.PrintUtil.printByteArray; +import static com.sunyard.sydapi.util.PrintUtil.printRetWrap; + public class TestAllMethods { SydApi4j api; @@ -34,32 +38,6 @@ public class TestAllMethods { } } - public void printRetWrap(RetWrap rw) { - printRetWrap(rw, false); - } - - /** - * 输出 - * @param rw - */ - public void printRetWrap(RetWrap rw, boolean flag) { - for (String s : rw.keySet()) { - - Object o = rw.get(s); - if (o instanceof String) { - System.out.println(s + ":" + o); - } else if (o instanceof byte[]) { - if (flag) { - System.out.println(s + ": " + Util.bytes2HexString((byte[]) o)); - } else { - System.out.println(s + ": " + new String(Util.hexString2Bytes(Util.bytes2HexString((byte[]) o)))); - } - } else { - System.out.println(s + ":" + o); - } - } - } - // 获取证书 public String getCertStr(String path) { @@ -127,13 +105,14 @@ public class TestAllMethods { */ public byte[] inputStream2ByteArray(String filePath) { - InputStream in = null; + BufferedInputStream in = null; ByteArrayOutputStream out = null; byte[] data = null; try { - in = new FileInputStream(filePath); + in = new BufferedInputStream(new FileInputStream(filePath)); out = new ByteArrayOutputStream(); + byte[] buffer = new byte[1024 * 4]; int n = 0; while ((n = in.read(buffer)) != -1) { @@ -616,6 +595,82 @@ public class TestAllMethods { printRetWrap(retWrap, true); } + // 00650000000000000000 + // 4530 + // 30 + // 38 + // 3230583643454537343433323934393942343236434545373434333239343939423432303031303030303230303030303030303030303030303030303030303030303030303030303030303030423131313131313131313131 + + // 测试通过 + // E0 + @Test + public void testSM4EncryptDataCBC() { + String key = "X6CEE744329499B426CEE744329499B42"; + String msg = "1111111111111111111111"; + byte[] bytes = api.SM4EncryptDataCBC(0, key, 0, 0 , msg.getBytes()); + printByteArray(bytes); + + } + + // 00200000000000000000 + // 4531 + // 303030 + // 303130 + // FF045D9DFA5DBE95CBC4285499719EF1 + + // 006A000000000000000245303039323058364345453734343332393439394234323643454537343433323934393942343230303130303030323030303030303030303030303030303030303030303030303030303030303030303130FF045D9DFA5DBE95CBC4285499719EF1 + // 测试通过 + // E0 + @Test + public void testSM4DecryptDataCBC() { + String key = "X6CEE744329499B426CEE744329499B42"; + String msg = "11111111111"; + byte[] bytes = api.SM4EncryptDataCBC(0, key, 0, 0 , msg.getBytes()); + + byte[] bytes1 = api.SM4DecryptDataCBC(0, key, 0, 0, bytes); + + printByteArray(bytes1, false); + } + + // 00850000000000000000 + // 4530 + // 30 + // 38 + // 32 + // 30 + // 583643454537343433323934393942343236434545373434333239343939423432 + // 30 + // 30 + // 31 + // 30303030 + // 32 + // 3030303030303030303030303030303030303030303030303030303030303030 + // 303242 + // 31303130313131313131313131313131313131313131313030303030303030303031313131313131313131 + + // 测试通过 + // E0 + @Test + public void testSM4EncryptFileDataCBC() { + String key = "X6CEE744329499B426CEE744329499B42"; + String inFilePath = "C:\\Users\\edgar\\Desktop\\fsdownload\\test\\in1.txt"; + String outFilePath = "C:\\Users\\edgar\\Desktop\\fsdownload\\test\\in2.txt"; + boolean b = api.SM4EncryptFileDataCBC(0, key, 0, 0, inFilePath, outFilePath); + System.out.println(b); + } + + + // 测试通过 + // E0 + @Test + public void testSM4DecryptFileDataCBC() { + String key = "X6CEE744329499B426CEE744329499B42"; + String outFilePath = "C:\\Users\\edgar\\Desktop\\fsdownload\\test\\in2.txt"; + String outFilePath2 = "C:\\Users\\edgar\\Desktop\\fsdownload\\test\\out1.txt"; + boolean b = api.SM4DecryptFileDataCBC(0, key, 0, 0, outFilePath, outFilePath2); + System.out.println(b); + } + // 测试通过 // Y0 @Test @@ -642,7 +697,7 @@ public class TestAllMethods { // LF @Test public void testReadKey() { - String index = "000000000000000300000000003"; + String index = "333333333333333300A00000001"; RetWrap retWrap = api.readKey(index); printRetWrap(retWrap); } @@ -784,13 +839,13 @@ public class TestAllMethods { // E2 @Test public void testSM2OrRSAGenKeyPair() { - String index = "1111111111111115"; + String index = "1111111111111118"; // SM2 -// RetWrap retWrap = api.SM2OrRSAGenKeyPair(1, index, 0); + RetWrap retWrap = api.SM2OrRSAGenKeyPair(1, index, 0); // RSA - RetWrap retWrap = api.SM2OrRSAGenKeyPair(0, index, 1024); +// RetWrap retWrap = api.SM2OrRSAGenKeyPair(0, index, 1024); printRetWrap(retWrap, true); } @@ -868,6 +923,7 @@ public class TestAllMethods { printRetWrap(retWrap, true); } + // 测试通过 // 60 @Test public void testGetTransmissionKey() { @@ -1083,6 +1139,35 @@ public class TestAllMethods { System.out.println(s); } + // 测试通过 + // QQ + @Test + public void testSM2GetPublicKeyC2() { + String userId = "1111111111111117"; + + String s = api.SM2GetPublicKeyC(userId, 0); + System.out.println(s); + } + + // 测试通过 + // QQ + @Test + public void testSM2GetPublicKeyC3() { + + String tag = "111111111111111800000000001"; + String s = api.SM2GetPublicKeyC(tag); + System.out.println(s); + } + + // 测试通过 + // QP + @Test + public void testSM2GetPrivateKeyC() { + String tag = "111111111111111800000000001"; + String s = api.SM2GetPrivateKeyC(tag); + System.out.println(s); + } + // 测试通过 // HI @Test @@ -1175,6 +1260,71 @@ public class TestAllMethods { System.out.println(s); } + // 测试通过 + // 74 + @Test + public void testSM2SignC2() { + String thisPublicKey = "03420004549B6A1A09A5D0D9432C6829D443F85ED8785340FC1AB14118BB7637830C808F7A888DF0C4F988EA6FF2EE6C76ECD00C4B7CEC92CC8EA365F8EA291041CAB231"; + String thisOrgData = "FFFFFFFFFFFFFFFF"; + + String s = api.SM2SignC(1, "111111111111111300000000001", Util.hexString2Bytes(thisPublicKey), thisOrgData.getBytes()); + System.out.println(s); + } + + // 测试通过 + // 74 + @Test + public void testSM2SignC3() { + String privateKey = "00010000D7DBFD26A371D3B5BA58D3ECA98EAEFC1BCB65FA0DBBCFBC551E4315B8B2A8700000000000000000000000000000000000000000000000000000000000000000"; + String thisPublicKey = "034200042E624577E3BF1A510804346D1054B9205D97B4579D6528C25CAE6B74E5CDD19774AFA17CD9017E6BCBD8D9F3903492CD5288932941583E113C804537B69CDD46"; + String thisOrgData = "FFFFFFFFFFFFFFFF"; + + String s = api.SM2SignC(0, privateKey, Util.hexString2Bytes(thisPublicKey), thisOrgData.getBytes()); + System.out.println(s); + } + + // 00C40000000000000001 + // 3735 + // 30303731 + // 3045022100E5C51AE465EB085AC0A864414617D50776F7E93F9026F5E88FD8C1DC9DB38E9F022048A6E3CBE58837012FFF4281C8B53B98DCFBD6C250F0CD153C640C53FF8D78FB + // 31 + // 3136 + // 31323334353637383132333435363738 + // 30303136 + // 46464646464646464646464646464646 + // 30303638 + // 03420004549B6A1A09A5D0D9432C6829D443F85ED8785340FC1AB14118BB7637830C808F7A888DF0C4F988EA6FF2EE6C76ECD00C4B7CEC92CC8EA365F8EA291041CAB231 + + // 测试通过 + // 75 + @Test + public void testSM2Verify2() { + String privateKey = "00010000D7DBFD26A371D3B5BA58D3ECA98EAEFC1BCB65FA0DBBCFBC551E4315B8B2A8700000000000000000000000000000000000000000000000000000000000000000"; + String thisPublicKey = "034200042E624577E3BF1A510804346D1054B9205D97B4579D6528C25CAE6B74E5CDD19774AFA17CD9017E6BCBD8D9F3903492CD5288932941583E113C804537B69CDD46"; + String thisOrgData = "FFFFFFFFFFFFFFFF"; + + String s = api.SM2SignC(0, privateKey, Util.hexString2Bytes(thisPublicKey), thisOrgData.getBytes()); + + System.out.println(s); + boolean b = api.SM2Verify( Util.hexString2Bytes(thisPublicKey), thisOrgData.getBytes(), s); + System.out.println(b); + } + + // 测试通过 + // 75 + @Test + public void testSM2Verify3() { + + String thisPublicKey = "034200045AC5014ED6A2CA0F9F79F3A34ADF4B8B92383F09E2D2F2F5B56F3D6C05B3EE43A3D65E57D3979C6CE9F6CEC5E0E30DC564416BFCB9A3E2D071559098B6B6BEF6"; + String thisOrgData = "FFFFFFFFFFFFFFFF"; + + String s = api.SM2SignC(1, "111111111111111700000000001", Util.hexString2Bytes(thisPublicKey), thisOrgData.getBytes()); + + System.out.println(s); + boolean b = api.SM2Verify( Util.hexString2Bytes(thisPublicKey), thisOrgData.getBytes(), s); + System.out.println(b); + } + // 测试通过 // 75 @Test diff --git a/src/test/java/com/sunyard/sydapi/util/PrintUtil.java b/src/test/java/com/sunyard/sydapi/util/PrintUtil.java new file mode 100644 index 0000000..ab47fc8 --- /dev/null +++ b/src/test/java/com/sunyard/sydapi/util/PrintUtil.java @@ -0,0 +1,45 @@ +package com.sunyard.sydapi.util; + +import com.sunyard.RetWrap; +import com.sunyard.proto.Util; + +public class PrintUtil { + + public static void printRetWrap(RetWrap rw) { + printRetWrap(rw, false); + } + + /** + * 输出 + * @param rw + */ + public static void printRetWrap(RetWrap rw, boolean flag) { + for (String s : rw.keySet()) { + + Object o = rw.get(s); + if (o instanceof String) { + System.out.println(s + ":" + o); + } else if (o instanceof byte[]) { + if (flag) { + System.out.println(s + ": " + Util.bytes2HexString((byte[]) o)); + } else { + System.out.println(s + ": " + new String(Util.hexString2Bytes(Util.bytes2HexString((byte[]) o)))); + } + } else { + System.out.println(s + ":" + o); + } + } + } + + public static void printByteArray(byte[] bytes) { + printByteArray(bytes, true); + } + + public static void printByteArray(byte[] bytes, boolean flag) { + if (flag) { + System.out.println("输出为: " + Util.bytes2HexString(bytes)); + } else { + System.out.println("输出为: " + new String(Util.hexString2Bytes(Util.bytes2HexString(bytes)))); + } + } +}