本文记述一种本打算在项目中实际使用的用户鉴权系统,但是由于过于复杂,初期并不考虑实装,故撰文记述以备后续之用。
类似一种基于时间的 OTP 验证方法,这种方法是前者的一种变体。
正文
在数据库中每个用户有唯一ID、一个AES密钥和一个计数器。客户端通信时通过ID指定用户。每次客户端登陆时服务器分配一个新的AES密钥并将计数器清零;客户端则在登陆时接收并持久化保存AES密钥,同时客户端的计数器置为1
。客户端和服务端的通信需要使用Token作为验证,而AES密钥则用于服务器向客户端签发Token:
- 客户端先利用AES密钥加密当前计数器的值,随后计数器值加1。
- 客户端将当前用户的ID连同密文一同发送给服务器。
- 服务器收到后通过ID寻找对应用户的AES密钥,使用密钥解密密文得到明文。
- 检查明文中的值,与数据库中的计数器对比,若明文的值大于数据库中的值则认为有效,否则无效。
- 若明文有效,则将数据库中的数值修改为明文中的值(同步)。
- 服务器签发Token,返回给客户端
该过程中通过登陆时更换新的AES密钥,及变化的明文内容来达到每次申请Token时所发送的消息都不一样,同时还能够防止重放攻击。而加密使用的AES密钥只在成功登陆时传输一次,下次登陆时旧的密钥就自动失效,能够保证一定安全性。
可用性分析
假设token的有效期为5分钟,则每五分钟客户端请求一次token,每10次才成功获得一个token,则一个小时计数器增加120次。Java中long是64位的,除去负数部分不使用,非负范围是0到 $ 2^{63} - 1 $ ,经过计算,假设客户端不停的每5分钟请求一次token,失败情况如上所述,则需要8774136260326.0804861111111111111
(8万亿)年才能用完一个long变量,因此可以保证这种验证方式的可用性。
【歪门邪道】基于AES加密和OTP的用户鉴权 由 天空 Blond 采用 知识共享 署名 - 非商业性使用 - 相同方式共享 4.0 国际 许可协议进行许可。
本许可协议授权之外的使用权限可以从 https://skyblond.info/about.html 处获得。