USBKEY用户认证平台的研究和实现

来源:互联网 发布:网络侦探黄金大 编辑:程序博客网 时间:2024/06/01 09:16
  引言
        近几年来,随着信息化的快速发展,越来越多的企业认识到信息化对企业生产和管理的重要性,开始在信息化上展开工作并加大投入。一些大型企业实施了MIS、OA、MES、ERP等管理系统,逐步实现企业的生产、管理、电子商务等诸多业务电子化、无纸化。企业都期望借助信息化的平台,提供新的管理手段与模式,提高企业的管理效率,加快企业的发展。
企业中的这些应用系统采用不同的技术开发,虽然实现的功能千差万别,但是出于安全考虑,每个系统都要鉴别使用者的身份,都要求用户输入用户名和密码。
        用户在日常工作中,要记住每个系统的用户名和密码,在系统日益增多的情况下,很多用户会把不同的系统的帐号和密码搞混淆或忘记了密码。另一方面,每个单独的系统都会有自己的安全体系和身份认证系统,要求各用户密码必须有足够长度而且不能单纯为字母或数字,用户记住密码存在难度。
        在实际使用中由于一些原因,例如将用户名和密码记在本子上,长期不修改密码,恶意将用户名和密码信息告诉其他人,还有个别人暴力破解等,容易出现泄露事件,造成信息损失。而且一旦发生用户密码密码信息泄露,还不能确认其泄露行为。
        如今网络上的木马盗号违法行为盛行,可以说,只要上互联网,几乎每一台电脑都可能遭受到攻击,而传统使用的静态密码(用户名+密码)是被认为是极度危险的身份认证手段,所以对重要而敏感的网上身份认证安全不得不引起我们非常的重视。[1]
        综上所述,在今天企业信息化的发展形势下,简单的用户密码验证方式已经暴露出很多问题,给管理和安全上带来很大隐患。所以需要一种安全性更高的而且人为影响因素小的用户认证方式来替代原有方式。
1主要的身份认证技术及优势比较
        目前,计算机及网络系统中常用的身份认证方式主要有以下几种: 
        (1)用户名+密码方式 
        (2)智能卡认证 
        (3)动态口令 
        (4)USB KEY认证 
        (5)生物识别技术
        几种认证技术比较见表1。
       上述几种技术,安全性最高的是动态口令、USB KEY和生物特征识别,但生物识别技术还有待提高,而且根据现实使用情况适用于企业做身份认证的,只有动态口令和USB KEY,相比较USB KEY 成本较低,性价比较高,而且USB接口又有通用性,因此USB KEY认证技术最适合应用推广。由于USB KEY具有安全可靠,便于携带、使用方便、成本低廉的优点,加上PKI体系完善的数据保护机制,使用USB KEY存储数字证书的认证方式已经成为目前主要的认证模式。[2]
2 USB KEY认证概述
2.1 USB KEY认证
       USB KEY认证最早是由软件保护厂家提出来的,它结合了现代密码学技术、智能卡技术和USB技术,是新一代身份认证产品。它具有以下特点:
        (1) 双因子认证
        每一个USB KEY都具有硬件PIN码保护,PIN码和硬件构成了用户使用USB KEY的两个必要因素,即所谓"双因子认证"。用户只有同时取得了USB KEY和用户PIN码,才可以登录系统。即使用户的PIN码被泄漏,只要用户持有的USB KEY不被盗取,合法用户的身份就不会被仿冒;如果用户的USB KEY遗失,拾到者由于不知道用户PIN码,也无法仿冒合法用户的身份。
        (2) 带有安全存储空间
        USB KEY具有8K-128K的安全数据存储空间,可以存储数字证书、用户密钥等秘密数据,对该存储空间的读写操作必须通过程序实现,用户无法直接读取,其中用户私钥是不可导出的,杜绝了复制用户数字证书或身份信息的可能性。
        (3) 硬件实现加密算法
        USB KEY 内置CPU或智能卡芯片,可以实现PKI体系中使用的数据摘要、数据加解密和签名的各种算法,加解密运算在USB KEY内进行,保证了用户密钥不会出现在计算机内存中,从而杜绝了用户密钥被黑客截取的可能性。一般支持RSA,DES ,SSF33和3DES算法。
       (4) 使用方便,安全可靠
USB接口已经广泛应用,而且如拇指般大的USB KEY非常方便随身携带,并且密钥和证书不可导出,KEY的硬件不可复制,保证了使用的安全可靠。[3]
2.2 USB KEY认证的两种应用模式
        USB KEY身份认证主要有两种应用模式:
       (1)基于冲击-响应的认证模式
       USB KEY内置单向散列算法(MD5),预先在USB KEY和服务器中存储一个证明用户身份的密钥,当需要在网络上验证用户身份时,先由客户端向服务器发出一个验证请求。服务器接到此请求后生成一个随机数回传给客户端设备上插着的USB KEY,此为“冲击”。USB KEY使用该随机数与存储在USB KEY中的密钥进行MD5运算得到一个运算结果作为认证证据传送给服务器,此为“响应”。与此同时,服务器使用该随机数与存储在服务器数据库中的该客户密钥进行MD5运算,如果服务器的运算结果与客户端传回的响应结果相同,则认为客户端是一个合法用户。
        图1中“x”代表服务器提供的随机数,“KEY”代表密钥,“y”代表随机数和密钥经过MD5运算后的结果。通过网络传输的只有随机数“x”和运算结果“y”,用户密钥“KEY”既不在网络上传输也不在客户端电脑内存中出现,网络上的黑客和客户端电脑中的木马程序都无法得到用户的密钥。由于每次认证过程使用的随机数“x”和运算结果“y”都不一样,即使在网络传输的过程中认证数据被黑客截获,也无法逆推获得密钥。因此从根本上保证了用户身份无法被仿冒。
        (2)基于PKI的数字证书的认证模式
        ? 冲击响应模式可以保证用户身份不被仿冒,但无法保证认证过程中数据在网络传输过程中的安全。而基于PKI的“数字证书认证方式”可以有效保证用户的身份安全和数据传输安全。USBKEY存储了数字证书和用户私钥,在KEY内用私钥将原文加密,与原文和数字证书一起打包通过网络传输,服务器端接收后还原出数字证书,利用公钥解密,结果与原文校验,确定用户合法性。而数字证书存储在USB KEY中可以保障数字证书无法被复制,所有密钥运算在USB KEY中实现,用户密钥不在计算机内存出现也不在网络中传播,只有USB KEY的持有人才能够对数字证书进行操作。
3 USB KEY 认证设计
        USBKEY认证平台内容包括:构建企业CA签名及验证服务平台, 客户端使用签名控件对用户登录信息进行数字签名加密,服务器端使用验证服务平台对用户的数字签名加密信息进行解密并验证。
3.1 USB KEY认证的流程
        USB KEY认证采用目前普遍使用的基于PKI的数字证书验证方式,这种方式既保证了用户身份安全,也保证了数据传输安全。签名验证流程见图2。
        (1)用户输入PIN码?,通过控件来读取USB KEY中存储的的数字证书及私钥信息。
        (2)USBKEY内置加密算法,使用私钥,对用户登录信息进行签名加密。
        (3)根据PKCS#7标准,将原文和签名后的密文和自己的数字证书打包。
        (4)客户端将打包报文发送给认证服务器。
        (5)认证服务器收到报文,根据PKCS#7格式读出打包信息。
        (6)认证服务器验证用户端所提供的数字证书的有效期、证书链,并完成黑名单检查,失败则放弃。
        (7)有效期、证书链和黑名单验证通过后,认证服务器即使用用户的数字证书的公钥对用户所提供的密文进行解密。
        (8)解密后的报文和原文核对,相同则表明接受由用户提交的数字证书所申明的身份。 
        从上面过程看出,认证过程主要分为两部分:客户端数字签名过程和服务器端验证过程。
3.2 USB KEY认证系统构成
        USB KEY认证系统主要包括CA认证中心,验证服务器和USB KEY。CA认证中心实际是PKI的核心,还应该包括证书申请注册机构RA(Registration Authority),它是数字证书的申请注册、证书签发和管理机构。[4]签名验证服务器提供数字签名服务以及对数据验证其数字签名的真实性。USB KEY是数字证书的载体(见图3)。
3.3 证书认证系统
        证书认证系统一般包含PKI体系个人与服务器数字证书签发、废除等管理服务,密钥管理服务、证书认证服务、用户注册管理服务、Web服务、数据库服务、LDAP服务、日志审计服务等功能。签名验证服务器的结构如下:
        签名验证系统由验证服务器和验证客户端组成,验证服务器提供服务,验证客户端请求服务。应用的客户端需要进行二次开发,发送请求时需要调用格尔签名验证产品的客户端API发送验证请求,并且获得验证结果。
4 USB KEY认证系统实现
4.1 USB KEY认证开发环境
        USBKEY:握奇数据公司USBKEY
        CA服务器:上海格尔CA认证服务器
        签名验证服务器:上海格尔签名认证服务器(SVS)。
        接口包:格尔签名验证服务器提供的签名控件接口SignX.cab,及服务器端签名及验证开发包koal_svsapi_1.7.0_jdk1.4.2,握奇数据公司USB KEY开发包。
4.2 开发内容
        CA服务器数字证书颁发数字证书,通过USB KEY应用程序将数字证书和私钥写进USB KEY;客户端计算机通过签名控件读写USB KEY中的证书和私钥,并通过KEY中的智能芯片用私钥对用户信息加密,客户端将原文及密文和数字证书打包发给签名认证服务器,签名认证服务器将核对数字证书有效性,并用公钥揭秘出原文并核对,从而确认客户端身份。
        现在企业应用系统多为B/S模式,USB KEY认证需要开发的工作,除USB KEY读写应用程序外,客户端签名和服务器端验证都为B/S模式,需要在B/S开发环境下对签名控件和验证开发包做开发集成。
        客户端签名部分,通过控件开发接口,实现对USB KEY存储的数字证书的读取,实现用私钥对原文加密签名。
        服务器验证部分,通过接口开发包,实现数字证书读取核对,实现用公钥解密密文。
4.3 客户端签名控件函数定义
       (1)签名控件开发接口主要函数定义
       函数名:long HashData(const VARIANT FAR& varData,long lHashAlgorithm)
       说明:对内存中的数据块进行HASH算法处理。
       参数:varData 待HASH的数据,支持的数据输入格式有VT_BSTR和VT_BYREF|VT_BSTR、VT_ARRAY|VT_I1、VT_ARRAY|VT_UI1。
返回值:0表示成功,-1表示失败。
       函数名:long Sign(const VARIANT FAR& varData,long lHashAlgorithm)
       说明:对数据用lHashAlgorithm指定HASH方法进行签名,签名结果使用GetSignResult获取。
       参数:varData待签名的数据,支持的数据输入格式有VT_BSTR和VT_BYREF|VT_BSTR、VT_ARRAY|VT_I1、VT_ARRAY|VT_UI1。
       函数名:BSTR GetSignResult()
       说明:返回成功签名的签名数据,签名数据以BASE64编码返回。
       返回值:BASE64格式的签名数据。
       函数名:long SignPKCS7(const VARIANT FAR& varData,long lHashAlgorithm)
       说明:对数据进行PKCS#7的Attach方式的签名。签名结果使用GetSignResult取得。
       参数:varData 待签名的数据。支持的数据输入格式有VT_BSTR和VT_BYREF|VT_BSTR、VT_ARRAY|VT_I1、VT_ARRAY|VT_UI1。
返回值:0 表示成功,-1表示失败
        函数名:BSTR GetCurrentUsedCertInfo(long lID)
        说  明:获取当前正在使用的证书的信息
        参  数:lID 需要获取的信息。
        返回值:相应的证书信息。
        函数名:BSTR GetLastErrorString()
        说明:返回最后一次操作的错误说明。
        返回值:错误说明。
        函数名:long GetLastErrorCode()
        说明:返回最后一次操作的错误类型编号。使用GetLastErrorString来获取错
        误的详细信息。
        返回值:错误类型编号。
4.4 客户端签名程序设计
        对用户登录信息的数字签名可以采取两种方式:可以使用客户端签名控件进行签名的方式,也可以使用向签名验证服务器提交获取签名的方式。这里采取签名控件的方式对系统的帐号和密码进行数字签名,签名的方式使用PKCS#7,即签名数据和数字证书一起打包发送。经过PKCS#7进行签名的数据中包括三部分,即信息原文、密文和用户的数字证书。
客户端签名过程嵌入在用户登录界面login.jsp中,对用户口令进行数字签名部分的代码如下:
function SignPKCS7()
{
  var Data1 = GetData_username();
  var Data2 = GetData_password();
  var HashAlg = GetHashAlg();
  SetShowDataBeforeSign();
  if (0 == document.signx.selectcert())//选择用户数字证书
  {
   //签名用户名
    if (0 == document.signx.signpkcs7(Data1,HashAlg)){
     document.form1.username.value = document.signx.GetSignResult();
    }
    else {
     GetLastErrorString();
    }
   //签名用户口令
    if (0 == document.signx.signpkcs7(Data2,HashAlg)){
     document.form1.password.value = document.signx.GetSignResult();
    }
    else {
     GetLastErrorString();
    }
  }
  else {
   GetLastErrorString();
  }
}
</script>
 </head>
<body bgcolor="#FFFFFF" leftmargin="0" topmargin="0">
 <!-- 定义签名控件  -->
 <OBJECT id=signx height=40 width=200 classid=
                 CLSID:7AA0F60A-7F84-4233-9B84-15E0A9D6DCF1
                 codebase=Signx.cab VIEWASTEXT></OBJECT>
        在用户登录时,插入自己的USB KEY,选择自己的数字证书对用户口令进行数字签名后提交到服务器进行验证。
4.5 签名验证服务器接口函数设计
        格尔验证服务器接口包名:koal_svsapi_1.7.0_jdk1.4.2.jar,其中主要函数定义如下
对PKCS#7格式签名数据进行验证 :
Parameters:
szPKCS7BASE64Data - 待验证的PKCS#7签名数据(BASE64编码)
arrayOriginData - 如果PKCS#7签名数据中未包含签名原文信息,可在此添入,否则必须将该参数设置为NULL
nOriginLen - 签名数据原文的长度,如果pOriginData为NULL,则将该参数设置为0
hostInfo - 验证服务器的地址信息 
Returns:
0 // 获取证书信息成功 其它 // 错误码 
Throws:
java.lang.Exception
public int verifyCert(java.lang.String szBASE64Cert,
                      int nFlagOCSP,
                      int nFlagCRL,
                      THostInfoSt hostInfo)
         throws java.lang.Exception
验证证书的状态:
Parameters:
szBASE64Cert - 待验证的证书(BASE64编码)
nFlagOCSP - 是否进行OCSP验证 0 否 1 是
nFlagCRL - 是否进行黑名单验证 0 否 1 是
hostInfo - 验证服务器的地址信息 
Returns:
0 证书没有问题 1 证书尚未生效 2 证书已经过期 3 证书时间有问题 4 没有有效证书链 5 签名验证失败 6 上级证书未通过验证 7 已被废除 8 证书状态未知 其它负值 错误码 
Throws:
java.lang.Exception
getCertInfo
public GetCertInfoSt getCertInfo(java.lang.String
 szBASE64Cert,
int nType,java.lang.String
 szItemName, THostInfoSt hostInfo)
     throws java.lang.Exception
获取证书的证书项信息:
Parameters:
      szBASE64Cert - 待获取信息的证书(BASE64编码)
nType - 欲获取的证书项信息的类型 0 证书所有者信息 1 证书颁发者信息 2 证书扩展项信息
szItemName - 证书项的名称
hostInfo - 验证服务器的地址信息 
Returns:
GetCertInfoSt结构,其中包含返回结果及证书项信息 
Throws:
java.lang.Exception
4.6 USB KEY服务器验证过程实现
        用户提交的经过PKCS#7签名的登录信息到服务器,由服务器对签名后的用户信息进行验证,并且从签名信息中获取原文,然后对用户帐号和用户口令原文信息进行登录验证。
服务器端用户验证的部分代码如下:
   String hostip = "192.168.0.5";//签名验证服务器的IP地址
  int hostport = 5000;//签名验证服务器提供验证服务的端口
  THostInfoSt hostInfo = new THostInfoSt();
  hostInfo.setSvrIP(hostip);
  hostInfo.setPort(hostport);
  String szSignedData = request.getParameter("password"); 
 //获取经过数字签名后的用户口令
  nRet = SvsClientHelper.PKCS7DataVerify(szSignedData,null,0,hostInfo);
 //签名验证,返回0表示成功,否则验证失败。
  if(nRet==0){//如果签名验证成功
   String password = SvsClientHelper.
               PKCS7DataVerifyGetOriData(szSignedData,null,0,hostInfo);
               //获取签名后的原文数据,即用户口令的原文
   String username = request.getParameter("username");
   //String password = request.getParameter("password");
   request.setCharacterEncoding(ConnectOracleDB.CharEncoding);
   response.setContentType("text/html");
   response.setCharacterEncoding(ConnectOracleDB.CharEncoding);
   PrintWriter out = response.getWriter();
   if(ConnLogin.CheckUser(username,password))
 //用户帐号和口令验证成功
   {
    String theme = ConnLogin.getUserTheme(username);
    request.getSession().setAttribute("Theme",theme);
    request.getSession().setAttribute("username",username);
    request.getSession().setAttribute("adminlevel",ConnLogin.adminlevel);
    request.getSession().setAttribute("theme",theme);
    System.out.println("Login User is " +
                              request.getSession().getAttribute("username"));
    out.println("<META HTTP-EQUIV=/"REFRESH/"
                    CONTENT=/"0;url=/unisso/pages/theme/ssomain.jsp/">");
   } else{//用户帐号和口令验证失败
    String outs = "<html><head><meta http-equiv="Content-Type" content="text/html;charset=gb2312"><META HTTP-EQUIV="REFRESH" CONTENT="8;url=/unisso/"><link href="/css/style.css" rel="stylesheet" type="text/css"><title>登录失败</title></head><body><br><br><br><center><p class="unnamed1">登录失败,用户名不存在或者密码错误!</p><p class="unnamed1">8秒后返回登录页面或者点击<a href="/unisso/">这里</a>返回</p></center></body></html>";
    out.println(outs);
   }
  }else{//如果签名验证失败
   String outs = "<html><head><meta http-equiv="Content-Type" content="text/html;charset=gb2312"><META HTTP-EQUIV="REFRESH" CONTENT="8;url=/unisso/"><link href="/css/style.css" rel="stylesheet" type="text/css"><title>登录失败</title></head><body><br><br><br><center><p class="unnamed1">登录失败,签名验证失败!请插入正确的UsbKEY。</p><p class="unnamed1">8秒后返回登录页面或者点击<a href="/unisso/">这里</a>返回</p></center></body></html>"。
        这样通过验证签名信息的有效性,只有用户拥有USB KEY并且通过用户帐号和用户口令验证才能登录系统,即使拥有USB KEY,如果不知道系统中的用户口令,也无法正常登录和使用系统,从而充分保证了用户登录信息的安全。也就是说USB KEY、用户帐号和用户口令,缺少任何一个都无法登录和使用系统。
5结语

        本文分析了现在企业多数信息应用系统用户认证的安全弊端,提出了使用USB KEY来作为身份认证替代方式,提出了设计并搭建环境进行了实施,证明了该认证平台的可行性。该平台目前运行良好,极大地提升了应用系统的安全性,解决了企业现实存在的实际问题,具有较强的实用性。


转自:http://blog.csdn.net/loman_yt/article/details/44675671



原创粉丝点击