转载自: Yx.Ac 文章来源: 勇幸|Thinking ( http://www.ahathinking.com ) 。
---
前些日子为了搞清楚Kerberos原理,把 MIT的Kerberos经典对话 看了几遍,终于有了一个稍微清晰的认识,这里稍微记录下,因为Kerberos是使用传统加密技术实现的一个认证机制,所以顺便备忘下关于加密的一些知识概念。本文组织如下:
===关于Kerberos===
===认证授权===
===加密术语===
===单点登录===
===Kerberos术语===
===Kerberos原理===
===经典对话手记===
==============================================================
什么是Kerberos?
一句话,Kerberos是一种认证机制。
它的目的:通过密钥系统为 客户端/服务器应用程序 提供强大的 认证 服务:保护服务器防止错误的用户使用,同时保护它的用户使用正确的服务器,即支持 双向验证 ;
Kerberos协议的整个认证过程实现不依赖于主机操作系统的认证,无需基于主机地址的信任,不要求网络上所有主机的物理安全,并假定网络上传送的数据包可以被任意地读取、修改和插入数据。说白了, Kerberos通过 传统的加密技术 (共享密钥)实现了一种可信任的第三方 认证 服务。
认证授权(Anthentication and Authorization)是系统权限管理经常需要考虑的问题,也是一个很复杂的问题,至少我是这样觉得的。
认证:系统识别某个个体/请求的身份时,称为认证;即辨别身份真伪,解决“ 你是谁 ”的问题。
授权:系统赋予某个个体从事某种行动的权利,叫做授权;即解决“ 你能做什么 ”的问题。
感觉应该说清楚了,认证未必授权,授权必须认证。
上面说过,Kerberos是网络服务的认证机制,使用加密技术实现认证,这里再啰嗦下它们之间的关系。
加密:给数据加密,目的是保护数据,强调的是 安全性
认证:判断身份的真实性,目的是辨真伪,强调的是 真实性
授权:根据不同的身份给予不同的授权;所以认证(authentication)与授权(authorization)往往是相伴而生。
给出几个场景,来理解加密技术的一些术语:A为信息发送方;B为信息接收方
[密钥]:就是一个参数,明文转密文或密文转明文的算法输入数据
[对称加密](又称私钥加密):加密和解密使用同一个密钥(secret key)。常见的是使用用户名密码方式,例如A为服务器,存储了B的用户名密码,A发送一段数据给B前使用B的密码加密,B收到后使用自己的密码解密。
[非对称加密](又称公钥加密):采用公钥和私钥的方式,A和B都各有一对公钥和私钥;注意,公钥和私钥成对出现,一个公钥对应一个私钥。
[公钥]:公开的密钥,可以公开
[私钥]:私有的密钥,只有当事人自己知道
[数字证书]:用来辨别对方身份的,可以简单理解为一个被权威性机构验证过的公钥。
[数字签名]:使用私钥加密的数据叫做数字签名,采用对应的公钥来验证数字签名,从而确认发送方的身份。
公钥私钥的目的:实现信息的安全传输:1)A发送给B,信息传输过程必须加密,防止别人看;2)B收到后能够知道肯定是A发送的,而不是有人冒充A。
怎么实现呢?
场景理解:
1)首先A用B的公钥加密信息,进行发送,这保证了信息不会被别人看到或修改,B收到后使用B的私钥解密,就可以看到A发送的信息了。
2)其次,A用A的私钥给消息加密,B可以用A的公钥解密,因为A的私钥只在A手里,所以这可以确认信息是A发送的。
由此,可以看出【公钥私钥的主要用途】:
1) 公钥加密,对应上述场景中的前半段,重点是 加密 ;实际应用中,公钥常以数字证书的方式出现,为了公钥的安全性和有效性(被权威认证过的)。
2) 私钥加密,即公钥认证,对应上述场景中的后半段,重点是 认证 (认证A身份的真实性);私钥加密的主要用途就是数字签名。
现实的痛点:
上面说了大半天,使用公钥私钥不就可以实现安全通信么,A和B要进行安全的通信,互相使用对方的公钥加密信息,然后使用私钥解密不就好了。实际情况是,有时候不一定双方都有公私钥对;更为重要的是,使用公私钥很费时间,很慢,影响通信体验。SSL应运而生。
[SSL](security sockets layer):实际应用中实现安全通信。
简单理解: SSL就是使用公私钥约定会话密钥,然后使用会话密钥和对称加密算法 (例如DES)进行通信。
[会话密钥]:A要和B实现安全通信,A使用B的公钥加密一个密钥C发给B,B拿到后用私钥解密后得到密钥C,以后A和B之间传输的信息都使用约定的密钥C来加密,这个只有约定双方知道的密钥C叫做会话密钥(session key),其中约定会话密钥的过程叫做握手。
SSO(single sign on):单点登录。多系统共存的情况下,用户一次登录得到其他所有系统的信任;
单点登录到处可见,平时在公司上班,公司有多个内部系统,如果每个系统都要输入用户名密码真的是很崩溃的一件事情,登录一次就可以访问所有的系统,这就是单点登录;例如淘宝和天猫是两个不同的系统,你上淘宝买东西,买好又去天猫买,这个时候就不需要再重新登录,即单点登录。
SSO比较经典的解决方案是CAS(central authentication service):中央认证服务。
CAS的原理和工作流程基本都是参考Kerberos票据的原理,所以也不用去研究CAS原理,直接搞懂Kerberos原理,CAS原理也就通了。
KDC(key distribution center):密钥发放中心
AS(authentication service):认证服务,索取credential,发放 TGT
TGS(ticket granting service):票据授权服务,索取TGT,发放ST
ST(service ticket):服务票据,由KDC的TGS发放,任何一个应用(application)都需要一张有效的服务票据才能访问;如果能正确接受ST,说明client和server之间的信任关系已经被建立,通常为一张数字加密的证书。
TGT(ticket granting ticket):票据授权票据,由KDC的AS发放;获得这样一张票据后,以后申请其他应用的服务票据(ST)时,就不需要向KDC提交身份认证信息(credential),TGT具有一定的有效期,就像是kerberos进行kinit以后只是具有固定时间的有效期,需要不断的去renew来续约。
上面几个术语简单说下它们的关系:KDC由AS和TGS组成,AS进行身份认证发放TGT,TGT是用来避免多次请求而需要重复认证的凭证;TGS发放ST,ST用来访问某个service时的凭证,ST相当于告诉service你的身份被KDC认证为合法的一个凭证。可以参考Kerberos原理中所画的图来理解这些术语。
Authenticator:验证器,与票据结合用来证明提交票据的user就是其所声明的身份,内容包括{user, address, start_time, lifetime},这些内容使用user和service之间的session key加密;验证器是user客户端自己构建,只能“被使用一次”。
既然认证就是辨别身份,那我输入用户名密码不就好了,为何要有Kerberos这样一个复杂的东西;
举例来说,有A,B,C三个服务器,分别提供不同的服务,user要访问ABC都需要输入用户名密码,但是ABC没必要都存一份user的密码,所以就衍生出一个中央服务器D来专门存储用户名密码;如果user通过了D的认证,那就是合法的身份,就可以使用ABC任何一个服务,所以user需要告诉ABC它通过了D的认证。
如何证明这个事情,以及信息在网络传输过程如何防止被截获篡改而假冒等等,解决这些问题就靠Kerberos,强烈推荐阅读MIT经典对话,可以理解协议中每条信息有什么字段,为何要设置这个字段等。
这个部分简单总结下Kerberos协议的认证流程,只有几步,详细的请参见 [经典对话手记] 来细致理解。
1. User向KDC中的AS请求身份验证,AS为user和TGS生成一个session key:SK_TGS,并发送{ TGT, SK_TGS } K_USER;
其中,{TGT, SK_TGS}K_USER表示使用user的密码加密的packet,包含了TGT和用户与TGS的session key;这个请求验证的过程实际上是使用kinit来完成的,kinit将username传给AS,AS查找username的密码,将TGT和SK_TGS使用用户密码加密后发送给kinit,kinit要求用户输入密码,解密后得到TGT和SK;其中,TGT使用TGS的密码加密,信息内容为{ user, address, tgs_name, start_time, lisftime, SK_TGS} K_TGS
2. User向KDC中的TGS请求访问某个Service的ST,发送[ TGT, Authenticator ];
其中,Authenticator用于验证发送该请求的user就是TGT中所声明的user,内容为:{ user, addresss, start_time, lifetime};Authenticator使用的TGS和user之间的session key加密的,防止TGT被盗。TGS先使用自己的密码解开TGT获得它与user之间的session key,然后使用session key解密Authenticator,验证用户和有效期。
3. TGS判断无误后,为user和Service之间生成一个新的session key:SK_Service;然后发送给user一个包:[ {SK_Service} SK_TGS, ST ];
其中,ST是使用Service的密码加密的,SK_Service使用TGS和user之间的session key加密的;ST的内容为:{ user, address, start_time, lifetime, SK_Service } K_Service
4. User使用与TGS之间的会话秘钥解开包得到与Service之间的会话秘钥SK_Service,然后使用SK_Service生成一个Authenticator,向Service发送[ ST, Authenticator ];
其中,此处的Authenticator是使用user和service之间的会话秘钥加密的,Service收到包后先使用自己的密码解密ST,或者会话秘钥SK_Service,然后使用SK_Service解密Authenticator来验证发送请求的用户就是票中所声明的用户。
5. Service向用户发送一个包以证明自己的身份,这个包使用SK_Service加密 。
此后user与Service之间使用SK_Service进行通信,且在TGT有效期内,user直接跳过第一步直接从第二步使用TGT向TGS证明自己的身份。注意:user client会等待service server发送确认信息,如果不是正确的service server,就无法解开ST,也就无法获得会话秘钥,从而避免用户使用错误的服务器。
个人理解要点 :
至于为何要使用Session key,为何要使用Authenticator,原因还是去读一下经典对话吧,看看它们是如何被一步步设计出来的。
说到这里,其实上面的流程图也就是 CAS的原理 :
用户访问某个应用程序,应用服务器接收请求后检查ST和TGT,如果都有则用户正常进行访问;如果没有或者不对(如图,步骤1),转到CAS认证服务器的登录页面,通过安全认证后得到相应应用的TGT(步骤2-3)和该应用的ST(步骤4-5),再重定向到相关的应用服务器(步骤6),如果在会话周期内再定向到别的应用(步骤7),将出示TGT和该应用的ST(如果没有,就直接通过步骤4-5得到该应用的ST,即步骤8)进行认证。
------------------------------------------
这里引用参考文献的一个小场景,觉得作者写的非常好,拿来很助于理解:
用户要去游乐场,首先要在门口检查用户的身份(即 CHECK 用户的 ID 和 PASS), 如果用户通过验证,游乐场的门卫 (AS) 即提供给用户一张门卡 (TGT)。
这张卡片的用处就是告诉游乐场的各个场所,用户是通过正门进来,而不是后门偷爬进来的,并且也是获取进入场所一把钥匙。
现在用户有张卡,但是这对用户来不重要,因为用户来游乐场不是为了拿这张卡的而是为了游览游乐项目,这时用户摩天楼,并想游玩。
这时摩天轮的服务员 (client) 拦下用户,向用户要求摩天轮的 (ST) 票据,用户说用户只有一个门卡 (TGT), 那用户只要把 TGT 放在一旁的票据授权机 (TGS) 上刷一下。
票据授权机 (TGS) 就根据用户现在所在的摩天轮,给用户一张摩天轮的票据 (ST), 这样用户有了摩天轮的票据,现在用户可以畅通无阻的进入摩天轮里游玩了。
当然如果用户玩完摩天轮后,想去游乐园的咖啡厅休息下,那用户一样只要带着那张门卡 (TGT). 到相应的咖啡厅的票据授权机 (TGS) 刷一下,得到咖啡厅的票据 (ST) 就可以进入咖啡厅
当用户离开游乐场后,想用这张 TGT 去刷打的回家的费用,对不起,用户的 TGT 已经过期了,在用户离开游乐场那刻开始,用户的 TGT 就已经销毁了。