169 Commits
Author SHA1 Message Date
cheney c79aae14e8 证书工具 2026-06-10 15:01:42 +08:00
cheney cec433ad3b 重新合并代码 2026-06-10 14:30:08 +08:00
cheney 555da388ef Merge remote-tracking branch 'honor3/dev-V2.01' into dev-V2.01
# Conflicts:
#	src/main/java/racal/sunyard/main/SydApi4j.java
2026-06-10 14:27:54 +08:00
cheney dd44703a33 重新合并代码 2026-06-10 14:24:17 +08:00
cheney c8577571a6 Merge branch 'dev-sm2bigdata' into dev-V2.01
# Conflicts:
#	src/main/java/racal/sunyard/main/SydApi4j.java
2026-06-10 14:13:36 +08:00
cheney 374ddad9bc Merge remote-tracking branch 'honor3/dev-V2.01' into dev-V2.01
# Conflicts:
#	src/main/java/racal/sunyard/main/SydApi4j.java
2026-06-10 10:32:54 +08:00
cheney ecd2d6cfe1 SM3 性能优化 2026-06-10 10:29:39 +08:00
cheney 55c00b6579 jmeter 测试用例完成 2026-06-10 10:29:38 +08:00
cheney 6cd738a172 jmeter 测试可用 2026-06-10 10:29:37 +08:00
cheney 2c8638a167 jmeter 测试可用 2026-06-10 10:29:36 +08:00
cheney 9c4c19d271 性能简单测试 2026-06-10 10:29:35 +08:00
cheney 17a40377d7 功能测试通过 2026-06-10 10:29:35 +08:00
cheney 18aa757871 性能测试代码 2026-06-10 10:29:34 +08:00
cheney a452376d8d 小于 4M 可以 2026-06-10 10:29:16 +08:00
cheney 7a4a83e6d0 小数据测试通过 2026-06-10 10:27:36 +08:00
cheney b212a265ee byte 转长度 2026-06-10 10:27:16 +08:00
cheney c9a224f810 优化通信 2026-06-10 10:26:44 +08:00
cheney 09f5516792 QN 指令长度错误 2026-06-10 10:26:44 +08:00
cheney 3965146c77 强制指定大端模式 2026-06-10 10:26:21 +08:00
cheney 12b53a2e0f 测试代码整理 2026-06-10 10:25:53 +08:00
cheney 48d9719fbc 测试代码整理 2026-06-10 10:25:53 +08:00
cheney 882e84320c 调整协议,index 改为 4 字节。 2026-06-10 10:25:28 +08:00
cheney 12bdac2d7c 添加测试代码 2026-06-10 10:24:47 +08:00
cheney 31f8c9155e 添加一个性能测试模板 2026-06-10 10:24:46 +08:00
cheney 09a910006f SM3 性能优化 2026-06-10 10:21:15 +08:00
cheney 83e5033ba0 jmeter 测试用例完成 2026-06-09 09:41:10 +08:00
cheney 664bd110c6 jmeter 测试可用 2026-06-08 18:08:10 +08:00
cheney b82002801d jmeter 测试可用 2026-06-08 17:03:46 +08:00
cheney d6a27f3341 性能简单测试 2026-06-08 15:14:22 +08:00
cheney 01be8429be 功能测试通过 2026-06-08 14:08:25 +08:00
陈旻 799f3763d1 6.4警告修复-陈旻 2026-06-04 09:31:50 +08:00
cheney 76809e5521 性能测试代码 2026-06-03 17:23:41 +08:00
cheney 983dc8a47d 小于 4M 可以 2026-06-03 16:34:41 +08:00
cheney 0dc2d7c026 小数据测试通过 2026-06-03 14:08:19 +08:00
cheney 02fd07def2 byte 转长度 2026-06-03 11:44:40 +08:00
cheney 10d9d1b0d6 优化通信 2026-06-02 17:58:02 +08:00
cheney b8322538e7 QN 指令长度错误 2026-06-02 16:26:54 +08:00
cheney 83802b6ef6 强制指定大端模式 2026-06-02 15:06:29 +08:00
cheney 9062a9c17c 测试代码整理 2026-06-01 17:57:23 +08:00
cheney 88f4bdf603 测试代码整理 2026-06-01 13:41:28 +08:00
cheney 385e77b766 调整协议,index 改为 4 字节。 2026-06-01 10:02:49 +08:00
cheney 5259876780 添加测试代码 2026-05-29 18:03:08 +08:00
cheney f7fa777677 添加一个性能测试模板 2026-05-29 17:18:36 +08:00
cheney 1439f4aa63 整理依赖 2026-05-29 17:00:56 +08:00
cheney d1c8201f98 fix 长度问题 2026-05-29 16:44:04 +08:00
cheney 914ba8eee5 添加大数据加密指令 2026-05-29 16:25:04 +08:00
cheney e8a62c1d4a 一个 xml 测试 2026-05-18 17:15:00 +08:00
waner 8de764c731 fix:key漏洞 2025-07-31 11:57:12 +08:00
waner 1df1e64783 fix:key漏洞 2025-07-31 11:57:05 +08:00
waner 6df9d978d5 jmeter测试类 2025-07-25 09:39:03 +08:00
waner 7e4bc7f87b 增加参数范围校验 2025-07-24 18:02:14 +08:00
waner 1f2709326f jmeter测试修改 2025-07-18 09:44:54 +08:00
waner d80e225158 jmeter测试 2025-07-16 15:43:32 +08:00
waner 4372362086 证书导入结果修改 2025-06-19 11:05:12 +08:00
waner b4d3c1d193 jmeter测试完善 2025-06-09 10:51:51 +08:00
waner 9fbcd1baad 单元测试 2025-06-05 09:30:32 +08:00
waner e2c8695f47 fix:删除证书 2025-06-04 10:32:13 +08:00
waner e4020b1bbc fix:主备切换 2025-06-04 10:13:37 +08:00
waner fbcbe79388 fix:主备切换测试 2025-05-30 16:21:39 +08:00
waner 085d71feb9 fix:jmeter测试 2025-05-23 17:54:00 +08:00
waner 0f46865151 fix:测试demo完善 2025-05-20 17:12:54 +08:00
waner a919287719 fix:测试demo完善 2025-05-20 14:09:45 +08:00
waner 35150c9af4 fix 2025-05-20 14:01:25 +08:00
waner 4616f1b700 测试脚本 2025-05-20 10:30:45 +08:00
waner f8bf4b10fb fix 2025-05-15 13:58:53 +08:00
waner b7cd62a872 fix 2025-05-14 15:02:24 +08:00
waner d3ff2e3646 fix:完善多机证书导入功能 2025-05-14 14:25:34 +08:00
waner 55a9cfbdbe feat:多机证书导入功能 2025-05-08 16:46:30 +08:00
yihzhou db80b1dd83 增加二维码、条形码签名验签测试 2024-11-21 10:56:01 +08:00
yihzhou 25803c9d4f save 2024-07-01 16:10:48 +08:00
yihzhou e866887b3a 完善验证测试程序 2024-06-20 16:09:19 +08:00
yihzhou b37b962dd5 增加验证测试程序 2024-06-17 09:21:28 +08:00
yihzhou f05c04f957 增加证书删除指令 2024-04-11 15:29:30 +08:00
yihzhou 9c2cdb5214 优化E0指令 2023-12-06 15:25:13 +08:00
yihzhou ffd19acbfc 配合网联接口 2023-11-13 15:31:29 +08:00
yihzhou 62598e0c89 完善jmter 2023-11-10 10:03:55 +08:00
yihzhou 9af716e87d 暂存 2023-09-18 10:49:04 +08:00
yihzhou 6f833730c2 本地保存 2023-08-25 15:49:31 +08:00
yihzhou b26aab01a4 保留本地修改至上清分支 2023-08-10 10:45:41 +08:00
yihzhou 7a4f9892f5 保存周一豪电脑 2023-08-02 14:00:36 +08:00
yihzhou ad443356b3 Merge remote-tracking branch 'origin/dev-shangqing' into dev-shangqing 2023-05-18 16:47:53 +08:00
yihzhou 10622bfb23 p1 p7签名兼容RSA、SM2 2023-05-18 16:45:32 +08:00
cheney e675d8a530 hash 2023-04-17 14:35:01 +08:00
cheney 52e47a5809 整理示例代码 2023-04-17 14:29:04 +08:00
cheney ca32bb4c18 save 2023-02-28 15:20:38 +08:00
cheney 772458254e 添加单元测试 2022-12-16 16:58:31 +08:00
cheney 7d0aebad53 重命名函数 hash 2022-12-16 16:47:27 +08:00
cheney 56eb803514 添加测试 2022-12-16 16:46:06 +08:00
yihzhou 758a4ea116 Merge remote-tracking branch 'origin/dev-shangqing' into dev-shangqing
# Conflicts:
#	DProto/8003.xml
2022-12-15 17:38:09 +08:00
yihzhou 54e636dd4f 增加大数据裸签功能,完善RSA签名功能接口(修改counthash使用) 2022-12-15 17:26:22 +08:00
cheney 92d6301dcc 扩展 8003 指令 2022-12-15 10:02:41 +08:00
cheney 2419ae656a 忽略日志目录 2022-12-14 15:30:19 +08:00
cheney 35a25e2ca7 更新文档 2022-12-13 18:01:32 +08:00
cheney 4ed943b850 获取所有证书测试 2022-12-13 18:00:09 +08:00
yihzhou 85ef86ee49 增加获取所有证书列表问题 2022-12-13 14:08:24 +08:00
cheney 92ee7a17e8 升级 proto 版本 2022-12-13 11:04:52 +08:00
yihzhou 3f6d316d8b 增加配置项开关控制dn反序 2022-12-09 10:57:32 +08:00
yihzhou 0f28395ce9 完善异常信息捕获、证书列表获取 2022-11-28 10:17:52 +08:00
yihzhou 99a7462fdf Merge remote-tracking branch 'origin/dev-shangqing' into dev-shangqing 2022-11-10 15:54:40 +08:00
yihzhou d167339d72 SydAttachedSVApi修复 2022-11-10 15:53:47 +08:00
chuzhenyang 8fa39ff4fe Merge remote-tracking branch 'origin/branch' into dev-shangqing
# Conflicts:
#	src/main/java/racal/sunyard/main/SydApi4j.java
2022-11-10 15:51:45 +08:00
chuzhenyang d0fbe3e48c 获取证书列表测试 2022-11-10 15:47:29 +08:00
chuzhenyang 25af2e8fde 移除目标文件 2022-11-10 15:46:21 +08:00
yihzhou 9ab25d4899 修正SydAttachedSVApi 2022-11-08 17:36:45 +08:00
yihzhou 9fd5d5dc8e Merge remote-tracking branch 'origin/dev-shangqing' into dev-shangqing 2022-11-08 17:12:56 +08:00
yihzhou f345d47dd2 save 2022-11-08 17:12:14 +08:00
yihzhou ecd01a408e save 2022-11-08 17:12:05 +08:00
cheney 06e29e8821 开放接口 2022-11-04 18:27:51 +08:00
cheney 3941c3bf33 开放 pool 参数 2022-11-04 17:44:56 +08:00
chuzhenyang fef31bd7b9 查询所有证书及demo,P1P7性能测试demo 2022-11-03 09:21:27 +08:00
yihzhou fd6ef6050f 完善RSA大数据数字信封 2022-10-28 11:20:22 +08:00
cheney c95130c6ed Merge remote-tracking branch 'origin/dev-shangqing' into dev-shangqing 2022-10-26 17:44:17 +08:00
cheney fdadf11c93 连接池 2022-10-26 17:44:10 +08:00
yihzhou 952f274f5a Merge remote-tracking branch 'origin/dev-shangqing' into dev-shangqing 2022-10-26 17:36:02 +08:00
cheney 24161e2ad5 合并
# Conflicts:
#	pom.xml
#	src/main/java/com/sunyard/SydApiException.java
#	src/main/java/racal/sunyard/main/SydApi4j.java
#	src/test/java/com/sunyard/sydapi/test/TestAllMethods.java
2022-10-26 17:24:39 +08:00
cheney d0ea067870 整理日志
# Conflicts:
#	src/main/java/com/sunyard/log/SydLogFactory.java
#	src/main/java/com/sunyard/log/SydLogInfo.java
#	src/main/java/com/sunyard/log/SydLogger.java
#	src/main/java/racal/sunyard/main/SydApi4j.java
2022-10-26 17:19:33 +08:00
yihzhou 2ec20ad3c8 更新依赖 2022-10-26 16:40:18 +08:00
yihzhou 99b5956143 增加及修改文件以适应RSA密钥签名验签功能 2022-10-26 10:05:14 +08:00
cheney d7fe309b08 添加证书类型判断 2022-10-13 15:23:55 +08:00
cheney 01f7ac1f31 证书工具 2022-10-13 10:25:19 +08:00
cheney f36b8c2ca3 证书工具 2022-10-13 10:21:45 +08:00
cheney ee395aebee 证书工具 2022-10-12 16:31:11 +08:00
junj2.liang 48a1aa828c 修改异常类 2022-09-08 10:33:38 +08:00
cheney 1be35ace33 示例代码 2022-09-05 20:50:45 +08:00
cheney 37dd4ea78c fix bugs 2022-09-05 20:35:51 +08:00
cheney 055942f35f fix bugs 2022-09-05 20:35:09 +08:00
chuzhenyang 2cd50187d6 修改异常类 2022-09-05 16:02:14 +08:00
yihzhou 5f424168f7 测试上清所接口 2022-09-05 15:55:50 +08:00
cheney 77dd48f8a0 Merge remote-tracking branch 'gitrep/dev-shangqing' into dev-shangqing-origin
# Conflicts:
#	.gitignore
#	src/main/java/com/sunyard/SydApiException.java
2022-09-05 15:49:46 +08:00
cheney 8ccb1b983e 重命名 2022-09-05 13:54:31 +08:00
yihzhou 7e177e2518 Merge remote-tracking branch 'origin/dev-shangqing' into dev-shangqing 2022-09-05 11:09:04 +08:00
yihzhou bed95d2009 增加签名数字信封、解签名数字信封接口 2022-09-05 11:06:34 +08:00
junj2.liang 1816e26253 修改异常类 2022-08-24 16:51:02 +08:00
cheney f59e25757f 包大小 2022-08-18 20:21:02 +08:00
cheney 44beda611d 打包大小 2022-08-18 20:10:23 +08:00
cheney d8b40a51b5 Detach DN 反转问题 2022-08-18 18:25:22 +08:00
cheney 748571082b Detach DN 反转问题 2022-08-18 17:48:56 +08:00
cheney 0af77f706a 打包 2022-08-18 17:13:24 +08:00
cheney 726eecdbc6 打包 2022-08-18 16:03:43 +08:00
cheney f5ffa53b68 打包 2022-08-18 15:45:15 +08:00
cheney 44b3247d3d 不再提供 maven 2022-08-18 15:41:25 +08:00
cheney 4ddd0d47fd 优化异常 2022-08-18 15:36:12 +08:00
cheney 8ee487fbd0 合并代码 2022-08-18 15:05:35 +08:00
cheney 3b246776aa Merge branch 'dev-icbc' into dev-shangqing
# Conflicts:
#	.gitignore
#	doc/java接口说明文档.docx
#	src/main/java/racal/sunyard/main/SydApi4j.java
#	src/test/java/com/sunyard/sydapi/test/TestAllMethods.java
#	src/test/java/com/sunyard/sydapi/test/TestSV.java
2022-08-18 14:58:18 +08:00
cheney d1dab301d9 忽略目标文件 2022-08-18 14:39:30 +08:00
cheney db067ee91c 修正依赖 2022-08-18 10:29:06 +08:00
cheney 0e398363f4 更新文档 2022-08-18 10:22:17 +08:00
cheney fd0bd53a73 更新打包脚本 2022-08-09 14:39:36 +08:00
cheney f360712042 忽略 pack 2022-08-09 14:38:20 +08:00
cheney 6daefe5d48 添加 SM3 接口变种 2022-07-21 09:47:30 +08:00
cheney dbc5530853 添加 SM3 接口变种 2022-07-21 09:45:17 +08:00
cheney 899b0cc1ca 上清新增接口 2022-07-18 16:32:37 +08:00
cheney 959dd73022 更新上清大数据 P7 接口 2022-07-15 10:50:27 +08:00
cheney a982f8b2df 多线程安全的接口 2022-07-15 10:19:58 +08:00
cheney ba3f91df54 忽略临时文件 2022-07-15 10:19:22 +08:00
cheney 1e84209fea 更新打包命令 2022-07-13 11:31:51 +08:00
cheney 50178ef483 loadrunner 脚本 2022-07-13 11:04:30 +08:00
cheney d9c5e01105 扩展异常类 2022-07-12 09:47:34 +08:00
cheney 6cb3072453 打包签名验签 2022-06-24 11:52:03 +08:00
cheney 0c13d0c38a E0 分包设置为 4064 2022-06-22 20:53:33 +08:00
cheney 8e3e0c5f11 cms decrypt iv
1. 数字信封解封时使用数字信封中的 IV
2. 数字信封解封格式错误时抛出异常 IllegalArgumentException("数字信封解封格式错误")
2022-06-22 17:37:13 +08:00
cheney 6bd2cf1197 Add function "attachedSignC" for customized 2022-06-22 10:07:50 +08:00
cheney b5332438f4 function params type byte[] string 2022-06-22 09:58:51 +08:00
cheney 080c705d72 确认参数 2022-06-21 18:40:51 +08:00
cheney 3cd9e78990 DN reverse bug fix 2022-06-21 18:14:28 +08:00
cheney 15124bf487 DN auto reverse 2022-06-21 17:07:02 +08:00
cheney 9830dea17b 20M 依赖说明 2022-06-21 15:44:41 +08:00
cheney 787be6e294 20M 数字信封支持 2022-06-21 15:39:55 +08:00
cheney 4404f89dd6 p7 证书相关 2022-06-20 16:15:38 +08:00
151 changed files with 23224 additions and 7190 deletions
+3
View File
@@ -11,4 +11,7 @@
/.DS_Store /.DS_Store
src/test/java/com/sunyard/sydapi/sample/*.* src/test/java/com/sunyard/sydapi/sample/*.*
*.p7 *.p7
~$*
/pack/ /pack/
/.logs/
/bin/
+200 -152
View File
@@ -1,195 +1,233 @@
<?xml version="1.0" encoding="UTF-8" ?> <?xml version="1.0" encoding="UTF-8" ?>
<packet extend="base"> <packet extend="base">
<req> <req>
<command> <command>
<hex>6A</hex> <hex>6A</hex>
</command> </command>
<data extend="data"> <data extend="data">
<alg len="1" cn="算法标识"> <alg len="1" cn="算法标识">
<options> <options>
<option cn="RSA2048_AES256_ECB"> <option cn="RSA2048_AES256_ECB">
<hex>0</hex> <hex>0</hex>
</option> </option>
<option cn="SM2_SM4_ECB"> <option cn="SM2_SM4_ECB">
<hex>1</hex> <hex>1</hex>
</option> </option>
<option cn="SM2_SM4_ECB 机构码|02|密钥"> <option cn="SM2_SM4_ECB 机构码|02|密钥">
<hex>2</hex> <hex>2</hex>
</option> </option>
<option cn="PKCS7_SM2_SM4_ECB"> <option cn="PKCS7_SM2_SM4_ECB">
<hex>3</hex> <hex>3</hex>
</option> </option>
</options> <option cn="RSA2048_AES256_CBC">
</alg> <hex>4</hex>
</option>
</options>
</alg>
<pFlag len="1" required="false" cn="P标志"> <pFlag len="1" required="false" cn="P标志">
可选,存在,则固定值为‘P’ 可选,存在,则固定值为‘P’
</pFlag> </pFlag>
<certificateModel len="1" cn="证书模式"> <certificateModel len="1" cn="证书模式">
<options> <options>
<option cn="证书序号"> <option cn="证书序号">
<hex>0</hex> <hex>0</hex>
</option> </option>
<option cn="证书 DN"> <option cn="证书 DN">
<hex>1</hex> <hex>1</hex>
</option> </option>
</options> </options>
</certificateModel> </certificateModel>
<certificateLen len="4" :value="certificateLen()" cn="证书内容长度"> <certificateLen len="4" :value="certificateLen()" cn="证书内容长度">
根据证书模式,需要输入内容项的长度 n 根据证书模式,需要输入内容项的长度 n
</certificateLen> </certificateLen>
<certificateSn :len="strlen()" :if="0 == $packet.data.certificateModel$option" cn="X509 证书序号"> <certificateSn :len="strlen()" :if="0 == $packet.data.certificateModel$option" cn="X509 证书序号">
可选项,只针对“证书模式”为 0时有。 可选项,只针对“证书模式”为 0时有。
</certificateSn> </certificateSn>
<certificateDn :len="strlen()" :if="1 == $packet.data.certificateModel$option" cn="X509 证书的 subject"> <certificateDn :len="strlen()" :if="1 == $packet.data.certificateModel$option" cn="X509 证书的 subject">
可选项,只针对“证书模式”为 1时有。 可选项,只针对“证书模式”为 1时有。
</certificateDn> </certificateDn>
<orgDataLen len="4" :value="dataLen()" :if="3 == $packet.data.alg$option" cn="数据长度"> <orgDataLen len="4" :value="dataLen()" :if="3 == $packet.data.alg$option||4 == $packet.data.alg$option" cn="数据长度">
只针对算法标识为3时传入 只针对算法标识为3、4时传入
</orgDataLen> </orgDataLen>
<orgData :if="3 == $packet.data.alg$option" cn="数据长度"> <orgData :if="3 == $packet.data.alg$option||4== $packet.data.alg$option" cn="数据长度">
只针对算法标识为3时传入 只针对算法标识为3、4时传入
</orgData> </orgData>
<keyType len="1" cn="加密密钥方案"> <keyType len="1" cn="加密密钥方案">
LMK 下加密密钥的方案。 LMK 下加密密钥的方案。
</keyType> </keyType>
<orgCodeLen len="2" :value="orgCodeLen()" :if="hasOrgCode()" cn="机构码长度"> <orgCodeLen len="2" :value="orgCodeLen()" :if="hasOrgCode()" cn="机构码长度">
公钥加密的密钥格式3所需机构码长度,仅当格式3以及'P'存在时存在 公钥加密的密钥格式3所需机构码长度,仅当格式3以及'P'存在时存在
</orgCodeLen> </orgCodeLen>
<orgCode :if="hasOrgCode()" cn="机构码长度"> <orgCode :if="hasOrgCode()" cn="机构码长度">
公钥加密的密钥格式3所需机构码长度,仅当格式3以及'P'存在时存在 公钥加密的密钥格式3所需机构码长度,仅当格式3以及'P'存在时存在
</orgCode> </orgCode>
<tailSep len="1" :if=" null != $packet.data.tail " cn="尾分隔"> <!-- 新增功能-->
可选项。如果显示消息尾域,则该域必须显示。值为 <pSignFlag len="1" required="false" cn="可选字段">
“X’19”。 签名数字信封标识符,存在则为P
<hex>19</hex> </pSignFlag>
</tailSep>
<tail maxLen="32" required="false" cn="尾部"> <signCertificateLen len="4" :value="signCertificateLen()" :if="hasOrgCN()" cn="签名证书DN长度">
可选项。最大长度为 32个字符。 可选项,只针对"可选字段"为P时存在。
</tail> </signCertificateLen>
</data>
</req> <signCertificateDn :len="strlen()" :if="hasOrgCN()" cn="签名证书DN">
可选项,只针对“证书模式”为1时有,只针对"可选字段"为P时存在。
</signCertificateDn>
<signCertificateModel len="1" :if="hasOrgCN()" cn="是否附带公钥信息">
<options>
<option cn="无需附带">
<hex>0</hex>
</option>
<option cn="附带公钥信息">
<hex>1</hex>
</option>
</options>
</signCertificateModel>
<res> <tailSep len="1" :if=" null != $packet.data.tail " cn="尾分隔">
<command> 可选项。如果显示消息尾域,则该域必须显示。值为
<hex>6B</hex> “X’19”。
</command> <hex>19</hex>
<data> </tailSep>
<error len="2" cn="错误码" format="X" :catch="catchError('%s')">
<options>
<option cn="无错误">
<hex>00</hex>
</option>
<option cn="公钥不符合编码规则">
<hex>04</hex>
</option>
<option cn="无效的加密标识">
<hex>06</hex>
</option>
<option cn="无效的附加模式标识">
<hex>07</hex>
</option>
<option cn="密钥奇偶校验错误">
<hex>10</hex>
</option>
<option cn="LMK 错误">
LMK 错误;报告给管理员。
<hex>13</hex>
</option>
<option cn="输入数据错">
<hex>15</hex>
</option>
<option cn="DSP 错误">
DSP 错误;报告给管理员。
<hex>47</hex>
</option>
<option cn="密钥块长度错误">
<hex>76</hex>
</option>
<option cn="输入数据长度错误">
<hex>80</hex>
</option>
</options>
</error>
<keyLen len="4" cn="密钥密文长度"> <tail maxLen="32" required="false" cn="尾部">
公钥加密的密钥密文长度 可选项。最大长度为 32个字符。
</keyLen> </tail>
</data>
<key :len="getKeyLen()" cn="密钥密文"> </req>
公钥加密的密钥密文的 BASE64 编码
</key>
<lmkHead len="1" cn="lmk 头">
如果是 'L' ,lmk 32 个字节长,否则 lmk 64 个字节长。
</lmkHead>
<lmk :len="lmkLen()" cn="对称密钥的密文"> <res>
对称密钥的密文,由 LMK30-31 保护。 <command>
</lmk> <hex>6B</hex>
</command>
<data>
<error len="2" cn="错误码" format="X" :catch="catchError('%s')">
<options>
<option cn="无错误">
<hex>00</hex>
</option>
<option cn="公钥不符合编码规则">
<hex>04</hex>
</option>
<option cn="无效的加密标识">
<hex>06</hex>
</option>
<option cn="无效的附加模式标识">
<hex>07</hex>
</option>
<option cn="密钥奇偶校验错误">
<hex>10</hex>
</option>
<option cn="LMK 错误">
LMK 错误;报告给管理员。
<hex>13</hex>
</option>
<option cn="输入数据错">
<hex>15</hex>
</option>
<option cn="DSP 错误">
DSP 错误;报告给管理员。
<hex>47</hex>
</option>
<option cn="密钥块长度错误">
<hex>76</hex>
</option>
<option cn="输入数据长度错误">
<hex>80</hex>
</option>
</options>
</error>
<keyCheck len="16" cn="密钥校验值"> <keyLen len="4" cn="密钥密文长度">
密钥校验值 公钥加密的密钥密文长度
</keyCheck> </keyLen>
<tailSep len="1" required="false" cn="尾分隔"> <key :len="getKeyLen()" cn="密钥密文">
可选项。如果显示消息尾域,则该域必须显示。值为 “X’19”。 公钥加密的密钥密文的 BASE64 编码
<hex>19</hex> </key>
</tailSep>
<tail maxLen="32" required="false" cn="尾部"> <lmkHead len="1" cn="lmk 头">
可选项。最大长度为 32个字符。 如果是 'L' ,lmk 32 个字节长,否则 lmk 64 个字节长。
</tail> </lmkHead>
</data>
<lmk :len="lmkLen()" cn="对称密钥的密文">
对称密钥的密文,由 LMK30-31 保护。
</lmk>
<keyCheck len="16" cn="密钥校验值">
密钥校验值
</keyCheck>
<tailSep len="1" required="false" cn="尾分隔">
可选项。如果显示消息尾域,则该域必须显示。值为 “X’19”。
<hex>19</hex>
</tailSep>
<tail maxLen="32" required="false" cn="尾部">
可选项。最大长度为 32个字符。
</tail>
</data>
</res> </res>
<script> <script>
function certificateLen(){ function certificateLen(){
var data = $packet.data; var data = $packet.data;
if( 0 == data.certificateModel$option ){ if( 0 == data.certificateModel$option ){
return data.certificateSn.length return data.certificateSn.length
} }
if( 1 == data.certificateModel$option ){ if( 1 == data.certificateModel$option ){
return data.certificateDn.length return data.certificateDn.length
} }
} }
function signCertificateLen(){
var data = $packet.data;
if( 'P' == $packet.data.pSignFlag ){
return data.signCertificateDn.length
}
return null;
}
function getKeyLen() { function getKeyLen() {
return Util.a2i( $final.getSection('data').getSection('keyLen') ) return Util.a2i( $final.getSection('data').getSection('keyLen') );
} }
function lmkLen() { function lmkLen() {
if( Arrays.equals("L".getBytes(), if( Arrays.equals("L".getBytes(),
$final.getSection('data').getSection('lmkHead').getValue() $final.getSection('data').getSection('lmkHead').getValue()
) ){ ) ){
return 64 return 64;
}else{ }else{
return 32 return 32;
} }
} }
function dataLen() { function dataLen() {
return $packet.data.orgData.length() return $packet.data.orgData.length
} }
<![CDATA[ <![CDATA[
function hasOrgCode() { function hasOrgCode() {
if(2 == $packet.data.alg$option && 'P' == $packet.data.pFlag) { if(2 == $packet.data.alg$option && 'P' == $packet.data.pFlag) {
@@ -199,11 +237,21 @@
return false; return false;
} }
function hasOrgCN() {
if(1 == $packet.data.certificateModel$option && 'P' == $packet.data.pSignFlag) {
return true;
}
return false;
}
function orgCodeLen() { function orgCodeLen() {
def len = $packet.data.orgCode.length(); def len = $packet.data.orgCode.length();
def data = new byte[2]; def data = new byte[2];
data[0] = (byte)(len >> 8 & 0xFF) data[0] = (byte)(len >> 8 & 0xFF);
data[1] = (byte)(len & 0xFF) data[1] = (byte)(len & 0xFF);
return data; return data;
} }
+40 -9
View File
@@ -11,6 +11,18 @@
可选,如果输入P代表使用PKCS7_SM2_SM4_ECB模式解密数字信封 可选,如果输入P代表使用PKCS7_SM2_SM4_ECB模式解密数字信封
</pFlag> </pFlag>
<!--新增-->
<pSignFlag len="1" required="false" if="'P' == $packet.data.pFlag" cn="可选字段2">
如果输入P代表进行解封签名数字信封模式,必须当可选字段1为P时才可选
</pSignFlag>
<signCertificateLen len="4" :value="signCertificateLen()" if="'P' == $packet.data.pSignFlag" cn="签名证书内容长度">
根据证书模式,需要输入内容项的长度n,只针对可选字段2为P时存在
</signCertificateLen>
<signCertificateDn :if="hasSign()" cn="签名证书DN">
X509证书的subject可选项,只针对“证书模式”为1时有,只针对可选字段2为P时存在
</signCertificateDn>
<certificateModel len="1" cn="证书模式"> <certificateModel len="1" cn="证书模式">
<options> <options>
<option cn="证书序号"> <option cn="证书序号">
@@ -36,14 +48,16 @@
可选项,只针对“证书模式”为 1时有。 可选项,只针对“证书模式”为 1时有。
</certificateDn> </certificateDn>
<keyLen len="4" :value="keyLen()" cn="密钥密文长度"> <keyLen len="4" :value="keyLen()" cn="密钥密文长度">
公钥加密的密钥密文长度 公钥加密的密钥密文长度
</keyLen> </keyLen>
<key :len="getKeyLen()" cn="密钥密文"> <key :len="getKeyLen()" cn="密钥密文">
公钥加密的密钥密文的 BASE64 编码 公钥加密的密钥密文的 BASE64 编码
</key> </key>
<keyType len="1" cn="加密密钥方案"> <keyType len="1" cn="加密密钥方案">
LMK 下加密密钥的方案。 LMK 下加密密钥的方案。
</keyType> </keyType>
@@ -57,6 +71,8 @@
<tail maxLen="32" required="false" cn="尾部"> <tail maxLen="32" required="false" cn="尾部">
可选项。最大长度为 32个字符。 可选项。最大长度为 32个字符。
</tail> </tail>
</data> </data>
</req> </req>
@@ -126,7 +142,7 @@
对称密钥的密文,由 LMK30-31 保护。 对称密钥的密文,由 LMK30-31 保护。
</lmk> </lmk>
<keyCheck len="16" cn="密钥校验值"> <keyCheck len="32" cn="密钥校验值">
密钥校验值 密钥校验值
</keyCheck> </keyCheck>
@@ -155,15 +171,30 @@
function certificateLen(){ function certificateLen(){
var data = $packet.data; var data = $packet.data;
if( 0 == data.certificateModel$option ){ if( 0 == data.certificateModel$option ){
return data.certificateSn.length() return data.certificateSn.length
} }
if( 1 == data.certificateModel$option ){ if( 1 == data.certificateModel$option ){
return data.certificateDn.length() return data.certificateDn.length
} }
} }
function signCertificateLen(){
var data = $packet.data;
return data.signCertificateDn.length
}
<![CDATA[
function hasSign() {
if(1 == $packet.data.certificateModel$option && 'P' == $packet.data.pSignFlag) {
return true;
}
return false;
}
]]>
function keyLen() { function keyLen() {
return $packet.data.key.length() return $packet.data.key.length;
} }
@@ -175,17 +206,17 @@
if( Arrays.equals("L".getBytes(), if( Arrays.equals("L".getBytes(),
$final.getSection('data').getSection('lmkHead').getValue() $final.getSection('data').getSection('lmkHead').getValue()
) ){ ) ){
return 64 return 64;
}else{ }else{
return 32 return 32;
} }
} }
function orgCodeLen() { function orgCodeLen() {
return Util.a2i( $final.getSection('data').getSection('orgCodeLen') ) return Util.a2i( $final.getSection('data').getSection('orgCodeLen') );
} }
function oDataLen() { function oDataLen() {
return Util.a2i( $final.getSection('data').getSection('oDataLen') ) return Util.a2i( $final.getSection('data').getSection('oDataLen') );
} }
</script> </script>
</packet> </packet>
+191
View File
@@ -0,0 +1,191 @@
<?xml version="1.0" encoding="UTF-8" ?>
<packet extend="base">
<req>
<command>
<hex>6B</hex>
</command>
<data extend="data">
<pFlag len="1" required="false" cn="P标志">
可选,如果输入P代表使用PKCS7_SM2_SM4_ECB模式解密数字信封
</pFlag>
<certificateModel len="1" cn="证书模式">
<options>
<option cn="证书序号">
<hex>0</hex>
</option>
<option cn="证书 DN">
<hex>1</hex>
</option>
</options>
</certificateModel>
<certificateLen len="4" :value="certificateLen()" cn="证书内容长度">
根据证书模式,需要输入内容项的长度 n
</certificateLen>
<certificateSn :len="strlen()" :if="0 == $packet.data.certificateModel$option" cn="X509 证书序号">
可选项,只针对“证书模式”为 0时有。
</certificateSn>
<certificateDn :if="1 == $packet.data.certificateModel$option" cn="X509 证书的 subject">
可选项,只针对“证书模式”为 1时有。
</certificateDn>
<keyLen len="4" :value="keyLen()" cn="密钥密文长度">
公钥加密的密钥密文长度
</keyLen>
<key :len="getKeyLen()" cn="密钥密文">
公钥加密的密钥密文的 BASE64 编码
</key>
<keyType len="1" cn="加密密钥方案">
LMK 下加密密钥的方案。
</keyType>
<tailSep len="1" :if=" null != $packet.data.tail " cn="尾分隔">
可选项。如果显示消息尾域,则该域必须显示。值为
“X’19”。
<hex>19</hex>
</tailSep>
<tail maxLen="32" required="false" cn="尾部">
可选项。最大长度为 32个字符。
</tail>
</data>
</req>
<res>
<command>
<hex>6C</hex>
</command>
<data>
<error len="2" cn="错误码" format="X" :catch="catchError('%s')">
<options>
<option cn="无错误">
<hex>00</hex>
</option>
<option cn="公钥不符合编码规则">
<hex>04</hex>
</option>
<option cn="无效的加密标识">
<hex>06</hex>
</option>
<option cn="无效的附加模式标识">
<hex>07</hex>
</option>
<option cn="密钥奇偶校验错误">
<hex>10</hex>
</option>
<option cn="LMK 错误">
LMK 错误;报告给管理员。
<hex>13</hex>
</option>
<option cn="输入数据错">
<hex>15</hex>
</option>
<option cn="输入的数据格式错误">
<hex>21</hex>
</option>
<option cn="DSP 错误">
DSP 错误;报告给管理员。
<hex>47</hex>
</option>
<option cn="密钥块长度错误">
<hex>76</hex>
</option>
<option cn="输入数据长度错误">
<hex>80</hex>
</option>
</options>
</error>
<oDataLen len="4" cn="明文数据长度">
明文原始数据长度(只针对P存在时,无P时为0)
</oDataLen>
<oData :len="oDataLen()" cn="明文数据">
原始数据(只针对P存在时,无P时不存在)
</oData>
<!--<keyLen len="4" cn="密钥密文长度">-->
<!--公钥加密的密钥密文长度-->
<!--</keyLen>-->
<lmkHead len="1" cn="lmk 头">
如果是 'L' ,lmk 32 个字节长,否则 lmk 64 个字节长。
</lmkHead>
<lmk :len="lmkLen()" cn="对称密钥的密文">
对称密钥的密文,由 LMK30-31 保护。
</lmk>
<keyCheck len="16" cn="密钥校验值">
密钥校验值
</keyCheck>
<orgCodeLen len="4" cn="机构码长度">
公钥加密的密钥格式3所需机构码长度,仅当格式3以及'P'存在时存在
</orgCodeLen>
<orgCode :len="orgCodeLen()" cn="机构码长度">
公钥加密的密钥格式3所需机构码长度,仅当格式3以及'P'存在时存在
</orgCode>
<tailSep len="1" required="false" cn="尾分隔">
可选项。如果显示消息尾域,则该域必须显示。值为 “X’19”。
<hex>19</hex>
</tailSep>
<tail maxLen="32" required="false" cn="尾部">
可选项。最大长度为 32个字符。
</tail>
</data>
</res>
<script>
function certificateLen(){
var data = $packet.data;
if( 0 == data.certificateModel$option ){
return data.certificateSn.length
}
if( 1 == data.certificateModel$option ){
return data.certificateDn.length
}
}
function keyLen() {
return $packet.data.key.length
}
function getKeyLen() {
return Util.a2i( $final.getSection('data').getSection('keyLen') )
}
function lmkLen() {
if( Arrays.equals("L".getBytes(),
$final.getSection('data').getSection('lmkHead').getValue()
) ){
return 64
}else{
return 32
}
}
function orgCodeLen() {
return Util.a2i( $final.getSection('data').getSection('orgCodeLen') )
}
function oDataLen() {
return Util.a2i( $final.getSection('data').getSection('oDataLen') )
}
</script>
</packet>
+3
View File
@@ -6,6 +6,9 @@
<hex>72</hex> <hex>72</hex>
</command> </command>
<data extend="data"> <data extend="data">
<pFlag len="1" required="false" cn="RSA标志符">
可选,存在,则固定值为‘R’
</pFlag>
<publicKeyLength len="4" :value="publicKeyLen()" cn="公钥长度"> <publicKeyLength len="4" :value="publicKeyLen()" cn="公钥长度">
公钥长度 公钥长度
+12 -1
View File
@@ -75,7 +75,7 @@
</error> </error>
<hash len="32" :if="0 == $packet.data.packSn$option || 3 == $packet.data.packSn$option" cn="hash"></hash> <hash :len="hashLen()" :if="0 == $packet.data.packSn$option || 3 == $packet.data.packSn$option" cn="hash"></hash>
<filterDataLen len="4" :value="filterDataLength()" :if="2 == $packet.data.packSn$option || 1 == $packet.data.packSn$option" cn="过渡数据长度"> <filterDataLen len="4" :value="filterDataLength()" :if="2 == $packet.data.packSn$option || 1 == $packet.data.packSn$option" cn="过渡数据长度">
只对“消息块号”为 2、1 时有效 只对“消息块号”为 2、1 时有效
@@ -108,6 +108,17 @@ function filterDataLength(){
var data = $packet.data; var data = $packet.data;
return data.filterData.length; return data.filterData.length;
} }
function hashLen(){
if (0 == $packet.data.hashType$option){
return 20;
}
if (1== $packet.data.hashType$option){
return 32;
}
if (2 == $packet.data.hashType$option){
return 16;
}
}
function getFilterDataLen() { function getFilterDataLen() {
return Util.a2i( $final.getSection('data').getSection('filterDataLen') ) return Util.a2i( $final.getSection('data').getSection('filterDataLen') )
+116 -96
View File
@@ -1,117 +1,137 @@
<?xml version="1.0" encoding="UTF-8" ?> <?xml version="1.0" encoding="UTF-8" ?>
<packet extend="base"> <packet extend="base">
<req> <req>
<command> <command>
<bin>8003</bin> <bin>8003</bin>
</command> </command>
<data extend="data"> <data extend="data">
<signatureDataType len="1" cn="获取公私钥标记位">
<options>
<option cn="索引方式">
<bin>00</bin>
</option>
<option cn="DN 方式">
<bin>01</bin>
</option>
</options>
</signatureDataType>
<DN cn="DN 或 DN索引"> <algFlag len="1" :value="algFlag()" cn="算法标记">
若上面的标志为1,则此域为证书DN,若为0,则此域为两个字节的证书索引; </algFlag>
</DN>
<dataLength len="2" :value="dataLen()" cn="待签名数据长度"> <signatureDataType len="1" cn="获取公私钥标记位">
待签名数据长度 <options>
</dataLength> <option cn="索引方式">
<bin>00</bin>
</option>
<option cn="DN 方式">
<bin>01</bin>
</option>
</options>
</signatureDataType>
<signData cn="待签名数据"> <DN cn="DN 或 DN索引">
待签名数据 若上面的标志为1,则此域为证书DN,若为0,则此域为两个字节的证书索引;
</signData> </DN>
</data> <hashFlag len="1" :if="null != $packet.data.hash" :value="flag()" cn="外部 hash 标记">
</hashFlag>
<hash len="32" :if="null != $packet.data.hash" cn="外部 hash">
</hash>
<dataLength len="2" :value="dataLen()" :if="null == $packet.data.hash" cn="待签名数据长度">
待签名数据长度
</dataLength>
<signData cn="待签名数据" :if="null == $packet.data.hash">
待签名数据
</signData>
</data>
</req> </req>
<res> <res>
<command> <command>
<bin>8004</bin> <bin>8004</bin>
</command> </command>
<data> <data>
<error len="2" cn="错误码" format="X" :catch="catchError('%s')"> <error len="2" cn="错误码" format="X" :catch="catchError('%s')">
<options> <options>
<option cn="无错误"> <option cn="无错误">
<hex>00</hex> <hex>00</hex>
</option> </option>
<option cn="无效的私钥类型"> <option cn="无效的私钥类型">
<hex>03</hex> <hex>03</hex>
</option> </option>
<option cn="无效私钥标记"> <option cn="无效私钥标记">
<hex>04</hex> <hex>04</hex>
</option> </option>
<option cn="无效的哈希标识"> <option cn="无效的哈希标识">
<hex>05</hex> <hex>05</hex>
</option> </option>
<option cn="无效的签名标识"> <option cn="无效的签名标识">
<hex>06</hex> <hex>06</hex>
</option> </option>
<option cn="无效的附加标识"> <option cn="无效的附加标识">
<hex>07</hex> <hex>07</hex>
</option> </option>
<option cn="LMK 错误"> <option cn="LMK 错误">
LMK 错误;报告给管理员。 LMK 错误;报告给管理员。
<hex>13</hex> <hex>13</hex>
</option> </option>
<option cn="输入数据错"> <option cn="输入数据错">
<hex>15</hex> <hex>15</hex>
</option> </option>
<option cn="DSP 错误"> <option cn="DSP 错误">
DSP 错误;报告给管理员。 DSP 错误;报告给管理员。
<hex>47</hex> <hex>47</hex>
</option> </option>
<option cn="私钥错误"> <option cn="私钥错误">
私钥错误;报告给管理员。 私钥错误;报告给管理员。
<hex>49</hex> <hex>49</hex>
</option> </option>
<option cn="无效摘要信息语法(仅仅无哈希模式)"> <option cn="无效摘要信息语法(仅仅无哈希模式)">
<hex>74</hex> <hex>74</hex>
</option> </option>
<option cn="公钥长度错误"> <option cn="公钥长度错误">
<hex>76</hex> <hex>76</hex>
</option> </option>
<option cn="私钥长度错误"> <option cn="私钥长度错误">
<hex>78</hex> <hex>78</hex>
</option> </option>
<option cn="输入数据长度错误"> <option cn="输入数据长度错误">
<hex>80</hex> <hex>80</hex>
</option> </option>
</options> </options>
</error> </error>
<signatureLen len="2" cn="签名的字节长度"> <signatureLen len="2" cn="签名的字节长度">
签名的字节长度 签名的字节长度
</signatureLen> </signatureLen>
<signature :len="signatureLen()" cn="签名的 DER 编码"> <signature :len="signatureLen()" cn="签名的 DER 编码">
签名的 DER 编码 签名的 DER 编码
</signature> </signature>
<tailSep len="1" required="false" cn="尾分隔"> <tailSep len="1" required="false" cn="尾分隔">
可选项。如果显示消息尾域,则该域必须显示。值为 “X’19”。 可选项。如果显示消息尾域,则该域必须显示。值为 “X’19”。
<hex>19</hex> <hex>19</hex>
</tailSep> </tailSep>
<tail maxLen="32" required="false" cn="尾部"> <tail maxLen="32" required="false" cn="尾部">
可选项。最大长度为 32个字符。 可选项。最大长度为 32个字符。
</tail> </tail>
</data> </data>
</res> </res>
<script type="javascript"><![CDATA[ <script type="javascript"><![CDATA[
function algFlag(){
if( 'P' == $packet.data.rFlag ) {
return ''
} else {
$packet.data.rFlag
}
}
function flag(){
return $packet.data.rFlag;
}
function dataLen(){ function dataLen(){
def len = $packet.data.signData.length def len = $packet.data.signData.length
def ret = new byte[2] def ret = new byte[2]
+127 -107
View File
@@ -1,132 +1,152 @@
<?xml version="1.0" encoding="UTF-8" ?> <?xml version="1.0" encoding="UTF-8" ?>
<packet extend="base"> <packet extend="base">
<req> <req>
<command> <command>
<bin>8004</bin> <bin>8004</bin>
</command> </command>
<data extend="data"> <data extend="data">
<signatureDataType len="1" cn="获取公私钥标记位">
<options>
<option cn="索引方式">
<bin>00</bin>
</option>
<option cn="DN 方式">
<bin>01</bin>
</option>
<option cn="通过机构号获取">
<bin>02</bin>
</option>
</options>
</signatureDataType>
<DN :if="useDN()" cn="DN 或 DN索引"> <algFlag len="1" :value="algFlag()" cn="算法标记">
若上面的标志为1,则此域为证书DN,若为0,则此域为两个字节的证书索引;若为2,该域不存在 </algFlag>
</DN>
<organizationNumLen len="2" :if="useOrganization()" :value="bNumberLength()" cn="机构号长度"> <signatureDataType len="1" cn="获取公私钥标记位">
标志为2 时存在 <options>
</organizationNumLen> <option cn="索引方式">
<bin>00</bin>
</option>
<option cn="DN 方式">
<bin>01</bin>
</option>
<option cn="通过机构号获取">
<bin>02</bin>
</option>
</options>
</signatureDataType>
<organizationNum :if="useOrganization()" cn="机构号内容"> <DN :if="useDN()" cn="DN 或 DN索引">
标志为2 时存在 若上面的标志为1,则此域为证书DN,若为0,则此域为两个字节的证书索引;若为2,该域不存在
</organizationNum> </DN>
<organizationNumLen len="2" :if="useOrganization()" :value="bNumberLength()" cn="机构号长度">
标志为2 时存在
</organizationNumLen>
<dataLength len="2" :value="dataLen()" cn="待签名数据长度"> <organizationNum :if="useOrganization()" cn="机构号内容">
待签名数据长度 标志为2 时存在
</dataLength> </organizationNum>
<odata cn="待签名数据"> <hashFlag len="1" :if="null != $packet.data.hash" :value="flag()" cn="外部 hash 标记">
待签名数据 </hashFlag>
</odata>
<signatureLen len="2" :value="signLen()" cn="签名的字节长度"> <hash len="32" :if="null != $packet.data.hash" cn="外部 hash">
签名的字节长度 </hash>
</signatureLen>
<signature :len="signatureLen()" cn="已签名数据"> <dataLength len="2" :if="null == $packet.data.hash" :value="dataLen()" cn="待签名数据长度">
待验签的已签名数据,若为RSA签名则为相应长度的签名数据,若为SM2签名,则前半部分为R.后面半部分为S; 待签名数据长度
</signature> </dataLength>
<returnSign len="2" cn="返回证书信息标志"> <odata cn="待签名数据" :if="null == $packet.data.hash">
<options> 待签名数据
<option cn="不返回"> </odata>
<bin>0000</bin>
</option> <signatureLen len="2" :value="signLen()" cn="签名的字节长度">
<option cn="返回"> 签名的字节长度
<bin>0001</bin> </signatureLen>
</option>
</options> <signature :len="signatureLen()" cn="已签名数据">
</returnSign> 待验签的已签名数据,若为RSA签名则为相应长度的签名数据,若为SM2签名,则前半部分为R.后面半部分为S;
</data> </signature>
<returnSign len="2" cn="返回证书信息标志">
<options>
<option cn="不返回">
<bin>0000</bin>
</option>
<option cn="返回">
<bin>0001</bin>
</option>
</options>
</returnSign>
</data>
</req> </req>
<res> <res>
<command> <command>
<bin>8005</bin> <bin>8005</bin>
</command> </command>
<data> <data>
<error len="2" cn="错误码" format="X" :catch="catchError('%s')"> <error len="2" cn="错误码" format="X" :catch="catchError('%s')">
<options> <options>
<option cn="无错误"> <option cn="无错误">
<hex>00</hex> <hex>00</hex>
</option> </option>
<option cn="公钥不符合编码规则"> <option cn="公钥不符合编码规则">
<hex>04</hex> <hex>04</hex>
</option> </option>
<option cn="无效的加密标识"> <option cn="无效的加密标识">
<hex>06</hex> <hex>06</hex>
</option> </option>
<option cn="无效的附加模式标识"> <option cn="无效的附加模式标识">
<hex>07</hex> <hex>07</hex>
</option> </option>
<option cn="密钥奇偶校验错误"> <option cn="密钥奇偶校验错误">
<hex>10</hex> <hex>10</hex>
</option> </option>
<option cn="LMK 错误"> <option cn="LMK 错误">
LMK 错误;报告给管理员。 LMK 错误;报告给管理员。
<hex>13</hex> <hex>13</hex>
</option> </option>
<option cn="输入数据错"> <option cn="输入数据错">
<hex>15</hex> <hex>15</hex>
</option> </option>
<option cn="DSP 错误"> <option cn="DSP 错误">
DSP 错误;报告给管理员。 DSP 错误;报告给管理员。
<hex>47</hex> <hex>47</hex>
</option> </option>
<option cn="私钥错误"> <option cn="私钥错误">
私钥错误;报告给管理员。 私钥错误;报告给管理员。
<hex>49</hex> <hex>49</hex>
</option> </option>
<option cn="密钥块长度错误"> <option cn="密钥块长度错误">
<hex>76</hex> <hex>76</hex>
</option> </option>
<option cn="输入数据长度错误"> <option cn="输入数据长度错误">
<hex>80</hex> <hex>80</hex>
</option> </option>
</options> </options>
</error> </error>
<infoLen len="2" cn="信息长度" :if="0 != $packet.data.returnSign$option"> <infoLen len="2" cn="信息长度" :if="0 != $packet.data.returnSign$option">
信息长度 信息长度
</infoLen> </infoLen>
<info :len="getInfoLen()" cn="信息" :if="0 != $packet.data.returnSign$option"> <info :len="getInfoLen()" cn="信息" :if="0 != $packet.data.returnSign$option">
若发送报文返回证书信息标志位为0,则返回一段垃圾数据,可以不用管 若发送报文返回证书信息标志位为0,则返回一段垃圾数据,可以不用管
若发送报文返回证书信息标志位为1,则返回 CERT_INFO 结构的证书数据 若发送报文返回证书信息标志位为1,则返回 CERT_INFO 结构的证书数据
</info> </info>
</data> </data>
</res> </res>
<script><![CDATA[ <script><![CDATA[
function dataLen(){ function algFlag(){
if( 'P' == $packet.data.rFlag ) {
return ''
} else {
$packet.data.rFlag
}
}
function flag(){
return $packet.data.rFlag;
}
function dataLen(){
def len = $packet.data.odata.length def len = $packet.data.odata.length
def ret = new byte[2] def ret = new byte[2]
ret[0] = (byte)(len >> 8 & 0xFF) ret[0] = (byte)(len >> 8 & 0xFF)
+6 -3
View File
@@ -6,6 +6,9 @@
<bin>8005</bin> <bin>8005</bin>
</command> </command>
<data extend="data"> <data extend="data">
<rFlag len="1" required="false" cn="RSA算法标志">
可选,存在,则固定值为‘P’
</rFlag>
<DN len="256" cn="证书 DN"> <DN len="256" cn="证书 DN">
X509证书序号 X509证书序号
@@ -13,13 +16,13 @@
<hashFlag cn="是否为 hash 模式" len="1" required="false"></hashFlag> <hashFlag cn="是否为 hash 模式" len="1" required="false"></hashFlag>
<hash cn="hash 值" :if="'P' == $packet.data.hashFlag"></hash> <hash cn="hash 值" :if="null != $packet.data.hashFlag"></hash>
<dataLen :if="'P' != $packet.data.hashFlag" len="2" format="X" :value="dataLength()" cn="数据长度"> <dataLen :if="null == $packet.data.hashFlag" len="2" format="X" :value="dataLength()" cn="数据长度">
数据长度 数据长度
</dataLen> </dataLen>
<infoData :if="'P' != $packet.data.hashFlag" cn="数据"> <infoData :if="null == $packet.data.hashFlag" cn="数据">
数据 数据
</infoData> </infoData>
+6 -4
View File
@@ -6,16 +6,18 @@
<bin>8006</bin> <bin>8006</bin>
</command> </command>
<data extend="data"> <data extend="data">
<rFlag len="1" required="false" cn="RSA算法标志">
可选,存在,则固定值为‘P’
</rFlag>
<hashFlag cn="是否为 hash 模式" len="1" required="false"></hashFlag> <hashFlag cn="是否为 hash 模式" len="1" required="false"></hashFlag>
<hash cn="hash 值" :if="'P' == $packet.data.hashFlag"></hash> <hash cn="hash 值" :if="null != $packet.data.hashFlag"></hash>
<originLen :if="'P' != $packet.data.hashFlag" len="2" :value="orginLength()" cn="待签名数据长度"> <originLen :if=" null == $packet.data.hashFlag" len="2" :value="orginLength()" cn="待签名数据长度">
待签名数据长度 待签名数据长度
</originLen> </originLen>
<originData :if="'P' != $packet.data.hashFlag" cn="待签名数据"> <originData :if="null == $packet.data.hashFlag" cn="待签名数据">
待签名数据 待签名数据
</originData> </originData>
+4 -16
View File
@@ -7,18 +7,9 @@
</command> </command>
<data extend="data"> <data extend="data">
<dataFlag len="1" cn="数据包标志"> <dataFlag len="4" cn="数据包标志">
<options> 0:起始包
<option cn="起始包"> 其他:传入上一个包返回的数据标志
<bin>00</bin>
</option>
<option cn="中间包">
<bin>01</bin>
</option>
<option cn="结束包">
<bin>02</bin>
</option>
</options>
</dataFlag> </dataFlag>
<sqlite3 cn="Sqlite3 查询条件"> <sqlite3 cn="Sqlite3 查询条件">
@@ -75,10 +66,7 @@
</error> </error>
<dataFlag len="4" cn="数据包标志"> <dataFlag len="4" cn="数据包标志">
0:起始包 已返回证书个数
1:中间包
2:结束包
(可能hi因为字节对此,后三字节为垃圾值)
</dataFlag> </dataFlag>
<certAllNum len="4" cn="证书总数"> <certAllNum len="4" cn="证书总数">
+64
View File
@@ -0,0 +1,64 @@
<?xml version="1.0" encoding="UTF-8" ?>
<packet extend="base">
<req>
<command>
<bin>8011</bin>
</command>
<data extend="data">
<certDn cn="证书dn">
</certDn>
</data>
</req>
<res>
<command>
<bin>8012</bin>
</command>
<data>
<error len="2" cn="错误码" format="X" :catch="catchError('%s')">
<options>
<option cn="无错误">
<hex>00</hex>
</option>
<option cn="公钥不符合编码规则">
<hex>04</hex>
</option>
<option cn="无效的加密标识">
<hex>06</hex>
</option>
<option cn="无效的附加模式标识">
<hex>07</hex>
</option>
<option cn="密钥奇偶校验错误">
<hex>10</hex>
</option>
<option cn="LMK 错误">
LMK 错误;报告给管理员。
<hex>13</hex>
</option>
<option cn="输入数据错">
<hex>15</hex>
</option>
<option cn="DSP 错误">
DSP 错误;报告给管理员。
<hex>47</hex>
</option>
<option cn="私钥错误">
私钥错误;报告给管理员。
<hex>49</hex>
</option>
<option cn="密钥块长度错误">
<hex>76</hex>
</option>
<option cn="输入数据长度错误">
<hex>80</hex>
</option>
</options>
</error>
</data>
</res>
<script> </script>
</packet>
+3
View File
@@ -5,6 +5,9 @@
<bin>8018</bin> <bin>8018</bin>
</command> </command>
<data extend="data"> <data extend="data">
<rFlag len="1" required="false" cn="RSA标志">
可选,存在,则固定值为‘P’
</rFlag>
<DN len="256" cn="证书 DN"> <DN len="256" cn="证书 DN">
X509证书序号 X509证书序号
+66
View File
@@ -0,0 +1,66 @@
<?xml version="1.0" encoding="UTF-8" ?>
<packet extend="base">
<req>
<command>
<hex>GN</hex>
</command>
<data extend="data">
<Esign len="1" cn="E值">
<text>1</text>
</Esign>
<keyLen len="4" cn="密钥长度">
<text>2048</text>
</keyLen>
<sk len="27" cn="私钥索引"></sk>
<startTime len="8" cn="启用时间"></startTime>
<endTime len="8" cn="到期时间"></endTime>
</data>
</req>
<res>
<command>
<hex>QO</hex>
</command>
<data>
<error len="2" cn="错误码" format="X" :catch="catchError('%s')">
<options>
<option cn="无错误">
<hex>00</hex>
</option>
<option cn="无效的哈希标识">
<hex>05</hex>
</option>
<option cn="输入数据错">
<hex>15</hex>
</option>
<option cn="DSP 错误">
DSP 错误;报告给管理员。
<hex>47</hex>
</option>
<option cn="输入数据长度错误">
<hex>80</hex>
</option>
</options>
</error>
<pk len="270" cn="公钥"></pk>
<sk len="2824" cn="私钥"></sk>
</data>
</res>
<script> </script>
</packet>
+2 -2
View File
@@ -50,8 +50,8 @@
</options> </options>
</error> </error>
<pk len="32" cn="公钥"></pk> <pk len="128" cn="公钥"></pk>
<sk len="160" cn="私钥"></sk> <sk len="64" cn="私钥"></sk>
</data> </data>
+21
View File
@@ -1,3 +1,24 @@
# sydapi4j # sydapi4j
加密机 java 接口,基于 jna。 加密机 java 接口,基于 jna。
## 启动 Slave
在作为负载机的 Slave 机器上进行配置,主要有两种方式:
方法一:配置 jmeter.properties 文件
编辑 $JMETER_HOME/bin/jmeter.properties 文件,确认或取消注释以下配置:
```
server.rmi.ssl.disable=true # 禁用SSL,简化内网配置
server.rmi.localport=1099 # 固定RMI端口,方便防火墙放行
java.rmi.server.hostname=Slave_IP # 绑定本机网卡IP,避免多网卡问题
```
配置完成后,在 Slave 的 bin 目录下启动服务:
Windows: 双击 jmeter-server.bat
Linux/Mac: 运行 ./jmeter-server
./jmeter-server -Djava.rmi.server.hostname=172.1.41.24 -Dserver.rmi.localport=1099
+30
View File
@@ -0,0 +1,30 @@
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0
http://maven.apache.org/xsd/assembly-1.1.0.xsd">
<id>assembled-test-jar</id>
<formats>
<format>jar</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<!-- 打包主代码 -->
<fileSet>
<directory>${project.build.outputDirectory}</directory>
<outputDirectory>/</outputDirectory>
</fileSet>
<!-- 打包测试代码 -->
<fileSet>
<directory>${project.build.testOutputDirectory}</directory>
<outputDirectory>/</outputDirectory>
</fileSet>
</fileSets>
<!-- 打包依赖的Jar包 -->
<dependencySets>
<dependencySet>
<outputDirectory>/</outputDirectory>
<unpack>true</unpack>
<scope>runtime</scope>
</dependencySet>
</dependencySets>
</assembly>
+6
View File
@@ -0,0 +1,6 @@
{
"ip1": "172.1.41.3",
"ip2": "172.1.41.139",
"port": 8889,
"dn": "C=cn,O=CFCA OCA1 SM2,OU=Local RA OCA1,OU=Units,CN=041@N91330108762038374D@杭州信雅达科技有限公司@00000002"
}
-1
View File
@@ -1 +0,0 @@
~$*
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large Load Diff
+39 -22
View File
@@ -1,16 +1,16 @@
{ {
"vars": { "vars": {
"version": "%project.git_branch_version%", "version": "%project.git_branch_version%",
"out_path": "./pack", "out_path": "./pack"
"target_f1": "./target/sydapi4j-jar-with-dependencies.jar",
"target_t1": "%out_path%/sydapi4j-jar-with-dependencies.jar",
"target_f2": "./target/sydapi4j.jar",
"target_t2": "%out_path%/sydapi4j.jar"
}, },
"clear": [ "clear": [
{ {
"func": "rmdir", "func": "rm",
"path": "%out_path%" "path": "%out_path%"
},
{
"func": "rm",
"path": "./logs"
} }
], ],
"init": [ "init": [
@@ -31,19 +31,15 @@
"path": "%out_path%/doc" "path": "%out_path%/doc"
} }
], ],
"dependencies": [{
"func" : "pom",
"xml" : "%out_path%/jar"
}, {
"shell" : "mvn dependency:copy-dependencies -DincludeScope=runtime -DoutputDirectory=%out_path%/jar/dependences",
"check": "BUILD SUCCESS"
}],
"gen" : [{ "gen" : [{
"shell" : "dproto" "cmd" : "dproto"
}], }],
"build": [ "build": [
{ {
"cmd" : "init" "cmd": "clear"
},
{
"cmd": "init"
}, },
{ {
"shell": "mvn package -DskipTests", "shell": "mvn package -DskipTests",
@@ -51,22 +47,43 @@
}, },
{ {
"func": "cp", "func": "cp",
"from": "%target_f1%", "from": "./target/sydapi4j.jar",
"to": "%target_t1%" "to": "%out_path%/jar/sydapi4j.jar"
}, },
{ {
"func": "cp", "func": "cp",
"from": "%target_f2%", "from": "./target/sydapi4j-jar-with-dependencies.jar",
"to": "%target_t2%" "to": "%out_path%/jar/sydapi4j-jar-with-dependencies.jar"
},
{
"shell" : "mvn dependency:copy-dependencies -DincludeScope=runtime -DoutputDirectory=%out_path%/jar/dependences",
"check": "BUILD SUCCESS"
},
{
"func": "cp",
"from": "./doc",
"to": "%out_path%/doc"
},
{
"func": "cp",
"from": "./src/test/java/sample",
"to": "%out_path%/sample"
},
{
"func": "cp",
"from": "./˵Ã÷.txt",
"to": "%out_path%/˵Ã÷.txt"
}, },
{ {
"func": "zip", "func": "zip",
"from": "%out_path%", "from": "%out_path%/*",
"to": "%out_path%/sydapi-%version%.zip" "to": "%out_path%/sydapi-%version%.%project.git_commit_hash%.zip",
"vc" : "10M"
}, },
{ {
"func": "open", "func": "open",
"path": "%out_path%" "path": "%out_path%/"
} }
] ]
+148 -113
View File
@@ -4,7 +4,7 @@
<groupId>com.sunyard</groupId> <groupId>com.sunyard</groupId>
<artifactId>sydapi4j</artifactId> <artifactId>sydapi4j</artifactId>
<version>1.15.20250701</version> <version>2.01</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>sydapi4j</name> <name>sydapi4j</name>
@@ -14,8 +14,8 @@
<vertx>3.4.2</vertx> <vertx>3.4.2</vertx>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.encoding>UTF-8</maven.compiler.encoding> <maven.compiler.encoding>UTF-8</maven.compiler.encoding>
<maven.compiler.source>1.6</maven.compiler.source> <maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.6</maven.compiler.target> <maven.compiler.target>1.8</maven.compiler.target>
</properties> </properties>
<dependencies> <dependencies>
@@ -27,78 +27,77 @@
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.logging.log4j</groupId> <groupId>com.github.houbb</groupId>
<artifactId>log4j-api</artifactId> <artifactId>junitperf</artifactId>
<version>2.17.0</version> <version>1.0.3</version>
<scope>test</scope>
</dependency> </dependency>
<!-- JMeter Java Sampler 核心依赖 -->
<dependency> <dependency>
<groupId>org.apache.logging.log4j</groupId> <groupId>org.apache.jmeter</groupId>
<artifactId>log4j-core</artifactId> <artifactId>ApacheJMeter_java</artifactId>
<version>2.17.0</version> <version>5.4.3</version>
<scope>provided</scope>
</dependency> </dependency>
<!-- &lt;!&ndash; https://mvnrepository.com/artifact/org.apache.commons/commons-pool2 &ndash;&gt;-->
<!-- <dependency>-->
<!-- <groupId>org.apache.commons</groupId>-->
<!-- <artifactId>commons-pool2</artifactId>-->
<!-- <version>2.11.1</version>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.jetbrains.kotlin</groupId>-->
<!-- <artifactId>kotlin-test</artifactId>-->
<!-- <version>${kotlin.version}</version>-->
<!-- <scope>test</scope>-->
<!-- </dependency>-->
<!-- &lt;!&ndash; https://mvnrepository.com/artifact/dom4j/dom4j &ndash;&gt;-->
<!-- <dependency>-->
<!-- <groupId>dom4j</groupId>-->
<!-- <artifactId>dom4j</artifactId>-->
<!-- <version>1.6.1</version>-->
<!-- </dependency>-->
<!-- &lt;!&ndash; https://mvnrepository.com/artifact/com.alibaba/fastjson &ndash;&gt;-->
<!-- <dependency>-->
<!-- <groupId>com.alibaba</groupId>-->
<!-- <artifactId>fastjson</artifactId>-->
<!-- <version>1.2.80</version>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.jetbrains.kotlin</groupId>-->
<!-- <artifactId>kotlin-stdlib-jdk8</artifactId>-->
<!-- <version>${kotlin.version}</version>-->
<!-- </dependency>-->
<!--<dependency>-->
<!--<groupId>com.sunyard</groupId>-->
<!--<artifactId>Converter</artifactId>-->
<!--<version>[1.0.201807251700, 1.1-SNAPSHOT)</version>-->
<!--</dependency>-->
<dependency> <dependency>
<groupId>com.sunyard</groupId> <groupId>com.sunyard</groupId>
<artifactId>proto</artifactId> <artifactId>proto</artifactId>
<version>1.0-20220905</version> <version>1.1.20221215</version>
<exclusions>
<exclusion>
<groupId>cn.hutool</groupId>
<artifactId>hutool-core</artifactId>
</exclusion>
<exclusion>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-all</artifactId>
</exclusion>
</exclusions>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.codehaus.groovy</groupId> <groupId>com.google.zxing</groupId>
<artifactId>groovy</artifactId> <artifactId>core</artifactId>
<version>2.4.15</version> <version>3.5.0</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.5.0</version>
</dependency> </dependency>
<!--<dependency>-->
<!--<groupId>club.fullstack</groupId>-->
<!--<artifactId>serialize</artifactId>-->
<!--<version>[1.0.201806051035, 1.1.SNAPSHOT)</version>-->
<!--</dependency>-->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
<version>1.68</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.github.wvengen/proguard-maven-plugin --> <dependency>
<!-- https://mvnrepository.com/artifact/com.github.wvengen/proguard-maven-plugin --> <groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.68</version>
</dependency>
<!-- https://mvnrepository.com/artifact/cn.hutool/hutool-all -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.38</version>
</dependency>
<dependency>
<groupId>org.snmp4j</groupId>
<artifactId>snmp4j</artifactId>
<version>2.8.18</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.13.1</version>
</dependency>
</dependencies> </dependencies>
<build> <build>
<finalName>sydapi4j</finalName> <finalName>sydapi4j</finalName>
@@ -115,6 +114,7 @@
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId> <artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version> <version>3.3</version>
<!-- <version>3.8.1</version>-->
<executions> <executions>
<execution> <execution>
<id>compile</id> <id>compile</id>
@@ -132,8 +132,8 @@
</execution> </execution>
</executions> </executions>
<configuration> <configuration>
<source>1.6</source> <source>8</source>
<target>1.6</target> <target>8</target>
<compilerId>groovy-eclipse-compiler</compilerId> <compilerId>groovy-eclipse-compiler</compilerId>
<verbose>true</verbose> <verbose>true</verbose>
<fork>true</fork> <fork>true</fork>
@@ -152,65 +152,68 @@
</dependencies> </dependencies>
</plugin> </plugin>
<!-- <plugin>--> <plugin>
<!-- <groupId>org.apache.maven.plugins</groupId>--> <groupId>org.apache.maven.plugins</groupId>
<!-- <artifactId>maven-javadoc-plugin</artifactId>--> <artifactId>maven-javadoc-plugin</artifactId>
<!-- <version>3.1.1</version>--> <version>3.1.1</version>
<!-- <configuration>--> <configuration>
<!-- <reportOutputDirectory>./public/</reportOutputDirectory>--> <reportOutputDirectory>./public/</reportOutputDirectory>
<!-- <destDir>html</destDir>--> <destDir>html</destDir>
<!-- <additionalOptions>html5</additionalOptions>--> <additionalOptions>html5</additionalOptions>
<!-- <excludePackageNames>com.sunyard.SydApi:com.sunyard.inf.*:com.sunyard.cert.*</excludePackageNames>--> <excludePackageNames>com.sunyard.SydApi:com.sunyard.inf.*:com.sunyard.cert.*</excludePackageNames>
<!-- </configuration>--> </configuration>
<!-- </plugin>--> </plugin>
<!-- <plugin>--> <plugin>
<!-- <groupId>org.apache.maven.plugins</groupId>--> <groupId>org.apache.maven.plugins</groupId>
<!-- <artifactId>maven-source-plugin</artifactId>--> <artifactId>maven-source-plugin</artifactId>
<!-- <version>2.4</version>--> <version>2.4</version>
<!-- &lt;!&ndash; 进行package命令时就可以将源码同时进行打包 &ndash;&gt;--> <!-- 进行package命令时就可以将源码同时进行打包 -->
<!-- &lt;!&ndash; 所以我们需要绑定source插件到我们default生命周期的package阶段 &ndash;&gt;--> <!-- 所以我们需要绑定source插件到我们default生命周期的package阶段 -->
<!-- <executions>--> <executions>
<!-- <execution>--> <execution>
<!-- &lt;!&ndash; 定义一个阶段,这个阶段是package &ndash;&gt;--> <!-- 定义一个阶段,这个阶段是package -->
<!-- <phase>package</phase>--> <phase>package</phase>
<!-- <goals>--> <goals>
<!-- <goal>jar-no-fork</goal>--> <goal>jar-no-fork</goal>
<!-- </goals>--> </goals>
<!-- </execution>--> </execution>
<!-- </executions>--> </executions>
<!-- </plugin>--> </plugin>
<!-- <plugin>--> <plugin>
<!-- <groupId>org.apache.maven.plugins</groupId>--> <groupId>org.apache.maven.plugins</groupId>
<!-- <artifactId>maven-dependency-plugin</artifactId>--> <artifactId>maven-dependency-plugin</artifactId>
<!-- <configuration>--> <configuration>
<!-- <includeScope>runtime</includeScope>--> <includeScope>runtime</includeScope>
<!-- </configuration>--> </configuration>
<!-- <executions>--> <executions>
<!-- <execution>--> <execution>
<!-- <id>copy</id>--> <id>copy</id>
<!-- <phase>package</phase>--> <phase>package</phase>
<!-- <goals>--> <goals>
<!-- <goal>copy-dependencies</goal>--> <goal>copy-dependencies</goal>
<!-- </goals>--> </goals>
<!-- <configuration>--> <configuration>
<!-- <outputDirectory>--> <outputDirectory>
<!-- ${project.build.directory}/lib--> ${project.build.directory}/lib
<!-- </outputDirectory>--> </outputDirectory>
<!-- </configuration>--> </configuration>
<!-- </execution>--> </execution>
<!-- </executions>--> </executions>
<!-- </plugin>--> </plugin>
<plugin> <plugin>
<artifactId>maven-assembly-plugin</artifactId> <artifactId>maven-assembly-plugin</artifactId>
<configuration> <configuration>
<descriptors>
<descriptor>assembly.xml</descriptor>
</descriptors>
<archive> <archive>
<manifest> <manifest>
<mainClass>racal.sunyard.main.Version</mainClass> <mainClass>sample.TestDemo</mainClass>
</manifest> </manifest>
</archive> </archive>
<descriptorRefs> <descriptorRefs>
@@ -226,6 +229,38 @@
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
<!-- <plugin>-->
<!-- <groupId>org.jetbrains.kotlin</groupId>-->
<!-- <artifactId>kotlin-maven-plugin</artifactId>-->
<!-- <version>${kotlin.version}</version>-->
<!-- <executions>-->
<!-- <execution>-->
<!-- <id>compile</id>-->
<!-- <phase>compile</phase>-->
<!-- <goals>-->
<!-- <goal>compile</goal>-->
<!-- </goals>-->
<!-- <configuration>-->
<!-- <sourceDirs>-->
<!-- <source>src/main/java</source>-->
<!-- </sourceDirs>-->
<!-- </configuration>-->
<!-- </execution>-->
<!-- <execution>-->
<!-- <id>test-compile</id>-->
<!-- <phase>test-compile</phase>-->
<!-- <goals>-->
<!-- <goal>test-compile</goal>-->
<!-- </goals>-->
<!-- </execution>-->
<!-- </executions>-->
<!-- <configuration>-->
<!-- <jvmTarget>1.6</jvmTarget>-->
<!-- </configuration>-->
<!-- </plugin>-->
</plugins> </plugins>
<!-- 主资源目录 --> <!-- 主资源目录 -->
<resources> <resources>
-31
View File
@@ -1,31 +0,0 @@
// console.log('\x1B[36m%s\x1B[0m', info); //cyan
// console.log('\x1B[33m%s\x1b[0m:', path); //yellow
var styles = {
'bold' : ['\x1B[1m', '\x1B[22m'],
'italic' : ['\x1B[3m', '\x1B[23m'],
'underline' : ['\x1B[4m', '\x1B[24m'],
'inverse' : ['\x1B[7m', '\x1B[27m'],
'strikethrough' : ['\x1B[9m', '\x1B[29m'],
'white' : ['\x1B[37m', '\x1B[39m'],
'grey' : ['\x1B[90m', '\x1B[39m'],
'black' : ['\x1B[30m', '\x1B[39m'],
'blue' : ['\x1B[34m', '\x1B[39m'],
'cyan' : ['\x1B[36m', '\x1B[39m'],
'green' : ['\x1B[32m', '\x1B[39m'],
'magenta' : ['\x1B[35m', '\x1B[39m'],
'red' : ['\x1B[31m', '\x1B[39m'],
'yellow' : ['\x1B[33m', '\x1B[39m'],
'whiteBG' : ['\x1B[47m', '\x1B[49m'],
'greyBG' : ['\x1B[49;5;8m', '\x1B[49m'],
'blackBG' : ['\x1B[40m', '\x1B[49m'],
'blueBG' : ['\x1B[44m', '\x1B[49m'],
'cyanBG' : ['\x1B[46m', '\x1B[49m'],
'greenBG' : ['\x1B[42m', '\x1B[49m'],
'magentaBG' : ['\x1B[45m', '\x1B[49m'],
'redBG' : ['\x1B[41m', '\x1B[49m'],
'yellowBG' : ['\x1B[43m', '\x1B[49m']
};
module.exports = styles
-269
View File
@@ -1,269 +0,0 @@
const l = require("./log")
const os = require("os");
const fs = require('fs');
const path = require('path');
const util = require('util');
const { exec } = require('child_process')
function sync( cmds , options = {}){
if ( options.detached ) {
throw "sync 不支持 detached"
}
options = Object.assign({
// cwd : os.tmpdir(),
encoding: 'buffer'
}, options)
// 支持多命令
let cmd = cmds
// win 乱码问题
let encode = "win32" === os.platform() ? 'cp936' : "utf-8"
return new Promise(function (resolve, reject) {
let process = exec( cmd , options , function (e, stdout, stderr) {
// console.log( e,
// iconv.decode( stdout, 'cp936'),
// iconv.decode( stderr, 'cp936')
// )
if ( e ) {
reject( e )
} else {
resolve( stdout.toString() , stderr.toString() )
// resolve({
// pid : process.pid,
// exitCode : process.exitCode,
// stdout : stdout.toString(),
// stderr : stderr.toString()
// })
}
})
console.log( "process", process.pid )
})
}
var version = ""
const project_path = path.join(__dirname, "../")
const out_path = path.join(project_path, "public")
// 用户文档
const man = "说明.txt"
function prepareDir(){
return new Promise(function (cbok, cberr) {
if ( fs.existsSync( out_path ) ){
l.i("存在旧文件,清空旧文件")
}
sync("rd /s/q .\\public").catch(function (reason) {
// pass
}).finally(function () {
l.i("创建新文件")
fs.mkdirSync( out_path )
fs.mkdirSync( path.join( out_path, "jar" ))
fs.mkdirSync( path.join( out_path, "jar", "dependences"))
// fs.mkdirSync( path.join( out_path, "doc" ))
// fs.mkdirSync( path.join( out_path, "html" ))
// fs.mkdirSync( path.join( out_path, "sample" ))
l.i("目录准备完成")
cbok()
})
})
}
function mvn(){
l.i("调用 maven 打包,可能需要好几分钟。")
return new Promise(function (cbok, cberr) {
sync('mvn package -DskipTests').then(function (value, error) {
if ( error ) {
throw error
}
l.d( value )
if ( value.indexOf("BUILD SUCCESS") < 0 ){
throw new Error("请检查 maven package 命令")
}
// 移动文件到发布目录
fs.renameSync(path.join(project_path, "target", "sydapi4j-jar-with-dependencies.jar")
, path.join(out_path, "jar", "sydapi4j-jar-with-dependencies.jar"))
fs.renameSync(path.join(project_path, "target", "sydapi4j.jar")
, path.join(out_path, "jar", "sydapi4j.jar"))
cbok()
})
})
}
function doc(){
return sync('mvn javadoc:javadoc').then(function (value, error) {
l.d( value )
// if ( value.indexOf("BUILD SUCCESS") < 0 ){
// throw new Error("请检查 maven doc 命令")
// }
}).catch(function (reason) {
l.d("忽略文档生成错误")
})
}
function zipjar(){
return sync("7z a .\\public\\sydapi-"+ version +".zip .\\public\\jar\\").then(function (value, error) {
l.d( value )
if ( value.indexOf("Everything is Ok") < 0 ){
throw new Error("请检查 7z 命令")
}
})
}
function zipsample(){
return sync("7z a .\\public\\sydapi-"+ version +".zip .\\src\\test\\java\\com\\sunyard\\sydapi\\sample").then(function (value, error) {
l.d( value )
if ( value.indexOf("Everything is Ok") < 0 ){
throw new Error("请检查 7z 命令")
}
})
}
function zipdoc(){
return sync("7z a .\\public\\sydapi-"+ version +".zip " + man).then(function (value, error) {
l.d( value )
if ( value.indexOf("Everything is Ok") < 0 ){
throw new Error("请检查 7z 命令")
}
})
}
function dependencies(){
return sync('mvn dependency:copy-dependencies -DincludeScope=runtime -DoutputDirectory=./public/jar/dependences').then(function (value, error) {
l.d( value )
if ( value.indexOf("BUILD SUCCESS") < 0 ){
throw new Error("请检查 maven dependencies 命令")
}
})
}
async function main() {
l.i("项目目录 : " + project_path )
sync('git status').then(function (value, error) {
l.d( value )
if ( value.indexOf("Command failed") > 0 ){
throw new Error("请检查 git 命令")
}
if ( value.indexOf("Changes not staged for commit") > 0){
throw new Error("项目有文件未保存")
}
if ( value.indexOf("Changes to be committed") > 0 ){
throw new Error("项目有文件未提交")
}
// 匹配分支,获取前两位版本
var r = /^On branch dev-(?<version>\S+)$/gm.exec(value)
l.i( r.groups.version )
version = r.groups.version
return sync('git log -1')
}).then(function (value) {
l.d( value )
var r = /^commit\s(?<id>\S+)$/gm.exec(value)
l.i( r.groups.id )
// 缩短 HASH
var short = r.groups.id.substr(0, 6)
version += "." + short
l.i("目前版本: " + version )
return prepareDir()
}).then(function (value) {
return mvn()
}).then(function (value) {
return dependencies()
}).then(function (value) {
var pom = fs.readFileSync("pom.xml", { encoding : "UTF-8" })
var head = pom.indexOf("<dependencies>")
var tail = pom.indexOf("</dependencies>") + 15
var dependencies = pom.substring( head, tail )
fs.writeFileSync( path.join( out_path, "jar", "dependences.xml") , dependencies )
}).then(function (value) {
return zipjar()
}).then(function (value) {
return zipsample()
}).then(function (value) {
return zipdoc()
}).then(function () {
l.i("打包完成!")
sync('cd .\\public && start .')
}).catch(function (reason) {
l.e( reason )
})
}
main()
-31
View File
@@ -1,31 +0,0 @@
const style = require("./color")
const info = style.green
const error = style.red
const debug = style.cyan
const l = {
o : console.log,
i : function ( msg ) {
console.log('%s%s%s', info[0], msg , info[1]);
},
d : function ( msg ) {
console.log('%s%s%s', debug[0], msg , debug[1]);
},
e : function ( msg ) {
console.log('%s%s%s', error[0], msg , error[1]);
},
}
l.show = function () {
l.i("info")
l.d("debug")
l.e("error")
}
module.exports = l
-5
View File
@@ -1,5 +0,0 @@
v1.11 版本
- 修正不规范接口 GenerateRandom 返回值更改为 String 类型。老版本为 bool 类型,仅于活性检测。
v1.12 版本
- 新增编押验押接口/人行定制接口。
@@ -0,0 +1,109 @@
package com.sunyard;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* 管理多线程间对象
* 类似 ThreadLocal
* @param <T>
*/
public class MutiThreadHander<T> {
private static class Handler<T> {
private T obj = null;
private long creatAt = System.currentTimeMillis();
private long lastGetAt = System.currentTimeMillis();
public Handler(T obj) {
this.obj = obj;
}
public T getObj() {
return obj;
}
public long getCreatAt() {
return creatAt;
}
public long getLastGetAt() {
return lastGetAt;
}
}
private final Map<Thread, Handler> handers = new HashMap<Thread, Handler>();
private ScheduledExecutorService gcThread = Executors.newScheduledThreadPool(1);
private long maxLiveMillis = 8 * 3600 * 1000;
private long maxIdleMillis = 3600 * 1000;
private long checkEveryMillis = 5 * 60 * 1000;
public MutiThreadHander() {
gcThread.scheduleWithFixedDelay(new Runnable() {
@Override
public void run() {
try {
if ( handers.size() <= 0 ) {
return;
}
long now = System.currentTimeMillis();
Iterator<Map.Entry<Thread, Handler>>it = handers.entrySet().iterator();
while ( it.hasNext() ){
Map.Entry<Thread, Handler> entry = it.next();
// check maxLiveMillis
if ( entry.getValue().getCreatAt() - now > maxLiveMillis ){
synchronized ( handers ){
it.remove();
}
}
// check maxIdleMillis
if ( entry.getValue().getLastGetAt() - now > maxIdleMillis ){
synchronized ( handers ){
it.remove();
}
}
}
} catch ( Exception e) {
e.printStackTrace();
}
}
}, checkEveryMillis, checkEveryMillis, TimeUnit.MILLISECONDS );
}
protected T initialValue() {
return null;
}
public void clear(){
synchronized ( handers ) {
handers.remove( Thread.currentThread() );
}
}
public void set(T obj){
synchronized ( handers ) {
handers.put( Thread.currentThread() , new Handler(obj));
}
}
public T get(){
synchronized ( handers ) {
Handler hander = handers.get( Thread.currentThread() );
if ( null == hander ) {
T o = initialValue();
hander = new Handler( o );
handers.put( Thread.currentThread(), hander );
}
return (T) hander.getObj();
}
}
}
@@ -9,7 +9,7 @@ import racal.sunyard.main.SydApi4j;
public class SYMEnDeLongData { public class SYMEnDeLongData {
private SydApi4j api; private SydApi4j api;
private String key = ""; private String sykey = "";
private String keyValue = ""; private String keyValue = "";
private int keyType = 0; private int keyType = 0;
private int inType = 0; private int inType = 0;
@@ -95,11 +95,11 @@ public class SYMEnDeLongData {
public String getKey() { public String getKey() {
return key; return sykey;
} }
public SYMEnDeLongData setKey(String key) { public SYMEnDeLongData setKey(String sykey) {
this.key = key; this.sykey = sykey;
return this; return this;
} }
+24 -3
View File
@@ -1,20 +1,23 @@
package com.sunyard; package com.sunyard;
import com.sunyard.inf.cryption.*;
import com.sunyard.inf.*; import com.sunyard.inf.*;
import com.sunyard.inf.customize.Syd4DigitalEnvelope;
import com.sunyard.inf.customize.SydHAApi; import com.sunyard.inf.customize.SydHAApi;
import com.sunyard.inf.customize.SydQNUCApi; import com.sunyard.inf.customize.SydQNUCApi;
import com.sunyard.inf.customize.SydUnionPayApi; import com.sunyard.inf.customize.SydUnionPayApi;
import racal.sunyard.main.SydApiBuilder; import racal.sunyard.main.SydApiBuilder;
import java.util.List;
/** /**
* Created by Cheney on 2017/11/11. * Created by Cheney on 2017/11/11.
* 程序调用接口 * 程序调用接口
*/ */
public interface SydApi extends public interface SydApi extends
SydRawApi, SydCertApi, SydCryptionApi, SydGenApi, SydRawApi, SydCertApi, SydGenApi, SydSYMApi, SydASYMApi, SydHashApi,
SydSVApi, SydHAApi, SydQNUCApi, SydPledge, SydPINOpt, SydSVApi, SydHAApi, SydQNUCApi, SydPledge, SydPINOpt,
SydManufactureApi, SydZYOption, SydUnionPayApi { SydManufactureApi, SydZYOption, SydUnionPayApi ,Syd4DigitalEnvelope{
byte ALG_AES = 0x30; byte ALG_AES = 0x30;
byte ALG_SM4 = 0x31; byte ALG_SM4 = 0x31;
@@ -71,6 +74,18 @@ public interface SydApi extends
*/ */
SydApi connect(String ip, int port, String pwd, int connectTimeout, int readTimeout); SydApi connect(String ip, int port, String pwd, int connectTimeout, int readTimeout);
/**
* 建立到指定地址和端口号的加密设备的TCP/IP 连接,返回 TCP/IP 连接句柄。
* @param ip 加密机 ip
* @param port 加密机端口
* @param pwd 加密机密码,无密码写 null
* @param connectTimeout 网络连接时超时时间
* @param readTimeout 网络通信时,socket 超时时间
* @param retryWhenNetError 网络失败时重试次数
* @return
*/
SydApi connect(String ip, int port, String pwd, int connectTimeout, int readTimeout , int retryWhenNetError);
void init(SydApiBuilder builder); void init(SydApiBuilder builder);
/** /**
@@ -89,6 +104,7 @@ public interface SydApi extends
// 单例可以不实现 // 单例可以不实现
void error(); void error();
/** /**
* 获取加密机cpu,内存,磁盘使用状况 * 获取加密机cpu,内存,磁盘使用状况
* *
@@ -99,4 +115,9 @@ public interface SydApi extends
RetWrap getStatus(); RetWrap getStatus();
byte[] directBytes(byte[] data); byte[] directBytes(byte[] data);
public Object getBindObject();
public void setBindObject(Object bindObject);
} }
+82 -37
View File
@@ -13,105 +13,139 @@ public class SydApiException extends RuntimeException{
return retCode; return retCode;
} }
private static String transMsg(int code){
public void transMsg(){ String msg = "未定义的错误";
switch (this.retCode){ switch (code){
case -1: case -1:
case -2: case -2:
case -3: case -3:
this.msg = "网络错误"; msg = "网络错误";
break; break;
case -4: case -4:
this.msg = "返回包的序列号有误"; msg = "返回包的序列号有误";
break; break;
case -5: case -5:
this.msg = "返回包的命令码有误"; msg = "返回包的命令码有误";
break; break;
case -6: case -6:
this.msg = "输出缓冲区预留太小"; msg = "输出缓冲区预留太小";
break; break;
case -25: case -25:
this.msg = "输入的 HASH 值长度应该为 32 个字节"; msg = "输入的 HASH 值长度应该为 32 个字节";
break; break;
case -26: case -26:
this.msg = "用户标识超长(应该<=16) "; msg = "用户标识超长(应该<=16) ";
break; break;
case -27: case -27:
this.msg = "数据类型不合法 "; msg = "数据类型不合法 ";
break; break;
case 33: case 33:
this.msg = "检索的数据或密钥不存在"; msg = "检索的数据或密钥不存在";
break; break;
case 4: case 4:
this.msg = "DER 编码格式错误(公钥) "; msg = "DER 编码格式错误(公钥) ";
break;
case 31:
msg = "缓冲区索引错误";
break;
case 0xd:
msg = "公钥加密错误";
break; break;
case 21: case 21:
this.msg = "输入的数据格式错误 "; msg = "输入的数据格式错误 ";
break; break;
case 19: case 19:
this.msg = "数据解密错(C3) "; msg = "数据解密错(C3) ";
break; break;
case 2: case 2:
this.msg = "签名验证错误 "; msg = "签名验证错误 ";
break; break;
case 129: case 129:
this.msg = "没有该指令"; msg = "没有该指令";
break; break;
case 0x8006 : { case 0x8006 : {
this.msg = "输入的数据格式错误"; msg = "输入的数据格式错误";
break;
}
case 0x7007 : {
msg = "实体白名单未添加";
break;
}
case 0x8004 : {
msg = "证书已过期";
break; break;
} }
case 32770: case 32770:
this.msg = "签名验证错误(P7) "; msg = "签名验证错误(P7) ";
break; break;
case 32773: case 32773:
this.msg = "证书不可信"; msg = "证书不可信";
break; break;
case 32884: case 32884:
this.msg = "证书或签名数据的格式错"; msg = "证书或签名数据的格式错";
break; break;
case 36868: case 36868:
this.msg = "DN 所指向的实体不存在"; msg = "DN 所指向的实体不存在";
break; break;
case 40000: case 40000:
this.msg = "输入的大数据处理异常"; msg = "输入的大数据处理异常";
break;
case 56300:
this.msg = "证书导入错误";
break;
case 56307:
this.msg = "证书删除错误";
break; break;
case 56300:
msg = "证书导入错误";
break;
case 56307:
msg = "证书删除错误";
break;
case 0xC101 :
msg = "证书识别异常";
break;
default: default:
this.msg = "未定义的错误"; msg = "未定义的错误";
} }
return msg;
}
public void transMsg(){
this.msg = transMsg( this.retCode );
} }
public SydApiException(int retCode) { public SydApiException(int retCode) {
super("SydApiException(" + "code = "+String.format("%d", retCode) + ")" ); super("SydApiException(" + "code = "+String.format("%04x", retCode) + ")" );
this.retCode = retCode; this.retCode = retCode;
transMsg(); transMsg();
} }
public SydApiException(String msg, int ret, Throwable e){ public SydApiException(int retCode, Exception e) {
super("SydApiException(" +"code ="+ String.format(" %d", ret) + " : "+"msg ="+ (null == msg ? "未定义的错误" : msg) +")" , e); super("SydApiException(" + "code = "+String.format("%04x", retCode) + ")" , e);
this.retCode = ret; this.retCode = retCode;
transMsg();
}
public SydApiException(String msg, int retCode){
super("SydApiException(" + String.format(" %04X", retCode) + ":" + ( null == msg ? transMsg(retCode) : msg ) + ")" );
this.retCode = retCode;
if (null == msg || "".equals(msg)){ if (null == msg || "".equals(msg)){
transMsg(); transMsg();
}else { }else {
this.msg = msg; this.msg = msg;
} }
} }
public SydApiException(String msg, int ret){
super("SydApiException(" +"code ="+ String.format(" %d", ret) + " : "+"msg ="+ (null == msg ? "未定义的错误" : msg) +")" ); public SydApiException(String msg, int retCode, boolean flag){
this.retCode = ret; super(null == msg ? transMsg(retCode) : msg);
this.retCode = retCode;
if (null == msg || "".equals(msg)){ if (null == msg || "".equals(msg)){
transMsg(); transMsg();
}else { }else {
@@ -119,6 +153,17 @@ public class SydApiException extends RuntimeException{
} }
} }
public SydApiException(String msg, int ret, Throwable e) {
super("SydApiException(code =" + String.format(" %04x", ret) + " : " + "msg =" + (msg == null ? "未定义的错误" : msg) + ")", e);
this.retCode = ret;
if (msg != null && !"".equals(msg)) {
this.msg = msg;
} else {
this.transMsg();
}
}
public static SydApiException fromBin( byte[] b , String msg){ public static SydApiException fromBin( byte[] b , String msg){
int code = null != b && b[0] >= 48 && b[0] <= 57 ? Util.a2i( b , 10) : Util.b2i( b ); int code = null != b && b[0] >= 48 && b[0] <= 57 ? Util.a2i( b , 10) : Util.b2i( b );
return new SydApiException(msg, code); return new SydApiException(msg, code);
@@ -135,7 +180,7 @@ public class SydApiException extends RuntimeException{
sb.append(Integer.toHexString(this.retCode)); sb.append(Integer.toHexString(this.retCode));
sb.append(" ) "); sb.append(" ) ");
sb.append(" msg = "); sb.append(" msg = ");
sb.append(this.msg); sb.append(msg);
return sb.toString(); return sb.toString();
} }
} }
@@ -0,0 +1,16 @@
package com.sunyard.constant;
/**
* 证书用途
*/
public enum CertUsage {
digitalSignature,
nonRepudiation,
keyEncipherment,
dataEncipherment,
keyAgreement,
keyCertSign,
cRLSign,
encipherOnly,
decipherOnly
}
@@ -0,0 +1,55 @@
package com.sunyard.entity;
import java.util.List;
/**
* 证书导入结果封装类
*/
public class ImportResult {
/** 成功状态码 */
public static final int CODE_SUCCESS = 2000;
/** 部分成功状态码 */
public static final int CODE_PARTIAL_SUCCESS = 2001;
/** 完全失败状态码 */
public static final int CODE_COMPLETE_FAILURE = 2002;
/** 参数错误状态码 */
public static final int CODE_INVALID_PARAM = 4001;
private int code; //返回码
private String certDn; // 证书主题(DN)
private List<String> errCnt; // 详细错误列表(每个失败的服务器)
// 构造方法
public ImportResult() {
}
public ImportResult(int code, String certDn) {
this.code = code;
this.certDn = certDn;
}
// Getters and Setters
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getCertDn() {
return certDn;
}
public void setCertDn(String certDn) {
this.certDn = certDn;
}
public List<String> getErrCnt() {
return errCnt;
}
public void setErrCnt(List<String> errCnt) {
this.errCnt = errCnt;
}
}
@@ -0,0 +1,42 @@
package com.sunyard.entity;
import java.nio.ByteBuffer;
public class MutiReturn7 {
// 返回码
private int ret;
// 0-不是最后 1-是最后
private int isLast;
// 数据
private ByteBuffer data;
public MutiReturn7(int ret, int isLast, ByteBuffer data) {
this.ret = ret;
this.isLast = isLast;
this.data = data;
}
public int getRet() {
return ret;
}
public void setRet(int ret) {
this.ret = ret;
}
public int getIsLast() {
return isLast;
}
public void setIsLast(int isLast) {
this.isLast = isLast;
}
public ByteBuffer getData() {
return data;
}
public void setData(ByteBuffer data) {
this.data = data;
}
}
@@ -0,0 +1,86 @@
package com.sunyard.entity;
import java.util.List;
public class ServerConfig {
/**
* 主机节点信息
*/
private List<ServerAddress> masterNodeList;
/**
* 备机节点信息
*/
private List<ServerAddress> slaveNodeList;
/**
* 连接超时时间
*/
private Integer timeout;
public ServerConfig(List<ServerAddress> masterNodeList, List<ServerAddress> slaveNodeList, Integer timeout) {
this.masterNodeList = masterNodeList;
this.slaveNodeList = slaveNodeList;
this.timeout = timeout;
}
public List<ServerAddress> getMasterNodeList() {
return masterNodeList;
}
public void setMasterNodeList(List<ServerAddress> masterNodeList) {
this.masterNodeList = masterNodeList;
}
public Integer getTimeout() {
return timeout;
}
public void setTimeout(Integer timeout) {
this.timeout = timeout;
}
public List<ServerAddress> getSlaveNodeList() {
return slaveNodeList;
}
public void setSlaveNodeList(List<ServerAddress> slaveNodeList) {
this.slaveNodeList = slaveNodeList;
}
public static class ServerAddress {
private String ip;
private Integer port;
public ServerAddress(String ip, Integer port) {
this.ip = ip;
this.port = port;
}
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public Integer getPort() {
return port;
}
public void setPort(Integer port) {
this.port = port;
}
}
}
@@ -0,0 +1,103 @@
package com.sunyard.entity;
/**
* SM2加密解密时间统计类
* 用于记录发送、计算、接收三个阶段的耗时
*/
public class TimeStats {
// 发送阶段总耗时(毫秒)- 循环发送数据块的时间
private long sendTime;
// 计算阶段耗时(毫秒)- 执行加密/解密计算的时间
private long computeTime;
// 接收阶段总耗时(毫秒)- 循环接收数据块的时间
private long receiveTime;
// 发送次数
private int sendCount;
// 接收次数
private int receiveCount;
public TimeStats() {
this.sendTime = 0;
this.computeTime = 0;
this.receiveTime = 0;
this.sendCount = 0;
this.receiveCount = 0;
}
public long getSendTime() {
return sendTime;
}
public void setSendTime(long sendTime) {
this.sendTime = sendTime;
}
public long getComputeTime() {
return computeTime;
}
public void setComputeTime(long computeTime) {
this.computeTime = computeTime;
}
public long getReceiveTime() {
return receiveTime;
}
public void setReceiveTime(long receiveTime) {
this.receiveTime = receiveTime;
}
public int getSendCount() {
return sendCount;
}
public void setSendCount(int sendCount) {
this.sendCount = sendCount;
}
public int getReceiveCount() {
return receiveCount;
}
public void setReceiveCount(int receiveCount) {
this.receiveCount = receiveCount;
}
/**
* 获取总耗时
*/
public long getTotalTime() {
return sendTime + computeTime + receiveTime;
}
/**
* 获取各阶段耗时占比
*/
public double getSendPercentage() {
long total = getTotalTime();
return total == 0 ? 0 : (double) sendTime / total * 100;
}
public double getComputePercentage() {
long total = getTotalTime();
return total == 0 ? 0 : (double) computeTime / total * 100;
}
public double getReceivePercentage() {
long total = getTotalTime();
return total == 0 ? 0 : (double) receiveTime / total * 100;
}
@Override
public String toString() {
return String.format(
"TimeStats{sendTime=%dms(%.1f%%), computeTime=%dms(%.1f%%), receiveTime=%dms(%.1f%%), total=%dms, sendCount=%d, receiveCount=%d}",
sendTime, getSendPercentage(),
computeTime, getComputePercentage(),
receiveTime, getReceivePercentage(),
getTotalTime(),
sendCount, receiveCount
);
}
}
@@ -3,8 +3,10 @@ package com.sunyard.inf;
import com.sunyard.RetWrap; import com.sunyard.RetWrap;
import com.sunyard.cert.X509; import com.sunyard.cert.X509;
import com.sunyard.constant.CertUsage;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.util.List;
/** /**
* 证书操作相关接口 * 证书操作相关接口
@@ -101,6 +103,14 @@ public interface SydCertApi {
String sign String sign
); );
/**
* 查询所有证书
* @return
* certDNs: 证书DN
*/
List<String> getAllCert() throws UnsupportedEncodingException;
/** /**
* 查询所有证书 * 查询所有证书
* @param dataFlag 数据包标志 0:起始包 1:中间包 2:结束包 * @param dataFlag 数据包标志 0:起始包 1:中间包 2:结束包
@@ -114,20 +124,57 @@ public interface SydCertApi {
*/ */
RetWrap getAllCert(int dataFlag) throws UnsupportedEncodingException; RetWrap getAllCert(int dataFlag) throws UnsupportedEncodingException;
/**
* 查询所有证书
* @param dataFlag 数据包标志 0:起始包 1:中间包 2:结束包
* @param sqlite 查询条件,默认查询所有"1=1"
* @return
* dataFlag: 数据包标志 0:起始包 1:中间包 2:结束包
* certAllNum: 证书总数
* realCertNum: 实际证书个数
* dataAttrFlag: 数据包属性标志
* certLenMax: 证书最大长度
* certDNs: 证书DN
*/
RetWrap getAllCert(int dataFlag,String sqlite) throws UnsupportedEncodingException;
/** /**
* 上传指定证书到加密设备 * 上传指定证书到加密设备
* @param certData 证书的字节数组 * @param certData 证书的字节数组
* @param organizationId 机构号的字节数组 * @param organizationId 机构号的字节数组
* @param us 白名单类型
* @return * @return
*/ */
RetWrap importCert(byte[] certData, byte[] organizationId, CertUsage... us);
RetWrap importCert(byte[] certData, byte[] organizationId); RetWrap importCert(byte[] certData, byte[] organizationId);
String importCert(String cert);
/**
* 从加密设备中删除指定 DN 的公钥证书
* @param dn:传入的证书
*
* @return
*/
boolean deleteCert(String dn);
/** /**
* 上传指定证书到加密设备,并在证书前后加上begin和end * 上传指定证书到加密设备,并在证书前后加上begin和end
* @param certData 证书的字节数组 * @param certData 证书的字节数组
* @param organizationId 机构号的字节数组 * @param organizationId 机构号的字节数组
* @param us 白名单类型
* @return * @return
*/ */
RetWrap importCertAddHT(String certData, byte[] organizationId, CertUsage... us);
RetWrap importCertAddHT(String certData, byte[] organizationId); RetWrap importCertAddHT(String certData, byte[] organizationId);
String getCertByDn(String dn) throws UnsupportedEncodingException;
String getCertByDn(String dn,int type) throws UnsupportedEncodingException;
public String getCertByDn(byte[] dnBytes);
} }
@@ -275,7 +275,7 @@ interface SydSYMApi {
byte[] SYMEncryptData(int nAlg, String seesionKey, int fullmode, byte[] pINdata); byte[] SYMEncryptData(int nAlg, String seesionKey, int fullmode, byte[] pINdata);
// List<byte[]> SYMEncryptDecryptBatchData(int nAlg, String[] seesionKey, int fullmode, List<byte[]> pINdata); List<byte[]> SYMEncryptDecryptBatchData(int nAlg, String[] seesionKey, int fullmode, List<byte[]> pINdata);
/** /**
* 用输入的会话密钥,对指定报文数据进行加密处理。 * 用输入的会话密钥,对指定报文数据进行加密处理。
@@ -0,0 +1,216 @@
package com.sunyard.inf;
import com.sunyard.RetWrap;
import com.sunyard.cert.X509;
/**
* 不带原文的签名验签
*/
public interface SydDetachedSVApi {
/**
* 对指定的原始数据核验其带公钥证书签名(PKCS#7)
* @param orgData 待签名的原始数据
* @param sign 签名数据
* @return 验签是否通过
*/
public boolean SYD_DetachedVerify(
byte[] orgData,
String sign);
/**
* 通过指定的私钥对指定的原始数据编制带公钥证书的数字签名(遵循PKCS#7)
* @param orgData 待签名的原始数据
* @param sCertDN 签名者证书 DN
* @return 签名数据
*/
public String SYD_DetachedSign(
byte[] orgData,
String sCertDN
);
/**
* 人行项目需要RSA支持
* 通过指定的私钥对指定的原始数据编制带公钥证书的数字签名(遵循PKCS#7)
* @param orgData 待签名的原始数据
* @param sCertDN 签名者证书 DN
* @return 签名数据
*/
public String SYD_DetachedSign(
int rFlag,
byte[] orgData,
String sCertDN
);
/**
* 通过指定的私钥对指定的原始数据编制带公钥证书的数字签名(遵循PKCS#7)
* 待签名的原始数据将在接口内部进行 sm3 ,然后做 Detach 签名
* @param orgData 待签名的原始数据
* @param publicKey sm3 hash 所用的公钥
* @param sCertDN 签名者证书 DN
* @return 签名数据
*/
public String sm3AndDetachedSign(
byte[] orgData,
String publicKey,
String sCertDN
);
/**
* 对指定的原始数据核验其带公钥证书签名(PKCS#7)
* 原始数据将在接口内部进行 sm3 ,然后做 Detach 验签
* @param orgData 待签名的原始数据
* @param publicKey sm3 hash 所用的公钥
* @param sign 签名数据
* @return 验签是否通过
*/
public boolean sm3AndDetachedVerify(
byte[] orgData,
String publicKey,
String sign);
/**
* 通过指定的私钥对指定的原始数据编制带公钥证书的数字签名(遵循PKCS#7)
* 待签名的原始数据将在接口内部进行不带公钥的 sm3 ,然后做 Detach 签名
* @param orgData 待签名的原始数据
* @param sCertDN 签名者证书 DN
* @return 签名数据
*/
String sm3WithoutPKDetachedSign(byte[] orgData, String sCertDN);
/**
* 对指定的原始数据核验其带公钥证书签名(PKCS#7)
* 原始数据将在接口内部进行无公钥的 sm3 ,然后做 Detach 验签
*
* @param orgData 待签名的原始数据
* @param sign 签名数据
* @return 验签是否通过
*/
boolean sm3WithoutPKDetachedVerify(byte[] orgData, String sign);
/**
*
* 通过指定的私钥对指定的原始数据编制带公钥证书的数字签名(遵循PKCS#7)
* 数据模式可选 DATA_HASH 或 DATA_ORIGIN
*
* @param dataType 数据模式,输入的数据为 HASH 后的数据 DATA_HASH = 0 ,输入的数据为原始数据库 DATA_ORIGIN = 1
* @param orgData 输入的数据
* @param sCertDN 签名者证书 DN
* @return 签名数据
*/
public String detachedSign(
int dataType,
byte[] orgData,
String sCertDN
);
//SM2与RSA兼容
public String detachedSignAll(int rFlag,byte[] orgData, String sCertDN);
//SM2与RSA兼容
public boolean detachedVerifyAll(int rFlag,byte[] orgData, String sign);
/**
* 带公钥证书与签名属性的数字签名(遵循 PKCS#7)
* @param dataType 数据类型:0,hash 模式,1为非hash模式
* @param orgData 当为hash模式时,值为hash值,当为非hash模式时,值为数据
* @param keyTag 密钥对应的索引号
* @return 签名的 DER 编码
*/
public byte[] detachedSign(
int dataType,
byte[] orgData,
int keyTag
);
public String detachedSign(int rFlag,int dataType, byte[] orgData, String sCertDN);
/**
* 带公钥证书的PKCS#7数字签名(序列号)
* @param dataType 数据类型:0,hash 模式,1为非hash模式
* @param orgData 当为hash模式时,值为hash值,当为非hash模式时,值为要签名的信息
* @param certificateNo X509证书序号
* @return 符合PKCS7标准的签名结果
*/
public String detachedSignbysn(
int dataType,
byte[] orgData,
String certificateNo);
/**
* 对指定的原始数据核验其带公钥证书签名(PKCS#7)
* 数据模式可选 DATA_HASH 或 DATA_ORIGIN
*
* @param dataType 输入的数据为 HASH 后的数据 DATA_HASH = 0 ,输入的数据为原始数据库 DATA_ORIGIN = 1
* @param orgData 待签名的原始数据
* @param sign 签名数据
* @return 验签是否通过
*/
boolean detachedVerify(
int dataType,
byte[] orgData,
String sign);
/**
* 对指定的原始数据核验其带公钥证书签名(PKCS#7)
* 数据模式可选 DATA_HASH 或 DATA_ORIGIN
*
*
* @param rFlag RSA标识
* @param dataType 输入的数据为 HASH 后的数据 DATA_HASH = 0 ,输入的数据为原始数据库 DATA_ORIGIN = 1
* @param orgData 待签名的原始数据
* @param sign 签名数据
* @return 验签是否通过
*/
boolean detachedVerify(
int rFlag,
int dataType,
byte[] orgData,
String sign);
/**
* 带公钥证书与签名属性的数字签名验签(遵循 PKCS#7)
* @param dataType 数据类型:0,hash 模式,1为非hash模式
* @param orgData 当为hash模式时,值为hash值,当为非hash模式时,值为数据
* @param sign 已签名数据
* @return 是否正确
*/
boolean detachedVerify(
int dataType,
byte[] orgData,
byte[] sign);
/**
* 对指定的原始数据核验其带公钥证书签名(PKCS#7)返回证书信息
* 数据模式可选 DATA_HASH 或 DATA_ORIGIN
*
* @param dataType 输入的数据为 HASH 后的数据 DATA_HASH = 0 ,输入的数据为原始数据库 DATA_ORIGIN = 1
* @param orgData 待签名的原始数据
* @param sign 签名数据
* @return 证书
*/
X509 detachedVerifyAndGetX509(int dataType,
byte[] orgData,
String sign);
/**
* 计算SM3散列值
* @param packSn 消息块号,0=仅一块,1=第一块,2=中间块,3=最后块
* @param userId 用户 ID,只对“消息块号”为 0、1 时有效
* @param publicKey 公钥的 DER 编码
* @param msg 二进制的消息块
* @param filterData 过渡消息数据,只对“消息块号”为 2、3 时有效
* @return
* filterData: 过渡消息数据,只对“消息块号”为 2、1 时有效
* hash: hash
*/
RetWrap SM3Hash(int packSn, String userId, byte[] publicKey, byte[] msg, byte[] filterData);
}
+37 -3
View File
@@ -132,6 +132,18 @@ public interface SydGenApi {
*/ */
RetWrap SM2GenSessionKey(String publicKey); RetWrap SM2GenSessionKey(String publicKey);
/**
* 此函数用于会话密钥的产生,用于发起端。
* 加密机产生随机会话密钥,输出两类密文:
* 1、 RSA公钥加密的密文,用于密钥的传递。
* 2、 本地 LMK 加密,用于本地应用数据的加解密。
*
* @param publicKey 公钥串,DER 编码,HEX 格式。
* @return CipherKey 公钥加密的会话密钥,DER 编码,HEX 格式, SessionKey 本地LMK 加密的会话密钥,HEX 格式 , KCV 会话密钥的检验值,HEX 格式,长度为 16H
*/
RetWrap RSAGenSessionKey(String publicKey);
/** /**
* 生成数字信封 * 生成数字信封
* @param publicKey 公钥 * @param publicKey 公钥
@@ -226,7 +238,12 @@ public interface SydGenApi {
* SessionKey 本地LMK 加密的会话密钥,HEX 格式, 本地 LMK 加密的会话密钥长度,HEX 格式(不包括第 1 个字符),一般为 33 个 Bytes。默认输入值为缓冲区的大小。 * SessionKey 本地LMK 加密的会话密钥,HEX 格式, 本地 LMK 加密的会话密钥长度,HEX 格式(不包括第 1 个字符),一般为 33 个 Bytes。默认输入值为缓冲区的大小。
* KCV 会话密钥的检验值,HEX 格式,长度为 32H。 * KCV 会话密钥的检验值,HEX 格式,长度为 32H。
*/ */
RetWrap generateDEByDn(String certSerial, String oData); RetWrap generateDEByDn(String certSerial, byte[] oData);
RetWrap generateDEByDnICBC(String certSerial,String iv, byte[] oData,int roundmod);
RetWrap generateDEByDnRSA(int alg,String certSerial, byte[] oData);
/** /**
* 产生对称密钥,通过公钥加密生成网联格式的数字信封。 * 产生对称密钥,通过公钥加密生成网联格式的数字信封。
@@ -240,7 +257,7 @@ public interface SydGenApi {
* SessionKey 本地LMK 加密的会话密钥,HEX 格式, 本地 LMK 加密的会话密钥长度,HEX 格式(不包括第 1 个字符),一般为 33 个 Bytes。默认输入值为缓冲区的大小。 * SessionKey 本地LMK 加密的会话密钥,HEX 格式, 本地 LMK 加密的会话密钥长度,HEX 格式(不包括第 1 个字符),一般为 33 个 Bytes。默认输入值为缓冲区的大小。
* KCV 会话密钥的检验值,HEX 格式,长度为 32H。 * KCV 会话密钥的检验值,HEX 格式,长度为 32H。
*/ */
RetWrap generateDE(byte[] certSerial, int alg, int model, String oData); RetWrap generateDE(byte[] certSerial, int alg, int model, byte[] oData);
/** /**
* 产生对称密钥,通过公钥加密生成网联格式的数字信封。 * 产生对称密钥,通过公钥加密生成网联格式的数字信封。
@@ -308,8 +325,10 @@ public interface SydGenApi {
* KCV 会话密钥的检验值,HEX 格式,长度为 36H。 * KCV 会话密钥的检验值,HEX 格式,长度为 36H。
* orgCode 如果有机构码的话会返回机构码 * orgCode 如果有机构码的话会返回机构码
*/ */
RetWrap decryptDEByDN(String certSerial, String pCipherKey); RetWrap decryptDEByDN(String certSerial, byte[] pCipherKey);
RetWrap decryptDEByDNICBC(String certSerial, String IV,String pCipherKey,int roundmod);
RetWrap decryptDEByDNRSA(int alg,String certSerial, byte[] pCipherKey);
/** /**
* 接收用私钥解密数字信封,还原对称密钥。 * 接收用私钥解密数字信封,还原对称密钥。
* *
@@ -325,6 +344,21 @@ public interface SydGenApi {
*/ */
RetWrap decryptDE(boolean pFlag, int model, byte[] certSerial, String pCipherKey); RetWrap decryptDE(boolean pFlag, int model, byte[] certSerial, String pCipherKey);
/**
* 接收用RSA私钥解密数字信封,还原对称密钥。
*
* @param pFlag 输入。 p标识,如果为true,则传入R
* @param model 输入。 证书模式,0:证书序号,1:证书 DN
* @param certSerial 输入。 对方 X509 证书的序列号或DN。
* @param pCipherKey 输入。 公钥加密的会话密钥,BASE64 编码
* @return RetWrap 包含 SessionKey KCV
* oData 如果有机构码的话会返回原数据
* SessionKey 输出。 本地LMK 加密的会话密钥,格式为:密钥类型|密钥密文,比如:02|密钥密文
* KCV 会话密钥的检验值,HEX 格式,长度为 36H。
* orgCode 如果有机构码的话会返回机构码
*/
RetWrap decryptDERSA(boolean pFlag, int model, byte[] certSerial, String pCipherKey);
/** /**
* 产生要求长度的随即数据串,可用于身份认证 * 产生要求长度的随即数据串,可用于身份认证
* *
@@ -0,0 +1,122 @@
package com.sunyard.inf;
import com.sunyard.SydApiException;
/**
* 不经过 CA 授信
* 直接使用公私钥对签名验签
*/
interface SydNakedSVApi {
/**
* 使用指定的证书 DN,从加密设备获取对应的私钥证书,对指定的原始数据编制裸签名(遵循 PKCS#1)
* @param orgData 待签名的原始数据
* @param sCertDN 签名者证书 DN
* @return 签名数据
*/
public byte[] SYD_NakedSign(
byte[] orgData,
String sCertDN
);
/**
* 使用指定的证书 DN,从加密设备获取对应的私钥证书,对指定的原始数据编制裸签名(遵循 PKCS#1)
* 人行项目增加RSA
* @param orgData 待签名的原始数据
* @param sCertDN 签名者证书 DN
* @return 签名数据
*/
public byte[] SYD_NakedSign(
int rFlag,
byte[] orgData,
String sCertDN
);
/**
* 使用指定的证书 DN,对指定的原始数据编制裸验签(遵循PKCS#1)
* @param orgData 待签名的原始数据
* @param sign 签名数据
* @param sCertDN 签名者证书 DN
* @return 验签是否通过
*/
public boolean SYD_NakedVerify(
byte[] orgData,
byte[] sign,
String sCertDN
);
/**
* 使用指定的证书 DN,对指定的原始数据编制裸验签(遵循PKCS#1)
* @param orgData 待签名的原始数据
* @param sign 签名数据
* @param sCertDN 签名者证书 DN
* @return 验签是否通过
*/
public boolean SYD_NakedVerify(
int rFlag,
byte[] orgData,
byte[] sign,
String sCertDN
);
/**
* 使用指定的证书 DN,从加密设备获取对应的私钥证书,对指定的原始数据编制裸签名(遵循 PKCS#1)
* @param rFlag 摘要算法 1—DIGEST_ALGO_MD5 M
* 2—DIGEST_ALGO_SHA1 S
* 3—DIGEST_ALGO_SHA256 R
* 4-SM2 国密证书,SM3算法
* S代表RSA-SHA1进行签名,如果为R代表RSA-SHA256进行签名,如果为M代表RSA-MD5进行签名
* @param orgData 待签名的原始数据
* @param sCertDN 签名者证书 DN
* @return 签名数据
*/
public byte[] SYD_NakedSignAll(
int rFlag,
byte[] orgData,
String sCertDN
);
/**
* 使用指定的证书 DN,对指定的原始数据编制裸验签(遵循PKCS#1)
* @param rFlag 摘要算法 1—DIGEST_ALGO_MD5 M
* * 2—DIGEST_ALGO_SHA1 S
* * 3—DIGEST_ALGO_SHA256 R
* 4-SM2 国密证书,SM3算法
* * S代表RSA-SHA1进行签名,如果为R代表RSA-SHA256进行签名,如果为M代表RSA-MD5进行签名
* @param orgData 待签名的原始数据
* @param sign 签名数据
* @param sCertDN 签名者证书 DN
* @return 验签是否通过
*/
public boolean SYD_NakedVerifyAll(
int rFlag,
byte[] orgData,
byte[] sign,
String sCertDN
);
/**
* 使用指定的证书 DN,对指定的原始数据编制裸验签(遵循PKCS#1) 安徽农信定制接口
* @param cert 上传证书
* @param rFlag 摘要算法 1—DIGEST_ALGO_MD5 M
* * 2—DIGEST_ALGO_SHA1 S
* * 3—DIGEST_ALGO_SHA256 R
* 4-SM2 国密证书,SM3算法
* * S代表RSA-SHA1进行签名,如果为R代表RSA-SHA256进行签名,如果为M代表RSA-MD5进行签名
* @param orgData 待签名的原始数据
* @param sign 签名数据
* @param sCertDN 签名者证书 DN
* @return 验签是否通过
*/
public boolean SYD_NakedVerifyAll4NX (
String cert,
int rFlag,
byte[] orgData,
byte[] sign,
String sCertDN
) ;
}
+3 -384
View File
@@ -3,6 +3,9 @@ package com.sunyard.inf;
import com.sunyard.RetWrap; import com.sunyard.RetWrap;
import com.sunyard.cert.X509; import com.sunyard.cert.X509;
import com.sunyard.inf.sva.SydAttachedSVApi;
import java.io.UnsupportedEncodingException;
/** /**
* 签名验签相关接口 * 签名验签相关接口
@@ -11,389 +14,5 @@ public interface SydSVApi extends SydNakedSVApi, SydAttachedSVApi, SydDetachedSV
} }
/**
* 不经过 CA 授信
* 直接使用公私钥对签名验签
*/
interface SydNakedSVApi {
/**
* 使用指定的证书 DN,从加密设备获取对应的私钥证书,对指定的原始数据编制裸签名(遵循 PKCS#1)
* @param orgData 待签名的原始数据
* @param sCertDN 签名者证书 DN
* @return 签名数据
*/
public byte[] SYD_NakedSign(
byte[] orgData,
String sCertDN
);
/**
* 使用指定的证书 DN,对指定的原始数据编制裸验签(遵循PKCS#1)
* @param orgData 待签名的原始数据
* @param sign 签名数据
* @param sCertDN 签名者证书 DN
* @return 验签是否通过
*/
public boolean SYD_NakedVerify(
byte[] orgData,
byte[] sign,
String sCertDN
);
}
/**
* 带原文的签名验签
*/
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);
String SM2SignC(int flag, String pUserID, String privateKey, byte[] publicKey, byte[] orgData);
/**
* SM2 私钥签名
* @param pUserID 使用者的 ID,最大长度为 16 位数字,右对齐。
* @param certNo 证书号
* @param nOrgDataType 原始数据类型 0 : hash 1 : 原数据
* @param publicKey 公钥的 DER 编码
* @param orgData 原始数据
* @return 签名的 base64 编码
*/
String SM2SignC(
String pUserID,
String certNo,
int nOrgDataType,
byte[] publicKey,
byte[] orgData
);
/**
* RSA 私钥签名
* @param HashMark 哈希标识 指示用于哈希证书数据的哈希算法的标识。0: SHA1 1: SHA256 2: MD5。
* @param privateKeyTag 私钥标记 指示私钥位置的标记。数字为存储私钥的索引,除了全9表示使用由命令中提供的密钥。
* 27位的索引号:16位机构号+3位密钥类型+8位密钥索引号
* @param nOrgDataType 原始数据类型 0 : hash 1 : 原数据
* @param orgData 原始数据
* @return 签名的 base64 编码
*/
byte[] RSASignC(
String privateKeyTag,
int HashMark,
int nOrgDataType,
byte[] orgData);
byte[] RSASign(
String privateKey,
int HashMark,
int nOrgDataType,
byte[] orgData);
/**
* 采用 RSA 算法,用指定的公钥对指定的原始数据进行数字签名验证。
* @param HashMark 哈希标识
* @param nOrgDataType 签名方式
* @param publicKey 公钥
* @param orgData 原始数据
* @param sign base64 格式的签名
* @return true 验签通过 false 验签失败
*/
boolean RSAVerify(
int HashMark,
int nOrgDataType,
byte[] publicKey,
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 算法,用指定的公钥对指定的原始数据进行数字签名验证。
* @param certNo id 用于计算SM3-HASH
* @param nOrgDataType 原始数据类型 0 : hash 1 : 原数据,用1.2.3章节限定符亦可
* @param publicKey 公钥
* @param orgData 原始数据
* @param sign base64 格式的签名
* @return true 验签通过 false 验签失败
*/
boolean SM2Verify(
String certNo,
int nOrgDataType,
byte[] publicKey,
byte[] orgData,
String sign
);
/**
* SM2 私钥签名
* @param certNo 证书号
* @param orgData 原始数据
* @return 签名的 base64 编码
*/
String SM2SignCustomized(
String certNo,
byte[] orgData
);
/**
* 采用 SM2 算法,用指定的公钥对指定的原始数据进行数字签名验证。
* @param certNo 证书号
* @param orgData 原始数据
* @param sign base64 格式的签名
* @return true 验签通过 false 验签失败
*/
boolean SM2VerifyCustomized(
String certNo,
byte[] orgData,
String sign
);
/**
* 带公钥证书与原始数据的数字签名(遵循 PKCS#7)
* 使用指定的证书 DN,从加密设备获取对应的私钥证书,对指定的原始数据编制带公钥证书的数字签名(遵循 PKCS#7)。
*
* @param orgData 待签名数据
* @param sCertDN 证书DN
* @return
* 符合PKCS7标准的签名结果
*/
String attachedSign(byte[] orgData, String sCertDN);
/**
* 带公钥证书与原始数据的数字签名验签(遵循 PKCS#7)
* 对指定的原始数据核验其带公钥证书签名。如签名有效(含证书无效)且需返回签名者公钥证书信息时,同时返回签名者公钥证书信息。
*
* @param sign 已签名数据
* @return true 验签通过 false 验签失败
*/
boolean attachedVerify(String sign);
/**
* 带公钥证书与原始数据的数字签名验签(遵循 PKCS#7)
* 对指定的原始数据核验其带公钥证书签名。如签名有效(含证书无效)且需返回签名者公钥证书信息时,同时返回签名者公钥证书信息。
*
* @param sign 已签名数据
* @return 成功返回签名的原数据,失败则报错
*/
String attachedVerifyRD(String sign);
/**
* 带公钥证书与原始数据的数字签名验签(遵循 PKCS#7)
* 对指定的原始数据核验其带公钥证书签名。如签名有效(含证书无效)且需返回签名者公钥证书信息时,同时返回签名者公钥证书信息。
*
* @param sign 已签名数据
* @return
* 若发送报文返回证书信息标志位为0,则返回已签名数据,
* 若发送报文返回证书信息标志位为1,则返回CERT_INFO结构的证书数据
*/
X509 attachedVerifyAndGetX509(String sign);
/**
* 带公钥证书与原始数据的数字签名验签(遵循 PKCS#7)
* 对指定的原始数据核验其带公钥证书签名。如签名有效(含证书无效)且需返回签名者公钥证书信息时,同时返回签名者公钥证书信息。
*
* @param sign 已签名数据
* @return
* 若发送报文返回证书信息标志位为0,则返回已签名数据,
* 若发送报文返回证书信息标志位为1,则返回CERT_INFO结构的证书数据
*/
RetWrap attachedVerifyAndGetAll(String sign);
}
/**
* 不带原文的签名验签
*/
interface SydDetachedSVApi {
/**
* 对指定的原始数据核验其带公钥证书签名(PKCS#7)
* @param orgData 待签名的原始数据
* @param sign 签名数据
* @return 验签是否通过
*/
public boolean SYD_DetachedVerify(
byte[] orgData,
String sign);
/**
* 通过指定的私钥对指定的原始数据编制带公钥证书的数字签名(遵循PKCS#7)
* @param orgData 待签名的原始数据
* @param sCertDN 签名者证书 DN
* @return 签名数据
*/
public String SYD_DetachedSign(
byte[] orgData,
String sCertDN
);
/**
* 通过指定的私钥对指定的原始数据编制带公钥证书的数字签名(遵循PKCS#7)
* 待签名的原始数据将在接口内部进行 sm3 ,然后做 Detach 签名
* @param orgData 待签名的原始数据
* @param publicKey sm3 hash 所用的公钥
* @param sCertDN 签名者证书 DN
* @return 签名数据
*/
public String sm3AndDetachedSign(
byte[] orgData,
String publicKey,
String sCertDN
);
/**
* 对指定的原始数据核验其带公钥证书签名(PKCS#7)
* 原始数据将在接口内部进行 sm3 ,然后做 Detach 验签
* @param orgData 待签名的原始数据
* @param publicKey sm3 hash 所用的公钥
* @param sign 签名数据
* @return 验签是否通过
*/
public boolean sm3AndDetachedVerify(
byte[] orgData,
String publicKey,
String sign);
/**
* 通过指定的私钥对指定的原始数据编制带公钥证书的数字签名(遵循PKCS#7)
* 待签名的原始数据将在接口内部进行不带公钥的 sm3 ,然后做 Detach 签名
* @param orgData 待签名的原始数据
* @param sCertDN 签名者证书 DN
* @return 签名数据
*/
String sm3WithoutPKDetachedSign(byte[] orgData, String sCertDN);
/**
* 对指定的原始数据核验其带公钥证书签名(PKCS#7)
* 原始数据将在接口内部进行无公钥的 sm3 ,然后做 Detach 验签
*
* @param orgData 待签名的原始数据
* @param sign 签名数据
* @return 验签是否通过
*/
boolean sm3WithoutPKDetachedVerify(byte[] orgData, String sign);
/**
*
* 通过指定的私钥对指定的原始数据编制带公钥证书的数字签名(遵循PKCS#7)
* 数据模式可选 DATA_HASH 或 DATA_ORIGIN
*
* @param dataType 数据模式,输入的数据为 HASH 后的数据 DATA_HASH = 0 ,输入的数据为原始数据库 DATA_ORIGIN = 1
* @param orgData 输入的数据
* @param sCertDN 签名者证书 DN
* @return 签名数据
*/
public String detachedSign(
int dataType,
byte[] orgData,
String sCertDN
);
/**
* 带公钥证书与签名属性的数字签名(遵循 PKCS#7)
* @param dataType 数据类型:0,hash 模式,1为非hash模式
* @param orgData 当为hash模式时,值为hash值,当为非hash模式时,值为数据
* @param keyTag 密钥对应的索引号
* @return 签名的 DER 编码
*/
public byte[] detachedSign(
int dataType,
byte[] orgData,
int keyTag
);
/**
* 带公钥证书的PKCS#7数字签名(序列号)
* @param dataType 数据类型:0,hash 模式,1为非hash模式
* @param orgData 当为hash模式时,值为hash值,当为非hash模式时,值为要签名的信息
* @param certificateNo X509证书序号
* @return 符合PKCS7标准的签名结果
*/
public String detachedSignbysn(
int dataType,
byte[] orgData,
String certificateNo);
/**
* 对指定的原始数据核验其带公钥证书签名(PKCS#7)
* 数据模式可选 DATA_HASH 或 DATA_ORIGIN
*
* @param dataType 输入的数据为 HASH 后的数据 DATA_HASH = 0 ,输入的数据为原始数据库 DATA_ORIGIN = 1
* @param orgData 待签名的原始数据
* @param sign 签名数据
* @return 验签是否通过
*/
boolean detachedVerify(
int dataType,
byte[] orgData,
String sign);
/**
* 带公钥证书与签名属性的数字签名验签(遵循 PKCS#7)
* @param dataType 数据类型:0,hash 模式,1为非hash模式
* @param orgData 当为hash模式时,值为hash值,当为非hash模式时,值为数据
* @param sign 已签名数据
* @return 是否正确
*/
boolean detachedVerify(
int dataType,
byte[] orgData,
byte[] sign);
/**
* 对指定的原始数据核验其带公钥证书签名(PKCS#7)返回证书信息
* 数据模式可选 DATA_HASH 或 DATA_ORIGIN
*
* @param dataType 输入的数据为 HASH 后的数据 DATA_HASH = 0 ,输入的数据为原始数据库 DATA_ORIGIN = 1
* @param orgData 待签名的原始数据
* @param sign 签名数据
* @return 证书
*/
X509 detachedVerifyAndGetX509(int dataType,
byte[] orgData,
String sign);
/**
* 计算SM3散列值
* @param packSn 消息块号,0=仅一块,1=第一块,2=中间块,3=最后块
* @param userId 用户 ID,只对“消息块号”为 0、1 时有效
* @param publicKey 公钥的 DER 编码
* @param msg 二进制的消息块
* @param filterData 过渡消息数据,只对“消息块号”为 2、3 时有效
* @return
* filterData: 过渡消息数据,只对“消息块号”为 2、1 时有效
* hash: hash
*/
RetWrap SM3Hash(int packSn, String userId, byte[] publicKey, byte[] msg, byte[] filterData);
}
@@ -0,0 +1,135 @@
package com.sunyard.inf.cryption;
public interface SydASYMApi {
/**
* 非对称加解密接口
*/
/**
* 用指定的 SM2 公钥对指定的密文数据进行加密。
*
* @param publicKey 公钥钥串,DER 编码,HEX 格式。
* @param pOrgData 加密的数据。
* @return 加密的数据 base64 编码。
*/
String SM2Encrypt(
byte[] publicKey,
byte[] pOrgData
);
/**
* 用指定的 SM2 公钥对指定的密文数据进行加密。
*
* @param publicKey 公钥钥串,DER 编码,HEX 格式。
* @param pOrgData 加密的数据。
* @return 加密的数据 der 编码。
*/
byte[] SYD_SM2_Encrypt(byte[] publicKey, byte[] pOrgData);
/**
* 用指定的 SM2 公钥对指定的密文数据进行加密。
* 输出的sm2密文结构为C1C2C3格式
* @param publicKey 公钥钥串,DER 编码,HEX 格式。
* @param pOrgData 加密的数据。
* @return 加密的数据 base64 编码。
*/
String SM2EncryptOrder(byte[] publicKey, byte[] pOrgData);
/**
* 通过使用者 ID 所对应的私钥对指定的密文数据进行解密。
*
* @param userId 使用者的 ID,最大长度为 16 位数字,右对齐。
* @param pEnData 加密的数据,base64 编码。
* @return 明文数据。
*/
byte[] SM2DecryptC(String userId, String pEnData);
/**
* 使用外部私钥解密
* @param sk LMK下加密的私钥
* @param enData 密文数据(base64 编码)
* @return 解密结果
*/
byte[] SM2Decrypt(byte[] sk, String enData);
/**
* 使用外部私钥解密
* @param sk LMK下加密的私钥
* @param enData 密文数据(DER 编码)
* @return 解密结果
*/
byte[] SYD_SM2_Decrypt(byte[] sk, byte[] enData);
/**
* 通过使用者 ID 所对应的私钥对指定的密文数据进行解密。
* 输入的sm2密文结构为C1C2C3格式
* @param userId 使用者的 ID,最大长度为 16 位数字,右对齐。
* @param enData 加密的数据,base64 编码。
* @param keyType 密钥类型,0:签名证书, 1:加密证书。
* @return 明文数据。
*/
byte[] SM2DecryptOrder(String userId, String enData, int keyType);
/**
* 用指定的 RSA 私钥对指定的密文数据进行加密。
*
* @param publicKey 私钥串,DER 编码,HEX 格式。
* @param pOrgData 加密的数据。
* @return 加密的数据 base64 编码。
*/
String RSAEncrypt(
String publicKey,
byte[] pOrgData
);
/**
* 通过使用者 ID 所对应的私钥对指定的密文数据进行解密。
*
* @param userId 使用者的 ID,最大长度为 16 位数字,右对齐。
* @param pEnData 加密的数据,base64 编码。
* @return 明文数据。
*/
byte[] RSADecryptC(
String userId,
String pEnData
) throws Exception;
/**
* 使用外部私钥解密
* @param sk
* @param enData
* @return
*/
public byte[] RSADecrypt(String sk, String enData) throws Exception;
/**
* 非对称公钥加密
* @param alg 算法标识,0 = RSA 1 = SM2
* @param pk 公钥的 DER 编码
* @param data 数据
* @return 公钥加密的密文的 DER 编码(对于 RSA 算法,数据类型为 BIT).
*/
public byte[] encryptByPk(int alg, String pk, byte[] data);
/**
* 非对称私钥解密
* @param alg 算法标识:0 = RSA 1 = SM2
* @param sk 私钥值,LMK下加密的私钥
* @param data 密文数据(DER 编码)
* @return 公钥加密的密文的 DER 编码(对于 RSA 算法,数据类型为 BIT)
*/
public byte[] decryptBySk(int alg, String sk, byte[] data);
/**
* 非对称私钥解密
* @param alg 算法标识:0 = RSA 1 = SM2
* @param userId 16位机构号
* @param data 密文数据(DER 编码)
* @return 公钥加密的密文的 DER 编码(对于 RSA 算法,数据类型为 BIT).
*/
public byte[] decryptBySkC(int alg, String userId, byte[] data);
}
@@ -0,0 +1,77 @@
package com.sunyard.inf.cryption;
import com.sunyard.RetWrap;
/**
* Hash 算法接口
*/
public interface SydHashApi {
/**
* 计算SM3散列值
* @param sn 证书序号
* @param userId 用户ID
* @param msg 原始数据,二进制的消息块
* @return
*/
// byte[] SM3HashSNaId(String sn, String userId, byte[] msg);
/**
* 输入对指定的原始数据和公钥,通过 SM3 算法计算数据的散列值。
* @param publicKey 公钥的 DER 编码(可以为空)
* @param msg 原始数据,二进制的消息块
* @param block 消息块标志
* @param mac 上一轮 mac 值,当 mac 不是 null,长度不为 0,则直接从第二包开始。
* @return HASH 值,32 个 Bytes.
*/
byte[] SM3Hash(String publicKey, byte[] msg, int block, byte[] mac);
/**
* 计算SM3散列值
* @param publicKey 公钥的 DER 编码 (03420004 开头)
* @param userId 用户ID
* @param msg 原始数据,二进制的消息块
* @return
*/
byte[] SM3Hash(String publicKey, String userId, byte[] msg);
/**
* 输入对指定的原始数据和公钥,通过 SM3 算法计算数据的散列值。
*
* @param publicKey 公钥(可以为空)
* @param msg 原始数据
* @return HASH 值,32 个 Bytes.
*/
byte[] SM3Hash(String publicKey, byte[] msg);
/**
* 输入对指定的原始数据 (无公钥),通过 SM3 算法计算数据的散列值。
*
* @param msg 原始数据
* @return HASH 值,32 个 Bytes.
*/
byte[] SM3Hash(byte[] msg);
public byte[] MACCalc(int alg, int keyType, int fullmode, int maclen, String key, byte[] infoData);
/**
* mac 计算
* @param alg 0=DES 1=3DES 2=SM4 3=AES 4=IDEA 5=SM1 6=3DES-X9.19
* @param keyType 0-TAK 1-ZAK
* @param fullMode 0-弱填充 1 强填充
* @param AK 密钥
* @param infoData <=1024
* @param macLen 1=4Byte 2=8Byte 3=16Byte(仅在SM4/AES 下有效)
* @return mac 值 hex 格式
*/
public String MACCalc(int alg, int keyType, String AK, int fullMode, byte[] infoData, int macLen);
public void MACCheck(int alg, int keyType, String AK, int fullMode, byte[] infoData, String mac);
public String calcPBOCMAC(int mode, int keyType, String key, byte[] data, int block, byte[] iv);
public RetWrap countHash(int hashType, int packSn, byte[] msg, byte[] filterData);
public byte[] itHash(int hashType, byte[] orgData);
}
@@ -0,0 +1,282 @@
package com.sunyard.inf.cryption;
import com.sunyard.RetWrap;
import java.io.UnsupportedEncodingException;
/**
* 对称加解密接口
*/
public interface SydSYMApi {
/**
* E0 指令复合接口
* @param isEn 指定加解密,true为加密,false为解密
* @param nAlg 密钥模式,当isEn为true时,默认为SM4加密,0为DES加密,1为AES256 加密。当isEn为false时,默认为SM4解密,0为DES解密,1为AES256解密
* @param seesionKey 密钥
* @param roundmod 轮模式,密钥加密模式:1=ECB,2=CBC,3=CFB,4=OFB
* @param fullMode 填充模式:0为饥饿模式,1为贪婪模式
* @param pInData 消息数据
* @param iv IV
* @param block 消息块号
* @return
* iv: IV 数据域
* msg_all: 消息数据
*/
RetWrap SYMEnDeData(Boolean isEn, int nAlg, String seesionKey, int roundmod, int fullMode, byte[] pInData, byte[] iv, int block);
/**
* 用输入的会话密钥,对指定报文数据进行加密处理。填充模式为1
*
* @param nAlg 算法标识., 0x00:3DES,0x01:SM4。
* @param seesionKey 本地LMK 加密的会话密钥,HEX 格式
* @param pINdata 要加密的报文明文。必须是 8 或16 的倍数。
* @return 输出的报文密文, 长度为报文明文 + 16
*/
byte[] SYMEncryptData(int nAlg, String seesionKey, byte[] pINdata);
/**
* 对指定报文数据进行SM4加密
* @param type 密钥类型。0: ZEK,1: TEK
* @param userId 生成密钥时的机构号。
* @param index 密钥索引
* @param data 待加密的数据
* @return
*/
byte[] SYMSM4EncDataByIndex(int type, String userId, String index, byte[] data);
/**
* 用输入的会话密钥,对指定报文数据进行加密处理。
*
* @param nAlg 算法标识.,0x00:3DES,0x01:SM4。
* @param seesionKey 本地LMK 加密的会话密钥,HEX 格式
* @param fullmode 填充模式:0为饥饿模式,1为贪婪模式
* @param pINdata 要加密的报文明文。必须是 8 或16 的倍数。
* @return 输出的报文密文, 长度为报文明文 + 16
*/
byte[] SYMEncryptData(int nAlg, String seesionKey, int fullmode, byte[] pINdata);
// List<byte[]> SYMEncryptDecryptBatchData(int nAlg, String[] seesionKey, int fullmode, List<byte[]> pINdata);
/**
* 用输入的会话密钥,对指定报文数据进行加密处理。
*
* @param nAlg 算法标识.,0x00:3DES,0x01:SM4。
* @param seesionKey 本地LMK 加密的会话密钥,HEX 格式
* @param pInData 要加密的报文明文。必须是 8 或16 的倍数。
* @return 输出的报文密文, 长度为报文明文 + 16
*/
byte[] SYMEncryptData_nofill(int nAlg, String seesionKey, byte[] pInData);
/**
* 用输入的会话密钥,对指定报文数据进行解密处理。填充模式为1
*
* @param nAlg  算法标识.0x00:3DES,0x01:SM4。
* @param seesionKey 本地LMK 加密的会话密钥,HEX 格式
* @param pINdata 要解密的报文密文。长度必须是8 或16 的倍数。
* @return 输出的报文明文。
*/
byte[] SYMDecryptData(int nAlg, String seesionKey, byte[] pINdata);
/**
* 用输入的会话密钥,对指定报文数据进行解密处理。
*
* @param nAlg  算法标识.,0x00:3DES,0x01:SM4。
* @param seesionKey 本地LMK 加密的会话密钥,HEX 格式
* @param fullmode 填充模式:0为饥饿模式,1为贪婪模式
* @param pINdata 要解密的报文密文。长度必须是8 或16 的倍数。
* @return 输出的报文明文。
*/
byte[] SYMDecryptData(int nAlg, String seesionKey, int fullmode, byte[] pINdata);
/**
* 用输入的会话密钥,对指定报文数据进行解密处理。
*
* @param nAlg  算法标识.,0x00:3DES,0x01:SM4。
* @param seesionKey 本地LMK 加密的会话密钥,HEX 格式
* @param pInData 要解密的报文密文。长度必须是8 或16 的倍数。
* @return 输出的报文明文。
*/
byte[] SYMDecryptData_nofill(int nAlg, String seesionKey, byte[] pInData);
/**
* 加解密数据(E1)
* @param nAlg 密钥模式,默认为SM4解密,0:DES加密,1:AES256 解密
* @param seesionKey 密钥
* @param inputPath 输入消息数据的文件路径
* @param outputPath 输出消息数据的文件路径
* @return
*/
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) throws UnsupportedEncodingException;
/**
* 使用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);
/**
* 用输入的会话密钥,对指定报文数据进行加密处理。
*
* @param nAlg  算法标识.,0x00:3DES,0x01:SM4。
* @param seesionKey  本地LMK 加密的会话密钥,HEX 格式
* @param pINdata  要加密的报文明文。必须是 8 或16 的倍数。
* @return 输出的报文密文, 长度为报文明文 + 16
*/
byte[] SYMEncryptDataCBC(int nAlg, String seesionKey, byte[] pINdata);
/**
* 用输入的会话密钥,对指定报文数据进行加密处理。
*
* @param nAlg  算法标识.,0x00:3DES,0x01:SM4。
* @param seesionKey  本地LMK 加密的会话密钥,HEX 格式
* @param fullmode  填充模式:0为饥饿模式,1为贪婪模式
* @param pInData  要加密的报文明文。必须是 8 或16 的倍数。
* @return 输出的报文密文, 长度为报文明文 + 16
*/
byte[] SYMEncryptDataCBC(int nAlg, String seesionKey, int fullmode, byte[] pInData);
/**
* 用输入的会话密钥,对指定报文数据进行解密处理。
*
* @param nAlg  算法标识.,0x00:3DES,0x01:SM4。
* @param seesionKey 本地LMK 加密的会话密钥,HEX 格式
* @param pINdata 要解密的报文密文。长度必须是8 或16 的倍数。
* @return 输出的报文明文。
*/
byte[] SYMDecryptDataCBC(int nAlg, String seesionKey, byte[] pINdata);
/**
* 用输入的会话密钥,对指定报文数据进行解密处理。
*
* @param nAlg  算法标识.,0x00:3DES,0x01:SM4。
* @param seesionKey 本地LMK 加密的会话密钥,HEX 格式
* @param fullmode 填充模式:0为饥饿模式,1为贪婪模式
* @param pInData 要解密的报文密文。长度必须是8 或16 的倍数。
* @return 输出的报文明文。
*/
byte[] SYMDecryptDataCBC(int nAlg, String seesionKey, int fullmode, byte[] pInData);
/**
* 用输入的会话密钥,对指定报文数据进行解密处理。
*
* @param srcKey  源秘钥.十六进制字符串。
* @param desKey  目的秘钥.十六进制字符串。
* @param sca  源算法SCA.Int类型。
* @param sPin  源PIN块.十六进制字符串。
* @param primaryAccount  主账号.十六进制字符串。
* @return 目的Pin块。
*/
byte[] transPinFrOneKeyToAno(String srcKey, String desKey, int sca, String sPin, String primaryAccount);
/**
* 用一把DEK密钥加密数据, 报文总长度不大于8192
*
* @param alg 加密算法
* @param DEK DEK密钥
* @param infoData 数据
* @param vector 初始向量数据 可选项,当加密模式为CBC,CFB或OFB时才显示此项
* @param disperseAlg 分散算法
* @return 密文数据
*/
byte[] SYD_Encrypt_Data(int alg, String DEK, byte[] infoData, byte[] vector, int disperseAlg, byte[] factor);
/**
* 用DEK密钥解密数据, 报文总长度不大于8192
*
* @param alg 解密算法
* @param DEK DEK密钥
* @param infoData 数据密文
* @param vector 初始向量数据 可选项,当加密模式为CBC,CFB或OFB时才显示此项
* @param disperseAlg 分散算法
* @return 解密后的明文数据
*/
byte[] SYD_Decrypt_Data(int alg, String DEK, byte[] infoData, byte[] vector, int disperseAlg, byte[] factor);
/**
* 对于给定的数据生成一个MAC
*
* @param key LMK对(16-17)下加密的TAK
* @param infoData 生成MAC的数据
* @param IV
* @param disperseNum 指定对根密钥分散的次数(1-3次)
* @param disperseAlg 分散算法
* @return 所计算出的MAC
*/
byte[] SYD_MAC_Data(String key, String infoData, byte[] factor, String IV, int disperseNum, int disperseAlg);
/**
* 对称加密数据
* @param key 索引地址,指示用户密钥存储区的27位地址
* @param intPutData 消息数据
* @return
* iv: IV 数据域
* msg_all: 消息数据
*/
public String SYMEncrytByKeyIndex( String key, String intPutData);
/**
* 对称解密数据
* @param key 索引地址,指示用户密钥存储区的27位地址
* @param intPutData 消息数据
* @return 消息数据
*/
public String SYMDecrytByKeyIndex(String key,String intPutData);
//通过索引读取对称秘钥
RetWrap readKey(String index);
}
@@ -0,0 +1,31 @@
package com.sunyard.inf.customize;
/**
* 上清所数字信封类接口
*/
public interface Syd4DigitalEnvelope {
/**
* 产生对称密钥,通过清算所公钥证书加密生成数字信封。
* 上清所
* @param pcDnEN: 清算所的公钥证书
* @param pcDnSign:会员的私钥证书
* @param pcData: 明文数据。
* @return pcSignData: 签名数字信封
*/
public String SYD_SignDigitalEnvelope (String pcDnEN, String pcDnSign, byte[] pcData);
/**
* 利用清算所公钥证书对签名数据进行验签。接收用会员的私钥证书解密数字信封,还原原文。
* 上清所
* @param pcDnDe: 会员的私钥证书
* @param pcDnVerify: 清算所公钥证书
* @param pcSignData: 签名数字信封数据。
* @return pcData:原数据
*/
public byte[] SYD_VerifyDigitalEnveloe(String pcDnDe, String pcDnVerify, String pcSignData );
}
@@ -117,9 +117,16 @@ public interface SydHAApi {
* @param nOrgDataType 签名数据类型,SydApi.DATA_ORIGIN(1) 原始数据 SydApi.DATA_HASH(0) : hash 后的类型 * @param nOrgDataType 签名数据类型,SydApi.DATA_ORIGIN(1) 原始数据 SydApi.DATA_HASH(0) : hash 后的类型
* @param publicKey 公钥串,DER编码,HEX格式 * @param publicKey 公钥串,DER编码,HEX格式
* @param orgData 待签名的原始数据,“签名数据类型”为 0 时:HASH 值。“签名数据类型”为 1 时:要签名的信息 * @param orgData 待签名的原始数据,“签名数据类型”为 0 时:HASH 值。“签名数据类型”为 1 时:要签名的信息
* @param base64Sign 签名数据 (DER 编码 + Base64 编码) * @param sign S+R
* @return 验签是否通过 * @return 验签是否通过
*/ */
public boolean SM2Verify(
int nOrgDataType,
byte[] publicKey,
byte[] orgData,
byte[] sign
);
public boolean SM2Verify( public boolean SM2Verify(
int nOrgDataType, int nOrgDataType,
byte[] publicKey, byte[] publicKey,
@@ -1,185 +0,0 @@
package com.sunyard.inf.customize;
import com.sunyard.SydApiException;
import com.sunyard.cert.X509;
import com.sunyard.proto.Packet;
import com.sunyard.proto.PacketSection;
import com.sunyard.proto.Util;
import com.sunyard.trans.PacketSN;
import racal.sunyard.main.SydApi4j;
import racal.sunyard.main.proto.Proto8003;
import racal.sunyard.main.proto.Proto8004;
import racal.sunyard.main.proto.Proto8012;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
public class SydSDNXApiImpl extends SydApi4j implements SydSDNXApi {
public String nakedSign(byte[] orgData, String sCertDN) {
Proto8003 proto = new Proto8003(); //pset.getProtocolReqRender("75");
byte[] dn = new byte[256];
byte[] s = null;
try {
s = sCertDN.getBytes("GBK");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
System.arraycopy(s, 0, dn, 0, s.length);
// 填充数据
HashMap<String, Object> packet = new HashMap<String, Object>();
HashMap<String, Object> data = new HashMap<String, Object>();
packet.put("data", data);
PacketSN sn = PacketSN.gen();
packet.put("header", sn.getSn().array());
data.put("signatureDataType$option", 1);
data.put("DN", dn);
data.put("data", orgData);
// 渲染发送
ByteBuffer bb = proto.rend(packet);
synchronized (this) {
// 响应解析
bb = syncRead(syncSend(bb));
}
Packet p = proto.parse(bb);
Map<String, Object> ret = p.toMap();
if (
!Arrays.equals(sn.getSn().array(), ((PacketSection) ret.get("header")).getBytes())
) {
throw new SydApiException("包序号不匹配", -4);
}
ret = (Map<String, Object>) ret.get("data");
PacketSection error = (PacketSection) ret.get("error");
byte[] be = error.getBytes();
if (
(0 != (be[0] ^ be[1]))) {
throw new SydApiException(error.getInfo(), error.autoInt());
}
return Util.encodeBase64(((PacketSection) ret.get("signature")).getBytes());
//return ((PacketSection) ret.get("signature")).getBytes();
}
@Override
public boolean SYD_NakedVerify(byte[] orgData, String sign, String organizationNum) {
Proto8004 proto = new Proto8004(); //pset.getProtocolReqRender("75");
byte[] dn = new byte[256];
byte[] s = null;
// 填充数据
HashMap<String, Object> packet = new HashMap<String, Object>();
HashMap<String, Object> data = new HashMap<String, Object>();
packet.put("data", data);
PacketSN sn = PacketSN.gen();
packet.put("header", sn.getSn().array());
data.put("signatureDataType$option", 2);
data.put("organizationNum", organizationNum);
data.put("data", orgData);
data.put("signature", Util.decodeBase64(sign));
data.put("returnSign$option", 0);
// 渲染发送
ByteBuffer bb = proto.rend(packet);
synchronized (this) {
// 响应解析
bb = syncRead(syncSend(bb));
}
Packet p = proto.parse(bb, packet);
Map<String, Object> ret = p.toMap();
if (
!Arrays.equals(sn.getSn().array(), ((PacketSection) ret.get("header")).getBytes())
) {
throw new SydApiException("包序号不匹配", -4);
}
ret = (Map<String, Object>) ret.get("data");
PacketSection error = (PacketSection) ret.get("error");
byte[] be = error.getBytes();
if ((0 != (be[0] ^ be[1]))) {
throw new SydApiException(error.getInfo(), error.autoInt());
}
return true;
}
@Override
public X509 SYD_Get_X509_CertInfo_HA(String bNumber, byte[] orgData, String sign) {
Proto8012 proto = new Proto8012(); //pset.getProtocolReqRender("75");
// 填充数据
HashMap<String, Object> packet = new HashMap<String, Object>();
HashMap<String, Object> data = new HashMap<String, Object>();
packet.put("data", data);
PacketSN sn = PacketSN.gen();
packet.put("header", sn.getSn().array());
data.put("originData", orgData);
data.put("signData", sign.getBytes());
data.put("flag$option", 2);
data.put("organizationNum", bNumber);
// 渲染发送
ByteBuffer bb = proto.rend(packet);
synchronized (this) {
// 响应解析
bb = syncRead(syncSend(bb));
}
Packet p = proto.parse(bb, packet);
Map<String, Object> ret = p.toMap();
if (
!Arrays.equals(sn.getSn().array(), ((PacketSection) ret.get("header")).getBytes())
) {
throw new SydApiException("包序号不匹配", -4);
}
ret = (Map<String, Object>) ret.get("data");
PacketSection error = (PacketSection) ret.get("error");
byte[] be = error.getBytes();
if ((0 != (be[0] ^ be[1]))) {
throw new SydApiException(error.getInfo(), error.autoInt());
}
PacketSection info = (PacketSection) ret.get("info");
byte[] pCertInfo = info.getBytes();
// X509 cinfo = new X509();
// cinfo.setIssuer(Util.toCleanString(pCertInfo, 0, 257));
// cinfo.setSerialNumber(Util.toCleanString(pCertInfo, 257, 65));
// cinfo.setSubject(Util.toCleanString(pCertInfo, 257 + 65, 257));
// cinfo.setNotBefore(Util.toCleanString(pCertInfo, 257 + 65 + 257, 15));
// cinfo.setNotAfter(Util.toCleanString(pCertInfo, 257 + 65 + 257 + 15, 15));
// byte[] blen = new byte[]{pCertInfo[257 + 65 + 257 + 15 + 15], pCertInfo[257 + 65 + 257 + 15 + 16]};
// int len = Util.b2i(blen);
// byte[] pem = new byte[len];
// System.arraycopy(pCertInfo, 257 + 65 + 257 + 15 + 17, pem, 0, len);
// String pp = new String(pem);
// 解析证书
return GetX509CertInfo(new String(pCertInfo));
}
}
@@ -0,0 +1,212 @@
package com.sunyard.inf.sva;
import com.sunyard.RetWrap;
import com.sunyard.cert.X509;
import java.io.UnsupportedEncodingException;
/**
* 带原文的签名验签
*/
public interface SydAttachedSVApi {
/**
* sm2私钥签名
* 用户id默认为1234567812345678
* 签名结果R/S序列串先进行der编码,再进行base64编码
*
* @param flag 私钥标志位,当为1时第二个参数传入存储私钥的索引,当为0时第二个参数传入私钥
* @param privateKey 当私钥标志位为1时传入存储私钥的索引,当为0时传入私钥
* @param publicKey 公钥
* @param orgData 要签名的信息
* @return 签名结果
*/
byte[] SM2SignC(int flag, String privateKey, byte[] publicKey, byte[] orgData);
byte[] SM2SignC(int flag, String pUserID, String privateKey, byte[] publicKey, byte[] orgData);
/**
* SM2 私钥签名
* @param pUserID 使用者的 ID,最大长度为 16 位数字,右对齐。
* @param certNo 证书号
* @param nOrgDataType 原始数据类型 0 : hash 1 : 原数据
* @param publicKey 公钥的 DER 编码
* @param orgData 原始数据
* @return 签名的 base64 编码
*/
String SM2SignC(
String pUserID,
String certNo,
int nOrgDataType,
byte[] publicKey,
byte[] orgData
);
/**
* RSA 私钥签名
* @param HashMark 哈希标识 指示用于哈希证书数据的哈希算法的标识。0: SHA1 1: SHA256 2: MD5。
* @param privateKeyTag 私钥标记 指示私钥位置的标记。数字为存储私钥的索引,除了全9表示使用由命令中提供的密钥。
* 27位的索引号:16位机构号+3位密钥类型+8位密钥索引号
* @param nOrgDataType 原始数据类型 0 : hash 1 : 原数据
* @param orgData 原始数据
* @return 签名的 base64 编码
*/
byte[] RSASignC(
String privateKeyTag,
int HashMark,
int nOrgDataType,
byte[] orgData);
byte[] RSASign(
String privateKey,
int HashMark,
int nOrgDataType,
byte[] orgData);
/**
* 采用 RSA 算法,用指定的公钥对指定的原始数据进行数字签名验证。
* @param HashMark 哈希标识
* @param nOrgDataType 签名方式
* @param publicKey 公钥
* @param orgData 原始数据
* @param sign base64 格式的签名
* @return true 验签通过 false 验签失败
*/
boolean RSAVerify(
int HashMark,
int nOrgDataType,
byte[] publicKey,
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 算法,用指定的公钥对指定的原始数据进行数字签名验证。
* @param certNo id 用于计算SM3-HASH
* @param nOrgDataType 原始数据类型 0 : hash 1 : 原数据,用1.2.3章节限定符亦可
* @param publicKey 公钥
* @param orgData 原始数据
* @param sign base64 格式的签名
* @return true 验签通过 false 验签失败
*/
boolean SM2Verify(
String certNo,
int nOrgDataType,
byte[] publicKey,
byte[] orgData,
byte[] sign
);
/**
* SM2 私钥签名
* @param certNo 证书号
* @param orgData 原始数据
* @return 签名的 base64 编码
*/
String SM2SignCustomized(
String certNo,
byte[] orgData
);
/**
* 采用 SM2 算法,用指定的公钥对指定的原始数据进行数字签名验证。
* @param certNo 证书号
* @param orgData 原始数据
* @param sign base64 格式的签名
* @return true 验签通过 false 验签失败
*/
boolean SM2VerifyCustomized(
String certNo,
byte[] orgData,
String sign
);
/**
* 带公钥证书与原始数据的数字签名(遵循 PKCS#7)
* 使用指定的证书 DN,从加密设备获取对应的私钥证书,对指定的原始数据编制带公钥证书的数字签名(遵循 PKCS#7)。
*
* @param orgData 待签名数据
* @param sCertDN 证书DN
* @return
* 符合PKCS7标准的签名结果
*/
String attachedSign(byte[] orgData, String sCertDN) throws UnsupportedEncodingException;
byte[] attachedSignC(byte[] orgData, String sCertDN);
/**
* 人行项目需要需要支持RSA
* 带公钥证书与原始数据的数字签名(遵循 PKCS#7)
* 使用指定的证书 DN,从加密设备获取对应的私钥证书,对指定的原始数据编制带公钥证书的数字签名(遵循 PKCS#7)。
*
* @param orgData 待签名数据
* @param sCertDN 证书DN
* @return
* 符合PKCS7标准的签名结果
*/
String attachedSignRSA(int rFlag,byte[] orgData, String sCertDN) throws UnsupportedEncodingException;
/**
* 带公钥证书与原始数据的数字签名验签(遵循 PKCS#7)
* 对指定的原始数据核验其带公钥证书签名。如签名有效(含证书无效)且需返回签名者公钥证书信息时,同时返回签名者公钥证书信息。
*
* @param sign 已签名数据
* @return true 验签通过 false 验签失败
*/
boolean attachedVerify(String sign);
/**
* 带公钥证书与原始数据的数字签名验签(遵循 PKCS#7)
* 对指定的原始数据核验其带公钥证书签名。如签名有效(含证书无效)且需返回签名者公钥证书信息时,同时返回签名者公钥证书信息。
*
* @param sign 已签名数据
* @return true 验签通过 false 验签失败
*/
boolean attachedVerifyRSA(int rFlag,String sign);
boolean attachedVerify(byte[] sign);
/**
* 带公钥证书与原始数据的数字签名验签(遵循 PKCS#7)
* 对指定的原始数据核验其带公钥证书签名。如签名有效(含证书无效)且需返回签名者公钥证书信息时,同时返回签名者公钥证书信息。
*
* @param sign 已签名数据
* @return 成功返回签名的原数据,失败则报错
*/
byte[] attachedVerifyRD(byte[] sign);
byte[] attachedVerifyRD(String sign);
/**
* 带公钥证书与原始数据的数字签名验签(遵循 PKCS#7)
* 对指定的原始数据核验其带公钥证书签名。如签名有效(含证书无效)且需返回签名者公钥证书信息时,同时返回签名者公钥证书信息。
*
* @param sign 已签名数据
* @return
* 若发送报文返回证书信息标志位为0,则返回已签名数据,
* 若发送报文返回证书信息标志位为1,则返回CERT_INFO结构的证书数据
*/
X509 attachedVerifyAndGetX509(byte[] sign);
X509 attachedVerifyAndGetX509(String sign);
/**
* 带公钥证书与原始数据的数字签名验签(遵循 PKCS#7)
* 对指定的原始数据核验其带公钥证书签名。如签名有效(含证书无效)且需返回签名者公钥证书信息时,同时返回签名者公钥证书信息。
*
* @param sign 已签名数据
* @return
* 若发送报文返回证书信息标志位为0,则返回已签名数据,
* 若发送报文返回证书信息标志位为1,则返回CERT_INFO结构的证书数据
*/
RetWrap attachedVerifyAndGetAll(byte[] sign);
}
@@ -0,0 +1,178 @@
package com.sunyard.inf.sva;
import com.sunyard.RetWrap;
import com.sunyard.cert.X509;
/**
* 不带原文的签名验签
*/
public interface SydDetachedSVApi {
/**
* 对指定的原始数据核验其带公钥证书签名(PKCS#7)
* @param orgData 待签名的原始数据
* @param sign 签名数据
* @return 验签是否通过
*/
public boolean SYD_DetachedVerify(
byte[] orgData,
String sign);
/**
* 通过指定的私钥对指定的原始数据编制带公钥证书的数字签名(遵循PKCS#7)
* @param orgData 待签名的原始数据
* @param sCertDN 签名者证书 DN
* @return 签名数据
*/
public String SYD_DetachedSign(
byte[] orgData,
String sCertDN
);
/**
* 通过指定的私钥对指定的原始数据编制带公钥证书的数字签名(遵循PKCS#7)
* 待签名的原始数据将在接口内部进行 sm3 ,然后做 Detach 签名
* @param orgData 待签名的原始数据
* @param publicKey sm3 hash 所用的公钥
* @param sCertDN 签名者证书 DN
* @return 签名数据
*/
public String sm3AndDetachedSign(
byte[] orgData,
String publicKey,
String sCertDN
);
/**
* 对指定的原始数据核验其带公钥证书签名(PKCS#7)
* 原始数据将在接口内部进行 sm3 ,然后做 Detach 验签
* @param orgData 待签名的原始数据
* @param publicKey sm3 hash 所用的公钥
* @param sign 签名数据
* @return 验签是否通过
*/
public boolean sm3AndDetachedVerify(
byte[] orgData,
String publicKey,
String sign);
/**
* 通过指定的私钥对指定的原始数据编制带公钥证书的数字签名(遵循PKCS#7)
* 待签名的原始数据将在接口内部进行不带公钥的 sm3 ,然后做 Detach 签名
* @param orgData 待签名的原始数据
* @param sCertDN 签名者证书 DN
* @return 签名数据
*/
String sm3WithoutPKDetachedSign(byte[] orgData, String sCertDN);
/**
* 对指定的原始数据核验其带公钥证书签名(PKCS#7)
* 原始数据将在接口内部进行无公钥的 sm3 ,然后做 Detach 验签
*
* @param orgData 待签名的原始数据
* @param sign 签名数据
* @return 验签是否通过
*/
boolean sm3WithoutPKDetachedVerify(byte[] orgData, String sign);
/**
*
* 通过指定的私钥对指定的原始数据编制带公钥证书的数字签名(遵循PKCS#7)
* 数据模式可选 DATA_HASH 或 DATA_ORIGIN
*
* @param dataType 数据模式,输入的数据为 HASH 后的数据 DATA_HASH = 0 ,输入的数据为原始数据库 DATA_ORIGIN = 1
* @param orgData 输入的数据
* @param sCertDN 签名者证书 DN
* @return 签名数据
*/
public String detachedSign(
int dataType,
byte[] orgData,
String sCertDN
);
/**
* 带公钥证书与签名属性的数字签名(遵循 PKCS#7)
* @param dataType 数据类型:0,hash 模式,1为非hash模式
* @param orgData 当为hash模式时,值为hash值,当为非hash模式时,值为数据
* @param keyTag 密钥对应的索引号
* @return 签名的 DER 编码
*/
public byte[] detachedSign(
int dataType,
byte[] orgData,
int keyTag
);
/**
* 带公钥证书的PKCS#7数字签名(序列号)
* @param dataType 数据类型:0,hash 模式,1为非hash模式
* @param orgData 当为hash模式时,值为hash值,当为非hash模式时,值为要签名的信息
* @param certificateNo X509证书序号
* @return 符合PKCS7标准的签名结果
*/
public String detachedSignbysn(
int dataType,
byte[] orgData,
String certificateNo);
/**
* 对指定的原始数据核验其带公钥证书签名(PKCS#7)
* 数据模式可选 DATA_HASH 或 DATA_ORIGIN
*
* @param dataType 输入的数据为 HASH 后的数据 DATA_HASH = 0 ,输入的数据为原始数据库 DATA_ORIGIN = 1
* @param orgData 待签名的原始数据
* @param sign 签名数据
* @return 验签是否通过
*/
boolean detachedVerify(
int dataType,
byte[] orgData,
String sign);
/**
* 带公钥证书与签名属性的数字签名验签(遵循 PKCS#7)
* @param dataType 数据类型:0,hash 模式,1为非hash模式
* @param orgData 当为hash模式时,值为hash值,当为非hash模式时,值为数据
* @param sign 已签名数据
* @return 是否正确
*/
boolean detachedVerify(
int dataType,
byte[] orgData,
byte[] sign);
/**
* 对指定的原始数据核验其带公钥证书签名(PKCS#7)返回证书信息
* 数据模式可选 DATA_HASH 或 DATA_ORIGIN
*
* @param dataType 输入的数据为 HASH 后的数据 DATA_HASH = 0 ,输入的数据为原始数据库 DATA_ORIGIN = 1
* @param orgData 待签名的原始数据
* @param sign 签名数据
* @return 证书
*/
X509 detachedVerifyAndGetX509(int dataType,
byte[] orgData,
String sign);
/**
* 计算SM3散列值
* @param packSn 消息块号,0=仅一块,1=第一块,2=中间块,3=最后块
* @param userId 用户 ID,只对“消息块号”为 0、1 时有效
* @param publicKey 公钥的 DER 编码
* @param msg 二进制的消息块
* @param filterData 过渡消息数据,只对“消息块号”为 2、3 时有效
* @return
* filterData: 过渡消息数据,只对“消息块号”为 2、1 时有效
* hash: hash
*/
RetWrap SM3Hash(int packSn, String userId, byte[] publicKey, byte[] msg, byte[] filterData);
}
@@ -0,0 +1,32 @@
package com.sunyard.inf.sva;
/**
* 不经过 CA 授信
* 直接使用公私钥对签名验签
*/
public interface SydNakedSVApi {
/**
* 使用指定的证书 DN,从加密设备获取对应的私钥证书,对指定的原始数据编制裸签名(遵循 PKCS#1)
* @param orgData 待签名的原始数据
* @param sCertDN 签名者证书 DN
* @return 签名数据
*/
public byte[] SYD_NakedSign(
byte[] orgData,
String sCertDN
);
/**
* 使用指定的证书 DN,对指定的原始数据编制裸验签(遵循PKCS#1)
* @param orgData 待签名的原始数据
* @param sign 签名数据
* @param sCertDN 签名者证书 DN
* @return 验签是否通过
*/
public boolean SYD_NakedVerify(
byte[] orgData,
byte[] sign,
String sCertDN
);
}
@@ -1,5 +1,5 @@
package com.sunyard.log; package com.sunyard.log;
public interface ILogFactory { public interface ILogFactory {
ILogger getLogger(Class var1); ILogger getLogger(Class cls);
} }
+4 -6
View File
@@ -1,13 +1,11 @@
package com.sunyard.log; package com.sunyard.log;
public interface ILogger { public interface ILogger {
int getCurrentLogLevel();
void error(String var1, Object... var2); public int getCurrentLogLevel();
void info(String var1, Object... var2); public void error(String msg, Object ...params);
public void info(String msg, Object ...params);
public void debug(String msg, Object ...params);
void debug(String var1, Object... var2);
boolean isDebugEnabled();
} }
@@ -1,10 +1,4 @@
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package com.sunyard.log; package com.sunyard.log;
import java.io.File; import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
@@ -14,87 +8,110 @@ import java.util.concurrent.Executor;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
public class SydLogFactory implements ILogFactory { public class SydLogFactory implements ILogFactory {
// 日期格式
private static SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); private static SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
// 日志目录
public static String pcLogPath = "./sydapi-logs/"; public static String pcLogPath = "./sydapi-logs/";
// 日志名
public static final String logName = "sydapi-log"; public static final String logName = "sydapi-log";
// 日志级别
public static int iLogLevel = 0; public static int iLogLevel = 0;
private static ConcurrentLinkedQueue<SydLogInfo> queue = new ConcurrentLinkedQueue();
// 日志队列
private static ConcurrentLinkedQueue<SydLogInfo> queue = new ConcurrentLinkedQueue<SydLogInfo>();
// 调试标记
public static boolean debug = false; public static boolean debug = false;
// 后台打印进程
private static Executor executor = Executors.newSingleThreadExecutor(); private static Executor executor = Executors.newSingleThreadExecutor();
static { static {
executor.execute(new Runnable() { executor.execute(new Runnable() {
@Override
public void run() { public void run() {
String logFileName = ""; String logFileName = "";
FileOutputStream logFos = null; FileOutputStream logFos = null;
while(true) { while (true) {
while(true) { try {
while(true) {
try {
if (SydLogFactory.queue.isEmpty()) {
Thread.sleep(500L);
} else {
String mayLogFileName = String.format("%s_%s.log", "sydapi-log", SydLogFactory.format.format(new Date()));
if (!logFileName.equals(mayLogFileName)) {
logFileName = mayLogFileName;
if (logFos != null) {
logFos.flush();
logFos.close();
}
File folder = new File(SydLogFactory.pcLogPath); if (queue.isEmpty()) {
if (!folder.exists()) { // 释放 CPU
folder.mkdirs(); Thread.sleep(500);
} continue;
File f = new File(SydLogFactory.pcLogPath, logFileName);
if (!f.exists()) {
f.createNewFile();
}
logFos = new FileOutputStream(f, true);
}
while(!SydLogFactory.queue.isEmpty()) {
SydLogInfo info = (SydLogInfo)SydLogFactory.queue.poll();
logFos.write(String.format("[%d:%s <%s-%d>] %s\r\n", info.getLevel(), SydLogFactory.format.format(new Date(info.getDatatime())), info.getTname(), info.getTid(), info.getMsg()).getBytes());
}
logFos.flush();
}
} catch (Exception var9) {
Exception e = var9;
e.printStackTrace();
} finally {
SydLogFactory.closeFileOutputStream(logFos);
logFileName = "";
}
} }
// 有日志
// 确认日期
String mayLogFileName = String.format("%s_%s.log", logName, format.format( new Date()));
if ( ! logFileName.equals( mayLogFileName ) ) {
logFileName = mayLogFileName;
if ( null != logFos ) {
logFos.flush();
logFos.close();
}
File folder = new File( pcLogPath );
if ( ! folder.exists() ) {
folder.mkdirs();
}
File f = new File( pcLogPath, logFileName );
if ( ! f.exists() ) {
f.createNewFile();
}
logFos = new FileOutputStream( f , true);
}
while (!queue.isEmpty()) {
SydLogInfo info = queue.poll();
logFos.write(String.format("[%d:%s <%s-%d>] %s\r\n",
info.getLevel(),
format.format( new Date(info.getDatatime()) ),
info.getTname(),
info.getTid(),
info.getMsg()
).getBytes()
);
}
logFos.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
closeFileOutputStream(logFos);
logFileName = "";
} }
} }
} }
}); });
} }
private static void closeFileOutputStream(FileOutputStream fos) {
if (fos != null) { private static void closeFileOutputStream(FileOutputStream fos){
if ( null != fos ) {
try { try {
fos.flush(); fos.flush();
} catch (Exception var2) { }catch (Exception e) {
//pass
} }
try { try {
fos.close(); fos.close();
} catch (Exception var1) { }catch (Exception e) {
//pass
} }
} }
} }
private SydLogFactory() { private SydLogFactory() {
} }
@Override
public ILogger getLogger(Class cls) { public ILogger getLogger(Class cls) {
return new SydLogger(queue); return new SydLogger(queue);
} }
+7 -11
View File
@@ -1,10 +1,6 @@
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package com.sunyard.log; package com.sunyard.log;
public class SydLogInfo { public class SydLogInfo {
private int level; private int level;
private long datatime; private long datatime;
@@ -23,26 +19,26 @@ public class SydLogInfo {
} }
public int getLevel() { public int getLevel() {
return this.level; return level;
} }
public long getDatatime() { public long getDatatime() {
return this.datatime; return datatime;
} }
public String getTname() { public String getTname() {
return this.tname; return tname;
} }
public long getTid() { public long getTid() {
return this.tid; return tid;
} }
public String getMsg() { public String getMsg() {
return this.msg; return msg;
} }
public Object[] getObjects() { public Object[] getObjects() {
return this.objects; return objects;
} }
} }
+9 -14
View File
@@ -1,42 +1,36 @@
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package com.sunyard.log; package com.sunyard.log;
import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ConcurrentLinkedQueue;
public class SydLogger implements ILogger { public class SydLogger implements ILogger{
private ConcurrentLinkedQueue<SydLogInfo> queue; private ConcurrentLinkedQueue<SydLogInfo> queue;
SydLogger(ConcurrentLinkedQueue<SydLogInfo> queue) { SydLogger(ConcurrentLinkedQueue<SydLogInfo> queue) {
this.queue = queue; this.queue = queue;
} }
@Override
public void debug(String msg, Object... params) { public void debug(String msg, Object... params) {
if (SydLogFactory.iLogLevel == 3) { if (SydLogFactory.iLogLevel == 3) {
this.queue.add(new SydLogInfo(3, msg, params)); this.queue.add(new SydLogInfo(3, msg, params));
} else {
return;
} }
} }
@Override
public boolean isDebugEnabled() {
return SydLogFactory.iLogLevel == 3;
}
@Override
public void info(String msg, Object... params) { public void info(String msg, Object... params) {
if (SydLogFactory.iLogLevel >= 2) { if (SydLogFactory.iLogLevel >= 2) {
this.queue.add(new SydLogInfo(2, msg, params)); this.queue.add(new SydLogInfo(2, msg, params));
} else {
return;
} }
} }
@Override
public void error(String msg, Object... params) { public void error(String msg, Object... params) {
if (SydLogFactory.iLogLevel >= 1) { if (SydLogFactory.iLogLevel >= 1) {
this.queue.add(new SydLogInfo(1, msg, params)); this.queue.add(new SydLogInfo(1, msg, params));
} else {
return;
} }
} }
@@ -44,4 +38,5 @@ public class SydLogger implements ILogger {
public int getCurrentLogLevel() { public int getCurrentLogLevel() {
return SydLogFactory.iLogLevel; return SydLogFactory.iLogLevel;
} }
} }
@@ -0,0 +1,63 @@
package com.sunyard.pool;
/**
* 到加密机的链接信息
*/
public class HsmLinkInfo {
private String pcIp;
private int iPort;
private int iConnectTimeOut;
private int iDealTimeOut;
public HsmLinkInfo(String pcIp, int iPort, int iConnectTimeOut, int iDealTimeOut) {
this.pcIp = pcIp;
this.iPort = iPort;
this.iConnectTimeOut = iConnectTimeOut;
this.iDealTimeOut = iDealTimeOut;
}
public static HsmLinkInfo[] mutiHsmLinkInfo(String[] pcIpList, int[] iPortList, int iConnectTimeOut, int iAllDealTimeOut) {
if (null == pcIpList &&
null == iPortList &&
pcIpList.length != iPortList.length) {
throw new IllegalArgumentException("入参错误");
}
if ( iAllDealTimeOut < pcIpList.length) {
throw new IllegalArgumentException("入参错误");
}
// 交易时间进行处理
int iDealTimeOut = iAllDealTimeOut / pcIpList.length;
HsmLinkInfo[]hsms = new HsmLinkInfo[ pcIpList.length ];
for ( int i = 0 ; i < pcIpList.length ; i++ ) {
hsms[ i ] = new HsmLinkInfo( pcIpList[i], iPortList[i], iConnectTimeOut, iDealTimeOut );
}
return hsms;
}
public String getPcIp() {
return pcIp;
}
public int getiPort() {
return iPort;
}
public int getiConnectTimeOut() {
return iConnectTimeOut;
}
public int getiDealTimeOut() {
return iDealTimeOut;
}
}
@@ -0,0 +1,28 @@
package com.sunyard.pool;
public class ObjectInPool<T> {
private T object;
private long lasUseAt = System.currentTimeMillis();
public ObjectInPool(T object) {
this.object = object;
}
public T getObjectForCheck() {
return this.object;
}
public void updateLastUseTime(){
this.lasUseAt = System.currentTimeMillis();
}
public T getObject() {
this.lasUseAt = System.currentTimeMillis();
return this.object;
}
public long getLasUseAt() {
return this.lasUseAt;
}
}
@@ -0,0 +1,26 @@
package com.sunyard.pool;
public class PoolConfig {
// 最大空闲时间
private long maxIdle = 5 * 60 *1000; // 5 分钟
// 最大无用时间
private long maxUseless = 30 * 60 * 1000; // 30 分钟
public long getMaxIdle() {
return maxIdle;
}
public void setMaxIdle(long maxIdle) {
this.maxIdle = maxIdle;
}
public long getMaxUseless() {
return maxUseless;
}
public void setMaxUseless(long maxUseless) {
this.maxUseless = maxUseless;
}
}
@@ -0,0 +1,84 @@
package com.sunyard.pool;
import com.sunyard.SydApi;
import com.sunyard.SydApiException;
import com.sunyard.proxy.ProxyInvocationHandler;
import racal.sunyard.main.SydApi4j;
public class SydApiPool extends ThreadBasedConnectPool<SydApi> {
private HsmLinkInfo[] linkInfos;
public SydApiPool(HsmLinkInfo[] linkInfos) {
this.linkInfos = linkInfos;
}
protected SydApi initialValue() {
SydApi4j[] apis = new SydApi4j[this.linkInfos.length];
boolean connected = false;
for(int i = 0; i < apis.length; ++i) {
HsmLinkInfo info = this.linkInfos[i];
try {
apis[i] = (SydApi4j)(new SydApi4j()).connect(info.getPcIp(), info.getiPort(), (String)null, info.getiConnectTimeOut(), info.getiDealTimeOut());
connected = true;
} catch (Exception var6) {
}
}
if (!connected) {
throw new SydApiException("连接错误", -1);
} else {
ProxyInvocationHandler proxyInvocationHandler = new ProxyInvocationHandler(apis, this.linkInfos, false);
return proxyInvocationHandler.getProxy();
}
}
public boolean check(SydApi s) {
boolean ret = super.check(s);
if (!ret) {
return false;
} else {
ProxyInvocationHandler o = (ProxyInvocationHandler)s.getBindObject();
try {
SydApi4j[] hsms = o.getApis();
boolean canUse = false;
int length = hsms.length;
for(int i = 0; i < length; ++i) {
if (null != hsms[i]) {
try {
synchronized(hsms[i]) {
hsms[i].GenerateRandom(1);
canUse = true;
}
} catch (Exception var12) {
hsms[i] = null;
}
} else {
HsmLinkInfo[] infos = o.getApisInfos();
HsmLinkInfo info = infos[i];
try {
hsms[i] = (SydApi4j)(new SydApi4j()).connect(info.getPcIp(), info.getiPort(), (String)null, info.getiConnectTimeOut(), info.getiDealTimeOut());
canUse = true;
} catch (Exception e) {
}
}
}
return canUse;
} catch (Exception e) {
return false;
}
}
}
protected void free(SydApi o) {
if (null != o) {
o.disconnect();
}
}
}
@@ -0,0 +1,125 @@
package com.sunyard.pool;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ThreadBasedConnectPool<T> {
// ThreadLocal
private final Map<Thread, ObjectInPool<T>> map = new HashMap<Thread, ObjectInPool<T>>();
// 守护
private final ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(1);
// 配置
private PoolConfig config;
public ThreadBasedConnectPool(final PoolConfig config) {
this.config = config;
threadPool.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
// 检测和回收逻辑
Iterator<Map.Entry<Thread, ObjectInPool<T>>> it = map.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<Thread, ObjectInPool<T>> entry = it.next();
ObjectInPool<T> oip = entry.getValue();
if (System.currentTimeMillis() - oip.getLasUseAt() < config.getMaxIdle()) {
// 空闲时间不足,免检。
continue;
}
if (System.currentTimeMillis() - oip.getLasUseAt() > config.getMaxUseless()) {
// 长时间未使用,回收链接
it.remove();
try {
free(oip.getObject());
} catch (Exception e) {
}
continue;
}
boolean checkPass = false;
try {
checkPass = check(entry.getValue().getObjectForCheck());
} catch (Exception e) {
checkPass = false;
}
finally {
}
if ( ! checkPass) {
// 检查未通过
it.remove();
try {
free(oip.getObject());
} catch (Exception e) {
}
continue;
}
}
}
}, config.getMaxIdle(), config.getMaxIdle(), TimeUnit.MILLISECONDS);
}
public ThreadBasedConnectPool() {
this(new PoolConfig());
}
// 继承 初始化
protected T initialValue() {
return null;
}
// 保活接口
protected boolean check(T o) {
return null != o;
}
// 释放
protected void free(T o) {
}
// 获取
public T get() {
ObjectInPool<T> o = map.get(Thread.currentThread());
if (null != o) {
return o.getObject();
}
return setInitialValue();
}
// 设置
public void set(T o) {
map.put(Thread.currentThread(), new ObjectInPool<T>(o));
}
// 清除
public void remove() {
map.remove(Thread.currentThread());
}
protected void afterInit(ObjectInPool oip, T value ){
}
private T setInitialValue() {
T value = initialValue();
ObjectInPool opi = new ObjectInPool<T>(value);
map.put(Thread.currentThread(), opi);
afterInit( opi , value);
return value;
}
}
@@ -0,0 +1,165 @@
package com.sunyard.proxy;
import com.sunyard.SydApi;
import com.sunyard.SydApiException;
import com.sunyard.log.ILogFactory;
import com.sunyard.log.ILogger;
import com.sunyard.pool.HsmLinkInfo;
import racal.sunyard.main.SydApi4j;
import racal.sunyard.main.SydApiMuti;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public class ProxyInvocationHandler implements InvocationHandler {
private static Map<String, SydApiException> innerFuncs = new HashMap<String, SydApiException>();
static {
innerFuncs.put("connect", new SydApiException("集群连接模式,不需要该连接", 0));
}
private SydApi4j[] apis;
private HsmLinkInfo[] apisInfos;
private boolean isShortLinkMode = true;
public ProxyInvocationHandler(SydApi4j[] apis) {
this.apis = apis;
}
public ProxyInvocationHandler(SydApi4j[] apis, HsmLinkInfo[] info, boolean isShortLinkMode) {
this.apis = apis;
this.apisInfos = info;
this.isShortLinkMode = isShortLinkMode;
}
public SydApi4j[] getApis() {
return apis;
}
public HsmLinkInfo[] getApisInfos() {
return apisInfos;
}
public SydApi getProxy() {
SydApi api = (SydApi) Proxy.newProxyInstance(
SydApi4j.class.getClassLoader(),
new Class[]{SydApi.class},
this
);
api.setBindObject( this );
return api;
}
public void disconnect() {
if (null != apis && isShortLinkMode) {
for (SydApi4j api4j : this.apis) {
try {
if (null != api4j) {
api4j.disconnect();
}
} catch (Exception e) {
// pass
}
}
}
}
//处理代理实例并返回结果
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
SydApiException le = null;
if ("disconnect".equals(method.getName())) {
this.disconnect();
}
// 屏蔽部分非业务接口
if ("connect".equals(method.getName())) {
throw new RuntimeException("不允许使用此接口");
}
if (innerFuncs.containsKey(method.getName())) {
innerFuncs.get(method.getName());
}
if ("deleteCert".equals(method.getName()) || "SYD_Get_X509_CertInfo_HA".equals(method.getName())) {
for (SydApi4j api : apis) {
if (null == api) {
if ("deleteCert".equals(method.getName())) {
throw new SydApiException("删除失败",56307);
} else {
throw new SydApiException("导入失败",56300);
}
}
try {
Object ret = method.invoke(api, args);
if ( ret instanceof Boolean ) {
if ( ! ( Boolean ) ret ) {
throw new RuntimeException("结果错误");
}
}
} catch (SydApiException e) {
if ("deleteCert".equals(method.getName())) {
throw new SydApiException("删除失败",56307);
} else {
throw new SydApiException("导入失败",56300);
}
}
}
}
for (SydApi4j api : apis) {
if (null == api) {
continue;
}
if ( isShortLinkMode ) {
try {
return method.invoke(api, args);
} catch (SydApiException e) {
le = e;
if (e.getRetCode() < 0) {
continue;
}
throw e;
}
} else {
synchronized (api) {
try {
return method.invoke(api, args);
} catch (SydApiException e) {
le = e;
if (e.getRetCode() < 0) {
continue;
}
throw e;
} catch ( Exception e ) {
ILogFactory factory = SydApi4j.getLogFactory();
if ( null != factory ) {
ILogger logger = factory.getLogger(ProxyInvocationHandler.class);
logger.error( "调用方法 {} 失败", method.getName() );
}
throw e;
}
}
}
}
throw le;
}
}
@@ -0,0 +1,112 @@
package com.sunyard.snmp;
import org.snmp4j.*;
import org.snmp4j.event.ResponseEvent;
import org.snmp4j.event.ResponseListener;
import org.snmp4j.mp.*;
import org.snmp4j.security.*;
import org.snmp4j.smi.*;
import org.snmp4j.transport.DefaultUdpTransportMapping;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.Properties;
import java.util.Vector;
public class SnmpTrapSender implements AutoCloseable{
private Snmp snmp;
// 配置参数
private String ip;
private int port;
private String enterpriseOid;
private String community;
private int version;
public SnmpTrapSender(Map<String, String> map) throws Exception {
loadConfig(map);
initializeSNMP();
}
public void loadConfig(Map<String, String> map) {
ip = map.getOrDefault("snmp.target.ip", null);
port = Integer.parseInt(map.getOrDefault("snmp.target.port", "162"));
enterpriseOid = map.getOrDefault("enterprise.oid", null);
community = map.getOrDefault("snmp.community", "public");
version = Integer.parseInt(map.getOrDefault("snmp.version", "1"));
}
private void initializeSNMP() throws Exception {
TransportMapping<?> transport = new DefaultUdpTransportMapping();
snmp = new Snmp(transport);
snmp.listen();
}
public ResponseEvent sendTrap(String message, int severity) throws Exception {
ResponseEvent event = null;
switch (version) {
case SnmpConstants.version1:
event = sendV1Trap(message, severity);
break;
case SnmpConstants.version2c:
event = sendV2Trap(message, severity);
break;
default:
throw new IllegalArgumentException("不支持的SNMP版本");
}
return event;
}
private ResponseEvent sendV1Trap(String message, int severity) throws Exception {
CommunityTarget target = createCommunityTarget(SnmpConstants.version1);
PDUv1 pdu = new PDUv1();
configureCommonTrap(pdu, message, severity);
pdu.setGenericTrap(PDUv1.ENTERPRISE_SPECIFIC);
return snmp.send(pdu, target);
}
private ResponseEvent sendV2Trap(String message, int severity) throws Exception {
CommunityTarget target = createCommunityTarget(SnmpConstants.version2c);
PDU pdu = new PDU();
configureCommonTrap(pdu, message, severity);
pdu.setType(PDU.TRAP);
return snmp.send(pdu, target);
}
private void configureCommonTrap(PDU pdu, String message, int severity) {
pdu.add(new VariableBinding(SnmpConstants.sysUpTime,
new TimeTicks(System.currentTimeMillis()/1000)));
pdu.add(new VariableBinding(SnmpConstants.snmpTrapOID,
new OID(enterpriseOid + ".1.1")));
byte[] msg = new byte[10];
try {
msg = message.getBytes("GBK");
} catch (Exception e) {
System.out.println("编码错误");
}
pdu.add(new VariableBinding(new OID(enterpriseOid + ".2.1"),
new OctetString(msg)));
pdu.add(new VariableBinding(new OID(enterpriseOid + ".2.2"),
new Integer32(severity)));
}
private CommunityTarget createCommunityTarget(int version) {
CommunityTarget target = new CommunityTarget();
target.setCommunity(new OctetString(community));
target.setAddress(GenericAddress.parse("udp:"+ip+"/"+port));
target.setVersion(version);
target.setTimeout(5000);
target.setRetries(3);
return target;
}
@Override
public void close() throws Exception {
if (snmp != null) {
snmp.close();
snmp = null;
}
}
}
@@ -0,0 +1,121 @@
package com.sunyard.task;
import java.util.List;
import java.util.concurrent.*;
import java.util.stream.Collectors;
public class AsyncTaskExecutor {
private final ExecutorService taskExecutor;
private final ScheduledExecutorService retryScheduler;
public AsyncTaskExecutor(int taskThreads, int retryThreads) {
this.taskExecutor = Executors.newFixedThreadPool(taskThreads);
this.retryScheduler = Executors.newScheduledThreadPool(retryThreads);
}
// 默认配置构造函数
public AsyncTaskExecutor() {
this(2, 2);
}
public List<TaskOutcome<String>> execBatchTasks(List<TaskContext<String>> taskContexts) {
// 转换每个Future为明确的TaskOutcome类型
List<CompletableFuture<TaskOutcome<String>>> futures = taskContexts.stream()
.map(task ->
retryWithDelay(task)
.<TaskOutcome<String>>handle((result, ex) -> {
if (ex != null) {
// 提取原始异常
Throwable cause = ex instanceof CompletionException ? ex.getCause() : ex;
return new TaskOutcome<>(task, cause);
} else {
return new TaskOutcome<>(task, result);
}
})
)
.collect(Collectors.toList());
// 等待所有任务完成
CompletableFuture<Void> allFutures = CompletableFuture.allOf(
futures.toArray(new CompletableFuture[0])
);
// 收集处理结果
return allFutures.thenApply(v ->
futures.stream()
.map(CompletableFuture::join)
.collect(Collectors.toList())
).join();
}
/**
* 带延迟的重试逻辑
*/
private <T> CompletableFuture<T> retryWithDelay(TaskContext<T> context) {
return CompletableFuture.supplyAsync(context.getTask(), taskExecutor)
.handleAsync((result, ex) -> {
if (ex == null) {
return CompletableFuture.completedFuture(result);
} else {
return handleRetry(context, ex);
}
}, taskExecutor)
.thenCompose(f -> f);
}
/**
* 处理重试逻辑
*/
private <T> CompletableFuture<T> handleRetry(TaskContext<T> context, Throwable ex) {
if (context.canRetry()) {
context.decreaseRetry();
// System.out.printf("[重试调度] ID: %s| IP:%s | 延迟: %ss | 剩余重试: %d | 错误: %s%n",
// context.getTaskId(),
// context.getAddress(),
// context.getRetryDelay().getSeconds(),
// context.getRetriesLeft(),
// ex.getCause().getMessage());
// 创建延迟重试的Future
CompletableFuture<T> delayedRetry = new CompletableFuture<>();
retryScheduler.schedule(() -> {
retryWithDelay(context).whenComplete((retryResult, retryEx) -> {
if (retryEx != null) {
delayedRetry.completeExceptionally(retryEx);
} else {
delayedRetry.complete(retryResult);
}
});
}, context.getRetryDelay().toMillis(), TimeUnit.MILLISECONDS);
return delayedRetry;
} else {
// 重试耗尽,传递原始异常
CompletableFuture<T> failed = new CompletableFuture<>();
failed.completeExceptionally(ex);
return failed;
}
}
/**
* 关闭线程池
*/
public void shutdown() {
taskExecutor.shutdown();
retryScheduler.shutdown();
try {
if (!taskExecutor.awaitTermination(1, TimeUnit.SECONDS)) {
taskExecutor.shutdownNow();
}
if (!retryScheduler.awaitTermination(1, TimeUnit.SECONDS)) {
retryScheduler.shutdownNow();
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
@@ -0,0 +1,50 @@
package com.sunyard.task;
import java.time.Duration;
import java.util.UUID;
import java.util.function.Supplier;
public class TaskContext<T> {
private final String taskId; // 唯一任务ID
private final Supplier<T> task; // 原始任务逻辑
private int retriesLeft; // 剩余重试次数
private final Duration retryDelay; // 重试延迟
private final String address;
public TaskContext(Supplier<T> task, int maxRetries, Duration retryDelay, String address) {
this.taskId = UUID.randomUUID().toString();
this.task = task;
this.retriesLeft = maxRetries;
this.retryDelay = retryDelay;
this.address = address;
}
public String getAddress() {
return address;
}
public String getTaskId() {
return taskId;
}
public Supplier<T> getTask() {
return task;
}
public int getRetriesLeft() {
return retriesLeft;
}
public boolean canRetry() {
return retriesLeft > 0;
}
public void decreaseRetry() {
retriesLeft--;
}
public Duration getRetryDelay() {
return retryDelay;
}
}
@@ -0,0 +1,35 @@
package com.sunyard.task;
public class TaskOutcome<T> {
private final TaskContext<T> context;
private final T result;
private final Throwable error;
public TaskOutcome(TaskContext<T> context, T result) {
this.context = context;
this.result = result;
this.error = null;
}
public TaskOutcome(TaskContext<T> context, Throwable error) {
this.context = context;
this.result = null;
this.error = error;
}
public boolean isSuccess() {
return error == null;
}
public TaskContext<T> getContext() {
return context;
}
public T getResult() {
return result;
}
public Throwable getError() {
return error;
}
}
@@ -0,0 +1,72 @@
package com.sunyard.util;
import cn.hutool.core.bean.BeanUtil;
import com.sunyard.RetWrap;
import com.sunyard.proto.R;
import com.sunyard.proto.Util;
import org.bouncycastle.asn1.*;
import java.io.IOException;
public class ASN1Util {
public static byte[] alignSignDer(byte[] der) {
String base64 = Util.encodeBase64(der);
return SYMUtil.base64SignAsDerSign(base64);
}
public static RetWrap takeOutOriginDataFromPKCS7Sign(String sign) throws IOException {
RetWrap ret = new RetWrap();
ASN1Sequence seq = ASN1Sequence.getInstance( Util.decodeBase64( sign ) );
ASN1TaggedObject tag = (ASN1TaggedObject) seq.getObjectAt(1).toASN1Primitive();
ASN1Sequence seq2 = (ASN1Sequence) tag.getObject();
ASN1Sequence seq3 = null;
try {
seq3 = (ASN1Sequence) seq2.getObjectAt( 2 ).toASN1Primitive();
ASN1TaggedObject tag2 = (ASN1TaggedObject) seq3.getObjectAt( 1 );
DEROctetString o = (DEROctetString) tag2.getObject();
ret.put( "orgData", o.getOctets() );
} catch (Exception e) {
}
ASN1TaggedObject tag3 = (ASN1TaggedObject) seq2.getObjectAt(3).toASN1Primitive();
ASN1Sequence seq4 = (ASN1Sequence) tag3.getObject();
ret.put("cert", CertUtil.encodeBase64(seq4.getEncoded()));
ASN1Sequence seq5 = (ASN1Sequence) seq4.getObjectAt( 0 ).toASN1Primitive();
ASN1Sequence seq6 = (ASN1Sequence) seq5.getObjectAt( 6 ).toASN1Primitive();
DERBitString pk = (DERBitString) seq6.getObjectAt( 1 ).toASN1Primitive();
ret.put("pk", pk.getEncoded() );
ASN1Encodable[] elements = seq3.toArray();
ASN1Encodable[] elements2 = new ASN1Encodable[ elements.length - 1];
for ( int i = 0; i < elements.length -1 ; i++ ){
elements2[i] = elements[i];
}
BeanUtil.setProperty( seq3, "elements", elements2);
ret.put("sign", Util.encodeBase64(seq.getEncoded()) );
return ret;
}
public static String addOriginDataToPKCS7Sign( byte[] originData, String sign) throws IOException {
ASN1Sequence seq = ASN1Sequence.getInstance( Util.decodeBase64( sign ) );
ASN1TaggedObject tag = (ASN1TaggedObject) seq.getObjectAt(1).toASN1Primitive();
ASN1Sequence seq2 = (ASN1Sequence) tag.getObject();
ASN1Sequence seq3 = (ASN1Sequence) seq2.getObjectAt( 2 ).toASN1Primitive();
ASN1Encodable[] elements = seq3.toArray();
ASN1Encodable[] elements2 = new ASN1Encodable[ elements.length + 1];
for ( int i = 0; i < elements.length ; i++ ){
elements2[i] = elements[i];
}
elements2[ elements.length ] = new DERTaggedObject(true, 0, new DEROctetString( originData ));
BeanUtil.setProperty( seq3, "elements", elements2);
return Util.encodeBase64(seq.getEncoded());
}
}
@@ -0,0 +1,70 @@
package com.sunyard.util;
import java.util.regex.Pattern;
public class AddressUtil {
// 处理带端口号的地址
public static boolean isValidAddressWithPort(String address) {
if (address == null) {
return false;
}
// 分离 IP:port 或 [IPv6]:port
String[] parts;
if (address.startsWith("[") && address.contains("]:")) {
parts = address.split("\\]:", 2);
parts[0] = parts[0] + "]"; // 补全 IPv6 的括号
} else {
parts = address.split(":", 2);
}
if (parts.length != 2) {
return false;
}
String ipPart = parts[0];
String portPart = parts[1];
return isValidIP(ipPart) &&
isValidPort(portPart);
}
// IPv4 正则(允许 0-255)
private static final Pattern IPV4_PATTERN = Pattern.compile(
"^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$"
);
// IPv6 正则(包含缩写形式)
private static final Pattern IPV6_PATTERN = Pattern.compile(
"^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$"
);
// 简化域名正则(允许字母、数字、连字符和点)
private static final Pattern DOMAIN_PATTERN = Pattern.compile(
"^([a-zA-Z0-9-]{1,63}\\.)+[a-zA-Z]{2,63}$"
);
public static boolean isValidIP(String ip) {
// 检查 IPv4 或 IPv6
return IPV4_PATTERN.matcher(ip).matches() ||
IPV6_PATTERN.matcher(ip).matches();
}
public static boolean isValidDomain(String domain) {
return DOMAIN_PATTERN.matcher(domain).matches();
}
public static boolean isValidPort(int port) {
return port >= 0 && port <= 65535;
}
// 字符串形式的端口校验
public static boolean isValidPort(String portStr) {
try {
int port = Integer.parseInt(portStr);
return port >= 0 && port <= 65535;
} catch (NumberFormatException e) {
return false;
}
}
}
@@ -0,0 +1,44 @@
package com.sunyard.util;
import java.nio.ByteBuffer;
public class ByteBufferUtil {
public static ByteBuffer sliceRange(ByteBuffer source, int start, int length) {
// 保存原 buffer 的 position 和 limit
int oldPos = source.position();
int oldLimit = source.limit();
// 设置新的 position 和 limit 为目标区间
source.position(start);
source.limit(start + length);
// 创建共享视图(零拷贝)
ByteBuffer slice = source.slice();
// 恢复原 buffer 的 position 和 limit
source.position(oldPos);
source.limit(oldLimit);
return slice;
}
public static ByteBuffer sliceAndConsume(ByteBuffer source, int length) {
// 保存原 buffer 的 position 和 limit
int oldPos = source.position();
int oldLimit = source.limit();
// 设置新的 position 和 limit 为目标区间
int start = oldPos;
source.position(start);
source.limit(start + length);
// 创建共享视图(零拷贝)
ByteBuffer slice = source.slice();
// 恢复原 buffer 的 position 和 limit
source.position(oldPos + length);
source.limit(oldLimit);
return slice;
}
}
@@ -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));
}
}
@@ -0,0 +1,170 @@
package com.sunyard.util;
import cn.hutool.core.codec.Base64;
import com.sunyard.RetWrap;
import com.sunyard.SydApiException;
import com.sunyard.constant.CertUsage;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import sun.misc.BASE64Encoder;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.security.NoSuchProviderException;
import java.security.Security;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.HashSet;
import java.util.Set;
public class CertUtil {
public static String encodeBase64(byte[] data) {
return new BASE64Encoder().encode(data);
}
static {
Security.addProvider(new BouncyCastleProvider());
}
public static X509Certificate convertToX509Cert(String certificateString) throws CertificateException, NoSuchProviderException {
// X509Certificate certificate = null;
// CertificateFactory cf = null;
// try {
// if (certificateString != null && !certificateString.trim().isEmpty()) {
// certificateString = certificateString.replace("-----BEGIN CERTIFICATE-----\n", "")
// .replace("-----END CERTIFICATE-----", ""); // NEED FOR PEM FORMAT CERT STRING
// byte[] certificateData = Base64.decode(certificateString);
// cf = CertificateFactory.getInstance("X509");
// certificate = (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(certificateData));
// }
// } catch (CertificateException e) {
// throw new CertificateException(e);
// }
// return certificate;
CertificateFactory CF = CertificateFactory.getInstance("X.509", "BC"); // 从证书工厂中获取X.509的单例类
return (X509Certificate) CF.generateCertificate(new ByteArrayInputStream(certificateString.getBytes())); // 将文件流的证书转化为证书类
}
public static String convertToPem(String cert) throws CertificateEncodingException {
String cert_begin = "-----BEGIN CERTIFICATE-----\n";
String end_cert = "\n-----END CERTIFICATE-----";
// byte[] derCert = cert.getEncoded();
byte[] derCert = cert.getBytes();
String pemCertPre = new String(Base64.encode(derCert, true));
String pemCert = cert_begin + pemCertPre + end_cert;
return pemCert;
// StringWriter sw = new StringWriter();
// PemWriter pw = new PemWriter(sw);
// try {
// pw.writeObject(new JcaMiscPEMGenerator(cert));
// }catch ( Exception e ) {
// e.printStackTrace();
// }finally {
// if (null == pw) {
// try {
// pw.close();
// } catch (IOException e) {
// e.printStackTrace();
// }
// }
// }
// return sw.toString();
}
/**
* 判断正式是否是国密证书
*
* @param cert 证书 base64 字符
* @return true 国密, false 非国密
*/
public static boolean isSM2Cert(String cert) {
String pemCert;
if(cert.contains("-----BEGIN CERTIFICATE-----")){
pemCert =cert;
}else {
String cert_begin = "-----BEGIN CERTIFICATE-----\n";
String end_cert = "\n-----END CERTIFICATE-----";
pemCert = cert_begin + cert + end_cert;
}
X509Certificate certificate = null;
try {
certificate = convertToX509Cert(pemCert);
} catch (Exception e) {
throw new SydApiException( 0xC101, e );
}
String signAlg = certificate.getSigAlgName();
return signAlg.toUpperCase().indexOf("SM2") >= 0;
}
public static String getDN(String cert) {
String pemCert;
if(cert.contains("-----BEGIN CERTIFICATE-----")){
pemCert =cert;
}else {
String cert_begin = "-----BEGIN CERTIFICATE-----\n";
String end_cert = "\n-----END CERTIFICATE-----";
pemCert = cert_begin + cert + end_cert;
}
X509Certificate certificate = null;
try {
certificate = convertToX509Cert(pemCert);
} catch (Exception e) {
throw new SydApiException( 0xC101, e );
}
return certificate.getSubjectDN().toString();
}
/**
* 判断 p7 是否是国密证书签的
*
* @param pkcs7 pkcs7
* @return true 国密, false 非国密
*/
public static boolean isSignedBySM2Cert(String pkcs7) throws IOException, CertificateException, NoSuchProviderException {
RetWrap ret = ASN1Util.takeOutOriginDataFromPKCS7Sign(pkcs7);
//return isSM2Cert((String) ret.get("cert"));
String cert =(String) ret.get("cert");
if(cert.contains("-----BEGIN CERTIFICATE-----")){
return isSM2Cert(cert);
}else{
String cert_begin = "-----BEGIN CERTIFICATE-----\n";
String end_cert = "\n-----END CERTIFICATE-----";
String pemCert = cert_begin + cert + end_cert;
return isSM2Cert(pemCert);
}
}
public static boolean certUsageCheck(String cert , CertUsage... us ) throws CertificateException, NoSuchProviderException {
if ( null == us || us.length == 0) {
return true;
}
X509Certificate certificate = convertToX509Cert(cert);
boolean[] usage = certificate.getKeyUsage();
if ( null == usage ) {
return false;
}
boolean checkRet = true;
Set<Integer> uset = new HashSet<Integer>();
for ( CertUsage u : us ) {
uset.add( u.ordinal() );
}
for ( int i = 0; i < usage.length; i++ ) {
if ( usage[ i ] ) {
checkRet &= uset.contains( i );
}
}
return checkRet;
}
}
@@ -0,0 +1,18 @@
package com.sunyard.util;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Properties;
public class Configure {
public static String getKey(String key) throws IOException {
Properties p = new Properties();
InputStream in = new FileInputStream("./sunyard.properties");
InputStreamReader sr = new InputStreamReader(in, "UTF-8");
p.load(sr);
String value = p.getProperty(key).trim();
return value;
}
}
@@ -0,0 +1,46 @@
package com.sunyard.util;
import java.util.LinkedHashMap;
import java.util.List;
public class DnUtil {
public static LinkedHashMap<String, String> dnToMap(String dn) {
LinkedHashMap<String, String> map = new LinkedHashMap<String, String>();
String[] kvs = dn.split(",");
for (String kv : kvs) {
String[] ps = kv.split("=");
map.put(ps[0].trim(), ps[1].trim());
}
return map;
}
public static String verifyDn(String dn) {
if ( "true".equals(System.getProperty("com.sunyard.dnsort", "true"))) {
if (dn.startsWith("C=") || dn.startsWith("c=")) {
return dn;
}
// 反转顺序
String[] kvs = dn.split(",");
StringBuilder sb = new StringBuilder();
for (String kv : kvs) {
if (sb.length() > 0) {
sb.insert(0, ",");
}
sb.insert(0, kv);
// if ( sb.length() > 0 ) {
// sb.append(",");
// }
// sb.append( key + "=" + map.get( key ) );
}
return sb.toString();
}
else return dn;
}
}
@@ -0,0 +1,107 @@
package com.sunyard.util;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
/**
* IP锁工具类 - 高并发安全实现
*
* 为每个IP地址提供唯一的可重入锁,确保同一IP的操作顺序执行
*/
public class IpLockUtils {
private static final ConcurrentMap<String, ReentrantLock> LOCK_MAP = new ConcurrentHashMap<>();
private static final Object CREATION_LOCK = new Object();
/**
* 获取IP对应的锁(保证唯一性)
* @param ip IP地址
* @return 可重入锁实例
*/
public static ReentrantLock getLockForIp(String ip) {
ReentrantLock lock = LOCK_MAP.get(ip);
if (lock != null) {
return lock;
}
synchronized (CREATION_LOCK) {
// 双重检查
lock = LOCK_MAP.get(ip);
if (lock == null) {
lock = new ReentrantLock(true); // 公平锁
LOCK_MAP.put(ip, lock);
}
return lock;
}
}
/**
* 安全加锁(带超时机制)
* @param ip IP地址
* @param timeout 超时时间
* @param unit 时间单位
* @return 是否成功获取锁
* @throws InterruptedException
*/
public static boolean lockWithTimeout(String ip, long timeout, TimeUnit unit)
throws InterruptedException {
ReentrantLock lock = getLockForIp(ip);
return lock.tryLock(timeout, unit);
}
/**
* 解锁指定IP的锁
* @param ip IP地址
*/
public static void unlockForIp(String ip) {
ReentrantLock lock = LOCK_MAP.get(ip);
if (lock != null && lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
/**
* 清理未使用的锁(可选)
*/
public static void cleanupUnusedLocks() {
LOCK_MAP.entrySet().removeIf(entry ->
!entry.getValue().isLocked() &&
entry.getValue().getQueueLength() == 0
);
}
/**
* 获取当前锁数量
*/
public static int getLockCount() {
return LOCK_MAP.size();
}
/**
* 获取IP锁状态
* @param ip IP地址
* @return 锁状态字符串
*/
public static String getLockStatus(String ip) {
ReentrantLock lock = LOCK_MAP.get(ip);
if (lock == null) {
return "No lock exists";
}
return String.format("Locked: %s, Queue: %d, HoldCount: %d",
lock.isLocked(), lock.getQueueLength(), lock.getHoldCount());
}
/**
* 重置所有锁
*/
public static void reset() {
synchronized (CREATION_LOCK) {
LOCK_MAP.clear();
}
}
}
@@ -0,0 +1,367 @@
package com.sunyard.util;
import java.util.Collection;
import java.util.Map;
/**
* 参数检查工具类,提供常见的参数校验方法。
* <p>
* 所有方法在校验失败时均抛出 {@link IllegalArgumentException} 异常,
* 并附带包含参数名的明确错误信息。成功时返回被校验的值,便于链式调用。
* </p>
*
* <p>使用示例:
* <pre>{@code
* public void setAge(int age) {
* ParamChecker.checkInRange(age, "age", 0, 150);
* }
*
* public void setName(String name) {
* ParamChecker.checkNotBlank(name, "name");
* }
*
* public void setStatus(int status) {
* ParamChecker.checkInValues(status, "status", 1, 2, 3);
* }
* }</pre>
* </p>
*
* @author Cheney
*/
public final class ParamChecker {
private ParamChecker() {
// 私有构造器,防止实例化
}
/**
* 检查表达式是否为真,若为假则抛出异常。
*
* @param expression 待检查的布尔表达式
* @param message 异常信息
* @throws IllegalArgumentException 如果 expression 为 false
*/
public static void checkArgument(boolean expression, String message) {
if (!expression) {
throw new IllegalArgumentException(message);
}
}
// ==================== 对象非空检查 ====================
/**
* 检查对象不为 null。
*
* @param obj 待检查的对象
* @param paramName 参数名称(用于异常信息)
* @param <T> 对象类型
* @return 传入的对象(便于链式调用)
* @throws IllegalArgumentException 如果 obj 为 null
*/
public static <T> T checkNotNull(T obj, String paramName) {
if (obj == null) {
throw new IllegalArgumentException("参数 '" + paramName + "' 不能为 null");
}
return obj;
}
// ==================== 字符串检查 ====================
/**
* 检查字符串不为 null 且长度大于 0(不忽略空白字符)。
*
* @param str 待检查的字符串
* @param paramName 参数名称
* @return 传入的字符串
* @throws IllegalArgumentException 如果 str 为 null 或空字符串
*/
public static String checkNotEmpty(String str, String paramName) {
if (str == null || str.isEmpty()) {
throw new IllegalArgumentException("参数 '" + paramName + "' 不能为 null 或空字符串");
}
return str;
}
/**
* 检查字符串不为 null 且去除首尾空白后长度大于 0。
*
* @param str 待检查的字符串
* @param paramName 参数名称
* @return 传入的字符串(原值,非 trim 后结果)
* @throws IllegalArgumentException 如果 str 为 null 或仅包含空白字符
*/
public static String checkNotBlank(String str, String paramName) {
if (str == null || !str.trim().isEmpty()) {
throw new IllegalArgumentException("参数 '" + paramName + "' 不能为 null、空字符串或仅包含空白字符");
}
return str;
}
/**
* 检查字符串长度在指定范围内(包含边界)。
*
* @param str 待检查的字符串
* @param paramName 参数名称
* @param min 最小长度(包含)
* @param max 最大长度(包含)
* @return 传入的字符串
* @throws IllegalArgumentException 如果 str 为 null,或长度不在 [min, max] 范围内
*/
public static String checkLengthBetween(String str, String paramName, int min, int max) {
checkNotNull(str, paramName);
if (min > max) {
throw new IllegalArgumentException("内部错误:长度检查的最小值 " + min + " 不能大于最大值 " + max);
}
int len = str.length();
if (len < min || len > max) {
throw new IllegalArgumentException(
String.format("参数 '%s' 的长度 %d 不在允许范围 [%d, %d] 内", paramName, len, min, max));
}
return str;
}
// ==================== 整数(int)检查 ====================
/**
* 检查 int 值大于 0。
*
* @param value 待检查的值
* @param paramName 参数名称
* @return 传入的值
* @throws IllegalArgumentException 如果 value <= 0
*/
public static int checkPositive(int value, String paramName) {
if (value <= 0) {
throw new IllegalArgumentException("参数 '" + paramName + "' 必须为正数,当前值: " + value);
}
return value;
}
/**
* 检查 int 值 >= 0。
*
* @param value 待检查的值
* @param paramName 参数名称
* @return 传入的值
* @throws IllegalArgumentException 如果 value < 0
*/
public static int checkNonNegative(int value, String paramName) {
if (value < 0) {
throw new IllegalArgumentException("参数 '" + paramName + "' 不能为负数,当前值: " + value);
}
return value;
}
/**
* 检查 int 值在指定范围内(包含边界)。
*
* @param value 待检查的值
* @param paramName 参数名称
* @param min 最小值(包含)
* @param max 最大值(包含)
* @return 传入的值
* @throws IllegalArgumentException 如果 value 不在 [min, max] 范围内,或 min > max
*/
public static int checkInRange(int value, String paramName, int min, int max) {
if (min > max) {
throw new IllegalArgumentException("内部错误:范围检查的最小值 " + min + " 不能大于最大值 " + max);
}
if (value < min || value > max) {
throw new IllegalArgumentException(
String.format("参数 '%s' 的值 %d 不在允许范围 [%d, %d] 内", paramName, value, min, max));
}
return value;
}
/**
* 检查 int 值是否等于给定集合中的任意一个值。
*
* @param value 待检查的值
* @param paramName 参数名称
* @param validValues 允许的值列表
* @return 传入的值
* @throws IllegalArgumentException 如果 value 不在 validValues 中,或 validValues 为空
*/
public static int checkInValues(int value, String paramName, int... validValues) {
if (validValues == null || validValues.length == 0) {
throw new IllegalArgumentException("内部错误:允许的值集合不能为空");
}
for (int v : validValues) {
if (value == v) {
return value;
}
}
// 构建允许值字符串用于提示
StringBuilder allowed = new StringBuilder();
for (int i = 0; i < validValues.length; i++) {
if (i > 0) allowed.append(", ");
allowed.append(validValues[i]);
}
throw new IllegalArgumentException(
String.format("参数 '%s' 的值 %d 不在允许值集合 [%s] 中", paramName, value, allowed));
}
// ==================== 长整型(long)检查 ====================
/**
* 检查 long 值大于 0。
*
* @param value 待检查的值
* @param paramName 参数名称
* @return 传入的值
* @throws IllegalArgumentException 如果 value <= 0
*/
public static long checkPositive(long value, String paramName) {
if (value <= 0) {
throw new IllegalArgumentException("参数 '" + paramName + "' 必须为正数,当前值: " + value);
}
return value;
}
/**
* 检查 long 值 >= 0。
*
* @param value 待检查的值
* @param paramName 参数名称
* @return 传入的值
* @throws IllegalArgumentException 如果 value < 0
*/
public static long checkNonNegative(long value, String paramName) {
if (value < 0) {
throw new IllegalArgumentException("参数 '" + paramName + "' 不能为负数,当前值: " + value);
}
return value;
}
/**
* 检查 long 值在指定范围内(包含边界)。
*
* @param value 待检查的值
* @param paramName 参数名称
* @param min 最小值(包含)
* @param max 最大值(包含)
* @return 传入的值
* @throws IllegalArgumentException 如果 value 不在 [min, max] 范围内,或 min > max
*/
public static long checkInRange(long value, String paramName, long min, long max) {
if (min > max) {
throw new IllegalArgumentException("内部错误:范围检查的最小值 " + min + " 不能大于最大值 " + max);
}
if (value < min || value > max) {
throw new IllegalArgumentException(
String.format("参数 '%s' 的值 %d 不在允许范围 [%d, %d] 内", paramName, value, min, max));
}
return value;
}
// ==================== 浮点数(double)简单检查 ====================
/**
* 检查 double 值大于 0(考虑极小正数,不做精度处理)。
*
* @param value 待检查的值
* @param paramName 参数名称
* @return 传入的值
* @throws IllegalArgumentException 如果 value <= 0 或为 NaN
*/
public static double checkPositive(double value, String paramName) {
if (value <= 0 || Double.isNaN(value)) {
throw new IllegalArgumentException("参数 '" + paramName + "' 必须为正数,当前值: " + value);
}
return value;
}
/**
* 检查 double 值 >= 0。
*
* @param value 待检查的值
* @param paramName 参数名称
* @return 传入的值
* @throws IllegalArgumentException 如果 value < 0 或为 NaN
*/
public static double checkNonNegative(double value, String paramName) {
if (value < 0 || Double.isNaN(value)) {
throw new IllegalArgumentException("参数 '" + paramName + "' 不能为负数或 NaN,当前值: " + value);
}
return value;
}
// ==================== 集合与数组非空检查 ====================
/**
* 检查集合不为 null 且非空。
*
* @param coll 待检查的集合
* @param paramName 参数名称
* @param <T> 集合元素类型
* @return 传入的集合
* @throws IllegalArgumentException 如果 coll 为 null 或空集合
*/
public static <T> Collection<T> checkNotEmpty(Collection<T> coll, String paramName) {
if (coll == null || coll.isEmpty()) {
throw new IllegalArgumentException("参数 '" + paramName + "' 不能为 null 或空集合");
}
return coll;
}
/**
* 检查 Map 不为 null 且非空。
*
* @param map 待检查的 Map
* @param paramName 参数名称
* @param <K> 键类型
* @param <V> 值类型
* @return 传入的 Map
* @throws IllegalArgumentException 如果 map 为 null 或空 Map
*/
public static <K, V> Map<K, V> checkNotEmpty(Map<K, V> map, String paramName) {
if (map == null || map.isEmpty()) {
throw new IllegalArgumentException("参数 '" + paramName + "' 不能为 null 或空 Map");
}
return map;
}
/**
* 检查数组不为 null 且长度大于 0。
*
* @param array 待检查的数组
* @param paramName 参数名称
* @param <T> 数组元素类型
* @return 传入的数组
* @throws IllegalArgumentException 如果 array 为 null 或长度为 0
*/
public static <T> T[] checkNotEmpty(T[] array, String paramName) {
if (array == null || array.length == 0) {
throw new IllegalArgumentException("参数 '" + paramName + "' 不能为 null 或空数组");
}
return array;
}
// ==================== 布尔条件检查 ====================
/**
* 检查布尔条件为 true。
*
* @param condition 待检查的条件
* @param paramName 参数名称(描述条件含义)
* @throws IllegalArgumentException 如果 condition 为 false
*/
public static void checkTrue(boolean condition, String paramName) {
if (!condition) {
throw new IllegalArgumentException("参数条件 '" + paramName + "' 必须为 true");
}
}
/**
* 检查布尔条件为 false。
*
* @param condition 待检查的条件
* @param paramName 参数名称(描述条件含义)
* @throws IllegalArgumentException 如果 condition 为 true
*/
public static void checkFalse(boolean condition, String paramName) {
if (condition) {
throw new IllegalArgumentException("参数条件 '" + paramName + "' 必须为 false");
}
}
}
@@ -0,0 +1,140 @@
package com.sunyard.util;
import com.google.zxing.*;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.QRCodeReader;
import com.sunyard.SydApiException;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Hashtable;
public class QRCodeUtil {
public static void genQRCode(String data,String filepath){
// 图片的尺寸(宽度和高度)
int width = 300;
int height = 300;
// 设置二维码的相关参数
Hashtable<EncodeHintType, Object> hintMap = new Hashtable<>();
hintMap.put(EncodeHintType.MARGIN, 1); // 设置二维码的空白边距
try {
// 创建二维码矩阵
BitMatrix bitMatrix = new MultiFormatWriter().encode(
data,
BarcodeFormat.QR_CODE,
width,
height,
hintMap
);
// 将二维码矩阵转换为图片,并保存
File outputFile = new File(filepath);
MatrixToImageWriter.writeToFile(bitMatrix, "PNG", outputFile);
} catch (Exception e) {
System.err.println("Error occurred while generating QR code: " + e.getMessage());
throw new SydApiException(1001,e);
}
}
public static void genBarCode(String data,String filepath){
// 图片的尺寸(宽度和高度)
int width = 300;
int height = 300;
// 设置二维码的相关参数
Hashtable<EncodeHintType, Object> hintMap = new Hashtable<>();
hintMap.put(EncodeHintType.MARGIN, 1); // 设置二维码的空白边距
try {
// 生成 Code 128 条形码
BitMatrix bitMatrix= new MultiFormatWriter().encode(
data,
BarcodeFormat.PDF_417,
width,
height,
hintMap
);
// 将二维码矩阵转换为图片,并保存
File outputFile = new File(filepath);
MatrixToImageWriter.writeToFile(bitMatrix, "PNG", outputFile);
} catch (Exception e) {
System.err.println("Error occurred while generating QR code: " + e.getMessage());
throw new SydApiException(1001,e);
}
}
public static String readQRCode(String filepath){
// 加载二维码图像
File qrCodeImage = new File(filepath);
// 读取二维码图像
BufferedImage bufferedImage = null;
try {
bufferedImage = ImageIO.read(qrCodeImage);
} catch (IOException e) {
throw new RuntimeException(e);
}
// 使用 ZXing 的 QRCodeReader 进行解码
QRCodeReader reader = new QRCodeReader();
LuminanceSource source = new BufferedImageLuminanceSource(bufferedImage);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
try {
// 解码二维码
Result result = reader.decode(bitmap);
// 提取二维码中的数据
return result.getText();
} catch (NotFoundException e) {
throw new SydApiException(1003,e);
} catch (ChecksumException e) {
throw new SydApiException(1004,e);
} catch (FormatException e) {
throw new SydApiException(1005,e);
}
}
public static String readBarCode(String filepath){
// 加载二维码图像
File BarCodeImage = new File(filepath);
try {
// 读取条形码图像
BufferedImage bufferedImage = ImageIO.read(BarCodeImage);
// 使用 ZXing 的 MultiFormatReader 进行解码
MultiFormatReader reader = new MultiFormatReader();
LuminanceSource source = new BufferedImageLuminanceSource(bufferedImage);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
// 解码条形码
Result result = reader.decode(bitmap);
// 提取条形码中的数据
return result.getText();
} catch (NotFoundException e) {
throw new SydApiException(1006,e);
} catch (IOException e) {
throw new SydApiException(1007,e);
}
}
}
@@ -0,0 +1,139 @@
package org.bouncycastle.cms;
import com.sunyard.SydApiException;
import org.bouncycastle.asn1.*;
import org.bouncycastle.asn1.cms.ContentInfo;
import org.bouncycastle.asn1.cms.EncryptedContentInfo;
import org.bouncycastle.asn1.cms.OriginatorInfo;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
public class SydCmsUtil {
public static Object readContentInfo(
byte[] input) {
ASN1InputStream is = new ASN1InputStream(input);
Object v = null;
try {
v = is.readObject();
} catch (IOException e) {
e.printStackTrace();
}
return v;
}
public static Map<String, Object> getEncryptedContentInfo(ASN1Encodable obj){
Map<String, Object>map = new HashMap<String, Object>();
ASN1Sequence seq = ASN1Sequence.getInstance(obj );
if (seq.size() < 2)
{
throw new IllegalArgumentException("Truncated Sequence Found");
}
ASN1ObjectIdentifier contentType = (ASN1ObjectIdentifier)seq.getObjectAt(0);
map.put( "contentType", contentType );
AlgorithmIdentifier contentEncryptionAlgorithm = AlgorithmIdentifier.getInstance(
seq.getObjectAt(1));
map.put( "contentEncryptionAlgorithm", contentEncryptionAlgorithm );
if (seq.size() > 2)
{
ASN1OctetString encryptedContent = ASN1OctetString.getInstance(
(ASN1TaggedObject)seq.getObjectAt(2), false);
map.put( "encryptedContent", encryptedContent );
}
return map;
}
public static Map<String, Object> getOriginatorInfo(ASN1TaggedObject obj,
boolean explicit){
Map<String, Object>map = new HashMap<String, Object>();
ASN1Sequence seq = ASN1Sequence.getInstance(obj, explicit);
switch (seq.size())
{
case 0: // empty
break;
case 1:
ASN1TaggedObject o = (ASN1TaggedObject)seq.getObjectAt(0);
switch (o.getTagNo())
{
case 0 :
ASN1Set certs = ASN1Set.getInstance(o, false);
map.put("certs", certs);
break;
case 1 :
ASN1Set crls = ASN1Set.getInstance(o, false);
map.put("crls", crls);
break;
default:
throw new IllegalArgumentException("Bad tag in OriginatorInfo: " + o.getTagNo());
}
break;
case 2:
ASN1Set certs = ASN1Set.getInstance((ASN1TaggedObject)seq.getObjectAt(0), false);
map.put("certs", certs);
ASN1Set crls = ASN1Set.getInstance((ASN1TaggedObject)seq.getObjectAt(1), false);
map.put("crls", crls);
break;
default:
throw new IllegalArgumentException("OriginatorInfo too big");
}
return map;
}
public static ContentInfo getContentInfo( byte[] input ) {
Object content = readContentInfo( input );
ASN1Sequence seq = ASN1Sequence.getInstance( content );
return new ContentInfo(seq);
}
public static Map<String, Object> readCmsInfo( byte[] input ) throws CMSException {
Map<String, Object>map = new HashMap<String, Object>();
Object content = readContentInfo( input );
ASN1Sequence seq = ASN1Sequence.getInstance( content );
ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier) seq.getObjectAt(0);
map.put("oid", oid);
seq = ASN1Sequence.getInstance((ASN1TaggedObject) seq.getObjectAt(1), true);
int index = 0;
ASN1Integer version = (ASN1Integer)seq.getObjectAt(index++);
map.put( "version", version );
Object tmp = seq.getObjectAt(index++);
if (tmp instanceof ASN1TaggedObject)
{
OriginatorInfo originatorInfo = OriginatorInfo.getInstance((ASN1TaggedObject)tmp, false);
// Map<String, Object>originatorInfo = getOriginatorInfo((ASN1TaggedObject)tmp, false);
map.put( "originatorInfo", originatorInfo );
tmp = seq.getObjectAt(index++);
}
ASN1Set recipientInfos = ASN1Set.getInstance(tmp);
map.put( "recipientInfos", recipientInfos );
EncryptedContentInfo encryptedContentInfo = EncryptedContentInfo.getInstance( seq.getObjectAt(index++) );
// Map<String, Object> encryptedContentInfo = getEncryptedContentInfo(seq.getObjectAt(index++));
map.put( "encryptedContentInfo", encryptedContentInfo );
if(seq.size() > index)
{
ASN1Set unprotectedAttrs = ASN1Set.getInstance((ASN1TaggedObject)seq.getObjectAt(index), false);
map.put( "unprotectedAttrs", unprotectedAttrs );
}
return map;
}
}
@@ -0,0 +1,45 @@
package racal.sunyard.main;
import java.util.ArrayList;
import java.util.List;
public class BytesList {
private List<byte[]> bytes = new ArrayList<byte[]>();
public BytesList(){
}
public BytesList(byte[] b){
this.append( b );
}
public void append( byte[] b ) {
bytes.add( b );
}
public byte[] toBytes(){
int len = 0;
if(1== bytes.size()){
return bytes.get(0);
}
for ( byte[] b : bytes ) {
len += b.length;
}
if ( 0 == len ) {
return new byte[0];
}
byte[] buff = new byte[ len ];
int idx = 0;
for ( byte[] b : bytes ) {
System.arraycopy( b, 0, buff, idx, b.length );
idx += b.length;
}
return buff;
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,42 @@
package racal.sunyard.main;
import com.sunyard.SydApi;
import com.sunyard.SydApiException;
import com.sunyard.proxy.ProxyInvocationHandler;
public class SydApiClusterBuilder {
public static SydApi SYD_Short_Connect_Ex(String[] pcIpList, int[] iPortList, int iConnectTimeOut, int allDealTimeOut) {
if (pcIpList.length != iPortList.length) {
throw new IllegalArgumentException("ip与端口数量不一致");
}
SydApi4j[] apis = new SydApi4j[pcIpList.length];
int iDealTimeOut = allDealTimeOut / pcIpList.length;
boolean connected = false;
SydApi4j sydApi4j = new SydApi4j();
for (int i = 0; i < pcIpList.length; i++) {
try {
apis[i] = (SydApi4j) sydApi4j.connect(pcIpList[i], iPortList[i], null, iConnectTimeOut, iDealTimeOut);
connected = true;
} catch (Exception e) {
// 忽略错误
// log.error("网络连接错误 {} {} - 忽略", pcIpList[i], iPortList[i]);
}
}
if (!connected) {
// TODO
throw new SydApiException("连接错误", -1);
}
// hsms = apis;
// isShortLinkMode = true;
ProxyInvocationHandler proxyInvocationHandler = new ProxyInvocationHandler(apis);
return proxyInvocationHandler.getProxy();
}
}
@@ -0,0 +1,4 @@
package racal.sunyard.main;
public class SydApiMuti extends SydApi4j {
}
@@ -0,0 +1,43 @@
package racal.sunyard.main;
import com.sunyard.SydApi;
import com.sunyard.pool.HsmLinkInfo;
import com.sunyard.pool.SydApiPool;
public class SydApiPoolBuilder {
private SydApiPool pool;
public SydApiPoolBuilder(String[] pcIpList, int[] iPortList, int iConnectTimeOut, int iDealTimeOut){
this(pcIpList, iPortList, iConnectTimeOut, iDealTimeOut, true);
}
public SydApiPoolBuilder(String[] pcIpList, int[] iPortList, int iConnectTimeOut, int iDealTimeOut, boolean warmup) {
HsmLinkInfo[] linkInfo = HsmLinkInfo.mutiHsmLinkInfo(pcIpList, iPortList, iConnectTimeOut, iDealTimeOut);
this.pool = new SydApiPool(linkInfo);
if ( warmup ) {
this.warmUp(pcIpList, iPortList, iConnectTimeOut, iDealTimeOut);
}
}
public SydApi build() {
return (SydApi)this.pool.get();
}
public SydApiPool getPool() {
return pool;
}
private void warmUp(String[] pcIpList, int[] iPortList, int iConnectTimeOut, int iDealTimeOut) {
// SydApi4j api = null;
SydApi api = null;
try {
// api = new SydApi4j();
api = SydApiClusterBuilder.SYD_Short_Connect_Ex(pcIpList, iPortList, iConnectTimeOut, iDealTimeOut);
} catch (Exception e) {
} finally {
if (null != api) {
api.disconnect();
}
}
}
}
@@ -0,0 +1,69 @@
package racal.sunyard.main;
public interface SydHashApiTest {
/**
* 计算SM3散列值
* @param sn 证书序号
* @param userId 用户ID
* @param msg 原始数据,二进制的消息块
* @return
*/
byte[] SM3HashSNaId(String sn, String userId, byte[] msg);
/**
* 输入对指定的原始数据和公钥,通过 SM3 算法计算数据的散列值。
* @param publicKey 公钥的 DER 编码(可以为空)
* @param msg 原始数据,二进制的消息块
* @param block 消息块标志
* @param mac 上一轮 mac 值,当 mac 不是 null,长度不为 0,则直接从第二包开始。
* @return HASH 值,32 个 Bytes.
*/
byte[] SM3Hash(String publicKey, byte[] msg, int block, byte[] mac);
/**
* 计算SM3散列值
* @param publicKey 公钥的 DER 编码 (03420004 开头)
* @param userId 用户ID
* @param msg 原始数据,二进制的消息块
* @return
*/
byte[] SM3Hash(String publicKey, String userId, byte[] msg);
/**
* 输入对指定的原始数据和公钥,通过 SM3 算法计算数据的散列值。
*
* @param publicKey 公钥(可以为空)
* @param msg 原始数据
* @return HASH 值,32 个 Bytes.
*/
byte[] SM3Hash(String publicKey, byte[] msg);
/**
* 输入对指定的原始数据 (无公钥),通过 SM3 算法计算数据的散列值。
*
* @param msg 原始数据
* @return HASH 值,32 个 Bytes.
*/
byte[] SM3Hash(byte[] msg);
public byte[] MACCalc(int alg, int keyType, int fullmode, int maclen, String key, byte[] infoData);
/**
* mac 计算
* @param alg 0=DES 1=3DES 2=SM4 3=AES 4=IDEA 5=SM1 6=3DES-X9.19
* @param keyType 0-TAK 1-ZAK
* @param fullMode 0-弱填充 1 强填充
* @param AK 密钥
* @param infoData <=1024
* @param macLen 1=4Byte 2=8Byte 3=16Byte(仅在SM4/AES 下有效)
* @return mac 值 hex 格式
*/
public String MACCalc(int alg, int keyType, String AK, int fullMode, byte[] infoData, int macLen);
public void MACCheck(int alg, int keyType, String AK, int fullMode, byte[] infoData, String mac);
public String calcPBOCMAC(int mode, int keyType, String key, byte[] data, int block, byte[] iv);
}
+116
View File
@@ -0,0 +1,116 @@
import com.sunyard.snmp.SnmpTrapSender;
import com.sunyard.task.AsyncTaskExecutor;
import com.sunyard.task.TaskContext;
import com.sunyard.task.TaskOutcome;
import java.io.File;
import java.io.IOException;
import java.time.Duration;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.function.Supplier;
import java.util.stream.Collectors;
public class SimpleTest {
public static void main(String[] args) throws Exception {
// testt();
testSnmp();
}
public static void testt() {
AsyncTaskExecutor executor = new AsyncTaskExecutor();
// 使用示例
List<TaskContext<String>> tasks = Arrays.asList(
createTaskContext("1", 1000, "cert"),
createTaskContext("2", 1000, "cert"),
createTaskContext("3", 1000, "cert"),
createTaskContext("4", 1000, "cert")
);
List<TaskOutcome<String>> outcomes = executor.execBatchTasks(tasks);
executor.shutdown();
// 分离成功失败
List<String> successes = outcomes.stream()
.filter(TaskOutcome::isSuccess)
.map(TaskOutcome::getResult)
.collect(Collectors.toList());
List<TaskOutcome<String>> failures = outcomes.stream()
.filter(out -> !out.isSuccess())
.collect(Collectors.toList());
String result = "[" + failures.stream()
.map(p -> p.getContext().getAddress())
.collect(Collectors.joining(",")) + "]";
String message = "信雅达签名服务器:" + result + ",证书: " + "cert" + ",导入失败";
System.out.println(message);
System.out.println("成功节点: " + successes);
System.out.println("失败详情: ");
failures.forEach(f ->
System.out.println(f.getContext().getAddress() + ": " + f.getError().getMessage())
);
}
private static TaskContext<String> createTaskContext(String address, int timeout, String cert) {
Supplier<String> task = () -> importS(address);
return new TaskContext<>(task, 2, Duration.ofSeconds(1), address);
}
public static void test() throws InterruptedException {
List<String> addressList = new ArrayList<>();
addressList.add("1");
addressList.add("2");
addressList.add("3");
addressList.add("4");
addressList.add("6");
CompletableFuture<String>[] futures = new CompletableFuture[addressList.size()];
for(int i = 0; i < addressList.size(); i++){
int finalI = i;
futures[i] = CompletableFuture.supplyAsync(() -> {
return importS(addressList.get(finalI));
});
}
// Thread.sleep(2000);
//汇总失败的任务
List<String> failedTasks = new ArrayList<>();
for(int i = 0; i < futures.length; i++){
if(futures[i].isCompletedExceptionally()){
failedTasks.add(addressList.get(i));
}
}
for (String s : failedTasks) {
System.out.println(s);
try {
String path = "/Users/waner/Work" + "/" + s + ".txt";
File file = new File(path);
file.createNewFile();
} catch (Exception e) {
}
}
}
public static String importS(String s){
// System.out.println("handle:" + s);
if (Integer.parseInt(s) % 2 == 0) {
System.out.println("handle1:" + s);
throw new RuntimeException();
}
return s;
}
public static void testSnmp() throws IOException {
Map<String, String> map = new HashMap<>();
map.put("snmp.target.ip", "172.16.18.113");
map.put("snmp.target.port", "162");
map.put("enterprise.oid", "11");
map.put("snmp.community", "public");
map.put("snmp.version", "1");
// SnmpTrapSender.getInstance().loadConfig(map);
// SnmpTrapSender.getInstance().sendTrap("serve ip[127.0.0.1], import cert failed", 1);
}
}
+54
View File
@@ -0,0 +1,54 @@
import org.snmp4j.CommunityTarget;
import org.snmp4j.PDU;
import org.snmp4j.Snmp;
import org.snmp4j.TransportMapping;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.smi.Address;
import org.snmp4j.smi.GenericAddress;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.UdpAddress;
import org.snmp4j.smi.VariableBinding;
import org.snmp4j.transport.DefaultUdpTransportMapping;
public class SnmpTrapSenderV2c {
public static void main(String[] args) {
try {
// 1. 创建SNMP对象并监听
TransportMapping<?> transport = new DefaultUdpTransportMapping();
Snmp snmp = new Snmp(transport);
transport.listen();
// 2. 创建目标地址
Address targetAddress = new UdpAddress("172.16.18.50/162"); // 接收方的IP和端口
CommunityTarget target = new CommunityTarget();
target.setCommunity(new OctetString("public")); // 社区字符串
target.setAddress(targetAddress);
target.setVersion(SnmpConstants.version2c);
target.setTimeout(3000);
target.setRetries(1);
// 3. 创建PDU(协议数据单元)
PDU pdu = new PDU();
// 必须的系统信息
pdu.add(new VariableBinding(SnmpConstants.sysUpTime, new OctetString("12345")));
pdu.add(new VariableBinding(SnmpConstants.snmpTrapOID, new OID("1.3.6.1.6.3.1.1.5.3")));
// 添加自定义变量绑定(可选)
pdu.add(new VariableBinding(new OID("1.3.6.1.2.1.1.1.0"), new OctetString("My Device")));
pdu.add(new VariableBinding(new OID("1.3.6.1.2.1.1.5.0"), new OctetString("Critical Error")));
pdu.setType(PDU.TRAP);
// 4. 发送Trap
snmp.send(pdu, target);
System.out.println("SNMPv2c Trap 发送成功");
snmp.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
+155
View File
@@ -0,0 +1,155 @@
package cmbpoc;
import com.sunyard.RetWrap;
import com.sunyard.SydApi;
import com.sunyard.proto.PacketSection;
import com.sunyard.proto.Util;
import org.junit.*;
import racal.sunyard.main.SydApi4j;
public class FunctionTest {
private SydApi4j api;
private String keypairIndex4Sign = "0000000000000sge00000000001";
private String keypairIndex4Ende = "0000000000000sge00100000001";
private byte[] privateKey4Sign;
private byte[] publicKey4Sign;
private byte[] privateKey4Ende;
private byte[] publicKey4Ende;
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[ 10 * 1024 * 1024 ];
private String sign;
@Before
public void start(){
// 调试模式
System.setProperty("com.sunyard.sydapi4j.debug", "true");
// 建立链接(单台)
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() );
// this.privateKey4Sign = Util.hexString2Bytes( keypair.get("sk").toString() );
//
// RetWrap keypair4Ende = this.getPrivateKeyAndPublickKey(keypairIndex4Sign);
// this.publicKey4Ende = Util.hexString2Bytes( keypair4Ende.get("pk").toString() );
// this.privateKey4Ende = Util.hexString2Bytes( keypair4Ende.get("sk").toString() );
// 使用预置密钥对
this.publicKey4Sign = Util.hexString2Bytes( "034200046508BC4FE965BEB1D57715C180135FC861FDC6527E82E7FD7A6CA25E7CE9CE75101181D7E2CDD16C1974652B38A045465C7FFBAC700E49F949AE5F4C57AEBEAA" );
this.privateKey4Sign = Util.hexString2Bytes( "00010000CF945DAFF49B9F3AB67A23E1E1BA700FF1F78F5DFFCBB518FD1303A51DABA6FC0000000000000000000000000000000000000000000000000000000000000000" );
this.publicKey4Ende = Util.hexString2Bytes("03420004AF3D4E55D26564C6C937E6EA9232691C01AC5E7916AD2136F788CE7C1E4D0AE8C4754DEC2F7F6A78962D51A171A6F5B4F11823390AEC8B5B0246CD2CCF8052B7");
this.privateKey4Ende = Util.hexString2Bytes("00010000963F7C3A98B7810F52D2861A060E18A9D4D59796CF33967DD61EEDA091E1AD9B0000000000000000000000000000000000000000000000000000000000000000");
}
@After
public void stop(){
if ( null != api ) {
this.api.disconnect();
this.api = null;
}
}
@Ignore
@Test
public void genKeyPair(){
// RetWrap r = this.api.SYD_SM2GenKeyPair();
// String pk = r.get("publicKey").toString();
// String sk = r.get("privateKey").toString();
//
// System.out.println("pk=" + pk);
// System.out.println("sk=" + sk);
//
// this.privateKey4Sign = Util.hexString2Bytes(sk);
// this.publicKey4Sign = Util.hexString2Bytes(pk);
RetWrap rw = this.api.SM2GenKeyPair();
byte[] pk = (byte[]) rw.get(SydApi.RET_PUBLIC_KEY);
byte[] sk = (byte[]) rw.get(SydApi.RET_PRIVATE_KEY);
System.out.println("pk=" + Util.bytes2HexString(pk));
System.out.println("sk=" + Util.bytes2HexString(sk));
}
public RetWrap getPrivateKeyAndPublickKey(String keypairIndex){
String pk = this.api.SM2GetPublicKeyC(keypairIndex);
String sk = this.api.SM2GetPrivateKeyC(keypairIndex);
System.out.println("pk=" + pk);
System.out.println("sk=" + sk);
RetWrap retWrap = new RetWrap();
retWrap.put("pk", pk);
retWrap.put("sk", sk);
return retWrap;
}
@Test
public void SYD_SM2_Sign(){
String sign = this.api.SYD_SM2_Sign_HA( SydApi.DATA_HASH, privateKey4Sign, publicKey4Sign, orgData);
this.api.SYD_SM2_Verify_HA(SydApi.DATA_HASH, publicKey4Sign, orgData, sign);
}
@Test
public void SYD_SM2_Sign_2M(){
String sign = this.api.SYD_SM2_Sign_HA( SydApi.DATA_HASH, privateKey4Sign, publicKey4Sign, orgData2M);
this.api.SYD_SM2_Verify_HA(SydApi.DATA_HASH, publicKey4Sign, orgData2M, sign);
}
@Test
public void SYD_SM2_Sign_10M(){
String sign = this.api.SYD_SM2_Sign_HA( SydApi.DATA_HASH, privateKey4Sign, publicKey4Sign, orgData10M);
this.api.SYD_SM2_Verify_HA(SydApi.DATA_HASH, publicKey4Sign, orgData10M, sign);
}
@Test
public void SYD_SM2_Encrypt(){
byte[] enData = this.api.SYD_SM2Encrypt(publicKey4Ende, orgData);
System.out.println("密文=" + Util.bytes2HexString(enData));
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("密文长度=" + enData.length);
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);
}
}
+156
View File
@@ -0,0 +1,156 @@
package cmbpoc;
import com.sunyard.SydApi;
import com.sunyard.proto.Util;
import org.apache.jmeter.config.Arguments;
import org.apache.jmeter.protocol.java.sampler.AbstractJavaSamplerClient;
import org.apache.jmeter.protocol.java.sampler.JavaSamplerContext;
import org.apache.jmeter.samplers.SampleResult;
import racal.sunyard.main.SydApi4j;
import java.util.Random;
public class JmeterTest extends AbstractJavaSamplerClient {
private byte[] publicKey;
private byte[] plainData;
private byte[] encryptedData;
private String sign;
private int sleep = 1;
private byte[] privateKey4Sign;
private byte[] publicKey4Sign;
private byte[] privateKey4Ende;
private byte[] publicKey4Ende;
private String ip ;
private int port;
private int timeout;
private String ip2 ;
private ThreadLocal<SydApi4j> api;
@Override
public Arguments getDefaultParameters() {
Arguments params = new Arguments();
params.addArgument("function", "sleep");
params.addArgument("sleep", "1");
params.addArgument("plainDataLen", "1024");
params.addArgument("publicKey4Ende", "", "加密用的公钥");
params.addArgument("privateKey4Ende", "", "解密用的公钥");
params.addArgument("publicKey4Sign", "", "验签用的公钥");
params.addArgument("privateKey4Sign", "", "签名用的公钥");
params.addArgument("ip", "192.168.100.145");
params.addArgument("ip2", "172.1.41.96");
params.addArgument("port", "8889");
params.addArgument("timeout", "3000");
return params;
}
@Override
public void setupTest(JavaSamplerContext context) {
// 签名密钥对
String publicKey4Sign = context.getParameter("publicKey4Sign");
if ( null != publicKey4Sign && !publicKey4Sign.isEmpty()) {
this.publicKey4Sign = Util.hexString2Bytes(publicKey4Sign);
}
String privateKey4Sign = context.getParameter("privateKey4Sign");
if ( null != privateKey4Sign && !privateKey4Sign.isEmpty()) {
this.privateKey4Sign = Util.hexString2Bytes(privateKey4Sign);
}
// 加密密钥对
String publicKey4Ende = context.getParameter("publicKey4Ende");
if ( null != publicKey4Ende && !publicKey4Ende.isEmpty()) {
this.publicKey4Ende = Util.hexString2Bytes(publicKey4Ende);
}
String privateKey4Ende = context.getParameter("privateKey4Ende");
if ( null != privateKey4Ende && !privateKey4Ende.isEmpty()) {
this.privateKey4Ende = Util.hexString2Bytes(privateKey4Ende);
}
// 原始数据
int plainDataLen = context.getIntParameter("plainDataLen");
plainData = new byte[plainDataLen];
new Random().nextBytes(plainData);
System.out.println("原始数据长度:" + plainDataLen);
// 校准测试
sleep = context.getIntParameter("sleep", 1);
// api
ip = context.getParameter("ip");
ip2 = context.getParameter("ip2");
port = context.getIntParameter("port");
timeout = context.getIntParameter("timeout");
api = new ThreadLocal<SydApi4j>() {
@Override
public SydApi4j initialValue() {
return (SydApi4j) new SydApi4j().connect(ip, port, null, timeout);
}
};
// 线程开始时准备解密、验签数据
String function = context.getParameter("function");
switch (function) {
case "SYD_SM2_Decrypt":
this.encryptedData = this.api.get().SYD_SM2Encrypt(this.publicKey4Ende, this.plainData);
break;
case "SYD_SM2_Verify":
this.sign = this.api.get().SYD_SM2_Sign_HA(SydApi.DATA_HASH, this.privateKey4Sign, this.publicKey4Sign, this.plainData);
break;
default:
break;
}
}
@Override
public SampleResult runTest(JavaSamplerContext context) {
SampleResult result = new SampleResult();
// 调用待测函数
String function = context.getParameter("function");
result.sampleStart(); // 开始计时
try {
switch (function) {
case "SYD_SM2_Encrypt":
this.api.get().SYD_SM2Encrypt(publicKey4Ende, this.plainData);
break;
case "SYD_SM2_Decrypt":
this.api.get().SYD_SM2Decrypt(privateKey4Ende, this.encryptedData);
break;
case "SYD_SM2_Sign":
this.api.get().SYD_SM2_Sign_HA(SydApi.DATA_HASH, privateKey4Sign, publicKey4Sign, this.plainData);
break;
case "SYD_SM2_Verify":
this.api.get().SYD_SM2_Verify_HA(SydApi.DATA_HASH, publicKey4Sign, this.plainData, this.sign);
break;
case "sleep":
Thread.sleep( this.sleep );
break;
default:
break;
}
// result.setResponseData(encrypted); // 可选
result.setSuccessful(true);
result.setResponseCodeOK();
result.setResponseMessage( function + "执行成功" );
} catch (Exception e) {
result.setSuccessful(false);
result.setResponseCode("500");
result.setResponseMessage( function + "执行失败。" + e.getMessage());
} finally {
result.sampleEnd(); // 结束计时
}
return result;
}
@Override
public void teardownTest(JavaSamplerContext context) {
// 释放资源(如有)
}
}
+51
View File
@@ -0,0 +1,51 @@
package cmbpoc;
import org.apache.jmeter.protocol.java.sampler.JavaSamplerContext;
import org.apache.jmeter.config.Arguments;
import org.apache.jmeter.protocol.java.sampler.JavaSamplerContext;
import org.apache.jmeter.samplers.SampleResult;
public class JmeterTestTest {
public static void main(String[] args) {
// 1. 创建 JMeter 参数集,并填入您提供的所有参数
Arguments jmeterArgs = new Arguments();
jmeterArgs.addArgument("function", "SYD_SM2_Encrypt");
jmeterArgs.addArgument("sleep", "1");
jmeterArgs.addArgument("plainDataLen", "2048");
jmeterArgs.addArgument("publicKey4Ende", "03420004AF3D4E55D26564C6C937E6EA9232691C01AC5E7916AD2136F788CE7C1E4D0AE8C4754DEC2F7F6A78962D51A171A6F5B4F11823390AEC8B5B0246CD2CCF8052B7");
jmeterArgs.addArgument("privateKey4Ende", "00010000963F7C3A98B7810F52D2861A060E18A9D4D59796CF33967DD61EEDA091E1AD9B0000000000000000000000000000000000000000000000000000000000000000");
jmeterArgs.addArgument("ip", "192.168.100.145");
jmeterArgs.addArgument("ip2", "172.1.41.96");
jmeterArgs.addArgument("port", "8889");
jmeterArgs.addArgument("timeout", "3000");
// 2. 基于参数集创建 JMeter 上下文对象
JavaSamplerContext context = new JavaSamplerContext(jmeterArgs);
// 3. 创建您的测试类实例
JmeterTest jmeterTest = new JmeterTest();
try {
// 4. 模拟 JMeter 执行周期:setup -> run -> teardown
jmeterTest.setupTest(context);
SampleResult result = jmeterTest.runTest(context);
if (result != null) {
System.out.println("SampleResult 状态: " + result.getResponseCode());
System.out.println("响应数据: " + result.getResponseDataAsString());
System.out.println("是否成功: " + result.isSuccessful());
} else {
System.out.println("runTest 返回 null,请检查实现逻辑");
}
jmeterTest.teardownTest(context);
} catch (Exception e) {
System.err.println("执行测试时发生异常:");
e.printStackTrace();
}
}
}
+186
View File
@@ -0,0 +1,186 @@
package cmbpoc;
import com.sunyard.RetWrap;
import com.sunyard.SydApi;
import com.sunyard.entity.TimeStats;
import com.sunyard.proto.Util;
import org.junit.*;
import racal.sunyard.main.SydApi4j;
public class PerformanceTest {
private SydApi4j api;
private byte[] privateKey4Ende;
private byte[] publicKey4Ende;
private byte[] orgData2K = new byte[2 * 1024];
private byte[] orgData2M = new byte[2 * 1024 * 1024];
private byte[] orgData10M = new byte[10 * 1024 * 1024];
private static final int TEST_ROUNDS = 10;
@Before
public void start() {
System.setProperty("com.sunyard.sydapi4j.debug", "false");
String ip = System.getProperty("ip", "192.168.100.145");
System.out.println("ip=" + ip);
this.api = (SydApi4j) new SydApi4j().connect(ip, 8889, null, 30000);
this.publicKey4Ende = Util.hexString2Bytes("03420004AF3D4E55D26564C6C937E6EA9232691C01AC5E7916AD2136F788CE7C1E4D0AE8C4754DEC2F7F6A78962D51A171A6F5B4F11823390AEC8B5B0246CD2CCF8052B7");
this.privateKey4Ende = Util.hexString2Bytes("00010000963F7C3A98B7810F52D2861A060E18A9D4D59796CF33967DD61EEDA091E1AD9B0000000000000000000000000000000000000000000000000000000000000000");
}
@After
public void stop() {
if (null != api) {
this.api.disconnect();
this.api = null;
}
}
@Test
public void SYD_SM2_Encrypt_Performance_2K() {
System.out.println("=== SYD_SM2_Encrypt Performance Test - 2K Data ===");
long totalEncryptTime = 0;
long totalDecryptTime = 0;
for (int i = 0; i < TEST_ROUNDS; i++) {
long encryptStart = System.currentTimeMillis();
byte[] enData = this.api.SYD_SM2Encrypt(publicKey4Ende, orgData2K);
long encryptEnd = System.currentTimeMillis();
long decryptStart = System.currentTimeMillis();
byte[] deData = this.api.SYD_SM2Decrypt(privateKey4Ende, enData);
long decryptEnd = System.currentTimeMillis();
totalEncryptTime += (encryptEnd - encryptStart);
totalDecryptTime += (decryptEnd - decryptStart);
Assert.assertArrayEquals(orgData2K, deData);
}
double avgEncryptTime = (double) totalEncryptTime / TEST_ROUNDS;
double avgDecryptTime = (double) totalDecryptTime / TEST_ROUNDS;
double encryptThroughput = (2.0 / avgEncryptTime) * 1000;
double decryptThroughput = (2.0 / avgDecryptTime) * 1000;
System.out.println("Test Rounds: " + TEST_ROUNDS);
System.out.println("Data Size: 2KB");
System.out.printf("Average Encrypt Time: %.2f ms%n", avgEncryptTime);
System.out.printf("Average Decrypt Time: %.2f ms%n", avgDecryptTime);
System.out.printf("Encrypt Throughput: %.2f KB/s%n", encryptThroughput);
System.out.printf("Decrypt Throughput: %.2f KB/s%n", decryptThroughput);
System.out.println();
}
@Test
public void SYD_SM2_Encrypt_Performance_2M() {
System.out.println("=== SYD_SM2_Encrypt Performance Test - 2M Data ===");
long totalEncryptTime = 0;
long totalDecryptTime = 0;
for (int i = 0; i < TEST_ROUNDS; i++) {
long encryptStart = System.currentTimeMillis();
byte[] enData = this.api.SYD_SM2Encrypt(publicKey4Ende, orgData2M);
long encryptEnd = System.currentTimeMillis();
long decryptStart = System.currentTimeMillis();
byte[] deData = this.api.SYD_SM2Decrypt(privateKey4Ende, enData);
long decryptEnd = System.currentTimeMillis();
totalEncryptTime += (encryptEnd - encryptStart);
totalDecryptTime += (decryptEnd - decryptStart);
Assert.assertArrayEquals(orgData2M, deData);
}
double avgEncryptTime = (double) totalEncryptTime / TEST_ROUNDS;
double avgDecryptTime = (double) totalDecryptTime / TEST_ROUNDS;
double encryptThroughput = (2048.0 / avgEncryptTime) * 1000;
double decryptThroughput = (2048.0 / avgDecryptTime) * 1000;
System.out.println("Test Rounds: " + TEST_ROUNDS);
System.out.println("Data Size: 2MB");
System.out.printf("Average Encrypt Time: %.2f ms%n", avgEncryptTime);
System.out.printf("Average Decrypt Time: %.2f ms%n", avgDecryptTime);
System.out.printf("Encrypt Throughput: %.2f KB/s%n", encryptThroughput);
System.out.printf("Decrypt Throughput: %.2f KB/s%n", decryptThroughput);
System.out.println();
}
@Test
public void SYD_SM2_Encrypt_Performance_10M() {
System.out.println("=== SYD_SM2_Encrypt Performance Test - 10M Data ===");
long totalEncryptTime = 0;
long totalDecryptTime = 0;
for (int i = 0; i < TEST_ROUNDS; i++) {
long encryptStart = System.currentTimeMillis();
byte[] enData = this.api.SYD_SM2Encrypt(publicKey4Ende, orgData10M);
long encryptEnd = System.currentTimeMillis();
long decryptStart = System.currentTimeMillis();
byte[] deData = this.api.SYD_SM2Decrypt(privateKey4Ende, enData);
long decryptEnd = System.currentTimeMillis();
totalEncryptTime += (encryptEnd - encryptStart);
totalDecryptTime += (decryptEnd - decryptStart);
Assert.assertArrayEquals(orgData10M, deData);
}
double avgEncryptTime = (double) totalEncryptTime / TEST_ROUNDS;
double avgDecryptTime = (double) totalDecryptTime / TEST_ROUNDS;
double encryptThroughput = (10240.0 / avgEncryptTime) * 1000;
double decryptThroughput = (10240.0 / avgDecryptTime) * 1000;
System.out.println("Test Rounds: " + TEST_ROUNDS);
System.out.println("Data Size: 10MB");
System.out.printf("Average Encrypt Time: %.2f ms%n", avgEncryptTime);
System.out.printf("Average Decrypt Time: %.2f ms%n", avgDecryptTime);
System.out.printf("Encrypt Throughput: %.2f KB/s%n", encryptThroughput);
System.out.printf("Decrypt Throughput: %.2f KB/s%n", decryptThroughput);
System.out.println();
}
@Test
public void SYD_SM2_Encrypt_TimeStats_2M() {
System.out.println("=== SYD_SM2_Encrypt Time Statistics Test - 2M Data ===");
// 预热
for (int i = 0; i < 2; i++) {
byte[] enData = this.api.SYD_SM2Encrypt(publicKey4Ende, orgData2M);
byte[] deData = this.api.SYD_SM2Decrypt(privateKey4Ende, enData);
}
// 正式测试
TimeStats encryptStats = new TimeStats();
TimeStats decryptStats = new TimeStats();
byte[] enData = this.api.SYD_SM2Encrypt(publicKey4Ende, orgData2M, encryptStats);
byte[] deData = this.api.SYD_SM2Decrypt(privateKey4Ende, enData, decryptStats);
Assert.assertArrayEquals(orgData2M, deData);
System.out.println("\n--- 加密阶段时间统计 ---");
System.out.printf("发送阶段: %d ms (%.1f%%), 发送次数: %d%n",
encryptStats.getSendTime(), encryptStats.getSendPercentage(), encryptStats.getSendCount());
System.out.printf("计算阶段: %d ms (%.1f%%)%n",
encryptStats.getComputeTime(), encryptStats.getComputePercentage());
System.out.printf("接收阶段: %d ms (%.1f%%), 接收次数: %d%n",
encryptStats.getReceiveTime(), encryptStats.getReceivePercentage(), encryptStats.getReceiveCount());
System.out.printf("加密总耗时: %d ms%n", encryptStats.getTotalTime());
System.out.println("\n--- 解密阶段时间统计 ---");
System.out.printf("发送阶段: %d ms (%.1f%%), 发送次数: %d%n",
decryptStats.getSendTime(), decryptStats.getSendPercentage(), decryptStats.getSendCount());
System.out.printf("计算阶段: %d ms (%.1f%%)%n",
decryptStats.getComputeTime(), decryptStats.getComputePercentage());
System.out.printf("接收阶段: %d ms (%.1f%%), 接收次数: %d%n",
decryptStats.getReceiveTime(), decryptStats.getReceivePercentage(), decryptStats.getReceiveCount());
System.out.printf("解密总耗时: %d ms%n", decryptStats.getTotalTime());
System.out.println("\n--- 汇总 ---");
long totalTime = encryptStats.getTotalTime() + decryptStats.getTotalTime();
System.out.printf("加密解密总耗时: %d ms%n", totalTime);
System.out.printf("加密吞吐量: %.2f KB/s%n", (2048.0 / encryptStats.getTotalTime()) * 1000);
System.out.printf("解密吞吐量: %.2f KB/s%n", (2048.0 / decryptStats.getTotalTime()) * 1000);
}
}
@@ -0,0 +1,84 @@
package cmbpoc;
import com.sunyard.RetWrap;
import com.sunyard.SydApi;
import com.sunyard.proto.Util;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import racal.sunyard.main.SydApi4j;
public class SignatureVerifyTest {
private SydApi4j api;
private byte[] orgData;
private String SM2dn;
@Before
public void setUp() {
System.setProperty("com.sunyard.sydapi4j.debug", "true");
this.api = (SydApi4j) new SydApi4j().connect("172.1.41.139", 8889, null, 3000);
this.orgData = "Hello, World! 测试数据".getBytes();
this.SM2dn = "C=cn,O=CFCA OCA1 SM2,OU=Local RA OCA1,OU=Units,CN=041@N91330108762038374D@sunyard@00000064";
}
@After
public void tearDown() {
if (api != null) {
this.api.disconnect();
this.api = null;
}
}
@Test
public void testP1SignAndVerify() {
byte[] sign = this.api.SYD_NakedSign(orgData, SM2dn);
Assert.assertNotNull("P1签名结果不应为空", sign);
System.out.println("P1签名结果: " + Util.bytes2HexString(sign));
boolean verifyResult = this.api.SYD_NakedVerify(orgData, sign, SM2dn);
Assert.assertTrue("P1验签应通过", verifyResult);
System.out.println("P1验签结果: " + verifyResult);
}
@Test
public void testP7DetachSignAndVerify() {
String sign = this.api.detachedSign(1, orgData, SM2dn);
Assert.assertNotNull("P7 Detach签名结果不应为空", sign);
System.out.println("P7 Detach签名结果: " + sign);
boolean verifyResult = this.api.detachedVerify(1, orgData, sign);
Assert.assertTrue("P7 Detach验签应通过", verifyResult);
System.out.println("P7 Detach验签结果: " + verifyResult);
}
@Test
public void testP7AttachSignAndVerify() throws Exception {
String sign = this.api.attachedSign(orgData, SM2dn);
Assert.assertNotNull("P7 Attach签名结果不应为空", sign);
System.out.println("P7 Attach签名结果: " + sign);
boolean verifyResult = this.api.attachedVerify(sign);
Assert.assertTrue("P7 Attach验签应通过", verifyResult);
System.out.println("P7 Attach验签结果: " + verifyResult);
}
@Test
public void testDigitalEnvelopeEncryptAndDecrypt() {
RetWrap genResult = this.api.generateDEByDn(SM2dn, orgData);
Assert.assertNotNull("数字信封生成结果不应为空", genResult);
byte[] cipherKey = (byte[]) genResult.get(SydApi.RET_CIPHER_KEY);
Assert.assertNotNull("数字信封密文密钥不应为空", cipherKey);
System.out.println("数字信封密文: " + new String(cipherKey));
RetWrap decryptResult = this.api.decryptDEByDN(SM2dn, cipherKey);
Assert.assertNotNull("数字信封解密结果不应为空", decryptResult);
byte[] decryptedData = (byte[]) decryptResult.get("oData");
Assert.assertNotNull("解密数据不应为空", decryptedData);
Assert.assertArrayEquals("解密数据应与原始数据一致", orgData, decryptedData);
System.out.println("数字信封解密结果: " + new String(decryptedData));
}
}
@@ -0,0 +1,45 @@
package com.sunyard.sydapi;
import org.junit.Test;
import racal.sunyard.main.SydApi4j;
/**
* 传化签名验签demo
* */
public class ChuanhuaDemo1 {
public static void main(String[] args) {
// 调试模式
System.setProperty("com.sunyard.sydapi4j.debug", "true");
// 建立链接(单台)
SydApi4j api = (SydApi4j) new SydApi4j().connect("192.168.0.100", 8889, null, 1000);
try {
final String testSN1 = "1004282451";
final String testSN2 = "1004282452";
byte[] testData = "1234567812345678信达雅SUNYARDsunyard".getBytes("UTF-8");
System.out.println("\n\n----- 用指定的证书私钥对指定的数据进行数字签名。 -----");
String signPri = api.netSign(testSN1, testData);
System.out.print("sign : ");
System.out.println(signPri);
// 验签传原始数据
System.out.println("\n\n----- 用指定的证书私钥对指定的数据进行数字验证。 -----");
if (api.netVerify(testSN1, testData, signPri)) {
System.out.println("验证通过");
} else {
System.out.println("验证失败");
}
}catch (Exception e){
e.printStackTrace();
}finally {
api.disconnect();
}
}
}
@@ -0,0 +1,65 @@
package com.sunyard.sydapi;
import com.sunyard.proto.Util;
import org.junit.Assert;
import racal.sunyard.main.SydApi4j;
/**
* 传化国密加解密demo
* */
public class ChuanhuaDemo2 {
/*public static void write(String file, byte[] content) {
try {
File f = new File(file);
if (!f.exists()) {
f.createNewFile();
}
FileOutputStream fos = new FileOutputStream(f);
fos.write(content);
} catch (Exception e) {
System.out.println("写入文件 " + file + " 异常");
}
}*/
public static void main(String[] args){
// 调试模式
System.setProperty("com.sunyard.sydapi4j.debug", "true");
// 建立链接(单台)
// SydApi4j api = (SydApi4j) new SydApi4j().connect("192.168.0.100", 8889, null, 1000);
SydApi4j api = (SydApi4j) new SydApi4j().connect("172.16.18.59", 8889, null, 1000);
try{
// final String testSN1 = "1004282451";//签名
// final String testSN2 = "1004282452";//加密
final String userId = "1747";
byte[] testData = "1234567812345678信达雅SUNYARDsunyard@!#$%^加密s".getBytes("GBK");
String pk = api.SM2GetPublicKeyC(userId, 1);
System.out.println("pk= " + pk);
System.out.println("\n\n----- 用输入的会话密钥,对指定报文数据进行加密处理。 SM2 -----");
String sdata = api.SM2Encrypt(Util.hexString2Bytes(pk), testData);
System.out.println("加密后的数据: " + sdata);
System.out.println("\n\n----- 用输入的会话密钥,对指定报文数据进行解密处理。 SM2 -----");
byte[] data = api.SM2DecryptC(userId, sdata);
Assert.assertArrayEquals(testData, data);
System.out.println("解密后的数据: " + new String(data));
// write("./data.txt",data);
}catch (Exception e){
e.printStackTrace();
}finally {
api.disconnect();
}
}
}
@@ -1,55 +0,0 @@
package com.sunyard.sydapi.loadrunner;
import com.sunyard.sydapi.loadrunner.action1.Actions;
import racal.sunyard.main.SydApi4j;
import racal.sunyard.main.SydApiBuilder;
public class ShangTest {
private static final String dn = "C=CN,O=CFCA OCA1,OU=YCCA,OU=Individual-2,CN=YCCA@黄金交易所@Zhuangj@1";
private static final byte[] testData = new byte[ 4 * 1024 ];
private SydApi4j api = null;
public void init() throws Exception {
if ( null == api ) {
api = (SydApi4j) new SydApiBuilder()
.setIp("172.16.18.59") // 192.168.0.162
.setPort( 8889 )
.useDebugMode()
.build();
}
}
public void action(){
String sign = api.attachedSign(testData, dn);
boolean ret = api.attachedVerify( sign );
assert ret;
sign = api.SYD_DetachedSign(testData, dn);
ret = api.SYD_DetachedVerify( testData, sign );
assert ret;
}
public void end(){
if (null != this.api ) {
this.api.disconnect();
}
}
public static void main(String[] args) throws Throwable {
System.out.println( SydApi4j.getVersion() );
// Actions test = new Actions();
ShangTest test = new ShangTest();
test.init();
test.action();
test.end();
}
}
@@ -1,44 +0,0 @@
package com.sunyard.sydapi.loadrunner.action1;
/*
* LoadRunner Java script. (Build: _build_number_)
*
* Script Description:
*
*/
import racal.sunyard.main.SydApi4j;
import racal.sunyard.main.SydApiBuilder;
public class Actions
{
private static final byte[] testData = new byte[ 4 * 1024 ];
private SydApi4j api = null;
public int init() throws Throwable {
if ( null == api ) {
api = (SydApi4j) new SydApiBuilder()
.setIp("172.16.18.59")
.setPort( 8889 )
.useDebugMode()
.build();
}
return 0;
}//end of init
public int action() throws Throwable {
api.SM3Hash( testData );
return 0;
}//end of action
public int end() throws Throwable {
if (null != this.api ) {
this.api.disconnect();
}
return 0;
}//end of end
}
@@ -1,203 +0,0 @@
package com.sunyard.sydapi.test;
import com.sunyard.RetWrap;
import com.sunyard.SydApi;
import com.sunyard.proto.Util;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import racal.sunyard.main.SydApi4j;
import java.io.UnsupportedEncodingException;
import static com.sunyard.sydapi.util.PrintUtil.printByteArray;
import static com.sunyard.sydapi.util.PrintUtil.printRetWrap;
/**
* 农行北分海淀支行-军队资金集中收付系统
*/
public class ABCNorthBranch {
SydApi4j api;
// SM2密钥索引
String SM2PrivateKeyTag = "111111111111115100000000001";
// SM2公钥
String SM2PublicKey = null;
// SM2私钥
String SM2PrivateKey = null;
// SM4密钥索引
String SM4PrivateKeyTag = "000000000000000100011111111";
// SM4密钥
String SM4Key = null;
@Before
public void before() {
System.setProperty("com.sunyard.sydapi4j.debug", "true");
api = (SydApi4j) new SydApi4j().connect("61.164.40.82", 8889, null, 5000);
SM2PublicKey = api.SM2GetPublicKeyC(SM2PrivateKeyTag);
SM2PrivateKey = api.SM2GetPrivateKeyC(SM2PrivateKeyTag);
SM4Key = new String((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 testSM2SignAndVerify() {
String orgData = "11111111111111";
// 这里,不管是签名还是验签,都需要在外部做一次hash。
byte[] hash = api.SM3Hash(SM2PublicKey, orgData.getBytes());
/**
* 用私钥签名(外部私钥)
* @param nOrgDataType 签名数据类型,0 : hash 1 : 原数据
* @param privateKey LMK34-35 下加密的私钥
* @param orgData “签名数据类型”为 0 时:HASH 值。“签名数据类型”为 1 时:要签名的信息
* @return 签名的 base64 编码
*/
String s = api.SM2Sign(SydApi.DATA_HASH, Util.hexString2Bytes(SM2PrivateKey), hash);
// 这里的签名结果已经符合条件了,不需要做转换
System.out.println("签名结果: " + s);
System.out.println("decBase64:" + Util.bytes2HexString(Util.decodeBase64(s)));
/**
* 用指定的公钥对指定的原始数据进行数字签名验证(PKCS#1)
* @param nOrgDataType 签名数据类型,SydApi.DATA_ORIGIN(1) 原始数据 SydApi.DATA_HASH(0) : hash 后的类型
* @param publicKey 公钥串,DER编码,HEX格式
* @param orgData 待签名的原始数据,“签名数据类型”为 0 时:HASH 值。“签名数据类型”为 1 时:要签名的信息
* @param base64Sign 签名数据 (DER 编码 + Base64 编码)
* @return 验签是否通过
*/
boolean b = api.SM2Verify(SydApi.DATA_HASH, Util.hexString2Bytes(SM2PublicKey), hash, 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() throws UnsupportedEncodingException {
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);
}
}
@@ -0,0 +1,90 @@
package com.sunyard.sydapi.test;
import com.github.houbb.junitperf.core.annotation.JunitPerfConfig;
import com.github.houbb.junitperf.core.rule.JunitPerfRule;
import com.sunyard.RetWrap;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import racal.sunyard.main.SydApi4j;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static com.sunyard.sydapi.util.PrintUtil.printRetWrap;
public class CertTest {
public static void main(String[] args) {
//System.setProperty("com.sunyard.sydapi4j.debug", "true");
SydApi4j api = (SydApi4j) new SydApi4j().connect("192.168.1.129", 8889, null, 1000);
try{
List<String>dns = api.getAllCert();
System.out.println(Arrays.toString( dns.toArray() ) );
// String sql=" certtype in (0,2) "; //签名解密
// String sql2=" certtype in (1,3) "; //验签加密
//
// ArrayList<String> m_certs =new ArrayList<String>();
// //查出证书总数,一次次的拿出来
// RetWrap allCert = api.getAllCert(0);
// printRetWrap(allCert);
// Integer allnum = (Integer) allCert.get("certAllNum");//总数
// List<String> certs = (List<String>)allCert.get("certDNs");//部分证书列表
// System.out.println(certs.toString());
// m_certs.addAll(certs);
// int loop = allnum%16;//循环次数
// for (int i = 1; i < loop; i++) {
// RetWrap partCert= api.getAllCert(16*i);
// List<String> partcerts = (List<String>)partCert.get("certDNs");
// m_certs.addAll(partcerts);
// }
// System.out.println("证书:"+m_certs);
// System.out.println("aa"+m_certs.get(20));
}catch (Exception e){
e.printStackTrace();
}finally {
api.disconnect();
}
}
// 测试参数
// private static final int threads = 1;
// private static final long duration = 120000;
// private static final long warmUp = 30000;
//
//
// @Rule
// public JunitPerfRule junitPerfRule = new JunitPerfRule();
// SydApi4j api = (SydApi4j) new SydApi4j().connect("192.168.1.129",8889,null,3000);
//
//
// @BeforeClass
// public static void init() throws UnsupportedEncodingException {
// System.out.println("begin");
//
// }
//
//
// @AfterClass
// public static void after() {
// System.out.println("all over");
// }
//
// @Test
// @JunitPerfConfig(threads = threads, warmUp = warmUp, duration = duration)
// public void getAllCert(){
// try {
// api.getAllCert(0);
// } catch (Exception e) {
// e.printStackTrace();
// }
//
// }
}
@@ -0,0 +1,114 @@
package com.sunyard.sydapi.test;
import com.sunyard.proto.Util;
import org.junit.runners.MethodSorters;
import racal.sunyard.main.SydApi4j;
import com.github.houbb.junitperf.core.annotation.JunitPerfConfig;
import com.github.houbb.junitperf.core.rule.JunitPerfRule;
import org.junit.*;
import org.junit.Test;
import java.io.UnsupportedEncodingException;
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class P1P7Test {
// 全局配置
private static final String dn = "C=CN,O=CFCA OCA1,OU=YCCA,OU=Individual-2,CN=YCCA@黄金交易所@Zhuangj@1";
// 测试参数
private static final int threads = 1;
private static final long duration = 120000;
private static final long warmUp = 30000;
// 原始数据
private static final byte[] data1k = new byte[ 1024 * 4];
private static final byte[] data1m = new byte[ 1024 * 1024 ];
// 临时数据
private static String pk = null;
private static String dm_1k;
private static String dm_1m = null;
private static byte[] p1sign_1k;
private static byte[] p1sign_1m = null;
private static String p7dsign_1k;
private static String p7dsign_1m = null;
private static String p7asign_1k;
private static String p7asign_1m = null;
@Rule
public JunitPerfRule junitPerfRule = new JunitPerfRule();
SydApi4j api = (SydApi4j) new SydApi4j().connect("192.168.0.200",8889,null,3000);
@BeforeClass
public static void init() throws UnsupportedEncodingException {
System.out.println("begin");
}
@AfterClass
public static void after() {
System.out.println("all over");
}
@Test
@JunitPerfConfig(threads = threads, warmUp = warmUp, duration = duration)
public void p1_sign_1k(){
p1sign_1k= api.SYD_NakedSign(data1k, dn);
}
@Test
@JunitPerfConfig(threads = threads, warmUp = warmUp, duration = duration)
public void p1_verify_1k(){
api.SYD_NakedVerify( data1k, p1sign_1k, dn );
}
@Test
@JunitPerfConfig(threads = threads, warmUp = warmUp, duration = duration)
public void p7a_sign_1k() throws UnsupportedEncodingException {
p7asign_1k = api.attachedSign(data1k, dn);
}
@Test
@JunitPerfConfig(threads = threads, warmUp = warmUp, duration = duration)
public void p7a_verify_1k(){
api.attachedVerifyAndGetAll( p7asign_1k );
}
@Test
@JunitPerfConfig(threads = threads, warmUp = warmUp, duration = duration)
public void p7d_sign_1k(){
p7dsign_1k = api.sm3AndDetachedSign(data1k, pk, dn);
}
@Test
@JunitPerfConfig(threads = threads, warmUp = warmUp, duration = duration)
public void p7d_verify_1k(){
api.sm3AndDetachedVerify(data1k, pk, p7dsign_1k );
}
@Test
@JunitPerfConfig(threads = threads, warmUp = warmUp, duration = duration)
public void dm_aen_1k() {
dm_1k = String.valueOf(api.generateDEByDn(dn, data1k));
}
@Test
@JunitPerfConfig(threads = threads, warmUp = warmUp, duration = duration)
public void dm_de_1k() {
api.decryptDEByDN(dn, Util.hexString2Bytes(dm_1k));
}
}
@@ -0,0 +1,73 @@
package com.sunyard.sydapi.test;
import com.sunyard.RetWrap;
import com.sunyard.proto.Util;
import com.sunyard.util.ASN1Util;
import racal.sunyard.main.SydApi4j;
import racal.sunyard.main.SydApiBuilder;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
public class RSASignVertify {
private static final String RSADN = "C=cn,O=CFCA TEST CA,OU=CIPSTEST,OU=Units,CN=041@3CIPSCNSHCLR@CN000000129@00000018";
private static final byte[] orgData={1,2,3,4,5,6};
private static final String SM2DN = "C=CN,O=123,OU=23,OU=23,CN=32";
// public p1
// p7attach
// p7detach
public static void main(String[] args) throws IOException {
//System.setProperty("com.sunyard.sydapi4j.debug", "true");
//long startTime = System.currentTimeMillis(); //设置系统时间
SydApiBuilder builder = new SydApiBuilder().setIp("172.16.18.59");
SydApi4j api = (SydApi4j) builder.build();
//
// byte[] nakedSign = api.SYD_NakedSign(1,orgData,RSADN);
// System.out.println("nakedSign"+nakedSign);
// byte[] sm2Sign = api.SYD_NakedSign(orgData,SM2DN);
// System.out.println("sm2Sign:"+sm2Sign);
//
// boolean nakedVerify = api.SYD_NakedVerify(1, orgData, nakedSign, RSADN);
// System.out.println(nakedVerify);
// boolean nakedVerify2 = api.SYD_NakedVerify( orgData, sm2Sign, SM2DN);
// System.out.println(nakedVerify2);
// String attachedSign = api.attachedSign(orgData, SM2DN);
// //System.out.println(attachedSign);
// boolean attachedVerify = api.attachedVerify(attachedSign);
// System.out.println(attachedVerify);
//
// String attachedSign2 = api.attachedSign(1,orgData, RSADN);
// String attachedSign3 = api.attachedSign(2,orgData, RSADN);
// String attachedSign4 = api.attachedSign(3,orgData, RSADN);
// System.out.println("签名1:"+attachedSign2);
// System.out.println("签名2:"+attachedSign3);
// System.out.println("签名3:"+attachedSign4);
// boolean attachedVerify2 = api.attachedVerify(attachedSign2);
// RetWrap retWrap = ASN1Util.takeOutOriginDataFromPKCS7Sign(attachedSign2);
// System.out.println(attachedVerify2);
// byte[] orgData = (byte[]) retWrap.get("orgData");
// String cert = (String) retWrap.get("cert");
// System.out.println(Util.bytes2HexString(orgData));
// System.out.println(Util.bytes2HexString(Util.decodeBase64(cert)));
// System.out.println("证书:"+Util.bytes2HexString(Util.encodeBase64(RSADN.getBytes("GBK")).getBytes("GBK")));
String detachedSign = api.detachedSign(1, orgData, SM2DN);
System.out.println(detachedSign);
String detachedSign2 = api.detachedSign(1,0, orgData, RSADN);
System.out.println(detachedSign2);
boolean detachedVerify = api.detachedVerify(1, orgData, detachedSign);
boolean detachedVerify2 = api.detachedVerify(1,0, orgData, detachedSign2);
System.out.println(detachedVerify);
System.out.println(detachedVerify2);
// String RSAsign = api.attachedSign(1, orgData.getBytes("GBK"), RSADN);
}
}
@@ -0,0 +1,415 @@
package com.sunyard.sydapi.test;
import com.sunyard.RetWrap;
import com.sunyard.SydApi;
import com.sunyard.cert.X509;
import com.sunyard.proto.Util;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import racal.sunyard.main.SydApi4j;
import java.io.UnsupportedEncodingException;
/**
* 上清例子
*/
public class Shanqing {
SydApi4j api;
@Before
public void before() {
// 通过设置debug的属性开启debug,如果不设置则默认不打开
System.setProperty("com.sunyard.sydapi4j.debug", "true");
api = (SydApi4j) new SydApi4j().connect("192.168.0.200", 8889, null, 1000);
}
@After
public void after() {
try {
this.api.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 流程演示
*/
@Test
public void testProcess() {
String dn = "C=CN,O=CFCA OCA1,OU=YCCA,OU=Individual-2,CN=YCCA@黄金交易所@Zhuangj@1";
byte[] orgData = new byte[2 * 1024 * 1024];
// 签名
String sign = api.attachedSign(orgData, dn);
System.out.println("签名结果: " + sign);
// 生成数字信封
RetWrap retWrap = api.generateDEByDn(dn, sign.getBytes());
byte[] cipherKey = (byte[]) retWrap.get(SydApi.RET_CIPHER_KEY);
System.out.println("数字信封: " + new String(cipherKey));
// 解密数字信封
RetWrap retWrap1 = api.decryptDEByDN(dn, cipherKey);
byte[] oData = (byte[]) retWrap1.get("oData");
System.out.println("原数据: " + retWrap1.get("oData"));
// 验签
RetWrap verify = api.attachedVerifyAndGetAll(oData);
if (verify != null) {
System.out.println("x509公钥: " + Util.bytes2HexString(((X509) verify.get("x509")).getPubKey()));
System.out.println("签名原数据: " + Util.bytes2HexString((byte[]) (verify.get("oData"))));
}
}
//
// 测试通过
// 73
@Test
public void testSM2ConfirmSessionKeyC() {
String userId = "8012";
byte[] data = "12343242".getBytes();
// 通过用户id获取公钥
String pk = api.SM2GetPublicKeyC(userId, SydApi.FOR_ENCRYPT);
// 生成数字信封
RetWrap retWrap = api.SM2GenSessionKey(pk);
printRetWrap(retWrap);
String cipherKey = (String) retWrap.get(SydApi.RET_CIPHER_KEY);
String sessionKey = (String) retWrap.get(SydApi.RET_SESSION_KEY);
String kcv = (String) retWrap.get(SydApi.RET_KCV);
// 使用生成的对称密钥加密数据
byte[] dataEnc = api.SYMEncryptData(SydApi.NALG_SM4, sessionKey, data);
// 解密数字信封
RetWrap retWrap1 = api.SM2ConfirmSessionKeyC(userId, cipherKey);
printRetWrap(retWrap1);
sessionKey = (String) retWrap1.get(SydApi.RET_SESSION_KEY);
kcv = (String) retWrap1.get(SydApi.RET_KCV);
// 使用解密出来的对称密钥解密数据
byte[] bytes1 = api.SYMDecryptData(SydApi.NALG_SM4, sessionKey, dataEnc);
System.out.println("解密后的数据:" + new String(bytes1));
}
@Test
public void testDetachedSignAndVerify1() throws UnsupportedEncodingException {
String dn = "C=CN,O=CFCA OCA1,OU=YCCA,OU=Individual-2,CN=YCCA@黄金交易所@Zhuangj@1";
String orgData = "111111213323143243243";
String sign = api.attachedSign(orgData.getBytes(), dn);
System.out.println("签名结果: " + sign);
System.out.println("签名结果 hex : " + Util.bytes2HexString(Util.decodeBase64(sign)));
boolean verify = api.attachedVerify(sign);
System.out.println("验签结果: " + verify);
Assert.assertTrue(verify);
}
@Test
public void testDetachedSignAndVerify2() throws UnsupportedEncodingException {
String dn = "C=CN,O=CFCA OCA1,OU=YCCA,OU=Individual-2,CN=YCCA@黄金交易所@Zhuangj@1";
String orgData = "111111213323143243243";
String sign = api.attachedSignSoft(orgData.getBytes(), dn);
System.out.println("签名结果: " + sign);
System.out.println("签名结果 hex: " + Util.bytes2HexString(Util.decodeBase64(sign)));
boolean verify = api.attachedVerify(sign);
System.out.println("验签结果: " + verify);
Assert.assertTrue(verify);
}
@Test
public void testDetachedSignAndVerify3() throws UnsupportedEncodingException {
String dn = "C=CN,O=CFCA OCA1,OU=YCCA,OU=Individual-2,CN=YCCA@黄金交易所@Zhuangj@1";
byte[] orgData = new byte[3 * 1024];
String sign = api.attachedSign(orgData, dn);
System.out.println("签名结果: " + sign);
System.out.println("签名结果 hex: " + Util.bytes2HexString(Util.decodeBase64(sign)));
boolean verify = api.attachedVerify(sign);
System.out.println("验签结果: " + verify);
Assert.assertTrue(verify);
}
@Test
public void testDetachedSignAndVerify8() throws UnsupportedEncodingException {
String dn = "C=CN,O=CFCA OCA1,OU=YCCA,OU=Individual-2,CN=YCCA@黄金交易所@Zhuangj@1";
byte[] orgData = new byte[8 * 1024];
String sign = api.attachedSign(orgData, dn);
System.out.println("签名结果: " + sign);
System.out.println("签名结果 hex: " + Util.bytes2HexString(Util.decodeBase64(sign)));
boolean verify = api.attachedVerify(sign);
System.out.println("验签结果: " + verify);
Assert.assertTrue(verify);
}
// 测试通过
// 8018
@Test
public void testAttachedSignAndVerify() {
String dn = "C=CN,O=CFCA OCA1,OU=YCCA,OU=Individual-2,CN=YCCA@黄金交易所@Zhuangj@1";
String orgData = "111111213323143243243";
String sign = api.attachedSign(orgData.getBytes(), dn);
System.out.println("签名结果: " + sign);
System.out.println("签名结果 hex : " + Util.bytes2HexString(Util.decodeBase64(sign)));
boolean verify = api.attachedVerify(sign);
System.out.println("验签结果: " + verify);
}
@Test
public void testAttachedSignAndVerifyGetX509() {
String dn = "C=CN,O=CFCA OCA1,OU=YCCA,OU=Individual-2,CN=YCCA@黄金交易所@Zhuangj@1";
byte[] orgData = "111111213323143243243".getBytes();
String sign = api.attachedSign(orgData, dn);
System.out.println("签名结果: " + sign);
X509 verify = api.attachedVerifyAndGetX509(sign);
System.out.println("验签结果: " + Util.bytes2HexString(verify.getPubKey()));
}
@Test
public void testAttachedSignAndVerifyRD() {
String dn = "C=CN,O=CFCA OCA1,OU=YCCA,OU=Individual-2,CN=YCCA@黄金交易所@Zhuangj@1";
String orgData = "111111213323143243243";
String sign = api.attachedSign(orgData.getBytes(), dn);
System.out.println("签名结果: " + sign);
byte[] verify = api.attachedVerifyRD(sign);
System.out.println("验签结果: " + Util.bytes2HexString(verify));
}
@Test
public void testAttachedSignAndVerifyGetAll() {
String dn = "C=CN,O=CFCA OCA1,OU=YCCA,OU=Individual-2,CN=YCCA@黄金交易所@Zhuangj@1";
byte[] orgData = "111111213323143243243".getBytes();
String sign = api.attachedSign(orgData, dn);
System.out.println("签名结果: " + sign);
RetWrap verify = api.attachedVerifyAndGetAll(sign);
if (verify != null) {
System.out.println("x509公钥: " + Util.bytes2HexString(((X509) verify.get("x509")).getPubKey()));
System.out.println("签名原数据: " + verify.get("oData"));
}
}
@Test
public void testAttachedSignAndVerifyGetAll8k() {
String dn = "C=CN,O=CFCA OCA1,OU=YCCA,OU=Individual-2,CN=YCCA@黄金交易所@Zhuangj@1";
byte[] orgData = new byte[ 8 * 1024 ];
String sign = api.attachedSign(orgData, dn);
System.out.println("签名结果: " + sign);
RetWrap verify = api.attachedVerifyAndGetAll(sign);
if (verify != null) {
System.out.println("x509公钥: " + Util.bytes2HexString(((X509) verify.get("x509")).getPubKey()));
System.out.println("签名原数据: " + verify.get("oData"));
}
}
@Test
public void testAttachedSignAndVerifyGetX509C() {
String dn = "C=CN,O=CFCA OCA1,OU=YCCA,OU=Individual-2,CN=YCCA@黄金交易所@Zhuangj@1";
byte[] orgData = "111111213323143243243".getBytes();
byte[] sign = api.attachedSignC(orgData, dn);
System.out.println("签名结果: " + sign);
X509 verify = api.attachedVerifyAndGetX509(sign);
System.out.println("验签结果: " + Util.bytes2HexString(verify.getPubKey()));
}
@Test
public void testAttachedSignAndVerifyRDC() {
String dn = "C=CN,O=CFCA OCA1,OU=YCCA,OU=Individual-2,CN=YCCA@黄金交易所@Zhuangj@1";
String orgData = "111111213323143243243";
byte[] sign = api.attachedSignC(orgData.getBytes(), dn);
System.out.println("签名结果: " + sign);
byte[] verify = api.attachedVerifyRD(sign);
System.out.println("验签结果: " + Util.bytes2HexString(verify));
}
@Test
public void testAttachedSignAndVerifyGetAllC() {
String dn = "C=CN,O=CFCA OCA1,OU=YCCA,OU=Individual-2,CN=YCCA@黄金交易所@Zhuangj@1";
byte[] orgData = "111111213323143243243".getBytes();
byte[] sign = api.attachedSignC(orgData, dn);
System.out.println("签名结果: " + sign);
RetWrap verify = api.attachedVerifyAndGetAll(sign);
if (verify != null) {
System.out.println("x509公钥: " + Util.bytes2HexString(((X509) verify.get("x509")).getPubKey()));
System.out.println("签名原数据: " + verify.get("oData"));
}
}
@Test
public void testDecryptDE54k12() throws UnsupportedEncodingException {
String dn = "C=CN,O=CFCA OCA1,OU=YCCA,OU=Individual-2,CN=YCCA@黄金交易所@Zhuangj@1";
byte[] oData = new byte[4 * 1024];
RetWrap retWrap = api.generateDEByDnHsm(dn, oData);
byte[] CipherKey = (byte[]) retWrap.get(SydApi.RET_CIPHER_KEY);
byte[] sessionKey = (byte[]) retWrap.get(SydApi.RET_SESSION_KEY);
printRetWrap(retWrap);
RetWrap retWrap1 = api.decryptDEByDNSoft(dn, new String(CipherKey));
printRetWrap(retWrap1);
byte[] deData = (byte[]) retWrap1.get("oData");
Assert.assertArrayEquals(deData, oData);
}
@Test
public void testDecryptDE54k21() throws UnsupportedEncodingException {
String dn = "C=CN,O=CFCA OCA1,OU=YCCA,OU=Individual-2,CN=YCCA@黄金交易所@Zhuangj@1";
byte[] oData = new byte[4 * 1024];
RetWrap retWrap = api.generateDEByDnSoft(dn, oData);
byte[] CipherKey = (byte[]) retWrap.get(SydApi.RET_CIPHER_KEY);
byte[] sessionKey = (byte[]) retWrap.get(SydApi.RET_SESSION_KEY);
printRetWrap(retWrap);
RetWrap retWrap1 = api.decryptDEByDNHsm(dn, new String(CipherKey));
printRetWrap(retWrap1);
byte[] deData = (byte[]) retWrap1.get("oData");
Assert.assertArrayEquals(deData, oData);
}
@Test
public void testDecryptDE54k() throws UnsupportedEncodingException {
String dn = "C=CN,O=CFCA OCA1,OU=YCCA,OU=Individual-2,CN=YCCA@黄金交易所@Zhuangj@1";
byte[] oData = new byte[4 * 1024];
RetWrap retWrap = api.generateDEByDn(dn, oData);
byte[] CipherKey = (byte[]) retWrap.get(SydApi.RET_CIPHER_KEY);
byte[] sessionKey = (byte[]) retWrap.get(SydApi.RET_SESSION_KEY);
printRetWrap(retWrap);
RetWrap retWrap1 = api.decryptDEByDN(dn, CipherKey);
printRetWrap(retWrap1);
}
@Test
public void testDecryptDE54kr() throws UnsupportedEncodingException {
String dn = "CN=YCCA@黄金交易所@Zhuangj@1,OU=Individual-2,OU=YCCA,O=CFCA OCA1,C=CN";
byte[] oData = new byte[4 * 1024];
RetWrap retWrap = api.generateDEByDn(dn, oData);
byte[] CipherKey = (byte[]) retWrap.get(SydApi.RET_CIPHER_KEY);
byte[] sessionKey = (byte[]) retWrap.get(SydApi.RET_SESSION_KEY);
printRetWrap(retWrap);
RetWrap retWrap1 = api.decryptDEByDN(dn, CipherKey);
printRetWrap(retWrap1);
}
@Test
public void testDecryptDE520M() throws UnsupportedEncodingException {
String dn = "C=CN,O=CFCA OCA1,OU=YCCA,OU=Individual-2,CN=YCCA@黄金交易所@Zhuangj@1";
byte[] oData = new byte[20 * 1024 * 1024];
RetWrap retWrap = api.generateDEByDn(dn, oData);
byte[] CipherKey = (byte[]) retWrap.get(SydApi.RET_CIPHER_KEY);
byte[] sessionKey = (byte[]) retWrap.get(SydApi.RET_SESSION_KEY);
printRetWrap(retWrap);
RetWrap retWrap1 = api.decryptDEByDN(dn, CipherKey);
printRetWrap(retWrap1);
}
@Test
public void testDecryptDE58k() throws UnsupportedEncodingException {
String dn = "C=CN,O=CFCA OCA1,OU=YCCA,OU=Individual-2,CN=YCCA@黄金交易所@Zhuangj@1";
byte[] oData = new byte[8 * 1024];
RetWrap retWrap = api.generateDEByDn(dn, oData);
byte[] CipherKey = (byte[]) retWrap.get(SydApi.RET_CIPHER_KEY);
byte[] sessionKey = (byte[]) retWrap.get(SydApi.RET_SESSION_KEY);
printRetWrap(retWrap);
RetWrap retWrap1 = api.decryptDEByDN(dn, CipherKey);
printRetWrap(retWrap1);
}
@Test
public void testDecryptDE5() throws UnsupportedEncodingException {
String dn = "C=CN,O=CFCA OCA1,OU=YCCA,OU=Individual-2,CN=YCCA@黄金交易所@Zhuangj@1";
byte[] oData = "00001111222233".getBytes();
RetWrap retWrap = api.generateDEByDn(dn, oData);
byte[] CipherKey = (byte[]) retWrap.get(SydApi.RET_CIPHER_KEY);
byte[] sessionKey = (byte[]) retWrap.get(SydApi.RET_SESSION_KEY);
printRetWrap(retWrap);
RetWrap retWrap1 = api.decryptDEByDN(dn, CipherKey);
printRetWrap(retWrap1);
}
// 测试通过
// 76
@Test
public void testSM3Hash() {
String orgData = "FFFFFFFFFFFFFFFF";
byte[] hash = api.SM3Hash(orgData.getBytes());
System.out.println("hash:" + Util.bytes2HexString(hash));
}
// =============================工具方法==============================================
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((byte[]) o));
}
} else {
System.out.println(s + ":" + o);
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More