您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 质量控制/管理 > kerberos安全协议解析与编程实现
Kerberos安全协议解析与编程实现1.引言看了好几期的黑防,发现谈论安全协议的文章很少,基本上都是一些HOOK各种API或者底层驱动方面的技术文章。下面我向大家介绍一种安全认证协议—kerberos安全协议的基本原理,并通过编程实现向大家展示如何借助编码设计,简单实现此协议。本文的读者可以是信息安全科班出身的学生但又未涉及到kerberos或者对安全协议感兴趣的任何读者,只要具有一定的安全编程知识即可。其实安全协议的研究很早就存在,只是以前国内的研究者比较少,国内也没有开设信息安全专业的相关课程,如密码学等课程。直到网络信息高速发展的今天,大量的信息非法盗取、恶意篡改、木马、病毒像幽灵般穿梭在网络中时,大家才开始紧密的关注网络安全技术领域,各大高校也都开始纷纷设立信息安全专业。伟大的信息通信专家Shannon发表《保密系统的信息理论》文章开始,基本上就掀起了信息通信保密学的研究热潮。OK,不多说了,直接切入正题。2.Kerberos安全认证协议基本框架Kerberos安全认证协议是由MIT的Athena计划的认证服务而开发的,并广泛的应用于开放式的网络环境中,为通信的双方提供很好的双向认证服务,在客户与服务器之间构筑了一个安全桥梁,要求用户对每个向服务器提交的服务请求及其权限,必须预先经过第三方认证中心服务器的认证后,才被允许执行。换句话说,kerberos的整体设计方案是完全基于协议的可信任第三方认证服务的,客户和服务器均信任Kerberos认证服务器的认证。好了,现在我们来揭开它的基本原理:一个Kerberos环境包含一个Kerberos服务器、若个客户端以及一些应用服务器。Kerberos服务器将客户端用户的用户名及口令均存放在它的数据库中。应用服务器和所有的客户都必须在初始化阶段到Kerberos服务器中注册。基本框架如图1所示:Kerberos服务器认证服务器(AS)服务授权服务器(TGS)数据库KDC应用服务器客户端123456图1kerberos安全认证协议基本结构3.Kerberos双向认证过程与逆向推理分析(1)Client→AS:客户端向认证服务器发送认证请求KRB_AS_REQ,其内容是:{c,Tgs,TS1}。其中,c表示客户标识,告诉AS客户端身份,便于AS到数据库中查询c的密钥;Tgs是TGS服务器标识,告诉AS用户请求访问的TGS;TS1用于使AS能验证客户端时钟是否与AS时钟同步,其实也就是一个时间戳的概念,给AS作参考判断来自Client端的消息是否已经过期。(2)AS→Client:向客户端发送认证回应KRB_AS_REP,其内容为{K(c,Tgs),TS2,lifetime,Tickets_Tgs}Kc。K(c,Tgs)是由AS随机产生的一个密钥,用于Client与TGS共享的一个会话私钥。TS2是票据发放的时间戳;Tickets_Tgs是AS发给Client的用于访问TGS的票据授权票据;有了此票据后,用户就可以向TGS申请任一的应用服务器,而不需要每次重复的输入Client端的登录密钥。它定义为:Tickets_Tgs={K(c,tgs),c,c_mac,Tgs,TS2,lifetime2}Ktgs。其中Tickets_Tgs已经采用TGS的私钥加密。这部分其实在KerberosV5的版本已经作了修改,因为Tickets_Tgs已经采用TGS的私钥加密,故没有必要采用客户端的私钥再次加密。(3)C→TGS:Client在第2步中获得AS认证,并取得票据授权票据后,Client即可向服务授权服务器(TGS)申请服务票据。发送的消息定义为KRB_TGS_REQ={AppServ,Tickets_Tgs,Authen_info},其中AppServ是用户期望访问的服务器;Authen_info是发送的一条认证消息,用于确认发送票据Tickets_Tgs的用户合法。定义为:Authen_info={c,c_mac,TS3}K(c,tgs)。这里我们可以假设,若不发送Authen_info消息,则当cracker截获了Tickets_Tgs票据,同时向TGS发送此票据,那么TGS只针对此Tickets_Tgs票据是无法判断此票据是否真正来自合法客户端,而验证器消息Authen_info则正好解决了此问题,当TGS收到Client发来的Req请求服务授权票据时,TGS首先会采用自己的私钥Ktgs解密Tickets_Tgs,获取AS为Client和TGS双方随机产生的共享密钥K(c,tgs),然后利用此密钥解密Authen_info消息,提取出客户端用户名及其MAC地址,然后将这些同Tickets_Tgs包含的C和c_mac进行比较,若一致,则断定此次Req来自合法客户端。(4)TGS→C:当TGS验证Req来自合法Client时,则构造下面这条消息KRB_TGS_REP={K(c,s),AppServ,TS4,S_Tickets}K(c,tgs)发送到Client端。其中K(c,s)是TGS随机生成的密钥,为Client端和AppServ共享的会话密钥。S_Tickets为服务授权票据定义为S_Tickets={K(c,s),c,c_mac,AppServ,TS4,lifetime}Ks;采用AppServ的私钥Ks加密此票据。写到这里,仔细阅读的读者可能会想为什么kerberos协议会介入一个应用服务器,当客户端送来合法的票据后,直接由TGS转入到相应的AS处理不就可以了嘛。大家应该都看过“无间道”这部影片吧,警方中有犯罪团伙的卧底,同样犯罪分子中有警署的卧底。给一个场景:若你一直对公司领导忽视你的才能,长期不提拔你感到懊恼,想跳槽到其它公司去,现需要打印一份求职简历,请求打印服务器资源,向TGS发送Req,但TGS却直接将此Req转到了老总办公室的打印机上打印,这显然不是你想要的。其实这就是安全协议中经常涉及到的双方认证协议。如何设计一种安全协议,使得双方都能在远端彼此信任。Client端在给TGS发送Req时,并不急于将需要服务的内容传送给TGS,而是等待TGS正常解密此消息,并生产KRB_TGS_REP应答消息返回给Client端,让Client端确认TGS为合法服务器。(5)C→AppServ:当客户端收到TGS传送来的服务授权票据后,Client端直接将此票据和验证器发送给应用服务器AppServ即可。KRB_APPSERV_REQ={S_Tickets,Authent_infor}Kc,这里的Authent_info消息需要采用会话密钥K(c,s)加密。(6)AppServ→C:应用服务器再次发送确认消息给Client端,告知对方它期待的服务器已收到它的服务请求。此时Client端与应用服务器即实现了可信的双方认证。讲了这么多,若仍然存在对此协议不太清楚的读者可以参考我的csdn博客,里面转载了MIT为了帮助更多的读者很好的理解kerberos协议设计的一篇精彩对话,看完以后相信你会对这个协议的设计有进一步的认识。OK,现在我们来编码设计实现此协议吧。4.Kerberos协议简单编程实现前面设计的加密算法大家应该可以推测出来,采用的肯定是私钥加密算法即对称加密算法,因为协议中涉及到Client和TGS、AppServ共享会话密钥的情形,故采用的是对称加密算法。这里我们采用CBC模式的DES加密算法,为了算法的安全强度性,大家也可以采用triple-des或者AES加密算法。现简要的给出CBC模式下的DES加密算法:voidDES::Des(intmode,unsignedcharinput[],unsignedcharoutput[])//加密函数入口{inti;IPConvert1(input,Xmatrix);//初始转换打乱顺序Left=&Xmatrix[0];//将比特块分为两部分Right=&Xmatrix[32];for(i=1;i=16;i++){//16轮循环BackupRight(RightT,Right);//将明文矩阵后半部分备份if(mode==0)//加密与解密只是用的密钥密钥顺序不一样ProductTransform(Right,SubKey[i-1],R_F);elseif(mode==1)ProductTransform(Right,SubKey[16-i],R_F);//第i-1轮明文的前半部分与F函数的结果做异或运算,其结果为第i轮明文矩阵的//后半部分Xor32(Right,Left,R_F);CopyRtoL(Left,RightT);//将明文矩阵第i-1轮的后半部分复制至第i轮的前半部分}ConnectLeftRight(M_connect,Right,Left);//将两部分比特块合在一起IPConvert2(M_connect,output);//末尾转换还原顺序}voidCKerberos_servDlg::DES_CBC_Encrypt(char*theKey,char*theInputFile,char*theOutputFile,intfsize)//对文件进行加密{unsignedcharin[64],out[64],key[64];//输入64比特明文输出64比特密文unsignedchartOut,ch[8],ck;//tOut用于向输出文件写数据ch数组用于读取每64比特inti,j;//i,j作循环之用to8用于判断数据块有没有8字节,即64比特unsignedlongintblock=0,last=0;//last文件余数block文件整块数unsignedinttheInFilePos=0,theOutFilePos=0;//输入输出文件在内存中的读写指针位置DESa_des;for(i=0;i8;i++){//从8字节的密钥转化为64比特keyck=theKey[i];for(j=7;j-1;j--){key[8*i+j]=ck,ck=1;}}a_des.GetSubKeys(key);//获取16轮迭代的每轮子密钥block=fsize;last=block%8;block/=8;//这里我做了一个处理,将文件大小存放到了密文的前5字节处。//以方便文件的解密操作,将每8字节的块暂存到前4字节中,对8字节取模的余数存//放到第5字节处。节((unsignedlongint*)theOutputFile)[theOutFilePos]=block;theOutFilePos+=4;theOutputFile[theOutFilePos++]=last;SetIV(out);//设置初始向量while(block0){for(i=0;i8;i++)//读取64比特ch[i]=theInputFile[theInFilePos++];for(i=0;i8;i++){//分解64比特位,存储至in数组中ck=ch[i];for(j=7;j-1;j--){in[8*i+j]=ck&1,ck=1;}}Xor_CBC(in,out);//CBCa_des.Des(0,in,out);//按mode模式对in加密或解密处理,其结果保存在out中for(i=0;i8;i++){//解读out,将结果写到输出文件中去tOut=(out[8*i])*128+(out[8*i+1])*64+(out[8*i+2])*32+(out[8*i+3])*16+(out[8*i+4])*8+(out[8*i+5])*4+(out[8*i+6])*2+out[8*i+7];theOutputFile[theOutFilePos++]=tOut;}block--;}if(last!=0){//存在数据块不足64比特for(i=0;ilast;i++)ch[i]=theInputFile[theInFilePos++];for(i=0;ila
本文标题:kerberos安全协议解析与编程实现
链接地址:https://www.777doc.com/doc-3449355 .html