package com.kayak.trade.api.branch.util;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.ParameterizedType;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.druid.util.StringUtils;
import com.kayak.gray.api.exception.BizException;
import com.kayak.gray.api.options.Options;
import com.kayak.trade.api.branch.annotation.SignatureAnotation_15;
import com.kayak.trade.api.branch.annotation.SignatureAnotation_16;
import com.kayak.trade.api.branch.annotation.SignatureClassAnotation;
import com.kayak.trade.api.branch.annotation.SignatureResultAnotation;
import com.kayak.trade.api.branch.code.IbpsBizErrorCode;
import com.union.dsignApi.UnionCertAppAPI;
import com.union.dsignApi.UnionCertInfo;
/**
* @ClassName: AutographUtil
* @Description: 对ibps报文进行加签及解签
* @author: qiran
* @date: 2018年7月13日 下午9:01:09
* 方法说明:1.getSignatureComnons
* 作用: 初始化加签规则
* 2.sign
* 作用: 加签
* 3.relieveSign
* 作用:验签
* 4.unionAppUpdateCert
* 作用 :更新证书
*
* 重点说明: 该工具类 只支持 1层list加签验签处理,多层集合需要自主调用加签验签类自行处理
*
*/
public class SignatureUtil {
private static final Logger log = LoggerFactory.getLogger(SignatureUtil.class);
protected static Options options = new Options();
/**
* 加签解签类 同包及私有类能够访问
*/
protected static UnionCertAppAPI UNION_CERTAPP_API= null;
/**
* 加签解签规则 1.5版本
*/
public static final Map<Class<?>,Map<Integer,Field>> SIGNATURE_CACHE_15 = new ConcurrentHashMap<>();
/**
* 加签解签规则 1.6版本
*/
public static final Map<Class<?>,Map<Integer,Field>> SIGNATURE_CACHE_16 = new ConcurrentHashMap<>();
/**
* 加签结果参数
*/
private static Map<Class<?>,Field > SignatureResultCache = new ConcurrentHashMap<>();
/**
* 裸签加签类 所有包都可以访问 该对象需要以参数传递给 SignatureUtil.sign( bean,unionAppRawSign)
*/
public static final UnionAppRawSign UNION_APPRAW_SIGN = new UnionAppRawSign();
/**
* 裸签验签方法 所有包都可以访问 该对象需要以参数传递给 SignatureUtil.relieveSign( bean,UnionAppRawVerify)
*/
public static final UnionAppRawVerify UNION_APPRAW_VERIFY= new UnionAppRawVerify();
/**
* PKCS7签名 加签类 所有包都可以访问 该对象需要以参数传递给 SignatureUtil.sign( bean,unionAppDetachedSign)
* 作废说明: 由于初始设计 与实际不符 注释该静态类 不外放使用
*/
public static final UnionAppDetachedSign UNION_APPDETACHED_SIGN = new UnionAppDetachedSign();
/**
* PKCS7签名 所有包都可以访问 该对象需要以参数传递给 SignatureUtil.relieveSign( bean,UnionAppRawVerify)
* 作废说明: 由于初始设计 与实际不符 注释该静态类 不外放使用
*/
//public static final UnionAppDetachedVerify UNION_APPDETACHED_VERIFY = new UnionAppDetachedVerify();
public static boolean signFlag= true;
static {
/**
* 1.读取加签服务器配置文件
* 用于初始化加签API
*/
//UNION_CERTAPP_API = new UnionCertAppAPI("conf"+File.separator+"sys"+File.separator+"srj1401Hsm.conf");
//由于加签服务器 目前不支持上面的方式 先使用ip 端口方式访问
//UNION_CERTAPP_API = new UnionCertAppAPI("21.129.12.2",1818, 0);
log.info("初始化加签配置文件成功!");
try {
/**
* 2.读取加签方式配置文件
* 用于配置加签方式
* 注意 :读取的是当前项目的配置 并非 kayak-trade-base
*/
options.load(new File("conf"+File.separator+"sys"+File.separator+"sign.conf"));
signFlag =options.get("sign.test");
UNION_CERTAPP_API = new UnionCertAppAPI();
} catch (Exception e) {
log.error("读取加签验签异常,请确认配置文件是否存在:",e);
}
}
/**
* @MethodName: getSignatureComnons
* @Description: 对加签的bean 参数加签规则进行初始化
* @param T clazz 需要被加签的bean
* Map<Class<?>,Map<Integer,Field>> signAtureMap 传入的保存加签规则的静态Map 内中保存加签规则
* 固定为 SignatureUtil.SIGNATURE_CACHE_15 超网 1.5版本
* SignatureUtil.SIGNATURE_CACHE_16 超网1.6版本
* annotaion 加签参数的实际注解 SignatureAnotation_15.class 超网 1.5版本
* SignatureAnotation_16.class 超网 1.6版本
* annotaion 与 signAtureMap 为 一对一关系 如 增加 annotaion 需要在 SignatureUtil 增加 静态 Map保存 加签规则
* annotaion 中必须实现 index() ,nameSpace() 方法
* SignatureClassAnotation 加签类 内部写死
* SignatureResultAnotation 加签结果参数 注解写死
* SignatureResultCache 加签结果Map 此处同一个Class 只能由一个加签结果参数
*
* @author: qiran
* @date: 2018年7月3日 下午3:24:19
* 调用者 beanToSignString (T t,Map<Class<?>,Map<Integer,Field>> signAtureMap, Class< ? extends Annotation> annotaion)
*/
private static <T> void getSignatureComnons(T t,Map<Class<?>,Map<Integer,Field>> signAtureMap, Class< ? extends Annotation> annotaion) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException{
if(signAtureMap.get(t.getClass())==null){
log.info("初始化加签规则类 : {} 注解标识:{} ",t.getClass(),annotaion.getName());
//判断类是否需要加签 不需要加签直接返回
SignatureClassAnotation signatureClassAnotation= t.getClass().getDeclaredAnnotation(SignatureClassAnotation.class);
//考虑性能 增加类注解 判断是否循环 类变量
if(signatureClassAnotation == null){
return;
}
//循环所有参数查询加签解签参数
Field[] fields= t.getClass().getDeclaredFields();
Map<Integer,Field> map = new HashMap<Integer,Field>(18);
for(Field field :fields){
Annotation signatureAnotation = field.getDeclaredAnnotation(annotaion);
if(signatureAnotation!=null){
//如果参数为集合 循环子类查询 加签参数 将子类重新定义加签规则
if(field.getType().isAssignableFrom(java.util.List.class)){
ParameterizedType parameterizedTypeSon = (ParameterizedType)field.getGenericType();
@SuppressWarnings("rawtypes")
Class clazzSon = (Class)parameterizedTypeSon.getActualTypeArguments()[0];
Field[] fieldSons = clazzSon.getDeclaredFields();
Map<Integer,Field> mapSon = new HashMap<Integer,Field>(18);
for(Field fieldSon :fieldSons){
Annotation signatureAnotationSon = fieldSon.getDeclaredAnnotation(annotaion);
if(signatureAnotationSon!=null){
mapSon.put((Integer) signatureAnotationSon.annotationType().getMethod("index").invoke(signatureAnotationSon),fieldSon);
}
}
signAtureMap.put((Class<?>) parameterizedTypeSon.getActualTypeArguments()[0], mapSon);
}
//保存加签解签参数
map.put((Integer) signatureAnotation.annotationType().getMethod("index").invoke(signatureAnotation),field);
}
//保存加签结果参数
SignatureResultAnotation signatureResultAnotation = field.getDeclaredAnnotation(SignatureResultAnotation.class);
if(signatureResultAnotation!=null){
SignatureResultCache.put(t.getClass(),field);
}
}
signAtureMap.put(t.getClass(), map);
}else{
log.info("加签类规则已初始化无需初始化 : {} 注解标识:{} ",t.getClass(),annotaion.getName());
}
}
/**
* @MethodName: beanToSignString
* @Description: 对bean 中参数进行解析获取对应的加签字符串 并初始化加签规则 以及加签结果参数初始化
* @param T clazz 需要被加签的bean
* Map<Class<?>,Map<Integer,Field>> signAtureMap 传入的保存加签规则的静态Map 内中保存加签规则
* 固定为 SignatureUtil.SIGNATURE_CACHE_15 超网 1.5版本
* SignatureUtil.SIGNATURE_CACHE_16 超网1.6版本
* annotaion 加签参数的实际注解 SignatureAnotation_15.class 超网 1.5版本
* SignatureAnotation_16.class 超网 1.6版本
* annotaion 与 signAtureMap 为 一对一关系 如 增加 annotaion 需要在 SignatureUtil 增加 静态 Map保存 加签规则
* annotaion 中必须实现 index() ,nameSpace() 方法
*
* @author: qiran
* @date: 2018年7月3日 下午3:24:19
* @调用者 1.sign15(T t,Function<byte[],String> fun) 超网1.5加签版本
* 2.sign16(T t,Function<byte[],String> fun) 超网1.6加签版本
* 3.relieveSign15(T t,Function<Map<String,Object>,Integer> fun) 超网1.5验签版本
* 4.relieveSign16(T t,Function<Map<String,Object>,Integer> fun) 超网1.6验签版本
* 或者 beanToSignString (T t, SignatureUtil 中新增的保存加签规则的Map, 自定义的 Annotation)
* 之后调用 SignatureUtil.UNION_APPRAW_SIGN.apply("".getBytes()); 自定义 裸加签
* SignatureUtil.UNION_APPRAW_VERIFY.apply(msg,signedData); 自定义 裸验签
* SignatureUtil.UNION_APPDETACHED_SIGN.apply("".getBytes()); 自定义 证书加签
* SignatureUtil.UNION_APPDETACHED_VERIFY.apply(msg,signedData); 自定义 证书验签
*
*/
public static <T> String beanToSignString(T t,Map<Class<?>,Map<Integer,Field>> signAtureMap, Class< ? extends Annotation> annotaion) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException{
//1.初始化加签规则方法
getSignatureComnons(t,signAtureMap,annotaion);
//2.获取加签的规则
Map<Integer,Field> mapSignature = signAtureMap.get(t.getClass());
//如果没有加签直接返回
if(mapSignature==null||mapSignature.size()<=0){
return null;
}
log.info("开始拼装加签串...");
StringBuffer sb = new StringBuffer();
//3.根据加签规则进行加签
for (int i = 0; i < mapSignature.size(); i++) {
Field field = mapSignature.get(i);
field.setAccessible(true);
//3.1 判断类中参数是否为集合形式
if(field.getType().isAssignableFrom(java.util.List.class)){
ParameterizedType parameterizedTypeSon = (ParameterizedType)field.getGenericType();
//获取list的泛型类并 获取对应的加签规则
List<?> objSons = (List<?>) field.get(t);
Map<Integer,Field> mapSignatureSon = signAtureMap.get((Class<?>)parameterizedTypeSon.getActualTypeArguments()[0]);
if(objSons!=null){
//3.2 对类中存在的集合进行加签处理 以list的size进行处理
for(Object obj: objSons){
for (int j = 0; j < mapSignatureSon.size(); j++) {
Field fieldSon = mapSignatureSon.get(j);
fieldSon.setAccessible(true);
//3.3 如果集合中参数 不为空才进行加签
if(fieldSon.get(obj)!=null&&!"".equals(fieldSon.get(obj).toString())){
//为解决金额加签问题 追加命名空间
Annotation signatureAnotation= fieldSon.getAnnotation(annotaion);
// 处理币种 也可以在前面添加其他内容
sb.append(signatureAnotation.annotationType().getMethod("nameSpace").invoke(signatureAnotation));
//组装加签串
String signature = fieldSon.get(obj).toString();
sb.append(signature);
sb.append("|");
}
}
}
}
//3.4 判断类中参数是否为集合形式
}else{
//3.5 如果集合中参数 不为空才进行加签
if(field.get(t)!=null&&!"".equals(field.get(t).toString())){
//为解决金额加签问题 追加命名空间
Annotation signatureAnotation = field.getAnnotation(annotaion);
//处理币种 也可以在前面添加其他内容
sb.append(signatureAnotation.annotationType().getMethod("nameSpace").invoke(signatureAnotation));
//组装加签串
String signature = field.get(t).toString();
sb.append(signature);
//币种
sb.append("|");
}
}
}
log.info("加签串拼装结果为:[{}]", sb.toString());
return sb.toString();
}
/**
* @MethodName: addSignature
* @Description: 对业务流转的bean加签参数进行加签 1.5 版本 该方法会读取bean中 SignatureAnotation_15的注解
* @param T clazz 需要被加签的bean Function fun
* @return T 加签结果bean
* @author: qiran
* @throws SecurityException
* @throws NoSuchFieldException
* @throws NoSuchMethodException
* @throws InvocationTargetException
* @throws BizException
* @date: 2018年7月3日 下午3:24:19
*
*/
public static <T> T sign15(T t,Function<byte[],String> fun) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException, InvocationTargetException, NoSuchMethodException, BizException{
//1.根据加签规则 获取需验签的字符串 bean中1.5版本的注解
String msg= beanToSignString(t,SIGNATURE_CACHE_15,SignatureAnotation_15.class);
if(msg == null){
log.info("该接口无需加签,未做加签操作!");
return null;
}
//4.调用加签接口进行加签操作
String unionAppRawSign = null;
try {
unionAppRawSign = fun.apply(msg.getBytes());
} catch (Exception e) {
log.error("加签出错,出错原因为:{}", e);
throw new BizException(IbpsBizErrorCode.BR400001_加签失败,"加签失败,失败原因为:["+ e.getMessage() + "]");
}
log.info("加签成功,加签结果为:[{}]", unionAppRawSign);
//5.将加签结果参数添加值
Field fieldResult = SignatureResultCache.get(t.getClass());
fieldResult.setAccessible(true);
fieldResult.set(t, unionAppRawSign);
return t;
}
/**
* @MethodName: addSignature
* @Description: 对业务流转的bean加签参数进行加签 1.6 版本 该方法会读取bean中 SignatureAnotation_16的注解
* @param T clazz 需要被加签的bean Function fun
* @return T 加签结果bean
* @author: qiran
* @throws SecurityException
* @throws NoSuchFieldException
* @throws NoSuchMethodException
* @throws InvocationTargetException
* @throws BizException
* @date: 2018年7月3日 下午3:24:19
*
*/
public static <T> T sign16(T t,Function<byte[],String> fun) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException, InvocationTargetException, NoSuchMethodException, BizException{
//1.根据加签规则 获取需验签的字符串 bean中1.5版本的注解
String msg= beanToSignString(t,SIGNATURE_CACHE_16,SignatureAnotation_16.class);
if(msg == null){
log.info("该接口无需加签,未做加签操作!");
return null;
}
//4.调用加签接口进行加签操作
String unionAppRawSign = null;
try {
unionAppRawSign = fun.apply(msg.getBytes());
} catch (Exception e) {
log.error("加签出错,出错原因为:{}", e);
throw new BizException(IbpsBizErrorCode.BR400001_加签失败,"加签失败,失败原因为:["+ e.getMessage() + "]");
}
log.info("加签成功,加签结果为:[{}]", unionAppRawSign);
//5.将加签结果参数添加值
Field fieldResult = SignatureResultCache.get(t.getClass());
fieldResult.setAccessible(true);
fieldResult.set(t, unionAppRawSign);
return t;
}
/**
* @MethodName: signString
* @Description: 对传入参数参数进行加签
* @param T clazz 需要被加签的bean Function fun
* @return String 加签结果
* @author: qiran
* @throws BizException
* @date: 2018年7月3日 下午3:24:19
*
*/
public static String signString(String signMsg,Function<byte[],String> fun) throws BizException{
log.info("加签串内容 :[{}]",signMsg);
if(StringUtils.isEmpty(signMsg)){
log.info("加签字符串为空,无需加签!");
return null;
}
//调用加签接口进行加签操作
String unionAppRawSign = null;
try {
unionAppRawSign = fun.apply(signMsg.getBytes());
} catch (Exception e) {
log.error("加签出错,出错原因为:{}", e);
throw new BizException(IbpsBizErrorCode.BR400001_加签失败,"加签失败,失败原因为:["+ e.getMessage() + "]");
}
log.info("加签成功,加签结果为:[{}]", unionAppRawSign);
//5.将加签结果返回
return unionAppRawSign;
}
/**
*
* @MethodName: addSignature
* @Description: 对业务流转的bean加签参数进行加签 该方法会读取bean中 SignatureAnotation_15的注解
* @param T clazz 需要被加签的bean
* @return T 加签结果bean
* @author: qiran
* @throws BizException
* @throws SecurityException
* @throws NoSuchMethodException
* @throws InvocationTargetException
* @date: 2018年7月3日 下午3:24:19
*
*/
public static <T> boolean relieveSign15(T t,Function<Map<String,Object>,Integer> fun,String bankId) throws IllegalArgumentException, IllegalAccessException, BizException, InvocationTargetException, NoSuchMethodException, SecurityException {
//1.根据加签规则 获取需验签的字符串 bean中1.5版本的注解
String msg= beanToSignString(t,SIGNATURE_CACHE_15,SignatureAnotation_15.class);
if(msg == null){
log.info("该接口无需验签,无需进行验签操作!");
return true;
}
// if(!signFlag){
// log.debug("----------验签开关关闭,无需验签------------");
// return true;
// }
//5.将加签结果参数添加值
Field fieldResult = SignatureResultCache.get(t.getClass());
fieldResult.setAccessible(true);
String signedData =fieldResult.get(t).toString();
Map<String,Object> map =new HashMap<String,Object>(18);
map.put("signedData", signedData);
map.put("msg", msg);
map.put("bankId", bankId);
log.info("验签直参行行号为:[{}]",bankId);
log.info("验签加签结果为:[{}]", signedData);
Integer signatureResult = fun.apply(map);
log.info("验签返回结果为:[{}]!",signatureResult);
if(signatureResult!=0){
if(signFlag){
log.error("超网1.6接口版本报文验签失败!");
throw new BizException(IbpsBizErrorCode.BR999999_验签失败,"参数验签错误" );
}else{
log.info("----------验签开关关闭,无需验签------------");
return true;
}
}else{
log.info("[超网1.5接口版本报文验签成功]");
}
return true;
}
/**
*
* @MethodName: addSignature
* @Description: 对业务流转的bean加签参数进行加签 该方法会读取bean中 SignatureAnotation_16的注解
* @param T clazz 需要被加签的bean
* @return T 加签结果bean
* @author: qiran
* @throws BizException
* @throws SecurityException
* @throws NoSuchMethodException
* @throws InvocationTargetException
* @date: 2018年7月3日 下午3:24:19
*
*/
public static <T> boolean relieveSign16(T t,Function<Map<String,Object>,Integer> fun,String bankId) throws IllegalArgumentException, IllegalAccessException, BizException, InvocationTargetException, NoSuchMethodException, SecurityException {
//1.根据加签规则 获取需验签的字符串 bean中1.6版本的注解
String msg= beanToSignString(t,SIGNATURE_CACHE_16,SignatureAnotation_16.class);
if(msg == null){
log.info("该接口无需验签,无需进行验签操作!");
return true;
}
// if(!signFlag){
// log.info("----------验签开关关闭,无需验签------------");
// return true;
// }
//2.将加签结果参数添加值
Field fieldResult = SignatureResultCache.get(t.getClass());
fieldResult.setAccessible(true);
String signedData =fieldResult.get(t).toString();
Map<String,Object> map =new HashMap<String,Object>(18);
map.put("signedData", signedData);
map.put("msg", msg);
map.put("bankId", bankId);
log.info("验签直参行行号为:[{}]",bankId);
log.info("验签加签结果为:[{}]", signedData);
Integer signatureResult = fun.apply(map);
log.info("验签返回结果为:[{}]",signatureResult);
if(signatureResult!=0){
if(signFlag){
log.error("超网1.6接口版本报文验签失败!");
throw new BizException(IbpsBizErrorCode.BR999999_验签失败,"参数验签错误" );
}else{
log.info("----------验签开关关闭,无需验签------------");
return true;
}
}else{
log.info("[超网1.6接口版本报文验签成功]");
}
return true;
}
/**
*
* @MethodName: relieveSignString
* @Description: 对 参数进行 验签
* @param signMsg 待验签 的拼接字符串结果
* fun 验签方法
* bankId 发送行行号
* signedData 对手方发送的加签串
* @return boolean 验签结果
* @author: qiran
* @throws BizException
* @date: 2018年7月3日 下午3:24:19
*
*/
public static boolean relieveSignString(String signMsg,Function<Map<String,Object>,Integer> fun,
String bankId,String signedData) throws BizException {
// if(!signFlag){
// log.info("----------验签开关关闭,无需验签------------");
// return true;
// }
if(StringUtils.isEmpty(signMsg)){
log.info("验签字符串为空,无需验签!");
return true;
}
log.info("验签字符串:[{}]",signMsg);
log.info("验签直参行行号:[{}]",bankId);
Map<String,Object> map =new HashMap<String,Object>(18);
map.put("signedData", signedData);
map.put("msg", signMsg);
map.put("bankId", bankId);
Integer signatureResult = fun.apply(map);
log.info("验签返回结果为:[{}]",signatureResult);
//验签返回不为0 并且 验签开关为 true false 不进行验签
if(signatureResult!=0){
if(signFlag){
log.error("超网1.6接口版本报文验签失败!");
throw new BizException(IbpsBizErrorCode.BR999999_验签失败,"参数验签错误" );
}else{
log.info("----------验签开关关闭,无需验签------------");
return true;
}
}else{
log.info("[报文验签成功]");
}
return true;
}
/**
* @MethodName: unionAppUpdateCert
* @Description: 对他行证书进行上传
* @param bankId: 对手行行号
* cert:公钥证书(base64格式)
* @return 返回参数值:false 上传失败 true 上传成功
* @author: qiran
* @date: 2018年7月3日 下午3:24:19
*
*/
public static boolean unionAppUpdateCert(String bankId, String cert){
String appName = SignatureUtil.options.get("unionAppRawVerify.appId")+bankId+SignatureUtil.options.get("unionAppRawVerify.appVer");
log.info("开始将公钥证书上传至加签服务器 appName:[{}]",appName);
int result = UNION_CERTAPP_API.UnionAppUpdateCert(appName,cert);
if(result!=0){
log.info("公钥证书上传失败,错误码为:[]", result);
return false;
}else{
log.info("[公钥证书上传成功]");
return true;
}
}
/**
* @MethodName: UnionAppDetachedVerify
* @Description: 证书验签
* @param T t 需要 证书验签的bean
* @return String Base64Cert 加签服务器对手行的公钥信息
* @author: qiran
* @date: 2018年7月3日 下午3:24:19
*
*/
public static <T> String UnionAppDetachedVerify(T t) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, NoSuchMethodException, SecurityException, BizException{
String msg= beanToSignString(t,SIGNATURE_CACHE_15,SignatureAnotation_15.class);
if(msg == null){
log.info("该接口无需验签,无需进行验签操作!");
return null;
}
//5.将加签结果参数添加值
Field fieldResult = SignatureResultCache.get(t.getClass());
fieldResult.setAccessible(true);
String signedData =fieldResult.get(t).toString();
UnionCertInfo unionCertInfo = SignatureUtil.UNION_CERTAPP_API.UnionAppDetachedVerify(msg.getBytes(),signedData);
//由于 调用方法 以 0为成功 方法 所以 此处修改为返回0
if(unionCertInfo==null){
log.error("903证书验签错误!");
//throw new BizException(IbpsBizErrorCode.BR999999_验签失败,"903证书验签错误");
}
if(StringUtils.isEmpty(unionCertInfo.getBase64Cert())){
log.error("903证书验签错误,未获取到公钥信息!");
// throw new BizException(IbpsBizErrorCode.BR999999_验签失败,"903证书验签错误,未获取到公钥信息!");
}
String Base64Cert= unionCertInfo.getBase64Cert();
log.info("证书 Ser_number : "+unionCertInfo.getSer_number());
log.info("证书 Base64Cert : "+unionCertInfo.getBase64Cert());
log.info("证书验签已成功 ");
return Base64Cert;
}
public static void main(String[] args) throws Exception {
String signedData = "MEYCIQDn4x0W0iReQNNkiuHgxvxGbAU91MNUpmXeLKi8r3PijgIhAJDF9kbVuyLA+nU/L/rI7HpKML4etrkRSBWofCsYkMnW";
String signMsg = "0000000000012018110815073363|2018-11-08T17:38:40|0000|323241000016|323241000016|3232410000162018110800026420|ibps.101.001.01|PR09|IB1O4001|2018-11-08|";
String bankId = "313770000016";
Map<String,Object> map =new HashMap<String,Object>(18);
map.put("signedData", signedData);
map.put("msg", signMsg);
map.put("bankId", bankId);
Integer signatureResult = UNION_APPRAW_VERIFY.apply(map);
System.out.println("验签返回结果为:" + signatureResult);
if(signatureResult!=0){
System.out.println("报文验签失败!");
}else{
System.out.println("[报文验签成功]");
}
// Ibps805Model model = new Ibps805Model();
//
// model.setMsgid("3232410000162018072459718890");
// model.setCreDtTm("2018-07-24T19:33:21");
// model.setSendBank("323241000016");
// model.setRecvBank("0000");
// model.setOperationType("OT00");
//
// UNION_CERTAPP_API = new UnionCertAppAPI("21.129.12.2",1818, 0);
//
// System.out.println("裸签加签前:"+model.toString());
// SignatureUtil.sign(model,SignatureUtil.UNION_APPRAW_SIGN);
// System.out.println("裸签加签后:"+model.toString());
////
// Ibps805Model model = new Ibps805Model();
//
// model.setMsgid("11");
// model.setCreDtTm("22");
// model.setSendBank("333");
// model.setRecvBank("444");
// model.setSysCd("555");
// model.setOperationType("666");
// model.setPmcCode("888");
// sign15(model, SignatureUtil.UNION_APPRAW_SIGN);
// UnionCertAppAPI UNION_CERTAPP_API = new UnionCertAppAPI("conf"+File.separator+"sys"+File.separator+"srj1401Hsm.conf");
//
// UNION_CERTAPP_API = new UnionCertAppAPI("21.129.12.3",22308, 0);
// System.out.println("加签结果"+UNION_CERTAPP_API.UnionAppRawSign("11|22|333|444|555|666|".getBytes(),2,"PMS.323241000016.2"));
//
////
//
// relieveSign16(model,UNION_APPRAW_VERIFY);
//
// SignatureUtil.relieveSign(model,SignatureUtil.UNION_APPRAW_VERIFY);
//
// System.out.println("裸签验签通过");
//
//
// Ibps311Model model2 = new Ibps311Model();
//
// model2.setMsgid("111111");
//
// model2.setCreDtTm("22222");
//
// model2.setInstgPty("3333");
//
// model2.setInstdPty("4444");
//
// model2.setPtcId("55555");
//
// System.out.println("证书签加签前 :"+model2.toString());
//
// // 证书 解签未过
// SignatureUtil.sign15(model2,SignatureUtil.UNION_APPRAW_SIGN);
// System.out.println("证书签加签后 :"+model2.toString());
//
// SignatureUtil.relieveSign(model2,SignatureUtil.UNION_APPDETACHED_VERIFY);
//
// System.out.println("证书签验签通过");
// try {
// UnionCertAppAPI unionCertAppAPI = new UnionCertAppAPI("conf"+File.separator+"sys"+File.separator+"srj1401Hsm.conf");
// String str = "11";
// System.out.println(str);
// unionCertAppAPI.initCertAppContext();
//
// String str2 = unionCertAppAPI.UnionAppRawSign(str.getBytes(),2 ,"PMS.323241000016.2");
//
// System.out.println(str2);
// System.out.println("测试结果 :"+str2);
// } catch (Exception e) {
// // handle exception
// e.printStackTrace();
// }
// String appName = SignatureUtil.options.get("unionAppRawVerify.appId")+"3232100006"+SignatureUtil.options.get("unionAppRawVerify.appVer");
// UnionCertInfo unionCertInfo=UNION_CERTAPP_API.UnionAppDetachedVerify("111".getBytes(),"111");
// System.out.println(UNION_CERTAPP_API.getErrorCode());
// System.out.println(UNION_CERTAPP_API.getErrorMessage());
// System.out.println(appName);
}
}
/**
* @ClassName: UnionAppRawSign
* @Description: 普通裸签类
* @author: qiran
* @date: 2018年7月13日 下午9:01:09
*
*/
class UnionAppRawSign implements Function<byte[],String>{
private static final Logger log = LoggerFactory.getLogger(UnionAppRawSign.class);
/**
* UnionAppRawSign(byte[] msg,int iAlgorithm,String appName);
* 参数1: msg 待签名 数据原文
* 参数2: iAlgorithm 摘要算法1 表示SHA1, 2 表示SM3, 256表示SHA256,512表示SHA512
* 参数3: appName:证书应用名称,命名需遵循规则appID.bankID.ver, appID为 应用标识,bankID为机构标识, ver为版本号
* 返回值: 加签结果
*/
@Override
public String apply(byte[] t) {
String result = SignatureUtil.UNION_CERTAPP_API.UnionAppRawSign(t,SignatureUtil.options.get("unionAppRawSign.iAlgorithm"),SignatureUtil.options.get("unionAppRawSign.appName"));
log.info("加签ErrorCode:{}",SignatureUtil.UNION_CERTAPP_API.getErrorCode());
log.info("加签ErrorMessage:{}",SignatureUtil.UNION_CERTAPP_API.getErrorMessage());
return result;
}
}
/**
* @ClassName: UnionAppRawVerify
* @Description: 普通验签类
* @author: qiran
* @date: 2018年7月13日 下午9:01:09
* @return 返回值: 0:验证结果正确 其他:验证结果失败
*/
class UnionAppRawVerify implements Function<Map<String,Object>,Integer>{
private static final Logger log = LoggerFactory.getLogger(UnionAppRawVerify.class);
/**
* UnionAppRawVerify(byte[] msg,String signedData,String appName,int iAlgorithm);
* 参数1: msg 待验签 数据原文
* 参数2: signedData base64签名信息
* 参数3:appName:证书应用名称,命名需遵循规则appID.bankID.ver, appID 为应用标识,bankID为机构标识, ver为版本号
* 参数4: iAlgorithm:摘要算法1 表示SHA1, 2 表示SM3, 256表示SHA256,512表示SHA512
RSA证书只能选择SHA1/ SHA256/SHA512;SM2证书只能选择SM3算法
* 返回值: 0:验证结果正确 其他:验证结果失败
*/
@Override
public Integer apply(Map<String,Object> map) {
byte[] one = null;
try {
one = map.get("msg").toString().getBytes("UTF-8");
} catch (UnsupportedEncodingException e) {
log.error("系统异常",e);
}
String signedData = map.get("signedData").toString();
String appName = SignatureUtil.options.get("unionAppRawVerify.appId")+map.get("bankId").toString()+SignatureUtil.options.get("unionAppRawVerify.appVer");
int iAlgorithm = SignatureUtil.options.get("unionAppRawVerify.iAlgorithm");
Integer a = SignatureUtil.UNION_CERTAPP_API.UnionAppRawVerify(one,signedData,appName,iAlgorithm);
log.info("验签ErrorCode:{}",SignatureUtil.UNION_CERTAPP_API.getErrorCode());
log.info("验签ErrorMessage:{}",SignatureUtil.UNION_CERTAPP_API.getErrorMessage());
//SignatureUtil.UNION_CERTAPP_API.UnionAppRawVerify(map.get("msg").toString().getBytes(),map.get("signedData").toString(),SignatureUtil.options.get("unionAppRawVerify.appId")+map.get("bankId").toString()+SignatureUtil.options.get("unionAppRawVerify.appVer"),SignatureUtil.options.get("unionAppRawVerify.iAlgorithm"));
return a;
}
}
/**
* @ClassName: UnionAppDetachedSign
* @Description: PKCS7签名
* @author: qiran
* @date: 2018年7月13日 下午9:01:09
*
*/
class UnionAppDetachedSign implements Function<byte[],String>{
/**
* UnionAppDetachedSign(byte[] msg,String appName,int iAlgorithm);
* 参数1: msUnionAppRawVerifyg:待签名数据
* 参数2: appName:证书应用名称,命名需遵循规则appID.bankID.ver, appID
* 为应用标识,bankID为机构标识, ver为版本号
* 参数3: iAlgorithm:摘要算法1 表示SHA1, 2 表示SM3, 256表示SHA256,512表示SHA512
RSA证书只能选择SHA1/SHA256/SHA512;SM2证书只能选择SM3算法
* 返回值:base64格式P7签名数据包
*/
@Override
public String apply(byte[] t) {
return SignatureUtil.UNION_CERTAPP_API.UnionAppDetachedSign(t,SignatureUtil.options.get("unionAppDetachedSign.appName"),SignatureUtil.options.get("unionAppDetachedSign.iAlgorithm"));
}
}
/**
* @ClassName: UnionAppDetachedVerify
* @Description: PKCS7验签
* @author: qiran
* @date: 2018年7月13日 下午9:01:09
* @return 返回值: 0:验证结果正确 其他:验证结果失败
*/
class UnionAppDetachedVerify implements Function<Map<String,Object>,Integer>{
/**
* UnionCertInfo UnionAppDetachedVerify(byte[] msg,String signedMsg);
* 参数1: msg:待签名数据原文
* 参数2: signedMsg:base64格式PKCS7数据
* 返回值 :UnionCertInfo
* String subject; 证书主题
* String ser_number; 证书序号
* String issuer_subject; 证书颁发者
* String start_time; 证书生效日期yyyyMMdd
* String end_time; 证书失效日期yyyyMMd
* String alg_id; 证书算法标识 "RSA"或"SM2"
* String pk; 证书公钥(RSA公钥格式为DER Hex格式,SM2公钥 为”04||xHex||yHex”)
* String base64Cert; 证书数据(base64)
*/
@Override
public Integer apply(Map<String,Object> map) {
UnionCertInfo unionCertInfo = SignatureUtil.UNION_CERTAPP_API.UnionAppDetachedVerify(map.get("msg").toString().getBytes(),map.get("signedData").toString());
System.out.println(unionCertInfo.getPk());
//由于 调用方法 以 0为成功 方法 所以 此处修改为返回0
if(unionCertInfo!=null&&unionCertInfo.getPk()!=null&&"".equals(unionCertInfo.getPk())){
return 0;
}
return 1;
}
}
网友评论