Kerberos 是一种身份认证协议。
对于A要访问B:
一般的认证只需要B确保A不是假冒。
而在Kerberos中,不但要保证上面的问题,还要A确保B也不是假冒的
要保证在不告诉对方自己的密码的前提下,还要让对方知道自己有密码(向对方证明自己)
首先,A使用一个hash函数把自己的密码加密成一把密钥--Kclt(由A的密码加密而来)
A使用上面生成的密钥Kclt来加密时间戳,得到{timestamp}Kclt
A给KDC发送的AS_REQ包括以下数据
AS_REQ = {timestamp}Kclt, A的信息,一个随机的字符串 图中1
后面的字符串是为了让A能够认证KDC,加密时间戳可以防止重放攻击。
KDC收到AS_REQ之后,用从AS_REQ中读到A的信息,那么就可以调出A的密码,
然后用与A同样的方式(用同样的hash函数加密A的密码),这样KDC也得到了与A相同的Kclt,
然后用这个Kclt解密{timestamp}Kclt, 如果能解开,说明对方是A,也就完成了KDC对A的认证,
此时完成了KDC对A的认证。
其实可以把AS_REQ中的随机字符串用Kclt加密(真正发给A的AS_REP不是这个),然后发给A,如果A能解开,就能完成A对KDC的认证,但是由于每次认证都需要KDC从AS_REQ中取出A的信息,然后调出A的密码,所以对KDC的资源消耗比较大,为了解决这个问题,Kerberos采用如下方法:
首先,KDC直接生成两把用于以后A与KDC相互认证使用的密钥Kclt-Kdc,然后把其中一把交给A,另一把应该是自己的,但是也交给了A来保管(减轻了KDC存储密钥的负担),
但是自己的密钥不能就这么直接交给A,有可能有个假的客户端发送过来一个假的密钥,所以KDC要能辨别出这把密码确实是自己交给A保管的那把,所以KDC用自己的密码hash成的Kkdc来加密交给A保管的密钥(注意这里的密码是KDC自己的密码,而不是上文生成Kclt时使用的A的密码),当密钥还回来时,如果这个密钥真的是自己交给A保管的,那么用Kkdc肯定能够解开,解不开,说时是假的。(这里说的是KDC自己的但是交给A保管的密钥,还有一把是真正属于A的)
KDC用Kkdc加密的不仅有自己交给别人保管的密钥,还有对方的信息,总共叫做TGT
TGT = {对方的信息,Kclt-Kdc}Kkdc,
所以回复给A的内容AS_REP有如下内容
AS_REP = TGT, {Kclt-kdc, timestamp, 随机字符串}Kclt 图中2
TGT是交给A保管的,A不用对它进行任意解密操作,只要需要时把它交回KDC就好了。
后面用Kclt进行加密的内容,上文说了Kclt是A的密码hash出来的,所以只有A能解开,
解开之后,通过随机字符串就可以判断KDC的身份(即完成了A对KDC的认证)
Kclt-kdc:是KDC与A以后认证要使用的密钥,这是那把属于A的密钥,而TGT里边的是KDC自己的,只是暂时交给A来保管(共两把)
至此:A与KDC的相互认证完成,此时完成了图中的1,2
那么肯定得告诉KDC你要认证谁,也就是B的信息要发给KDC,
别人的东西也要还回去,也就是KDC暂时交给A保管的TGT也要发回给KDC,还有一些用于A与KDC相互认证的信息(可不是经过了上面一次认证就完事了的,每次A与KDC通信都要证明自己的身份,所以KDC比较忙,才使用了TGT),
所以A发给KDC的信息TGS_REQ有如下部分:
TGS_REQ = TGT, B的信息, {A的信息,timestamp}Kclt-Kdc 图中3
TGS_REQ的信息有要还给KDC的TGT, A要认证的B的信息,以及要证明自己身份的信息(使用的是Kclt-Kdc也就是KDC与A间的密钥来进行加密了),此时KDC是还没有这把密钥的,因为KDC的密钥是在TGT里边,还没发给KDC;
当KDC收到TGS_REQ之后,用自己的Kkdc把TGT进行解密(TGT是KDC用自己的Kkdc加密的),得到密钥Kdlt-Kdc,然后就能解密后面的 {A的信息,timestamp}Kclt-Kdc,就可以认证A的身份了。
此时KDC会生成两把A与B间认证使用的密钥Kclt-srv(上文中的Kclt-kdc是A与KDC间相互认证使用的),一把是A的,另一把是B的,但是B的那把由A转交给B,与上面A暂时存放KDC的密钥Kclt-kdc时的操作一样,属于B的那把密钥要用B的密码hash成的Ksrv来对属于B的那把密钥进行加密,叫做Ticket(要发给B的)
Ticket = {A的信息,Kclt-srv}Ksrv 用Ksrv来加密,只有B能解开,里边存放了A、B间相互认证使用的密钥
KDC发给A的回复信息包括
TGS_REP = {Kclt-srv}Kclt-kdc, Ticket 图中4
其中包含要转交给B的Ticket,
还有属于A的那把用于A与B认证的密钥(用A与KDC间的密钥Kclt-kdc加密,因为这是KDC与A之间交换的数据)
A收到TGS_REP之后,就有了一把与B之间相互认证的密钥:Kclt-srv, 还有要交给B的Ticket,
此时B是没有用于与A相互认证的密钥的,还在Ticket中(未发送)。
AP_REQ : A给B发送 {A信息,timestamp}Kclt-srv, Ticket 图中5
B收到这个Ticket,用自己的Ksrv解开得到与A间认证的密钥Kclt-srv, 然后用这把密钥解开 {A信息,timestamp}Kclt-srv,
来完成对A的身份的认证
AP_REP : B向A证明自己的身份,AP_REP = {timestamp}Kclt-srv, 图中6
如果A能解开,说明B是真的,其他人不可能有这把密钥(Kclt-srv)
Reference : 《Wirshark 网络分析就这么简单》 林沛满