前言
因工作中需要使用到epass1000ND ,网上找到大多是原生的VBscript,不适应业务的开发要求,写了一个javascript版本放在网上,之后经常碰到朋友留言咨询epass1000ND代码和使用上的问题,有些没有时间解答,本文档详细介绍这款产品的场景和使用流程,方便该产品的在项目中的集成和使用。
对USBKEY比较陌生的同学,请参考:https://blog.csdn.net/liujoi/article/details/106150546
业务场景
epass1000ND的定位集中在普通的企业客户使用自带的私有算法(HMAC-MD5),开发简单,能够迅速的集成到项目中,登录过程使用双因子,避免系统客户账户密码泄密造成的安全隐患。
1 产品说明
epass1000ND有两种用法:
1)证书体系
证书是基于PKI体系实现,需要证书和签名控件支持,一般情况下需要联系CA公司或者自身有对PKI体系有完整理解的情况下使用,开发较为复杂,建议用在安全等级较高的场景,比如:PDF签名、转账交易;其他情况不建议企业使用。
产品的选择上不建议使用epass1000ND,因为这款产品的用户空间较小,芯片运算速度较慢,推荐使用epss3003。
2)自有实现
自带算法HMAC-MD5,这种用法适合企业加固自身系统安全,比如OA登录等,开发较为简单,本文主要讲解的也是这种用法:
- 主要参数
序号 | 参数 | 支持版本 |
1 | 操作系统支持 | Windows、mac、linux |
2 | 浏览器 | IE:√ chrom:× Firefox:× 其他:× |
3 | 协议支持 | CryptoAPI √ PCKS11 √ SKF × |
4 | 开发语言 | Java: √ Vc:√ Asp.net: √ 其他:基本都支持 |
自有实现采用了HMAC-MD5,KEY自带了这个算法,算法的网上有很多的教程,理解这个算法,后续KEY做写入密钥的时候会比较清楚,算法原理如下:
1 定义两个固定且不同的字符串ipad,opad:
ipad = the byte 0x36 repeated B times
opad = the byte 0x5C repeated B times.
2 计算‘text'的HMAC:
H( K XOR opad, H(K XOR ipad, text))
1)即为以下步骤:
2)在密钥key后面添加0来创建一个长为B(64字节)的字符串(str)。
3)将上一步生成的字符串(str)与ipad(0x36)做异或运算,形成结果字符串(istr)。
4)将数据流data附加到第二步的结果字符串(istr)的末尾。
5)做md5运算于第三步生成的数据流(istr)。
6)将第一步生成的字符串(str)与opad(0x5c)做异或运算,形成结果字符串(ostr)。
7)再将第四步的结果(istr)附加到第五步的结果字符串(ostr)的末尾。
8)做md5运算于第六步生成的数据流(ostr),输出最终结果(out)。
业务流程
1 注册
注册一般由管理员操作,主要的工作是完成对KEY密钥写入、及数据库保持对应的KEY和密钥。
2 认证
认证一般由客户登录的时候发起,使用随机数进行验证,通过则允许登录系统。
3 注销
删除epass1000ND中的数据,后端解除绑定关系。
示例代码
<html>
<head>
<title>ePass测试</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<link href="css/styles.css" rel="stylesheet" type="text/css" />
</head>
<OBJECT id="ePass" name="ePass" height="10" width="10" classid="clsid:C7672410-309E-4318-8B34-016EE77D6B58" >
</OBJECT>
<script language="javascript" type="text/javascript" src="js/jquery-1.7.1.min.js"></script>
<script language="javascript" type="text/javascript" src="js/epass.js"></script>
<script type="text/javascript">
var epass1000ND=new epass1000ND(ePass);
/**
*初始化key
*1 创建目录
*2 创建文件
*3 写入秘钥
*/
function iniKey()
{
/** ********创建目录******* */
var pName=document.all.cspNameID.value;
var userPIN=document.all.qdPINID.value;
epass1000ND.CreateDir(pName,userPIN);
/** ********创建文件和数据******* */
var key=document.all.cspKeyID.value;
//第一个文件
var epsFileID=0x01;
var kIpad=epass1000ND.HMACMD5(0,key);
// alert("kIpad:==="+kIpad);
epass1000ND.CreateFile(pName,epsFileID,kIpad);
//第二个文件
epsFileID=0x02;
var kOpad=epass1000ND.HMACMD5(1,key);
// alert("kOpad:==="+kOpad);
epass1000ND.CreateFile(pName,epsFileID,kOpad);
alert("初始化成功!");
}
/**
*
*前端计算结果
**/
function getMD5HMAC()
{
var pName=document.all.qdpNameID.value;
var userPIN=document.all.qdPINID.value;
var data=document.all.qdData.value;
var s;
try
{
s=epass1000ND.getHashToken(pName,userPIN,data);
}
catch(err)
{
alert("计算失败,请检查pin是否正确"+err);
}
document.all.qdJSID.value=s;
}
/**
*
* 从后台计算计算
**/
function getHDJG()
{
var key=document.all.hdKeyID.value;
var data=document.all.hdDataID.value;
var s="key="+encodeURIComponent(key)+"&data="+encodeURIComponent(data);
//调用后台
$.ajax({
type: "POST",
url: "/epass/epass1000ND",
dataType:"text",
data:s,
async: true, //true异步执行
success:function(result){
document.all.hdJSID.value=result;
},
error:function(response, textStatus, errorThrown)
{
alert("响应失败:"+response.status);
}
});
}
/**
*
* 页面初始化读取
*
**/
function setOnload()
{
var snID =epass1000ND.getKeyInfo();
if(snID!='')
{
document.all.xlhID.value=snID;
$("#keyStats").html("连接正常");
$("#keyStats").attr("style","color:green;");
}
else
{
$("#keyStats").html("连接异常");
$("#keyStats").attr("style","color:red;");
}
//获取32位种子
var key=epass1000ND.getRanSeed(32);
document.getElementById("cspKeyID").value=key;
document.getElementById("hdKeyID").value=key;
}
/**
*
* 控制LED灯
*
**/
function controlLED(b)
{
epass1000ND.controlLED(b);
}
/**
*
* 重置密码
**/
function resetPass()
{
var adminPin="rockey";
var new_pass="1234";
epass1000ND.changePass(1,adminPin,new_pass);
}
/**
* 修改密码
**/
function changePass()
{
var old_pass=document.getElementById("old_pass_id").value;
var new_pass=document.getElementById("new_pass_id").value;
epass1000ND.changePass(0,old_pass,new_pass);
}
</script>
<body onload="setOnload()">
<p>说明:</p>
<p>1 本例测试为epass1000ND私有接口</p>
<p>2 控件仅支持IE</p>
<a href="/epass/index.html" >返回首页</a>
<table>
<tr>
<td width="147">KEY序列号:</td>
<td width="542">
<input type="text" id="xlhID" size="25" >
</td>
<td>
<span id="keyStats" />
</td>
</tr>
<tr>
<td width="147">初始化:</td>
<td width="542">
项目名称:<input type="text" id="cspNameID" size="25" value="ftDEMO">
key秘钥:<input type="text" id="cspKeyID" size="25" value="">
</td>
<td width="100">
<input type="button" value="初始化" onclick="iniKey()">
</td>
</tr>
<tr>
<td width="147">前端:</td>
<td width="542">
项目名称:<input type="text" id="qdpNameID" size="25" value="ftDEMO"><br>
用户pin码:<input type="text" id="qdPINID" size="25" value="1234"><br>
数据:<input type="text" id="qdData" size="25" value="mytest">
</td>
<td width="100">
<input type="button" value="计算" onclick="getMD5HMAC()" >
</td>
</tr>
<tr>
<td width="147">后端:</td>
<td width="542">
key秘钥:<input type="text" id="hdKeyID" size="25" value="">
数据:<input type="text" id="hdDataID" size="25" value="mytest">
</td>
<td width="100">
<input type="button" value="计算" onclick="getHDJG()">
</td>
</tr>
<tr>
<td width="147">计算结果:</td>
<td colspan="2">
前端:<input type="text" id="qdJSID" size="40"><br>
后端:<input type="text" id="hdJSID" size="40">
</td>
</tr>
<tr>
<td width="147">LED控制:</td>
<td colspan="2">
<input type="button" id="LEDKID" value="LED灯开" onclick="controlLED(true)">
<input type="button" id="LEDGID" value="LED灯关" onclick="controlLED(false)">
</td>
</tr>
<tr>
<td width="147">修改密码:</td>
<td width="542">
原密码:<input type="text" id="old_pass_id" size="40"><br>
新密码:<input type="text" id="new_pass_id" size="40">
</td>
<td width="100">
<input type="button" id="xg_id" value="修改密码" onclick="changePass()">
</td>
</tr>
<tr>
<td width="147">重置密码:</td>
<td colspan="2">
实现将密码重置,重置后的密码为"1234"<input type="button" id="cz_id" value="重置密码" onclick="resetPass()">
</td>
</tr>
</table>
</body>
</html>
java完整源码:https://download.csdn.net/download/liujoi/12425011,或通过上方链接下载。