我想要一些关于以下身份验证想法的反馈,它是否有意义,是否有这样做的标准方法(或类似方法),所以我可以依赖经过良好测试的实现。
我在这里看到了很多关于如何保护与服务器的通信的答案,大多数答案都是简单地正确使用 TLS。我正在寻找一种允许对消息本身进行加密和签名的解决方案,以便消息在通过后端时保持安全,直到它们到达目标服务。
语境
- 使用 phonegap 构建的适用于 android 2.3+ 和 iOS 6+ 的移动应用程序(因此使用的库应该可以从 Java/obj-c 或 js 中使用)
- 该应用程序使用 REST json api 与服务器通信
- 消息内容在通过后端时应保持机密(代理/负载均衡器没有终止)
- 应该支持“记住我”,所以用户不必一直重新输入他们的密码
- 所有通信都通过 ssl/tls 完成
验证
- 客户端收集用户凭据(用户名、密码和一些额外的安全信息)
- 客户端生成对称密钥
- 客户端使用对称密钥加密凭证
- 客户端使用服务器公钥加密对称密钥(客户端随附)
- 客户端通过 https 发送加密消息、密钥和随机数(验证服务器证书)
- 服务器代理将认证请求转发给认证服务
- 身份验证服务解密对称密钥和消息
- 如果凭据有效,则服务会生成身份验证令牌
- 令牌与服务器上的对称密钥相关联,如果凭据无效,则在回复请求后丢弃该密钥
- 令牌返回给用户,使用对称密钥加密
- 令牌和密钥存储在客户端本地,由短密码加密
我假设如果使用 tls,这些请求不会受到重放攻击,因此攻击者不存在重放消息以获取新令牌的风险。
其他 API 调用
- 客户端生成请求消息,对其进行加密并签署加密消息
- 客户端将加密的消息、随机数和签名及其身份验证令牌发送到服务器
- 在接收时,服务器查找与接收到的令牌关联的密钥,验证签名并在处理之前解密消息
问题
- 重复使用相同的对称密钥有什么问题吗?
- 什么是对称密钥的好选择?
- AES-OCB 或 AES-CBC + HMAC 签名呢?
- 应该多久更改一次对称密钥?
- 更新密钥/刷新令牌的最佳方式是什么?我正在考虑在身份验证响应期间发出刷新令牌并让密钥在特定时间段后过期,因此如果用户不刷新他们的密钥,他们必须再次登录。
谢谢