分享

【hadoop大数据安全基础知识】Kerberos安全协议(原理)解析与编程实现

本帖最后由 pig2 于 2015-2-8 00:17 编辑
问题导读

1.Kerberos安全认证协议是由谁来开发的?
2.客户端用户的用户名及口令存储在什么位置?
3.Kerberos双向认证包含哪些过程?
4.Kerberos协议如何编程实现?





1.引言
       看了好几期的黑防,发现谈论安全协议的文章很少,基本上都是一些HOOK各种API或者底层驱动方面的技术文章。下面我向大家介绍一种安全认证协议—kerberos安全协议的基本原理,并通过编程实现向大家展示如何借助编码设计,简单实现此协议。本文的读者可以是信息安全科班出身的学生但又未涉及到kerberos或者对安全协议感兴趣的任何读者,只要具有一定的安全编程知识即可。
其实安全协议的研究很早就存在,只是以前国内的研究者比较少,国内也没有开设信息安全专业的相关课程,如密码学等课程。直到网络信息高速发展的今天,大量的信息非法盗取、恶意篡改、木马、病毒像幽灵般穿梭在网络中时,大家才开始紧密的关注网络安全技术领域,各大高校也都开始纷纷设立信息安全专业。伟大的信息通信专家Shannon发表《保密系统的信息理论》文章开始,基本上就掀起了信息通信保密学的研究热潮。OK,不多说了,直接切入正题。

2. Kerberos安全认证协议基本框架
       Kerberos安全认证协议是由MIT的Athena计划的认证服务而开发的,并广泛的应用于开放式的网络环境中,为通信的双方提供很好的双向认证服务,在客户与服务器之间构筑了一个安全桥梁,要求用户对每个向服务器提交的服务请求及其权限,必须预先经过第三方认证中心服务器的认证后,才被允许执行。换句话说,kerberos的整体设计方案是完全基于协议的可信任第三方认证服务的,客户和服务器均信任Kerberos认证服务器的认证。好了,现在我们来揭开它的基本原理:
       一个Kerberos环境包含一个Kerberos服务器、若个客户端以及一些应用服务器。Kerberos服务器将客户端用户的用户名及口令均存放在它的数据库中。应用服务器和所有的客户都必须在初始化阶段到Kerberos服务器中注册。基本框架如图1所示:

1.png


图 1 kerberos安全认证协议基本结构


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的私钥加密。这部分其实在Kerberos V5的版本已经作了修改,因为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博客http://blog.csdn.net/shanndyw,里面转载了MIT为了帮助更多的读者很好的理解kerberos协议设计的一篇精彩对话,看完以后相信你会对这个协议的设计有进一步的认识。OK,现在我们来编码设计实现此协议吧。

4.Kerberos协议简单编程实现
前面设计的加密算法大家应该可以推测出来,采用的肯定是私钥加密算法即对称加密算法,因为协议中涉及到Client和TGS、AppServ共享会话密钥的情形,故采用的是对称加密算法。这里我们采用CBC模式的DES加密算法,为了算法的安全强度性,大家也可以采用triple-des或者AES加密算法。
现简要的给出CBC模式下的DES加密算法:
  1. void DES::Des(int mode, unsigned char input[], unsigned char output[])//加密函数入口
  2. {
  3. int i;
  4. IPConvert1(input,Xmatrix);//初始转换 打乱顺序
  5. Left=&Xmatrix[0];//将比特块分为两部分
  6. Right=&Xmatrix[32];
  7. for(i=1;i<=16;i++) {//16轮循环
  8.        BackupRight(RightT,Right);//将明文矩阵后半部分备份
  9.        if(mode==0)//加密与解密只是用的密钥密钥顺序不一样
  10.               ProductTransform(Right,SubKey[i-1],R_F);
  11.        else if(mode==1)  ProductTransform(Right,SubKey[16-i],R_F);
  12. //第i-1轮明文的前半部分与F函数的结果做异或运算,其结果为第i轮明文矩阵的//后半部分
  13.        Xor32(Right,Left,R_F);
  14.        CopyRtoL(Left,RightT);//将明文矩阵第i-1轮的后半部分复制至第i轮的前半部分
  15. }
  16. ConnectLeftRight(M_connect,Right,Left);//将两部分比特块合在一起
  17. IPConvert2(M_connect,output);//末尾转换 还原顺序
  18. }
  19. void CKerberos_servDlg::DES_CBC_Encrypt(char *theKey,char *theInputFile,
  20. char *theOutputFile, int fsize)  //对文件进行加密
  21. {
  22. unsigned char in[64],out[64],key[64]; //输入64比特明文 输出64比特密文  unsigned char tOut,ch[8],ck; //tOut用于向输出文件写数据 ch数组用于读取每64比特
  23. int i,j; //i,j作循环之用 to8用于判断数据块有没有8字节,即64比特
  24. unsigned long int block=0,last=0; //last文件余数 block文件整块数
  25. unsigned int theInFilePos=0,theOutFilePos=0; //输入输出文件在内存中的读写指针位置
  26. DES a_des;
  27. for(i=0;i<8;i++) {//从8字节的密钥转化为64比特key
  28.        ck=theKey[i];
  29.        for(j=7;j>-1;j--){
  30.               key[8*i+j]=ck,ck>>=1;
  31.        }
  32. }
  33. a_des.GetSubKeys(key); //获取16轮迭代的每轮子密钥
  34. block = fsize;
  35. last = block % 8;
  36. block /= 8;
  37. //这里我做了一个处理,将文件大小存放到了密文的前5字节处。
  38. //以方便文件的解密操作,将每8字节的块暂存到前4字节中,对8字节取模的余数存//放到第5字节处。节
  39. ((unsigned long int*)theOutputFile)[theOutFilePos]=block; theOutFilePos+=4;
  40. theOutputFile[theOutFilePos++]=last;
  41. SetIV(out);//设置初始向量
  42. while(block>0){
  43.        for(i=0;i<8;i++)//读取64比特
  44.        ch[i]=theInputFile[theInFilePos++];
  45.        for(i=0;i<8;i++){//分解64比特位,存储至in数组中
  46.               ck=ch[i];
  47.               for(j=7;j>-1;j--){
  48.                      in[8*i+j]=ck&1,ck>>=1;
  49.               }
  50.        }
  51.        Xor_CBC(in,out); //CBC
  52.        a_des.Des(0, in, out);//按mode模式对in加密或解密处理,其结果保存在out中
  53.        for(i=0;i<8;i++){//解读out,将结果写到输出文件中去
  54.                      tOut=(out[8*i])*128+(out[8*i+1])*64+(out[8*i+2])*32+(out[8*i+3])*16+
  55. (out[8*i+4])*8+(out[8*i+5])*4+(out[8*i+6])*2+out[8*i+7];
  56.               theOutputFile[theOutFilePos++]=tOut;
  57.        }
  58.        block--;
  59. }
  60. if(last!=0) {//存在数据块不足64比特
  61.        for(i=0;i<last;i++)
  62.        ch[i]=theInputFile[theInFilePos++];
  63.        for(i=0;i<last;i++){
  64.               ck=ch[i];
  65.               for(j=7;j>-1;j--){
  66.                      in[8*i+j]=ck&1,ck>>=1;
  67.               }
  68.        }
  69.        Xor_CBC(in,out);
  70.        a_des.Des(0,in,out);
  71.        for(i=0;i<8;i++){
  72.           tOut=(out[8*i])*128+(out[8*i+1])*64+(out[8*i+2])*32+(out[8*i+3])*16+
  73. (out[8*i+4])*8+(out[8*i+5])*4+(out[8*i+6])*2+out[8*i+7];
  74.           theOutputFile[theOutFilePos++]=tOut;
  75.        }
  76. }}
复制代码

对DES的更深入理解可以参考本文附的基于CBC模式的DES加密算法C语言实现版本,这里就不再多说了。要编程实现Kerberos协议,肯定要设计到socket编程了,我们可以采用面向连接的TCP协议实现。
(1)首先Client端构造KRB_AS_REQ消息发送给AS端。
  1. void CKerberos_clientDlg::OnSendReqToAS()
  2. {
  3.        char req_buf[50] = {0};
  4.        char dest_addr[] = "127.0.0.1";
  5.        short port = 6000;
  6.        SYSTEMTIME sys_time; // 变量声明
  7.        GetSystemTime(&sys_time); // 取得现在的日期时间
  8.        sprintf(req_buf, "Name:kevin\\Tgs:mailServ\\Req:AS");
  9.        sendMsgToAs(req_buf, dest_addr, port);
  10. }
复制代码

(2)AS解析发送的Req消息,访问数据库查阅Client注册时提供的私钥和Client请求的TGS的私钥,最后构造KRB_AS_REP消息。这里我们采用V5版本的说明,不再对Ktgs加密后生成的票据授权票据再次实施加密。编程实现上,我采用先将Tickets_Tgs和{k(c,tgs),tgs,TS2,lifetime}Kc密文写入本地文件,然后再通过TCP协议发送到Client端。相关代码如下:
  1. void CKerberos_servDlg::Translate_Msg(char *recv_buf, char *client_addr)
  2. {
  3.      char *p, *q, temp[10]={0};
  4.      char keys_client_tgs[300], tickets[300];
  5.      char clientName[30], tgs[30];
  6.      p = strstr(recv_buf, "Req:");
  7.      strcpy(temp, p+4);
  8.      if(!strcmp(temp, "AS")) {
  9.             //***获取客户端用户名********//
  10.             memset(temp, 0, sizeof(temp));
  11.             p = strstr(recv_buf, "Name:");
  12.             q = strstr(recv_buf, "Tgs:");
  13.             strncpy(temp, p+5, q-p-6);
  14.             memset(clientName, 0, sizeof(clientName));
  15.             strcpy(clientName, temp);
  16.             //*******获取Tgs服务器**********//
  17.             memset(temp, 0, sizeof(temp));
  18.             p = strstr(recv_buf, "Tgs:");
  19.             q = strstr(recv_buf, "Req:");
  20.             strncpy(temp, p+4, q-p-5);
  21.             memset(tgs, 0, sizeof(tgs));
  22.             strcpy(tgs, temp);
  23.             //*******访问数据库查询Client私钥和TGS私钥**********//
  24.             char Kc[9] = "12345678";  //客户端用户在AS服务器登记的密钥
  25.             char Key_Tgs[9] = "23456789"; //TGS服务器在AS服务器登记的密钥
  26.    
  27.             //****构造随机密钥(Client和TGS共享的会话密钥)********//
  28.             srand(GetTickCount());
  29.             char keys_client_tgs[8] = {0};
  30.             char buf[2];
  31.             for(int i=0;i<8;i++){
  32.                    memset(buf, 0, sizeof(buf));
  33.                    sprintf(buf, "%d", rand() % 10);
  34.                    strcat(keys_client_tgs, buf);
  35.             }
  36.             SYSTEMTIME sys_time; // 变量声明
  37.             GetSystemTime(&sys_time); // 取得现在的日期时间
  38.             char time_stamp[30] = {0};
  39.             sprintf(time_stamp, "%4d-%2d-%2d %2d:%2d:%2d", sys_time.wYear,
  40. sys_time.wMonth,sys_time.wDay,sys_time.wHour,
  41. sys_time.wMinute,sys_time.wSecond);
  42.             unsigned int lifetime = 240;  //定义有效期为4小时
  43.             memset(tickets, 0, sizeof(tickets));
  44.             sprintf(tickets, "K(c,tgs):%s\\C:%s\\AD(c):%s\\tgs:%s\\TS:%s\\lifeTime:%d",
  45.                    keys_client_tgs, clientName, client_addr,tgs, time_stamp, lifetime);
  46.             int Tgs_ticket_len = strlen(tickets);
  47.             char *Tickets_Tgs = new char[Tgs_ticket_len+5]; //多申请5字节存放明文文件大小
  48.             memset(Tickets_Tgs, 0, sizeof(Tickets_Tgs));
  49.             ((unsigned int*)Tickets_Tgs)[0] = Tgs_ticket_len; //前4个字节标定文件的大小
  50.             //调用CBC模式的DES加密算法,加密文件使其成为一个票据授权票据
  51.             DES_CBC_Encrypt(Key_Tgs, tickets, Tickets_Tgs, Tgs_ticket_len);
  52.            
  53.             //构造{k(c,tgs),tgs,TS2,lifetime}消息,并用Kc私钥加密
  54.             char AS_Rep_P[300];
  55.             sprintf(AS_Rep_P, "K(c,tgs):%s\\tgs:%s\\TS:%s\\lifetime:%d",
  56.                    keys_client_tgs, tgs, time_stamp, lifetime);
  57.             int AStoClient_len = strlen(AS_Rep_P);
  58.             char *AS_Rep_S = new char[AStoClient_len+5];
  59.             memset(AS_Rep_S, 0, sizeof(AS_Rep_S));
  60.             ((unsigned int*)AS_Rep_S)[0] = AStoClient_len;
  61.             DES_CBC_Encrypt(Kc, AS_Rep_P, AS_Rep_S, AStoClient_len);
  62.             //将这些信息写入到本地文件
  63.             FILE *fp = fopen("d:\\AStoClient.txt", "w+");
  64.             if(!fp){
  65.                    printf("open file failure!\n");
  66.                    return;
  67.             }
  68.             fwrite("Client:", sizeof(char), strlen("Client:"), fp);
  69.             fwrite(AS_Rep_S, sizeof(char), AStoClient_len+5, fp);
  70.             fwrite("\r\nTickets:", sizeof(char), strlen("\r\nTickets:"), fp);
  71.             fwrite(Tickets_Tgs, sizeof(char), Tgs_ticket_len+5, fp);
  72.             fwrite("\\Rep:AS", sizeof(char), strlen("Rep:AS"), fp);
  73.             fclose(fp); return;
  74.      }
  75. }
复制代码


构造好如图2所示的消息后,即可向Client端发送此KRB_AS_REP消息了。
2.png

图 2 构造好的KRB_AS_REP消息Client:{k(c,tgs),tgs,TS2,lifetime}kc和Tickets_Tg

注意:这里最好不要使用sprintf、strncpy等函数对密文字符串格式化及拷贝等操作,因为密文字符串中极有可能存在空字符,若存在会导致忽略空格后面的字符,使得发送Client端的密文无法正常解密,进而使得Client端将合法的AS或者TGS认为非法端,而做出放弃再次发出Req的举动。
       OK,现在AS可以将AStoClient.txt文件发送到Client端了。文件之间的发送大家应该会吧,还是采用TCP协议实现,代码如下:
(1)AS端:

  1. FILE *fp = fopen("d:\\AStoClient.txt", "rb");
  2.                  if(!fp){
  3.                        printf("open file failure!\n"); return;
  4.                  }
  5.                  fseek(fp, 0, SEEK_END); //将文件指针移动到末端,获取文件大小
  6.                  unsigned int fsize = ftell(fp);
  7.                  char f_size[4] = {0}; //用于存放文件大小
  8.                  *((unsigned int*)&f_size[0]) = fsize;
  9.                  send(sockClient,f_size,4,0); //首先将文件大小发送到客户端
  10.                  char buff[1024] = {0};
  11.                  fseek(fp, 0, SEEK_SET); //文件指针重新回到文件头位置
  12.                  unsigned int readbytes = 0;
  13.                  while(fsize > 0){
  14.                       readbytes = fread(buff, sizeof(char), 1024, fp); //每次读取1024字节
  15.                       send(sockClient,buff,readbytes,0); //将读取到得字节发送到Client端
  16.                       fsize -= readbytes;
  17.                 }  fclose(fp);
复制代码


(2)Client端://******接收AS服务器发送来的票据授权票据文件**********//

  1. FILE *fp;
  2.             fp = fopen("D:\\mytext.txt", "w+");
  3.             if(!fp){
  4.                    printf("file open failure!\n"); return;
  5.             }
  6.             char f_size[4] = {0},buff[1024] = {0};
  7.             int fsize,  recvbytes;
  8.             recv(sockClient, f_size, 4, 0); //接收文件大小
  9.          fsize = *((int*)&f_size[0]);
  10.             while(fsize>0){ //根据文件大小与每次循环接收到的字节数来判断循环次数
  11.                    recvbytes = recv(sockClient, buff, 1024, 0);
  12. //将接收到的字节写入到Client端的文件中,便于调用Translate_ASMsg()函数进一步解析。
  13.                    if(!fwrite(buff, sizeof(char), recvbytes, fp)){
  14.                           printf("write failed!\n");
  15.                    }
  16.                    fsize -= recvbytes;
  17.             }
  18.             fclose(fp);
  19.             Translate_ASMsg(); //客户端解析AS发送来的票据授权票据消息
复制代码

当文件成功接收后,Client端就可以在本地解析此文件了,将文件中的票据授权票据Tickets_tgs和{k(c,tgs),tgs,TS2,lifetime}kc正确分离出来,并调用DES_CBC_Decrypt()函数解密{k(c,tgs),tgs,TS2,lifetime}kc消息,因为Client在向AS注册时已经和AS共享了自己的私钥Kc。正确解密后,则可在此消息中提取出AS为Client和TGS随机产生的共享会话密钥K(c, tgs),进而构造发往TGS的KRB_TGS_REQ= {AppServ, Tickets_Tgs, Authen_info}消息。相关代码如下:



  1.   FILE *fp;
  2.        fp = fopen("D:\\AStoClient.txt", "rb");
  3.        if(!fp){
  4.               printf("file open failure!\n"); return;
  5.        }
  6.        //*****提取AS发给client端的加密消息********
  7.        char line[300] = {0};
  8.        fgets(line, 300, fp);
  9.        if(strstr(line,"Client:")){
  10.               memset(line, 0, sizeof(line));
  11.               fseek(fp, strlen("Client:"), SEEK_SET);
  12.               fgets(line, 300, fp);
  13.        }
  14.        char Kc[9] = "12345678";  //客户端用户在AS服务器登记的密钥
  15.        //从密文中提取出加密前的明文大小含8字节的块数,这就是为何在加密前需要对密文//数组多申请5个字节空间的缘由,方便后面的解密操作,当然这也必须是加密双方协
  16. //商后的结果,否则解密方不知道你所做的处理。
  17.        int block = ((unsigned int *)line)[0];
  18.        int last = line[4]; //文件大小对8字节取余的结果
  19.        int fsize = block * 8 + last; //计算出文件大小
  20.        char *ASToC_Plain = new char[fsize];
  21.        memset(ASToC_Plain, 0, sizeof(ASToC_Plain));
  22.        //调用CBC模式的DES加密算法解密{K(c,tgs), tgs, TS2, lifetime}
  23.        DES_CBC_Decrypt(Kc, line, ASToC_Plain);
  24.       
  25.        //*****从client端的加密消息中提取tgs和客户端共享的密钥k(c,tgs)******//
  26.        char *p, *q;
  27.        char key_c_tgs[9] = {0};
  28.        p = strstr(ASToC_Plain, "K(c,tgs):");
  29.        q = strstr(       ASToC_Plain, "tgs:");
  30.        memcpy(key_c_tgs, p+9, q-p-10);
  31.       
  32.        //******构造验证器消息{c,ADc,TS3}K(c,tgs)**********//
  33.        SYSTEMTIME sys_time; // 变量声明
  34.        GetSystemTime(&sys_time); // 取得现在的日期时间
  35.        char time_stamp[30] = {0};
  36.        sprintf(time_stamp, "%4d-%2d-%2d %2d:%2d:%2d", sys_time.wYear,sys_time.wMonth,
  37.               sys_time.wDay,sys_time.wHour,sys_time.wMinute,sys_time.wSecond);
  38.        char Authen_info[100];
  39.        memset(Authen_info, 0, sizeof(Authen_info));
  40.        sprintf(Authen_info, "Name:kevin\\c_ip:127.0.0.1\\TS:%s", time_stamp);
  41.        int Authen_info_len = strlen(Authen_info);
  42.        char *Authen_info_S = new char[Authen_info_len+5];
  43.        memset(Authen_info_S, 0, sizeof(Authen_info_S));
  44.        ((unsigned int*)Authen_info_S)[0] = Authen_info_len;
  45.        //采用密钥K(c,tgs)加密验证器消息
  46.        DES_CBC_Encrypt(key_c_tgs, Authen_info, Authen_info_S, Authen_info_len);
  47.        //*****提取AS发给Client端的票据授权票据********
  48.        memset(line, 0, sizeof(line));
  49.        fgets(line, 300, fp);
  50.        if(strstr(line,"Tickets:")){
  51.               memset(line, 0, sizeof(line));
  52.               fseek(fp, strlen("Tickets:"), SEEK_CUR);
  53.               fgets(line, 300, fp);
  54.        }
  55.       
  56.        char tgs_tickets[300] = {0};
  57.        memcpy(tgs_tickets, line, strlen(line)-7); //获得票据
  58.        fclose(fp);
  59.        fp = fopen("D:\\CToTgs.txt", "w+");
  60.        if(!fp){
  61.               MessageBox("file open failure!\n");
  62.               return;
  63.        }
  64.        fwrite("AppServ:FTPServ", sizeof(char), strlen("AppServ:FTPServ"), fp);
  65.        fwrite("\r\nTickets:", sizeof(char), strlen("\r\nTickets:"), fp);
  66.        fwrite(tgs_tickets, sizeof(char), strlen(tgs_tickets), fp);
  67.        fwrite("\r\nAuthen_info:", sizeof(char), strlen("\r\nAuthen_info:"), fp);
  68. fwrite(Authen_info_S, sizeof(char), Authen_info_len+5, fp);
  69.        fclose(fp);
复制代码



       接下来大家应该知道如何操作了,就是将文件发送给TGS。TGS接收到消息后解析出Tickets_tgs,然后采用自己的私钥Ktgs解密此票据,判断是否为合法Client的请求,以便进一步处理。OK,关键的部分全部分析完了,相信大家应该知道如何实现了吧,一定要动手自己编写代码试试咯。


5 小结
       本文分析了Kerberos安全认证协议的基本原理,并通过简单编程实现了此协议,给出了编程过程中需要注意的部分及核心代码说明。


hbase_kerberos_权限认证配置.zip (15.15 KB, 下载次数: 6, 售价: 5 云币)

已有(2)人评论

跳转到指定楼层
pengsuyun 发表于 2015-2-8 09:14:58
回复

使用道具 举报

zhujun182104906 发表于 2015-2-12 09:39:41
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

推荐上一条 /2 下一条