Merge branch 'dailyfix_yijie230703' into dailyfix

This commit is contained in:
zhanglei 2023-08-10 15:18:41 +08:00
commit d1906b70d7
23 changed files with 1394 additions and 14 deletions

View File

@ -5,7 +5,7 @@
type="javax.sql.DataSource" maxActive="30" maxIdle="2" maxWait="10000"
username="apzl" password="apzl@2018"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://47.93.34.101:3306/apzl?rewriteBatchedStatements=true&useUnicode=true&characterEncoding=GBK&autoReconnectForPools=true&autoReconnect=true&useSSL=false" />
url="jdbc:mysql://47.93.34.101:10323/apzl?rewriteBatchedStatements=true&useUnicode=true&characterEncoding=GBK&autoReconnectForPools=true&autoReconnect=true&useSSL=false" />
<!-- 18测试环境 -->
<!-- <Resource name="jdbc/als" auth="Container" type="javax.sql.DataSource"
maxActive="30" maxIdle="2" maxWait="10000" username="apzl" password="apzl@2018"

View File

@ -41,12 +41,13 @@
var customertype = "<%=customertype%>";
var relations=getItemValueArray(0,"relation").toString().replace(/,/g,"@");
var fullNames=getItemValueArray(0,"fullName").toString().replace(/,/g,"@");
var certIds=getItemValueArray(0,"certId").toString().replace(/,/g,"@");
if(relations.length==0){
alert("请先选择数据!!!");
return;
}
var result = RunJavaMethodTrans("com.tenwa.lease.flow.project.validate.IdentityVerification","doIdentityVerification","FlowUnid="+flowunid+",UserName="+username+",OrgName="+orgname+",relations="+relations+",fullNames="+fullNames+",customertype="+customertype+",SubjectId=<%=SubjectId%>");
var result = RunJavaMethodTrans("com.tenwa.lease.flow.project.validate.alpha.identity.IdentityAlphaVerification","doIdentityVerification","FlowUnid="+flowunid+",UserName="+username+",OrgName="+orgname+",relations="+relations+",fullNames="+fullNames+",certIds="+certIds+",customertype="+customertype+",SubjectId=<%=SubjectId%>");
if(result == 'ERROR'){
alert("调用数据失败");
reloadSelf();
@ -55,7 +56,7 @@
reloadSelf();
}else{
alert(result);
reloadSelf();
reloadSelf();
}
}
function viewAndEdit(){

View File

@ -1,4 +1,4 @@
org.quartz.dataSource.zhulhDS.URL=jdbc:mysql://47.93.34.101:3306/apzl?rewriteBatchedStatements=true&useUnicode=true&characterEncoding=GBK&autoReconnectForPools=true&autoReconnect=true&useSSL=false
org.quartz.dataSource.zhulhDS.URL=jdbc:mysql://47.93.34.101:10323/apzl?rewriteBatchedStatements=true&useUnicode=true&characterEncoding=GBK&autoReconnectForPools=true&autoReconnect=true&useSSL=false
org.quartz.dataSource.zhulhDS.user=338A48E135315FDBC2DF24EB080903D7
org.quartz.dataSource.zhulhDS.key=431DC9744DEF477868F97C4842F87AB3
org.quartz.dataSource.zhulhDS.driver=com.mysql.jdbc.Driver

View File

@ -40,10 +40,10 @@ public abstract class BasicWebAction implements WebAction {
public static String describe(int flag){
switch(flag){
case WEB_ACTION_成功:
return ACTION_DESC_成功;
case WEB_ACTION_suc:
return ACTION_DESC_suc;
default:
return ACTION_DESC_失败;
return ACTION_DESC_fail;
}
}

View File

@ -33,7 +33,7 @@ public class UndefinedPolicyAction implements WebAction {
*/
public int execute(JBOTransaction tx) throws SADREException {
// throw new UnsupportedOperationException(this.getClass().getName()+"未定义授权方案不支持执行execute(Transaction)");
return WEB_ACTION_ʧ°Ü;
return WEB_ACTION_fail;
}
}

View File

@ -26,12 +26,12 @@ import com.amarsoft.are.jbo.JBOTransaction;
* logs: 1.
*/
public interface WebAction {
public static final int WEB_ACTION_成功 = 1;
public static final int WEB_ACTION_失败 = 0;
public static final int WEB_ACTION_未知 = -1;
public static final int WEB_ACTION_suc = 1;
public static final int WEB_ACTION_fail = 0;
public static final int WEB_ACTION_un = -1;
public static final String ACTION_DESC_成功 = "SUCCESSFUL";
public static final String ACTION_DESC_失败 = "FAILED";
public static final String ACTION_DESC_suc = "SUCCESSFUL";
public static final String ACTION_DESC_fail = "FAILED";
/**

View File

@ -0,0 +1,333 @@
package com.tenwa.lease.flow.project.validate.alpha.identity;
import com.amarsoft.are.jbo.*;
import com.tenwa.lease.flow.project.validate.NciicClient;
import com.tenwa.lease.flow.project.validate.SoapRequest;
import com.tenwa.lease.flow.project.validate.ValidatePropertiesUtil;
import com.tenwa.lease.flow.project.validate.alpha.identity.ejy.EJQuestClient;
import jbo.app.tenwa.customer.CUSTOMER_FAMILY_TEMP;
import jbo.app.tenwa.customer.CUSTOMER_PERSON_TEMP;
import jbo.com.tenwa.lease.comm.LB_GUARANTEE_UNIT_TEMP;
import jbo.com.tenwa.lease.comm.LC_IDENTITY_CHECK_RESULT_TEMP;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sun.misc.BASE64Decoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
/**
* 身份证校验类
* @author 张磊
* 2023年7月3日 下午2:18:21
*/
public class IdentityAlphaVerification {
private static final Logger logger = LoggerFactory.getLogger(IdentityAlphaVerification.class);
private String FlowUnid;
private String UserName;
private String OrgName;
private String relations;
private String fullNames;
private String certIds;
private String customertype;
private String SubjectId;
public String getCertIds() {
return certIds;
}
public void setCertIds(String certIds) {
this.certIds = certIds;
}
public String getFlowUnid() {
return FlowUnid;
}
public void setFlowUnid(String flowUnid) {
FlowUnid = flowUnid;
}
public String getUserName() {
return UserName;
}
public void setUserName(String userName) {
UserName = userName;
}
public String getOrgName() {
return OrgName;
}
public void setOrgName(String orgName) {
OrgName = orgName;
}
public String getRelations() {
return relations;
}
public void setRelations(String relations) {
this.relations = relations;
}
public String getFullNames() {
return fullNames;
}
public void setFullNames(String fullNames) {
this.fullNames = fullNames;
}
public String getCustomertype() {
return customertype;
}
public void setCustomertype(String customertype) {
this.customertype = customertype;
}
public String getSubjectId() {
return SubjectId;
}
public void setSubjectId(String subjectId) {
SubjectId = subjectId;
}
/**
* 保存校验结果
* @param tx
* @param name
* @param certId
* @param httpRes
* @throws JBOException
*/
private void saveIdentityRes(JBOTransaction tx, String name, String certId, String httpRes) throws JBOException {
logger.info("IdentityAlphaVerificationSaveIdentityRes --【begin】--保存校验结果-"+name);
BizObjectManager bom4 = JBOFactory.getBizObjectManager(LC_IDENTITY_CHECK_RESULT_TEMP.CLASS_NAME,tx);
BizObject resultObject = bom4.newObject();
//向校验结果临时表存入数据
resultObject.setAttributeValue("flowunid",FlowUnid);
resultObject.setAttributeValue("name",name);
resultObject.setAttributeValue("certid", certId);
resultObject.setAttributeValue("inputuserid",UserName);
resultObject.setAttributeValue("inputorgid", OrgName);
resultObject.setAttributeValue("inputtime", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
String finalResult;
String[] httpResArr = httpRes.split(",");
if("0".equals(httpResArr[0])){
logger.info("IdentityAlphaVerificationSaveIdentityRes --【info】--校验结果:一致-"+name);
finalResult = "身份证校验结果:一致,姓名校验结果:一致";
resultObject.setAttributeValue("result",finalResult);
}else{
logger.info("IdentityAlphaVerificationSaveIdentityRes --【info】--校验错误原因为:"+httpResArr[1]);
finalResult = "错误原因为:"+httpResArr[1];
}
resultObject.setAttributeValue("result", finalResult);
bom4.saveObject(resultObject);
logger.info("IdentityAlphaVerificationSaveIdentityRes --【end】--保存校验结果-"+name);
}
/**
* 实名认证
* @param tx
* @return
*/
public String doIdentityVerification(JBOTransaction tx){
String res = "";
logger.info("IdentityAlphaVerificationDoIdentityVerification --begin--" + UserName+"@"+OrgName+"@"+FlowUnid);
try {
// TODO: 2023-7-4 整理参数
String[] fullNamesArr = fullNames.split("@");
String[] certIdsArr = certIds.split("@");
if(fullNamesArr.length != certIdsArr.length){
logger.info("IdentityAlphaVerificationDoIdentityVerificationError --【end】--姓名和身份证信息数量不一致");
return "姓名和身份证信息数量不一致!";
}
// TODO: 2023-7-4 循环参数
for(int i=0; i < fullNamesArr.length; i++){
logger.info("IdentityAlphaVerificationDoIdentityVerification --【info】--begin-foreach"+fullNamesArr[i]);
// TODO: 2023-7-5 判断是否已身份校验过
BizObjectManager bom4 = JBOFactory.getBizObjectManager(LC_IDENTITY_CHECK_RESULT_TEMP.CLASS_NAME,tx);
BizObject queryResult = bom4.createQuery("select result from O where flowunid=:FLOWUNID and name = '"+fullNamesArr[i]+"'").setParameter("FLOWUNID",FlowUnid).getSingleResult(false);
if(null != queryResult){
logger.info("IdentityAlphaVerificationDoIdentityVerification --【info】--已身份校验过:"+fullNamesArr[i]);
if(i == fullNamesArr.length-1){
res += fullNamesArr[i]+ ":身份校验成功,请点击详情查看!";
}else {
res += fullNamesArr[i]+ ":身份校验成功,请点击详情查看!\n";
}
continue;
}
// TODO: 2023-7-4 发起请求
String httpRes = EJQuestClient.httpIdentityUser(fullNamesArr[i], certIdsArr[i]);
// String httpRes = "0,成功";
// TODO: 2023-7-4 保存结果
if(null == httpRes){
if(i == fullNamesArr.length-1){
res += fullNamesArr[i]+ ":易捷云身份校验接口异常,请稍后再试!";
}else {
res += fullNamesArr[i]+ ":易捷云身份校验接口异常,请稍后再试!\n";
}
logger.info("IdentityAlphaVerificationDoIdentityVerificationError --【info】--易捷云身份校验接口异常,请稍后再试!:"+fullNamesArr[i]);
continue;
}else {
if(i == fullNamesArr.length-1){
res += fullNamesArr[i]+ ":身份校验成功,请点击详情查看!";
}else {
res += fullNamesArr[i]+ ":身份校验成功,请点击详情查看!\n";
}
}
saveIdentityRes(tx, fullNamesArr[i], certIdsArr[i], httpRes);
logger.info("IdentityAlphaVerificationDoIdentityVerification --【info】--end-foreach"+fullNamesArr[i]);
}
// TODO: 2023-7-4 整理返回结果
} catch (Exception e) {
e.printStackTrace();
logger.error("IdentityAlphaVerificationDoIdentityVerificationError 报错:", e);
res += "ERROR";
}
logger.info("IdentityAlphaVerificationDoIdentityVerification --end--" + UserName+"@"+OrgName+"@"+FlowUnid);
return res;
}
public String doIdentityVerification2(JBOTransaction tx){
logger.info("IdentityAlphaVerificationDoIdentityVerification --begin--" + UserName+"@"+OrgName+"@"+FlowUnid);
try {
BizObjectManager bom1 = JBOFactory.getBizObjectManager(CUSTOMER_PERSON_TEMP.CLASS_NAME,tx);
BizObjectManager bom2 = JBOFactory.getBizObjectManager(CUSTOMER_FAMILY_TEMP.CLASS_NAME, tx);
BizObjectManager bom3 = JBOFactory.getBizObjectManager(LB_GUARANTEE_UNIT_TEMP.CLASS_NAME, tx);
BizObjectManager bom4 = JBOFactory.getBizObjectManager(LC_IDENTITY_CHECK_RESULT_TEMP.CLASS_NAME,tx);
String newfullName = fullNames.replace("@", "','");
logger.info(newfullName);
BizObject queryResult = bom4.createQuery("select result from O where flowunid=:FLOWUNID and name in ('"+newfullName+"')").setParameter("FLOWUNID",FlowUnid).getSingleResult(false);
if(queryResult!=null){
return "数据中已有身份证校验已校验过,不可重复执行!!!";
}else{
String[] NewRelations = relations.split("@");
BizObject coborrowerResult = null;
@SuppressWarnings("unchecked")
List<BizObject> guarantorResultList = null ;
BizObject borrowerResult = null;
for(int i=0;i<NewRelations.length;i++){
if("共同申请人".equals(NewRelations[i])){
//查询共同借款人
coborrowerResult = bom2.createQuery("SELECT "+
"name,"+
"certid "+
"FROM "+
"O WHERE flowunid=:FLOWUNID AND Partner_ = 'Y'").setParameter("FLOWUNID", FlowUnid).getSingleResult(false);
}else if("担保人".equals(NewRelations[i])){
//查询担保人
guarantorResultList = bom3.createQuery("SELECT "+
"fullname,"+
"certid "+
"FROM "+
"O WHERE flowunid=:FLOWUNID and FULLNAME in ('"+newfullName+"')"
).setParameter("FLOWUNID",FlowUnid).getResultList(false);
}else if("申请人".equals(NewRelations[i])){
//查询借款人
borrowerResult = bom1.createQuery("SELECT "+
"O.fullname,"+
"O.certid,"+
"O.BalancesHEET,"+
"ci.customertype "+
" FROM "+
"O left join jbo.app.tenwa.customer.CUSTOMER_INFO_TEMP ci "+
" ON O.customerid = ci.customerid "+
" WHERE O.flowunid=:FLOWUNID "+
"AND O.BALANCESHEET = '申请人' ").setParameter("FLOWUNID",FlowUnid).getSingleResult(false);
}
}
//判断用户是自然人还是法人
//将申请人,共同申请人,担保人等信息传入该类构建xml入参参数
String inConditions = "";
//if("03".equals(borrowerResult.getAttribute("customertype").toString())){
if("03".equals(customertype)){
inConditions = SoapRequest.FirstXMLConfiguration(borrowerResult,coborrowerResult,guarantorResultList,SubjectId);
//}else if("01".equals(borrowerResult.getAttribute("customertype").toString())){
}else if("01".equals(customertype)){
if(coborrowerResult == null && guarantorResultList.size()<=0 ){
return "共同申请人与担保人信息都为空!";
}else{
inConditions = SoapRequest.SecondXMLConfiguration(coborrowerResult,guarantorResultList,SubjectId);
}
}
logger.info(inConditions);
//读取授权文件
String license = null;
if("d989246c11c111eaaa0000163e0e11e6".equals(SubjectId)){
license = ValidatePropertiesUtil.get("t_key");
}else{
license =ValidatePropertiesUtil.get("key");
}
String decode = new String(new BASE64Decoder().decodeBuffer(license));
String result = NciicClient.executeClient("NciicServices",decode,inConditions,SubjectId);
logger.info("result:="+result);
//使用Document解析返回的响应XML
Document document = DocumentHelper.parseText(result);
Element rootElement = document.getRootElement();
String finalResult = "";
//判断根元素rootElement若为RESPONSE则调用出现问题
if("RESPONSE".equals(rootElement.getName())){
Element rowElement = rootElement.element("ROWS").element("ROW");
@SuppressWarnings("unchecked")
List<Element> elements = rowElement.elements();
String errormessage = elements.get(1).getText();
return "验证失败,错误原因:"+errormessage;
//若根元素是ROWS则调用成功
}else if("ROWS".equals(rootElement.getName())){
@SuppressWarnings("unchecked")
List<Element> rowElement = rootElement.elements("ROW");
for(int i=0;i<rowElement.size();i++){
BizObject resultObject = bom4.newObject();
@SuppressWarnings("unchecked")
//获取响应XML中INPUT标签内的入参内容
List<Element> inputElements = rowElement.get(i).element("INPUT").elements();
String certid = inputElements.get(0).getText();
String name = inputElements.get(1).getText();
//向校验结果临时表存入数据
resultObject.setAttributeValue("flowunid",FlowUnid);
resultObject.setAttributeValue("name",name);
resultObject.setAttributeValue("certid", certid);
resultObject.setAttributeValue("inputuserid",UserName);
resultObject.setAttributeValue("inputorgid", OrgName);
resultObject.setAttributeValue("inputtime", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
//获取output中的所有item
@SuppressWarnings("unchecked")
List<Element> itemElements = rowElement.get(i).element("OUTPUT").elements("ITEM");
//获取第一个item
@SuppressWarnings("unchecked")
List<Element> outputCertIdElements= itemElements.get(0).elements();
//获取第二个item
@SuppressWarnings("unchecked")
List<Element> outputNameElements= itemElements.get(1).elements();
//判断第一个item中的第一个标签元素的名字
if("gmsfhm".equals(outputCertIdElements.get(0).getName())){
String certIdResult = outputCertIdElements.get(1).getText();
String nameResult = outputNameElements.get(1).getText();
finalResult = "身份证校验结果:"+certIdResult+",姓名校验结果:"+nameResult;
resultObject.setAttributeValue("result",finalResult);
}else if("errormesage".equals(outputCertIdElements.get(0).getName())){
String errorResult = outputCertIdElements.get(0).getText();
finalResult = "错误原因为:"+errorResult;
resultObject.setAttributeValue("result", finalResult);
}
bom4.saveObject(resultObject);
}
}
}
} catch (Exception e) {
e.printStackTrace();
return "ERROR";
}
return "SUCCESS";
}
}

View File

@ -0,0 +1,204 @@
package com.tenwa.lease.flow.project.validate.alpha.identity.ejy;
import com.tenwa.lease.flow.project.validate.alpha.identity.ejy.bean.GlobalReqBizPackage;
import com.tenwa.lease.flow.project.validate.alpha.identity.ejy.bean.GlobalVo;
import com.tenwa.lease.flow.project.validate.alpha.identity.ejy.bean.apply.ApplyRequestBizData;
import com.tenwa.lease.flow.project.validate.alpha.identity.ejy.bean.apply.ApplyResponseBizData;
import com.tenwa.lease.flow.project.validate.alpha.identity.ejy.bean.verification.VerificationRequestBizData;
import com.tenwa.lease.flow.project.validate.alpha.identity.ejy.bean.verification.VerificationResponseBizData;
import com.tenwa.lease.flow.project.validate.alpha.identity.ejy.config.Config;
import com.tenwa.lease.flow.project.validate.alpha.identity.ejy.config.EJYEnums;
import com.tenwa.lease.flow.project.validate.alpha.identity.ejy.utils.EncodesUtil;
import com.tenwa.lease.flow.project.validate.alpha.identity.ejy.utils.HttpUtil;
import com.tenwa.lease.flow.project.validate.alpha.identity.ejy.utils.JSONUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* 易捷云平台对接内容汇总
* 统一申请接口
* 校验接口
*/
public class EJQuestClient {
private static final Logger logger = LoggerFactory.getLogger(EJQuestClient.class);
/**
* 实名认证单个用户
* @return
*/
public static String httpIdentityUser(String name, String idCard){
logger.info("EJQuestClientErrorApplyIdentity 身份校验: name" + name + "idCard" + idCard);
String applyRes = createApply();
if(null == applyRes){
return null;
}
String[] applyResArr = applyRes.split(",");
return applyIdentity(name, idCard, applyResArr[0], applyResArr[1]);
}
/**
* 统一申请接口调用
* @return
* @throws Exception
*/
private static String createApply() {
//1组装赋码申请数据
GlobalReqBizPackage<ApplyRequestBizData> createApply = new GlobalReqBizPackage<>();
// : 2023-7-4 统一申请接口的参数 业务类型 与平台确认6000
createApply.setBizType(6000);
// : 2023-7-4 平台分配的机构代号 与平台确认
createApply.setOrgCode("c747ddaff13f4b719d25793f58329173");
createApply.setBizData(new ApplyRequestBizData());
// : 2023-7-4 统一申请接口的参数 认证模式 与平台确认0x40
createApply.getBizData().setAuthMode("0x40");
String createApplyJson = JSONUtil.toJson(createApply); //转换成json格式
//2签名
byte[] signArray = new byte[0];
try {
signArray = Config.signService.sign(Config.PRIVATE_KEY, createApplyJson.getBytes());
} catch (Exception e) {
e.printStackTrace();
logger.error("EJQuestClientErrorCreateApply 统一申请: 签名报错:", e);
return null;
}
String signString = EncodesUtil.encodeBase64(signArray);
//3请求包组装
GlobalVo globalVo = new GlobalVo();
globalVo.setSign(signString);
globalVo.setBizPackage(createApplyJson);
String createApplyPackage = JSONUtil.toJson(globalVo);
logger.info("EJQuestClientINFO 统一申请: 统一申请: " + createApplyPackage);
//4发送请求
String createApplyResult = null;
try {
createApplyResult = HttpUtil.doPost(Config.URL_APPLY, createApplyPackage);
logger.info("EJQuestClientINFO 统一申请: 统一申请申请结果: " + createApplyResult);
} catch (Exception e) {
e.printStackTrace();
logger.error("EJQuestClientErrorCreateApply 统一申请: 发送请求报错:", e);
return null;
}
//5解析返回结果
GlobalVo createApplyResultJson = JSONUtil.json2Object(createApplyResult, GlobalVo.class);
ApplyResponseBizData applyResponseBizData = JSONUtil.json2Object(createApplyResultJson.getBizPackage(), ApplyResponseBizData.class);
//对返回结果进行验签
byte[] signByte = EncodesUtil.decodeBase64(createApplyResultJson.getSign());
try {
if (!Config.signService.verifySign(Config.PUBLIC_SIGN_KEY, signByte, createApplyResultJson.getBizPackage().getBytes())) {
logger.info("--------生码请求请求成功,对返回结果验签未通过");
logger.error("EJQuestClientErrorCreateApply 统一申请: 生码请求请求成功,对返回结果验签未通过");
return null;
}
} catch (Exception e) {
e.printStackTrace();
logger.error("EJQuestClientErrorCreateApply 统一申请: 对返回结果进行验签报错:", e);
return null;
}
// 如果返回结果为0表示成功
if ("0".equals(applyResponseBizData.getResultCode())) {
//保存流水号随机数,后续请求使用
String bsn = applyResponseBizData.getBizData().getBsn();
String randomNumber = applyResponseBizData.getBizData().getRandomNumber();
logger.info("EJQuestClientINFO 统一申请: bsn = " + bsn);
logger.info("EJQuestClientINFO 统一申请: randomNumber = " + randomNumber);
return bsn+","+randomNumber;
} else {
logger.error("EJQuestClientErrorCreateApply 统一申请: 未成功申请请求");
return null;
}
}
/**
* 身份核验接口调用
* @param name
* @param idCard
* @param bsn
* @param randomNumber
* @return
* @throws Exception
*/
private static String applyIdentity(String name, String idCard, String bsn, String randomNumber) {
GlobalReqBizPackage<VerificationRequestBizData> req = new GlobalReqBizPackage<>();
// : 2023-7-4 身份核验接口的参数 业务类型 与平台确认6000
req.setBizType(6000);
// : 2023-7-4 平台分配的机构代号 与平台确认
req.setOrgCode("c747ddaff13f4b719d25793f58329173");
req.setBsn(bsn);
req.setBizData(new VerificationRequestBizData());
// : 2023-7-4 身份核验接口的参数 认证模式 与平台确认0x40
req.getBizData().setAuthMode("0x40");
VerificationRequestBizData.AuthApplyRetainData authApplyRetainData = new VerificationRequestBizData.AuthApplyRetainData();
authApplyRetainData.setName(name);
authApplyRetainData.setIdNo(idCard);
String strAuthApplyRetainData = JSONUtil.toJson(authApplyRetainData);
logger.info("EJQuestClientErrorApplyIdentity 身份校验: 核心请求参数:" + strAuthApplyRetainData);
byte[] res = Config.signService.encryptAES(Config.PUBLIC_ENCRYPT_KEY, strAuthApplyRetainData.getBytes());
req.getBizData().setAuthApplyRetainData(EncodesUtil.encodeBase64(res));
String createApplyJson = JSONUtil.toJson(req); //转换成json格式
//2签名
byte[] signArray = new byte[0];
try {
signArray = Config.signService.sign(Config.PRIVATE_KEY, createApplyJson.getBytes());
} catch (Exception e) {
e.printStackTrace();
logger.error("EJQuestClientErrorApplyIdentity 身份校验: 签名报错:", e);
return null;
}
String signString = EncodesUtil.encodeBase64(signArray);
//3请求包组装
GlobalVo globalVo = new GlobalVo();
globalVo.setSign(signString);
globalVo.setBizPackage(createApplyJson);
String createApplyPackage = JSONUtil.toJson(globalVo);
//4发送请求
String createApplyResult;
try {
createApplyResult = HttpUtil.doPost(Config.URL_VERIFICATION, createApplyPackage);
logger.info(" 核验请求响应: " + createApplyResult);
} catch (Exception e) {
e.printStackTrace();
logger.error("EJQuestClientErrorApplyIdentity 身份校验: 发送请求报错:", e);
return null;
}
GlobalVo createApplyResultJson = JSONUtil.json2Object(createApplyResult, GlobalVo.class);
VerificationResponseBizData applyResponse = JSONUtil.json2Object(createApplyResultJson.getBizPackage(), VerificationResponseBizData.class);
//对返回结果进行验签
byte[] signByte = EncodesUtil.decodeBase64(createApplyResultJson.getSign());
try {
if (!Config.signService.verifySign(Config.PUBLIC_SIGN_KEY, signByte, createApplyResultJson.getBizPackage().getBytes())) {
logger.info("--------生码请求请求成功,对返回结果验签未通过");
logger.error("EJQuestClientErrorApplyIdentity 身份校验: 生码请求请求成功,对返回结果验签未通过");
return null;
}
} catch (Exception e) {
e.printStackTrace();
logger.error("EJQuestClientErrorApplyIdentity 身份校验: 对返回结果验签报错:", e);
return null;
}
//如果返回结果为0表示成功
if ("0".equals(applyResponse.getResultCode())) {
logger.info(" bId=" + applyResponse.getBizData().getBId());
logger.info(" photoCompareScore=" + applyResponse.getBizData().getPhotoCompareScore());
return "0"+","+applyResponse.getBizData().getBId();
} else {
String errorDesc = EJYEnums.ResCodeEnum.findDesc(applyResponse.getResultCode());
if(null == errorDesc){
errorDesc = "易捷云平台异常状态:" + applyResponse.getResultCode();
}
logger.info("============= 未成功核验请求 ===========");
logger.error("EJQuestClientErrorApplyIdentity 身份校验: 未成功核验请求");
return "1"+","+errorDesc;
}
}
}

View File

@ -0,0 +1,49 @@
package com.tenwa.lease.flow.project.validate.alpha.identity.ejy.bean;
/**
* @author Ivan on 2019/11/15.
* @version 1.0
*/
public class GlobalReqBizPackage<T> {
private Integer bizType;
private String orgCode;
private String bsn;
private T bizData;
public Integer getBizType() {
return bizType;
}
public void setBizType(Integer bizType) {
this.bizType = bizType;
}
public String getOrgCode() {
return orgCode;
}
public void setOrgCode(String orgCode) {
this.orgCode = orgCode;
}
public String getBsn() {
return bsn;
}
public void setBsn(String bsn) {
this.bsn = bsn;
}
public T getBizData() {
return bizData;
}
public void setBizData(T bizData) {
this.bizData = bizData;
}
}

View File

@ -0,0 +1,35 @@
package com.tenwa.lease.flow.project.validate.alpha.identity.ejy.bean;
/**
* @author Ivan on 2019/11/15.
* @version 1.0
*/
public class GlobalVo {
private String bizPackage;
private String sign;
public GlobalVo(String bizPackage, String sign) {
this.bizPackage = bizPackage;
this.sign = sign;
}
public GlobalVo() {
}
public String getBizPackage() {
return bizPackage;
}
public void setBizPackage(String bizPackage) {
this.bizPackage = bizPackage;
}
public String getSign() {
return sign;
}
public void setSign(String sign) {
this.sign = sign;
}
}

View File

@ -0,0 +1,14 @@
package com.tenwa.lease.flow.project.validate.alpha.identity.ejy.bean.apply;
public class ApplyRequestBizData {
private String authMode;
public String getAuthMode() {
return authMode;
}
public void setAuthMode(String authMode) {
this.authMode = authMode;
}
}

View File

@ -0,0 +1,44 @@
package com.tenwa.lease.flow.project.validate.alpha.identity.ejy.bean.apply;
public class ApplyResponseBizData {
private BizData bizData;
private String resultCode;
public BizData getBizData() {
return bizData;
}
public void setBizData(BizData bizData) {
this.bizData = bizData;
}
public String getResultCode() {
return resultCode;
}
public void setResultCode(String resultCode) {
this.resultCode = resultCode;
}
public class BizData {
private String bsn;
private String randomNumber;
public String getBsn() {
return bsn;
}
public void setBsn(String bsn) {
this.bsn = bsn;
}
public String getRandomNumber() {
return randomNumber;
}
public void setRandomNumber(String randomNumber) {
this.randomNumber = randomNumber;
}
}
}

View File

@ -0,0 +1,82 @@
package com.tenwa.lease.flow.project.validate.alpha.identity.ejy.bean.verification;
public class VerificationRequestBizData {
private String authMode;
private String photoData;
private String authApplyRetainData;
private String photoData2;
public String getAuthMode() {
return authMode;
}
public void setAuthMode(String authMode) {
this.authMode = authMode;
}
public String getPhotoData() {
return photoData;
}
public void setPhotoData(String photoData) {
this.photoData = photoData;
}
public String getAuthApplyRetainData() {
return authApplyRetainData;
}
public void setAuthApplyRetainData(String authApplyRetainData) {
this.authApplyRetainData = authApplyRetainData;
}
public String getPhotoData2() {
return photoData2;
}
public void setPhotoData2(String photoData2) {
this.photoData2 = photoData2;
}
public static class AuthApplyRetainData {
private String name;
private String idNo;
private String idIssueDate;
private String idExpireDate;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getIdNo() {
return idNo;
}
public void setIdNo(String idNo) {
this.idNo = idNo;
}
public String getIdIssueDate() {
return idIssueDate;
}
public void setIdIssueDate(String idIssueDate) {
this.idIssueDate = idIssueDate;
}
public String getIdExpireDate() {
return idExpireDate;
}
public void setIdExpireDate(String idExpireDate) {
this.idExpireDate = idExpireDate;
}
}
}

View File

@ -0,0 +1,47 @@
package com.tenwa.lease.flow.project.validate.alpha.identity.ejy.bean.verification;
public class VerificationResponseBizData {
private BizData bizData;
private String resultCode;
public BizData getBizData() {
return bizData;
}
public void setBizData(BizData bizData) {
this.bizData = bizData;
}
public String getResultCode() {
return resultCode;
}
public void setResultCode(String resultCode) {
this.resultCode = resultCode;
}
public class BizData {
private String bId;
private String photoCompareScore;
public String getBId() {
return bId;
}
public void setBId(String bId) {
this.bId = bId;
}
public String getPhotoCompareScore() {
return photoCompareScore;
}
public void setPhotoCompareScore(String photoCompareScore) {
this.photoCompareScore = photoCompareScore;
}
}
}

View File

@ -0,0 +1,43 @@
package com.tenwa.lease.flow.project.validate.alpha.identity.ejy.config;
import com.tenwa.lease.flow.project.validate.alpha.identity.ejy.utils.SignService;
import java.util.HashMap;
import java.util.Map;
public class Config {
public static Map<Integer, String> bizTypeMode = new HashMap<>();
static {
bizTypeMode.put(BizType.X6000, "6000-身份核验");
}
public static class BizType {
//调用申请接口
public static final Integer X1000 = 1000;
//身份核验
public static final Integer X6000 = 6000;
}
/**
* 签名工具
*/
public static SignService signService = new SignService();
public static String domain = "api.easyctid.cn";
public static String URL_APPLY = "http://" + domain + "/v1/apply";
public static String URL_VERIFICATION = "http://" + domain + "/ctid/v1/verification";
//用户签名私钥
public static String PRIVATE_KEY = "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBALc+4knB/IrtbqaXRmHHSFv8YHec6YO0mrVld4r3LN6n+YoqHG2a9PPNN5jsnX23k3X7zR81ovDm3WyyFiDVCSZrAxUIx/+BF3YWOw1aBZUz7xqByhm+zSmtEYdTOhUpWpXR1KxLzhSJgf4ki24kntv2o/tfLqCv5rL3OnVgazgbAgMBAAECgYEAitmIZ/EopjCRBoRb3V0+lAzhH+FzA8xG6ipvcYonorNPH4UXM2oWL+KRPTwVfhwrDVx2Ki7fP4D/yQwMPmaOXhVeyFKdrVfGs/vJloP9dxlZZT8awTgBP6OHr514Civ0+PKYdTdMid5Bo20y9KjiW/A+hD086A51fl4xCrYsfokCQQD58IvnIHvCkEpd5JaRSlwAQl/+w8w0KHg4bCOBT4NGlBTEs7U5HHoPZvEAQYuem5n4XNS3u0krQV1w/fnSBgSvAkEAu7BY0gccsgltajVYf+4n7DduIBDyVncvbvKrjvE3etdt0dJdixlRtoWBydGa/chMlYHe88hAPvH8rUTdjK12VQJBAKbbmAqs/PJfMcaNHJfSdKkXps6GGIWZnujMCMgDNTihE1xePNXr1PEDYFEzcOpqJthP4RLnzWk7Mg6E/4reybECQHIwF9mv+gVXNvom+nDas+9Cyf04UjfIy1L00OtmVhqmdmnxUngOL2icURo4K9O6yN0s5jfq3Stujgvcme28mwECQQCbzs0YrMO0Emcr2yMKW3E7x2NP//8Sa4R47ZhcgXZ1JuNjplhAXH61HsefKOzHjqXX1R7w/kDOYra0K1u6Pgsw";
//平台验签公钥
public static String PUBLIC_SIGN_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCDN70NRLHpbemf3wDwBqgVi7oClnERyel6nGXBd6ng8MNMDyWc8DG3QPgbGhbWikN8559rlzXPkowqx2ZqQUfLWcMSZ0YqMh7wdT25uQfjmQJ2t5lZt5ZjsWuJit5mjIyDaQgymBaB3Lnvk+5Z6WFhrkNg0zSVs10JusXwiDhS3wIDAQAB";
//平台加密公钥
public static String PUBLIC_ENCRYPT_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCl23X1jCttl9A93NT1Uev8/5rXZezm83BwbJKQQFi8onP7lBRTBQh8/ahyhMX8Qc2QKEq4/t58Q0NVZE2/Yb8OqZk4LEu1pCt2ra57DSvgMQ41oxDere4kyTYAqFuMJoQQgEmyYpzpHQu1GlSYRtbJ3Oxd/JqHfOSjPVYJaDEBswIDAQAB";
}

View File

@ -0,0 +1,77 @@
package com.tenwa.lease.flow.project.validate.alpha.identity.ejy.config;
import com.tenwa.app.manage.qiyuesuo.v2.ContractSignEnums;
/**
* 易捷云平台的枚举
*/
public class EJYEnums {
/**
* 返回状态
*
*/
public enum ResCodeEnum{
SUCCESS("0", "成功"),
ERR_I120000("I120000", "网关:内部异常、访问后台服务失败等 网关:内部异常、访问后台服务失败等 ,对应 http 状态码 状态码 : 404 、 500 、503"),
ERR_I120001("I120001", "网关层系统繁忙过载保护对应http状态码 503"),
ERR_I110000("I110000","网关无法解析的请求、缺少键字段对应http状态码 400"),
ERR_I110001("I110001","网关:身份获取失败、验签等,对应 网关:身份获取失败、验签等,对应 网关身份获取失败、验签等对应http状态码 401"),
ERR_I110002("I110002","网关:应用无权限 网关:应用无权限 网关:应用无权限 对应 http 状态码: 状态码: 403"),
ERR_I110003("I110003","网关:服务调用次数上限,对应 http http 状态码: 状态码: 403"),
ERR_100000("100000","系统异常,请联管理员!"),
ERR_100001("100001","CTID系统异常,请联系管理员!"),
ERR_100002("100002","授权流量达到上限"),
ERR_100003("100003","授权用户已达上限"),
ERR_100004("100004","授权文件更新失败"),
ERR_100005("100005","请求头校验失败"),
ERR_110001("110001","包格式错误"),
ERR_110002("110002","参数错误"),
ERR_110003("110003","业务流水号错误或者失效"),
ERR_110004("110004","网证下载参数错误"),
ERR_110005("110005","数据解密失败"),
ERR_110006("110006","申请、请求两包随机数不匹配"),
ERR_110007("110007","数据字段值非法"),
ERR_110008("110008","签名验失败"),
ERR_200001("200001","身份信息无效或不匹配,请检查身份信息是否正确或使用具有"),
ERR_200002("200002","身份信息格式不正确或匹配 ,请检查身份信息"),
ERR_200003("200003","证件已过期"),
ERR_210001("210001","人像非同一人"),
ERR_210002("210002","人像疑似 ,请重新拍照或传入合格片"),
ERR_210003("210003","无人像信息 ,请检查身份信息是否正确或使用"),
ERR_210004("210004","图像格式不支持"),
ERR_210005("210005","待比对图像建模失败"),
ERR_210006("210006","现场照片质量不合格"),
ERR_210007("210007","活体检测控件版本过期"),
ERR_210008("210008","活体检测数据校验失败"),
ERR_210009("210009","现场照片小于5K,请重新拍照或传入合格片"),
ERR_210010("210010","证件照片小于5k, 建议使用具有NFC功能的手机下载CTID官方APP开通网证。");
private String type; //流程编号
private String desc; //描述
private ResCodeEnum(String type, String desc){
this.type=type;
this.desc=desc;
}
public String getType() {
return type;
}
public String getDesc() {
return desc;
}
public static String findDesc(String code){
for(ResCodeEnum e : ResCodeEnum.values()){
if(code.equals(e.getType())){
return e.getDesc();
}
}
return null;
}
}
}

View File

@ -0,0 +1,42 @@
package com.tenwa.lease.flow.project.validate.alpha.identity.ejy.config;
import java.util.HashMap;
import java.util.Map;
public class VerificationConfig {
public static Map<String, String> verificationMode = new HashMap<>();
static {
verificationMode.put(VerificationMode.X70, "1");
verificationMode.put(VerificationMode.X69, "1");
verificationMode.put(VerificationMode.X68, "1");
verificationMode.put(VerificationMode.X65, "1");
verificationMode.put(VerificationMode.X66, "1");
verificationMode.put(VerificationMode.X10, "1");
verificationMode.put(VerificationMode.X12, "1");
verificationMode.put(VerificationMode.X40, "1");
verificationMode.put(VerificationMode.X42, "1");
verificationMode.put(VerificationMode.X18, "1");
}
public static class VerificationMode {
public static final String X70 = "0x70";
public static final String X69 = "0x69";
//2项信息(返PID)
public static final String X68 = "0x68";
//
public static final String X65 = "0x65";
//
public static final String X66 = "0x66";
//4项信息
public static final String X10 = "0x10";
//人像+ 4项信息
public static final String X12 = "0x12";
//2项信息
public static final String X40 = "0x40";
//人像+2项信息
public static final String X42 = "0x42";
//4项信息返证件状态
public static final String X18 = "0x18";
}
}

View File

@ -0,0 +1,94 @@
package com.tenwa.lease.flow.project.validate.alpha.identity.ejy.utils;
import org.apache.commons.lang3.RandomStringUtils;
import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.*;
public class AESCryptService {
public static final int AES_KEY_LENGTH = 128;
public static final int AES_IV_SIZE = 16;
private static final String ALGORITHM_KEY = "AES";
private static final String ALGORITHM_CIPHER = "AES/CBC/PKCS5Padding";
private static ThreadLocal<Cipher> localCipher = new ThreadLocal<>();
private KeyGenerator keyGenerator;
public AESCryptService() {
try {
keyGenerator = KeyGenerator.getInstance(ALGORITHM_KEY);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("没有" + ALGORITHM_KEY + "相关的实现");
}
keyGenerator.init(AES_KEY_LENGTH, new SecureRandom());
}
public byte[] encrypt(Key key, IvParameterSpec iv, byte[] content) throws InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
return doCrypt(key, Cipher.ENCRYPT_MODE, iv, content, 0, content.length);
}
public byte[] encrypt(Key key, IvParameterSpec iv, byte[] content, int start, int length) throws InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
return doCrypt(key, Cipher.ENCRYPT_MODE, iv, content, start, length);
}
public byte[] deCrypt(Key key, IvParameterSpec iv, byte[] content) throws BadPaddingException, InvalidKeyException, IllegalBlockSizeException {
return doCrypt(key, Cipher.DECRYPT_MODE, iv, content, 0, content.length);
}
public byte[] deCrypt(Key key, IvParameterSpec iv, byte[] content, int start, int length) throws BadPaddingException, InvalidKeyException, IllegalBlockSizeException {
return doCrypt(key, Cipher.DECRYPT_MODE, iv, content, start, length);
}
public SecretKey parseKey(byte[] bytes, int start, int length) {
return new SecretKeySpec(bytes, start, length, ALGORITHM_KEY);
}
public IvParameterSpec parseIv(byte[] bytes, int start, int length) {
return new IvParameterSpec(bytes, start, length);
}
public SecretKey randomKey() {
return keyGenerator.generateKey();
}
public IvParameterSpec randomIv() {
return parseIv(randomString(AES_IV_SIZE).getBytes(), 0, AES_IV_SIZE);
}
public static String randomString(int length) {
return RandomStringUtils.random(length, "1234567890abcdefABCDEF-/=+_");
}
private byte[] doCrypt(Key key, int mode, IvParameterSpec iv, byte[] content, int start, int length) throws InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
Cipher cipher = getCipher();
try {
cipher.init(mode, key, iv);
} catch (InvalidAlgorithmParameterException e) {
//正常情况不会出现该异常
throw new RuntimeException("un expect algorithm-parameter", e);
}
return cipher.doFinal(content, start, length);
}
private Cipher getCipher() {
Cipher cipher = localCipher.get();
if (null == cipher) {
try {
cipher = Cipher.getInstance(ALGORITHM_CIPHER);
} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
throw new RuntimeException("没有找到'" + ALGORITHM_CIPHER + "'的实现", e);
}
localCipher.set(cipher);
}
return cipher;
}
}

View File

@ -0,0 +1,21 @@
package com.tenwa.lease.flow.project.validate.alpha.identity.ejy.utils;
import org.apache.commons.codec.binary.Base64;
public class EncodesUtil {
/**
* Base64±àÂë.
*/
public static String encodeBase64(byte[] input) {
return Base64.encodeBase64String(input);
}
/**
* Base64½âÂë.
*/
public static byte[] decodeBase64(String input) {
return Base64.decodeBase64(input);
}
}

View File

@ -0,0 +1,36 @@
package com.tenwa.lease.flow.project.validate.alpha.identity.ejy.utils;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
public class HttpUtil {
public static String doPost(String uri, String param) throws IOException {
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpPost post = new HttpPost(uri);
post.setHeader("Content-Type", "application/json");
StringEntity entity = new StringEntity(param, StandardCharsets.UTF_8);
post.setEntity(entity);
HttpResponse response = httpClient.execute(post);
// int statusCode = response.getStatusLine().getStatusCode();
// if (statusCode != 200) {
// throw new RuntimeException("httpÇëÇóÒì³£" + statusCode);
// }
return EntityUtils.toString(response.getEntity(), "UTF-8");
}
}

View File

@ -0,0 +1,52 @@
package com.tenwa.lease.flow.project.validate.alpha.identity.ejy.utils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson.serializer.SerializerFeature;
import java.util.Map;
public class JSONUtil {
/**
* 将JSON字符串转换为Java对象.
*
* @param jsonStr
* @param clazz 目标对象的Class类.
* @return Java对象
*/
@SuppressWarnings("unchecked")
public static <T> T json2Object(String jsonStr, Class<?> clazz) {
try {
return (T) JSON.parseObject(jsonStr, clazz);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 将Java对象转换为json字符串.
* 禁用循环引用检测.
*
* @param obj
* @return json字符串.
*/
public static String toJson(Object obj) {
try {
return JSON.toJSONString(obj, SerializerFeature.DisableCircularReferenceDetect);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static Map<String, Object> json2Map(String jsonString) {
try {
return JSON.parseObject(jsonString,
new TypeReference<Map<String, Object>>() {
});
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

View File

@ -0,0 +1,32 @@
package com.tenwa.lease.flow.project.validate.alpha.identity.ejy.utils;
import java.security.Key;
public class KeyStore {
public KeyStore(Key key, int keyType) {
this.key = key;
byte[] src = key.getEncoded();
base64Src = EncodesUtil.encodeBase64(src);
this.mode = keyType;
}
private String base64Src;
private Key key;
private int mode;
public String getBase64Src() {
return base64Src;
}
public Key getKey() {
return key;
}
public int getMode() {
return mode;
}
}

View File

@ -0,0 +1,174 @@
package com.tenwa.lease.flow.project.validate.alpha.identity.ejy.utils;
import com.sun.crypto.provider.SunJCE;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import java.io.ByteArrayOutputStream;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
public class SignService {
private static final String ALGORITHM = "RSA";
private static final byte[] VER = EncodesUtil.decodeBase64("Gdp0WDe1XR/BFs9qHai3Gg==");
private static final KeyFactory keyFactory;
private AESCryptService aesService = new AESCryptService();
private static ThreadLocal<Cipher> cipherLocal = new ThreadLocal<>();
static {
try {
keyFactory = KeyFactory.getInstance(ALGORITHM);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("no ALGORITHM for '" + ALGORITHM + "'");
}
}
public byte[] encryptAES(String pubKey, byte[] plaintext) {
//AES
SecretKey aesKey = aesService.randomKey();
IvParameterSpec iv = aesService.randomIv();
byte[] enContent = new byte[0];
try {
enContent = aesService.encrypt(aesKey, iv, plaintext);
} catch (IllegalBlockSizeException | BadPaddingException e) {
System.out.println("AES加密失败");
} catch (InvalidKeyException e) {
System.out.println("AES秘钥不可用");
}
try {
//RSA
ByteArrayOutputStream bout = new ByteArrayOutputStream();
bout.write(aesKey.getEncoded());
bout.write(iv.getIV());
bout.write(VER); //版本信息对加解密无任何影响
byte[] enDes = encryptKey(pubKey, bout.toByteArray());
//parse
bout.reset();
bout.write(enDes);
bout.write(enContent);
return bout.toByteArray();
} catch (Exception e) {
throw new RuntimeException("加密发生错误", e);
}
}
public byte[] encryptKey(String pubKey, byte[] content) throws InvalidKeySpecException, BadPaddingException, IllegalBlockSizeException {
return encrypt(pubKey, content, 0, content.length);
}
public byte[] encrypt(String pubKey, byte[] content, int start, int length) throws InvalidKeySpecException, BadPaddingException, IllegalBlockSizeException {
return doCrypt(pubKey, Cipher.ENCRYPT_MODE, content, start, length);
}
private byte[] doCrypt(String key, int mode, byte[] content, int start, int length) throws InvalidKeySpecException, BadPaddingException, IllegalBlockSizeException {
KeyStore store = prepareKeyStore(key, mode);
Cipher cipher = getCipher(store);
return cipher.doFinal(content, start, length);
}
protected Cipher getCipher(KeyStore store) {
try {
Cipher cipher = cipherLocal.get();
if (null == cipher) {
cipher = Cipher.getInstance(SYSTEM_CIPHER_ALGORITHM, new SunJCE());
cipherLocal.set(cipher);
}
cipher.init(store.getMode(), store.getKey());
return cipher;
} catch (Exception e) {
throw new RuntimeException("没有找到" + SYSTEM_CIPHER_ALGORITHM + "的加密算法", e);
}
}
public static RSAPublicKey getRSAPublicKey(byte[] pubKeyData) throws InvalidKeySpecException {
X509EncodedKeySpec spec = new X509EncodedKeySpec(pubKeyData);
return (RSAPublicKey) keyFactory.generatePublic(spec);
}
public static RSAPrivateKey getRSAPrivateKey(byte[] priKeyData) throws InvalidKeySpecException {
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(priKeyData);
return (RSAPrivateKey) keyFactory.generatePrivate(spec);
}
public boolean verifySign(String pubKey, byte[] sign, byte[] content) throws Exception {
return verifySign(pubKey, sign, content, 0, content.length);
}
public byte[] sign(String priKey, byte[] content) throws Exception {
return sign(priKey, content, 0, content.length);
}
public boolean verifySign(String pubKey, byte[] sign, byte[] content, int start, int length) throws InvalidKeySpecException, SignatureException {
KeyStore store = prepareKeyStore(pubKey, Cipher.PUBLIC_KEY);
Signature signature = getSignature(store);
signature.update(content, start, length);
return signature.verify(sign);
}
private static final String SYSTEM_CIPHER_ALGORITHM = "RSA";
private static final String SYSTEM_SIGNATURE_ALGORITHM = "SHA256withRSA";
private Map<String, KeyStore> priKeyMap = new HashMap<>(512);
private Map<String, KeyStore> pubKeyMap = new HashMap<>(512);
public byte[] sign(String priKey, byte[] content, int start, int length) throws InvalidKeySpecException, SignatureException {
KeyStore store = prepareKeyStore(priKey, Cipher.PRIVATE_KEY);
Signature signature = getSignature(store);
signature.update(content, start, length);
return signature.sign();
}
protected Signature getSignature(KeyStore store) {
try {
Signature signature = Signature.getInstance(SYSTEM_SIGNATURE_ALGORITHM);
if (store.getMode() == Cipher.PRIVATE_KEY) {
signature.initSign((PrivateKey) store.getKey());
} else if (store.getMode() == Cipher.PUBLIC_KEY) {
signature.initVerify((PublicKey) store.getKey());
}
return signature;
} catch (Exception e) {
throw new RuntimeException("没有找到" + SYSTEM_SIGNATURE_ALGORITHM + "的签名算法", e);
}
}
private KeyStore prepareKeyStore(String key, int mode) throws InvalidKeySpecException {
Map<String, KeyStore> storeMap = mode == Cipher.PUBLIC_KEY ? pubKeyMap : priKeyMap;
KeyStore store = storeMap.get(key);
if (null == store) {
byte[] keyByte = EncodesUtil.decodeBase64(key);
Key rsaKey;
if (mode == Cipher.ENCRYPT_MODE) {
rsaKey = getRSAPublicKey(keyByte);
} else {
rsaKey = getRSAPrivateKey(keyByte);
}
store = new KeyStore(rsaKey, mode);
storeMap.put(key, store);
}
return store;
}
}