一、服务能力
eID认证服务可提供eID实名认证和eID匿名认证服务。
服务名称 | 输入 | 输出 | 说明 |
eID实名认证 | 姓名+身份证号、自定义待签业务数据、eID签名验证数据包 | 认证结果、eID签名值 | 使用公钥证书对待签业务数据、eID签名验证数据包进行合法性验证,验证通过后同时比对身份信息(姓名、身份证号码)与eID持有者信息是否一致。 |
eID匿名认证 | 自定义待签业务数据、eID签名验证数据包 | 认证结果、eID签名值、H2(可选) | 使用公钥证书对待签业务数据、eID签名验证数据包进行合法性验证,验证通过时返回H2(可选,应用按照自身业务场景需求选择)。
H2:身份信息索引值(Hash),具备大量身份信息的应用根据指定运算规则对现有身份库进行改造,增加身份信息索引值H2,与eID匿名认证返回的H2进行比对,关联本地身份信息,常用于登录场景。 H2计算规则 |
二、准备接入
1、应用申请:点击进入申请界面
2、客户端SDK及使用手册:点击下载
3、服务端SDK及使用手册:点击下载
三、实现流程
四、流程说明
1、步骤1
手机应用使用客户端SDK,获取包含eID载体信息的eID签名请求数据包(eIDReqPacket)。参照客户端SDK文档以下内容:
代码样例
// 调用客户端SDK接口获取eid_req_packet
msgToUI = mUIHandler.obtainMessage(MSG_SIGN_REQ_BEGIN, msg.obj);
mUIHandler.sendMessage(msgToUI);
StringResult reqPacket = new StringResult();
long ret = signEngine.eID_GetInfo(reqParams, reqPacket);
if (TeIDResultCode.RC_00.getIndex() != ret) {
msgToUI = mUIHandler.obtainMessage(MSG_SIGN_REQ_FAILED, signEngine.eID_GetLastError());
mUIHandler.sendMessage(msgToUI);
return false;
}
String eIDReqPacket = reqPacket.data;
2、步骤2
手机应用将获取到的eID签名请求数据包(eIDReqPacket)透传给手机APP服务后台。
3、步骤3
APP服务后台,使用服务端SDK,请求eID服务,获取签名指令(sign_cmd)。
业务参数说明
参数 | 命名 | 是否必填 | 描述 |
业务流水号 | biz_sequence_id | 是 | 业务流水号,应用方生成,针对本次请求的唯一标识。 |
待签原文 | data_to_sign | 是 | 业务处理参数,用户使用eID对此待签原文进行数字签名。 |
显示信息 | data_to_be_displayed | 是 | 待显示信息,手机钱包弹出用户确认界面时显示的文字信息内容。 |
请求数据包 | eid_req_ packet | 是 | 通过客户端SDK获取。 |
代码样例
private static String test_0000001(String sequenceId, String eid_req_packet) {
Calendar rightNow = Calendar.getInstance();
SimpleDateFormat fmt = new SimpleDateFormat("yyyyMMddHHmmss");
String sysDatetime = fmt.format(rightNow.getTime());
// yyyyMMddHHmmss:64字节内流水号:业务
String data_to_sign = sysDatetime + ":" + sequenceId + ":" + "123456";
byte[] data_to_sign_64 = data_to_sign.getBytes();
// 待签原文
data_to_sign = Base64.encode(data_to_sign_64);
// 显示信息
String data_to_be_displayed = "确认信息显示内容";
SIMEidParameters pkiparam = new SIMEidParameters(data_to_sign,data_to_be_displayed,"","00",eid_req_packet);
ESEEidSignRequestParam signRequestParam = new ESEEidSignRequestParam(pkiparam);
// 业务流水号
signRequestParam.setBizSequenceId(sequenceId);
CommonResult result = EidService.eSEEidSignRequestSyn(signRequestParam);
return new Gson().toJson(result).toString();
}
响应数据样例
{"version":"2.0.0","result":"00","resultDetail":"0000000","resultTime":"20200424162138","bizSequenceId":"0105f3f48e59488ebfd6671405549db0","sign_cmd":"AEQ4OGI2MWI3NzhiZjQ0MzhmODIxNGQ4OTQ3NjkwZTE2ZAF4AHYWFgAXFwCQSVi7ppF0skw0CtqMHfpunFRcQ1G2042oZ7N5FtexoYXi0LHgFYY8hwKGiMagF3B69oI9d9ShMEOXbZRVUddxTfbKsP8V3ZKlhbwUgic4dS8cRr8EgREWa8A3DuLQk6b2VD5ET79RCGBeM9IHGhpW"}
4、步骤4
应用APP将从服务端获取到的签名指令(步骤3的响应数据中的sign_cmd), 通过客户端SDK请求手机钱包,拉起确认界面,完成用户签名,获得用户签名后的eID签名验证数据包(eid_sign_packet)。
代码样例
// 拿到服务端获取的签名指令包
String signCmd = sign_cmd;
msgToUI = mUIHandler.obtainMessage(MSG_SIGN_REQ_OK, signCmd);
mUIHandler.sendMessage(msgToUI);
// 调用接口获取eid_sign_packet
mUIHandler.sendEmptyMessage(MSG_SIGN_BEGIN);
StringResult signPacket = new StringResult();
ret = signEngine.eID_PerformSign(signCmd, signPacket);
if (TeIDResultCode.RC_00.getIndex() != ret) {
msgToUI = mUIHandler.obtainMessage(MSG_SIGN_FAILED, signEngine.eID_GetLastError());
mUIHandler.sendMessage(msgToUI);
return false;
}
// 拿到用户签名后的eID签名验证数据包
String eid_sign_packet = signPacket.data;
5、步骤5
手机应用将获取到的eID签名验证数据包(eid_sign_packet)透传给手机APP服务后台。
6、步骤6
APP服务后台,使用服务端SDK,请求eID服务,进行eID签名验签(实名认证/匿名认证/签名验签)。 本服务为异步,应用通过结果返回URL接收eID服务的返回结果。
业务参数说明
参数 | 命名 | 是否必填 | 描述 |
结果返回URL | return_url | 是 | 第三方应用异步接收结果的路径地址。 |
姓名 | name | 否 | 实名认证时非空。 |
身份证号码 | idnum | 否 | 实名认证时非空。 |
eID签名验证数据包 | eid_sign_packet | 是 | 通过客户端SDK获取。 |
代码样例
// 结果返回URL
String return_url = "http://10.0.0.1:10008/xxxx/callback";
// eID签名验证数据包
String eid_sign_packet = "AQQACXXXXXXXXgAAAAAANw==";
// 姓名、身份证号码
String name = "XXXX";
String idnum = "XXXX";
RealName realName = new RealName(name, idnum);
SIMEidParameters pkiparam = new SIMEidParameters(return_url,eid_sign_packet);
ESEEidRealNameParam realNameParam = new ESEEidRealNameParam(pkiparam, realName);
// 1.eID实名认证
boolean result = EidService.eSEEidRealNameAsyn(realNameParam);
// 2.匿名认证
boolean result = EidService.eSEDirectloginAsync(signVerifyParam);
响应数据样例
{"version":"2.0.0","result":"00","result_detail":"0000000","result_time":"20200424100840","biz_sequence_id":"c033b99d52b841b89cebc59f19c05a83","security_factor":{"sign_factor":"aa6e07fd1db7b35d","encrypt_factor":"8f87686796f1fc17"},"encrypt_type":"1","sign_type":"1","extension":{},"user_info":"dwpJUjXPkPH7MPSVfoKtz1s5d8WwYBBAxdZ7VlLGTWHqHekFcpVZDD6ca0obxOrcK3P/a+0WzUqYI02tiKihvgMtc6XKnDi7","eid_sign":"deIOkXM+cOwqnCiSKKJlXmN1vsGNDEfkrI5o17Si8Y24SO/mnLAf4TGcWqN9u5P3ehbD4AMADsSe+aT8DdcBjA==","sign":"GAiTSMcx0Cgpz/LjmE/wxmN3tTI="}
异步获取到密文数据(user_info)需要使用appkey对其解密时:
// 加密值(返回参数中动态获取)
String userInfo_return = "dwpJUjXPkPH7MPSVfoKtz1s5d8WwYBBAxdZ7VlLGTWHqHekFc";
// 应用key(替换为应用的appkey)
String app_key = "1234567890";
// 报文参数安全因子(返回参数中动态获取)
String encrypt_factor = "8f87686796f1fc17";
// 调用解密方法(服务端SDK实现类:SecurityUtils)
String userInfo_decrypt = SecurityUtils.do3desDecrypt(userInfo_return, app_key, encrypt_factor);
System.out.println("解密结果:" + userInfo_decrypt);
五、H2计算规则
H2 = SM3(SM3(身份证号 + salt_1) + salt_2)
其中:salt_1:公安指定盐、salt_2:应用指定盐,应用注册时提交。
H2计算实现样例
// 身份证号码
String idnum = "XXXXXXXXXXXXXXXXXX";
// 公安指定盐
String salt_1 = "eID00000000";
// 应用指定盐
String salt_app = "123456";
// 计算H2(服务端SDK提供实现类)
byte[] h2_hash = H2Util.generateH2SaltNOSm3(idnum, salt_app, salt_1);
System.out.println("h2:" + new String(Base64.encode(h2_hash)));