1. scram-sha1 鉴权机制说明
1.2. 鉴权交互流程
1.2.1. 初始化
-
服务端使用一个salt和一个iteration-count,对password进行加盐哈希(使用H表示哈希函数,这里就是SHA1,iteration-count就是哈希迭代次数),得到一个password[s]:
_password[s] = H(password, salt, iteration-count)_
-
服务端拿这个password[s]分别和字符串『Client Key』和『Server Key』进行计算HMAC摘要,得到一个key[c]和一个key[s]:
_key[c] = HMAC(password[s], "Client Key")_ _key[s] = HMAC(password[s], "Server Key")_
1.2.2. 一次认证
步骤一:
- 客户端发起一个SCRAM鉴权请求; 鉴权参数中带上用户名、客户端随机字符串(防止重放攻击)
步骤二:
- 服务端先检查用户名。
- 通过后生成一个salt因子、迭代数、合并字符串(包含客户端随机串和服务端随机串)。
步骤三:
-
客户端响应一个proof(证明数据)和合并字符串。
-
响应的 proof数据根据服务所给的随机参数以及客户端密钥生成,是一个客户端签名与密钥异或计算后的结果。
_Auth = client-first-message, server-first-message, client-final-message(without proof[c])_ 然后使用从服务端获取的salt和iteration-count,根据已知的password计算出加盐哈希password[s],然后根据password[s]得到key[c],再拿这个key[c]和Auth变量经过如下计算得到: _proof[c] = key[c] XOR HMAC(H(key[c]), Auth)_
步骤四:
-
服务端使用其保存的H(key[c])和Auth计算HMAC摘要,再和proof[c]进行异或,得出key[c],再对这个key[c]进行哈希,和其保存的H(key[c])进行比较是否一致。如果一致,则客户端的认证通过,服务端接下来会构造一个proof[s]用来向客户端证明自己是服务端
_proof[s] = HMAC(key[s], Auth)_
步骤五:
- 客户端使用password[s]得到key[s],然后使用相同算法计算key[s]和Auth的HMAC摘要,验证服务端发送过来的proof[s]是否和计算出来的一致,从而认证服务端的身份。