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
This commit is contained in:
cheney
2022-08-18 14:58:18 +08:00
17 changed files with 646 additions and 674 deletions
@@ -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();
}
}
}
@@ -3,6 +3,7 @@ package com.sunyard.inf;
import com.sunyard.RetWrap;
import java.io.UnsupportedEncodingException;
import java.util.List;
/**
* 对称加解密相关接口
@@ -273,6 +274,9 @@ interface SydSYMApi {
*/
byte[] SYMEncryptData(int nAlg, String seesionKey, int fullmode, byte[] pINdata);
List<byte[]> SYMEncryptDecryptBatchData(int nAlg, String[] seesionKey, int fullmode, List<byte[]> pINdata);
/**
* 用输入的会话密钥,对指定报文数据进行加密处理。
*
+3 -3
View File
@@ -60,8 +60,8 @@ interface SydAttachedSVApi {
* @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);
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 位数字,右对齐。
@@ -142,7 +142,7 @@ interface SydAttachedSVApi {
int nOrgDataType,
byte[] publicKey,
byte[] orgData,
String sign
byte[] sign
);
@@ -117,13 +117,13 @@ public interface SydHAApi {
* @param nOrgDataType 签名数据类型,SydApi.DATA_ORIGIN(1) 原始数据 SydApi.DATA_HASH(0) : hash 后的类型
* @param publicKey 公钥串,DER编码,HEX格式
* @param orgData 待签名的原始数据,“签名数据类型”为 0 时:HASH 值。“签名数据类型”为 1 时:要签名的信息
* @param base64Sign 签名数据 (DER 编码 + Base64 编码)
* @param sign S+R
* @return 验签是否通过
*/
public boolean SM2Verify(
int nOrgDataType,
byte[] publicKey,
byte[] orgData,
String base64Sign
byte[] sign
);
}
+124 -5
View File
@@ -2073,7 +2073,119 @@ public class SydApi4j implements SydApi {
data.put("msg", pInData);
packet.put("data", data);
return repackEncrypt(packet);
return repackEncrypt( packet );
}
public List<byte[]> SYMEncryptDecryptBatchData(int nAlg, String[] seesionKey, int fullmode, List<byte[]> pINdata) {
int batchSize = pINdata.size();
if ( batchSize < 1 || batchSize > 10 ) {
throw new IllegalArgumentException("批量数量错误");
}
if ( seesionKey.length != pINdata.size() ) {
throw new IllegalArgumentException("密钥和数据数量不匹配");
}
if ( 0x0 != (byte) (nAlg & 0x1) ){
// 解密
for ( byte[]d : pINdata ) {
if ( d.length > 1040 ) {
throw new IllegalArgumentException("批量单数数据超长 1040");
}
}
} else {
// 加密
for ( byte[]d : pINdata ) {
if ( d.length > 1024 ) {
throw new IllegalArgumentException("批量单数数据超长 1024");
}
}
}
ByteBuffer bb = ByteBuffer.allocate(10 * 1024);
PacketSN sn = PacketSN.gen();
bb.put( new byte[2] );
bb.put( sn.getSn().array() );
bb.put( "E0".getBytes() );
bb.put( (byte) 0x34 ); // 批量加解密
bb.put( (byte) batchSize ); // 批量数
bb.put( (byte) ( 0x30 + nAlg) ); // 密钥模式
bb.put( (byte) ( 0x31) ); // ECB
bb.put( (byte) ( 0x30) ); // ZEK
// 填充多个密钥
for ( String key : seesionKey ) {
bb.put( key.getBytes() );
}
bb.put( (byte) ( 0x30) ); // 输入消息类型二进制
bb.put( (byte) ( 0x30) ); // 输出消息类型二进制
bb.put( (byte) ( 0x30 + fullmode) ); // 填充模式
bb.put( "0000".getBytes() ); // 填充字符
bb.put( (byte) ( 0x32) ); // 填充类型
// iv 暂未支持
// P 长度暂未支持
// 填充多个消息数据长度
for ( byte[] data : pINdata ) {
bb.put( String.format("%03X", data.length).getBytes() );
}
// 填充多个消息数据
for ( byte[] data : pINdata ) {
bb.put( data );
}
// 重新计算长度
int len = bb.position();
len -= 2;
byte[] lenArray = new byte[ 2 ];
lenArray[0] = (byte)((len >> 8) & 0xFF);
lenArray[1] = (byte)( len & 0xFF);
bb.put( 0, (byte)((len >> 8) & 0xFF) );
bb.put( 1, (byte)( len & 0xFF) );
// 通信
synchronized (this) {
// 响应解析
bb = syncRead(syncSend(bb));
}
bb.flip();
bb.position( 12 );
byte[] code = new byte[2];
bb.get( code );
int retCode = Integer.valueOf( new String( code ) );
if ( 0 != retCode ) {
throw new SydApiException( retCode );
}
// 跳过输出模式
bb.get();
// 获取 N 个长度
int[] lens = new int[ batchSize ];
for ( int i = 0; i < batchSize; i++ ){
byte[] iLenArray = new byte[3];
bb.get( iLenArray );
lens[ i ] = Integer.valueOf( new String( iLenArray ), 16 );
}
List<byte[]>ret = new ArrayList<byte[]>();
// 获取 N 个长度的数据
for ( int l : lens ) {
byte[] d = new byte[ l ];
bb.get(d);
ret.add( d );
}
return ret;
}
@@ -3626,6 +3738,13 @@ public class SydApi4j implements SydApi {
// 测试通过
public String SM2GetPrivateKeyC(String privateKeyTag) {
if ( privateKeyTag.length() < 16 ) {
privateKeyTag = "0000000000000000" + privateKeyTag;
privateKeyTag = privateKeyTag.substring( privateKeyTag.length() -16 );
privateKeyTag += "00000000001";
}
ProtoQP proto = new ProtoQP();
HashMap<String, Object> packet = new HashMap<String, Object>();
HashMap<String, Object> data = new HashMap<String, Object>();
@@ -3878,7 +3997,7 @@ public class SydApi4j implements SydApi {
// 测试通过
@Override
public String SM2SignC(int flag, String uid, String privateKey, byte[] publicKey, byte[] orgData) {
public byte[] SM2SignC(int flag, String uid, String privateKey, byte[] publicKey, byte[] orgData) {
Proto74 proto = new Proto74();
@@ -3919,7 +4038,7 @@ public class SydApi4j implements SydApi {
byte[] s = new byte[a];
bb.get(s, 0, a);
return SYMUtil.derSign2Base64Sign(s);
return Util.decodeBase64( SYMUtil.derSign2Base64Sign(s) );
}
@@ -4197,7 +4316,7 @@ public class SydApi4j implements SydApi {
// 测试通过
@Override
public boolean SM2Verify(String certNo, int nOrgDataType, byte[] publicKey, byte[] orgData, String base64Sign) {
public boolean SM2Verify(String certNo, int nOrgDataType, byte[] publicKey, byte[] orgData, byte[] sign) {
if (certNo.length() > 32) {
certNo = certNo.substring(0, 32);
@@ -4205,7 +4324,7 @@ public class SydApi4j implements SydApi {
Proto75 proto = new Proto75(); //pset.getProtocolReqRender("75");
byte[] sign = SYMUtil.base64Sign2DerSign(base64Sign);
sign = SYMUtil.base64Sign2DerSign( Util.encodeBase64(sign) );
// 填充数据
HashMap<String, Object> packet = new HashMap<String, Object>();