身份认证系统认证协议的设计与分析 摘 要 认证协议是身份认证系统最关键的部分,研究和分析系统认证协议,是保证网络安全通信的必要条件。Kerberos是一个典型的认证协议,其使用专门的服务器进行统一的身份认证和权限管理,但是由于当初使用环境的原因,并没有使用公钥体制,这影响了系统的扩展性和易管理性。本文描述了一个身份认证系统认证协议的设计思想,使用公钥对kerberos协议进行了改进,并使用BAN逻辑分析了协议的安全性。 关键词 身份认证,认证协议 认证协议是身份认证系统最关键的部分,它直接影响到系统效率、安全性等等。Kerberos是一个典型的认证协议,其使用专门的服务器进行统一的身份认证和权限管理,但是由于当初使用环境的原因,并没有使用公钥体制,这影响了系统的扩展性和易管理性。本文描述了一个身份认证系统认证协议的设计思想,使用公钥对kerberos协议进行了改进,并使用BAN逻辑证明了协议的安全性较高。 1 Kerberos协议分析 Kerberos是一个典型网络安全认证协议,它是应用对称密钥来对客户机(Client)/服务器(Server)应用程序作精确鉴定的。Kerberos主要为网络通信提供可信第三方服务的面向开放系统的认证机制。每当用户(Client)申请得到某服务程序(Server)的服务时,用户和服务程序会首先向Kerberos要求认证对方的身份,认证是建立在用户和服务程序对Kerberos的信任的基础上。在申请认证时,Client和Server都可看成是Kerberos认证服务的用户。为了和其它服务的用户区别,Kerberos将用户和服务器统称为参与者(Principle)。因此Principle既可以是用户也可以是某项服务。认证双方与Kerberos的关系用图1表示。 图1 Kerberos之间的认证关系 当用户登录到工作站时,Kerberos对用户进行初始认证,通过认证的用户可以在整个登录期间得到相应的服务。Kerberos既不依赖用户登录系统的终端,也不依赖用户所请求的服务的安全机制,它凭借本身提供的认证服务来完成对用户的认证工作。而时间戳技术被用来抵御可能发生的重放攻击(Replay Attack)。 Kerberos建立并保存本网络域中每个参与者的名称及其私有密钥的数据库,这样仅有参与者和Kerberos数据库掌握该参与者的私有密钥。使用私有密钥,Kerberos可以对参与者进行身份认证。另外,Kerberos还会随机生成一个会话密钥用来对通信双方的具体内容进行加密。 Kerberos存在以下局限性: 1)原有的认证服务可能被存储或替换,虽然时间戳是专门用于防止重放攻击的,但在票据的有效时间内仍然可能奏效,假设在一个Kerberos认证域内的全部时钟均保持同步,收到消息的时间在规定的范围内(假定规定为5分钟),就认为该消息是新的。而事实上,攻击者可以事先把伪造的消息准备好,一旦得到票据就马上发出伪造的票据,在这5分钟内是难以检查出来的。 2)认证票据的正确性是基于网络中所有的时钟保持同步,如果主机的时间发生错误,则原来的认证票据就是可能被替换的。因为大多数网络的时间协议是不安全的,所以,分布式计算机系统中这将导致极为严重的问题。 3) Kerberos防止口令猜测攻击的能力很弱,攻击者通过长期监听可以收集大量的票据,经过计算和密钥分析进行口令猜测。当用户选择的口令不够强时,就不能有效地防止口令猜测攻击。 4)Kerberos服务器与用户共享的秘密是用户的口令字,服务器在回应时不验证用户的真实性,而是假设只有合法用户拥有口令字。如果攻击者记录申请回答报文,就易形成代码本攻击。 5)实际上,最严重的攻击是恶意软件攻击。Kerberos认证协议依赖于Kerberos软件的绝对可信,而攻击者可以用执行Kerberos协议和记录用户口令的软件来代替所有用户的Kerberos软件,达到攻击的目的。一般而言,装在不安全计算机内的密码软件都会面临这一问题。 6)在分布式系统中,认证中心星罗棋布,域间的会话密钥数量惊人,密钥的管理、分配、存储都是很严峻的问题。 2 认证协议初步设计 Kerberos在最初设计时避免采用公钥体系,这是因为当时应用公钥体系的某些条件不完全成熟。但是随着时间的推移和技术的进步,目前采用公钥体系的一些条件已经具备或者正在具备,特别是从将来的发展来看,将公钥体系结合进现有的系统中去是一种趋势。从对于Kerberos的局限性分析可以看出,其很多缺陷均是由于单独采用对称密钥技术造成的。如果能将公钥技术有机地融合到Kerberos中去,便能克服其保密性不强,扩展性差等缺点。基于这种考虑,这里设计了一个认证协议。在此协议中使用代表用户访问次数的“共享变量”N来防止重放,符号表示说明: ◆CA:认证中心; ◆AA:认证代理服务器(Authentication Agent); ◆C:客户端(Client)唯一标识; ◆S:应用服务器(Server)唯一标识; ◆PRIx:X的私钥; ◆PUBx:X的公钥; ◆CERTc:C的证书序列号; ◆(Info)SIGNx:用X的私钥对信息Info签名; ◆(Info)ENCpubx:用X的公钥对Info加密; ◆(Info)K:用对称密钥K对Info加密; ◆Ts:认证代理为用户C访问服务器S而颁发的票据; ◆Nc:用户端C保存的一个整数,记录用户访问次数; ◆Ns:应用服务器S所保存的用户访问次数,用于防止重放; ◆N:协议消息中使用的用于防止重放的整数,其值由Nc决定,在此称之为“同步变量”。 协议具体工作流程如下: 1)票据请求 当客户端C想访问服务器S时,客户程序要求其输入私钥口令,以便将私钥文件解密,如果私钥口令不正确,则禁止用户进一步的操作。如果正确则发送Ticket_req消息到认证代理AA: C->AA:(C,S,N)SIGNc,CERTcTicket_req消息的具体构造过程如下: 用户取得本地所保存的Nc,然后使N=Nc 1,而后对用户标识C和要访问应用服务器S使用C的私钥签名,此签名可以证明自已的身份。为了便于身份的认证,客户端还需要将自已的证书序列号CERTc传送给AA。参量N的使用主要为了保持用户发送信息的新鲜性,当请求发送完之后,为了下一次会话做准备,需要使Nc=Nc 1。 2)票据发放 当认证代理服务器AA收到Ticket_req消息后,首先根据CERTc从CA或本地缓冲取得用户证书,利用CRL完成对证书有效性的检查。如果证书验证通过,则从用户终端C的证书中取得其公钥PUBc,用此公钥来验证C对信息(C,S,N)的签名,如果签名验证失败,则向客户端发送验证失败消息。签名验证通过后,AA找出C要访问的服务器S,检查其是否有对服务器S的信 息的访问权限,如果权限满足,将产生Ticket_rep消息: AA->C:Ts,((Kcs,N)SIGNAA)ENCpubc 其中Ts=((C,S,Kcs,N)SIGNAA)ENCpubs为用户用以访问服务的票据 Ticket_rep消息的构造过程如下: AA首先产生一个会话密钥Kcs,用于构造票据Ts,在Ts中要加入用户C的标识,以说明此票据为用户C所拥有,其他人不能使用;加入S说明此票据的目的是用于C向S发出的访问;而后还要加入N以保证票据的新鲜性;然后将这些信息签名,证明是由AA发出的,其它人不能假冒或篡改;最后用S的公钥将其加密,使得其它人不能查看其中的会话密钥Kcs。 Ts构造完后,还要将会话密钥Kcs通知用户C,与对票据Ts的处理相似,首先将其用AA的私钥签名,然后用C公钥加密以防止其他人查看会话密钥Kcs。为了保持其新鲜性,在其中加入了N。 3)服务请求 当用户收到Ticket_rep消息后,用户C利用自己的私钥解开((Kcs,N)SIGNAA)ENCpubc,用户检查得到的N,看N=Nc是否成立,如果成立,则证明了其新鲜性;如果NNc,则认为某一方程序出现了错误,则退出。而后,C利用AA的证书验证AA对以上数据的签名,如果成功则说明信息的确是AA发送的,而不是别人伪造的。当以上验证都通过后,C将票据Ts和会话密钥Kcs保存下来,用来向服务器申请服务。向服务器S申请服务的S_req消息如下: C->S:Ts,(C,S,N)Kcs S_req具体构造过程如下: C将自己标识C和服务器标识S以及同步变量N用会话密钥Kcs加密后,连同Ts一起发往服务器S。在这里不能单纯地将Ts直接发往S,因为如果这样的话,非法用户可以在第二步中截获Ts,然后去服务器认证。如果加上(C,S,N)Kcs,则可以说明此消息为拥有Kcs的用户发过来的,而且使用N保证了其新鲜性。 4)服务器身份认证 应用服务器S收到服务请求后,首先是对票据Ts的检查:先用自己的私钥将其解密,查看C和S可以知道此票据是否为用户C发出的,并且是发给自己的;然后取得N,检查N>Ns是否成立,如果成立则通过验证,但如果N<=Ns,则认为此数据为重放数据,予以抛弃,并发回出错消息;以上验证通过后,使用AA的证书验证其签名,如果签名不正确发回出错信息。 对票据本身检查完毕后,还要对票据持有者进行检查:使用Kcs解开(C,S,N)Kcs,检查这里C,S,N是否与票据中的相符,以防止非法攻击者将不同的Ts和(C,S,N)Kcs组合。当验证通过后,应该令Ns=N,以防止重放。 对用户验证通过后,服务器S向客户端C发送s_rep消息证明自己的身份: S->C:(N 1)Kcs 当客户端C收到此消息后,首先利用Kcs将其解开,检查N 1=Nc 1是否成立,如果成立,则认为服务器S合法,因为只有S才能将票据Ts解开来获取Kcs。之后二者便可以利用会话密钥Kcs来进行通话。 3 认证协议设计思想的进一步改进 在Kerberos中,采用了发放票据的方法实现了权限的集中管理,我们也吸取这一思想,用户向认证代理AA证实自己的身份来取得票据。此时,认证代理便可以根据用户的权限的情况来决定是否发给用户票据。当应用服务器S取得服务请求后,S应该可以验证票据的发放者和票据的持有者的身份。 由于采用了公钥体制,用户的身份已经包含在证书中了;利用签名,即可以保证消息来源的真实性、完整性和不可否认性;利用接收方的公钥加密,即可以保证只有接收方才能将数据解开,同时也能保证数据的完整性和机密性;使用各方所拥有的本地所保存的同步变量N,就可以保证消息的新鲜性。 在规模较大、各实体比较分散的网络环境下,实现系统各部分的时间同步可以说非常困难。本系统利用了同步变量N来替换Kerberos中的时间戳。对于同步变量N,其应为位数足够大的整数,在初始使用时,由于客户端C、服务器S本地均没有变量N,我们可以认为其值为null,null小于任何一个整数。当客户端第一次进行传输时需要取N=Nc 1,即N=null 1,这时可以取一个适当范围内的随机数,做为第一次会话中使用的N。当应用服务器S收到N后,便可以为此用户设置本地变量N的值。 在上述协议中,用户每次与服务器交互都必须向认证代理AA申请一次票据,这样显然对用户不方便,而且认证代理AA的负担很大。基于这两点考虑,在上述协议中可以引入票据生存期(lifetime)参量,在生存期内用户能够重复使用票据,而不必再向认证代理AA提出申请。对于票据生存时间,可以由应用服务器自己规定,也可以由认证代理AA在发放票据的时候给出。在此本系统采用了后一种方法。通过分析可以看出,在上述协议中,第一步的签名并不是必须的,因为非法用户根本无法得到会话密钥,也就无法向应用服务器证明自己是证书持有者,所以我们也将其去掉,减少不必要的计算。改进后的协议如下: 1)票据请求(Ticket_req),C->AA:C,S,N,CERTc 2) 票据发放(Ticket_rep),AA-> C:Ts, ((Kcs,N) SIGNAA) ENCpubc Ts=((C,S,Kcs,N,lifetime)SIGNAA)ENCpubs 3)服务请求(S_req),C->S:Ts,(N,ra,seq,opinion)Kcs 4)服务器身份认证(S_rep),S->C:(ra)Kcs(可选由 opinion决定) 符号说明如下: ◆Lifetime:票据生存时间,(从服务器第一次接收服务请求后开始计时); ◆ra:随机会话密钥; ◆seq:服务请求序列号; ◆opinion:用户是否要求对服务器验证,1为要求,0为不要求。 在第二步中,认证代理AA在票据中加入了票据的生存期lifetime,说明此票据的生存时间。 在第三步中,用户C除了向应用服务器S提交最初协议中的内容外,还加入了ra和seq,ra为C生成的一个随机数。在最初的协议中,使用Kcs做为会话密钥,在这里使用ra做为二者会话密钥,因为用户C在票据的生存期内可以重复访问服务器S,处于安全性考虑,每次会话都使用不同的会话密钥ra。为了防止在票据的生存期内攻击者对服务器请求消息的重放,协议中引入了请求的序列号seq。seq从1开始,每次加一。 对于服务器S,除了保留同步变量N外,还要保存用户票据的到期时间Texp,以及用户最后一次服务请求的序号seq。 当服务器S收到用户的请求服务消息后,取得票据中的N有可能出现以下三种情况: 1)N>Ns,说明此请求使用的是新票据,在对请求的所有验证通过后,则使Ns=N,设置过期时间Texp=Tnow lifetime,同时使本地所保存的seq为此次请求的中的seq; 2)N=Ns,说明此请求为重新登录请求,此时检查Tnow>Texp,看票据是否过期,在验证票据的发放者和持有者后,还要检查请求中的序列号seq是否大于本地所保存的上次请求的序列号,如果成立,则将seq更新为此次的请求的序列号,否则认为此消息为重放消息。 3)若N