如何在移动应用上实现“记住我”?

信息安全 应用安全 密码 移动的 密码管理
2021-09-08 03:54:12

我想在移动应用程序(Android 上)上实现“记住我”限时自动登录类型功能。要启动应用程序,用户必须输入用户名和密码。为了方便,

编辑

我想将最后输入的用户名和/或密码保存到手机上的文件中,以避免用户每次都重新输入。

我看了这个,但它似乎更面向浏览器..

问题:

  • 我将如何加密文件或密码?我不能只使用硬编码的密钥来加密它,可以吗?我必须以某种方式生成密钥。但是,如果用户退出并重新启动——我假设会生成一个单独的密钥——所以我必须以某种方式保存密钥?
  • 我应该打扰加密吗?(我想我应该,但是无论如何只有用户可以访问这个文件......)

编辑 2

我是否使用代理密钥和/或使用 ssl/tsl 的公钥身份验证使这些事情过于复杂?我的意思是,Firefox 会保存我的密码,而且它们肯定是以某种方式加密的吗?我正在考虑以类似的方式加密用户/通行证?这是个坏主意吗?

4个回答

我喜欢 symcbean 的建议,即在登录时创建一个与帐户相关的随机映射值,与用户名和密码分开。不过,要具体回答您的问题,还有一些方法可以在没有静态映射密钥的情况下加密数据。我会考虑使用手机独有的信息位生成密钥,并可通过 OS API 调用进行检索。

编辑:在@DW 的要求下,我将详细说明:UDID、序列号和其他识别信息可能具有足够的加密质量和保密性,无需访问手机以防止存储数据的解密。然而,访问存储的数据也意味着可能访问手机。因此,通过设备本地加密的任何级别的安全性都是简单的晦涩难懂。

其他受访者建议存储一个随机值,就像在 HTTP 会话中所做的那样。原来的提问者似乎没有使用 HTTP,并且不相信这种方法适用于他的软件。然而,存储和传输随机值的逻辑实现适用于任何传输协议。我强烈建议。

或者,可以使用公钥加密将凭据存储在手机上。应用程序可以在输入时使用服务器的公钥对用户名和密码进行加密。因此,即使设备遭到入侵,登录数据也将无法读取。

如果目标是防止检索登录凭据,我觉得最好使用随机时间标识符。这排除了将服务器数据(私钥)保密和可用的任何问题。如果该密钥被泄露,则保护将微乎其微,甚至毫无用处。如果丢失,则必须使用新的密钥重新部署应用程序。如果临时登录数据丢失,每个人都将被迫登录,但这不会导致任何明显的服务中断。

此外,对初始登录和任何其他可能的身份验证数据(无论是用户名和密码还是随机值)都使用传输的公钥加密(SSL 或嵌入到应用程序中的简单 PGP 密钥)。

不要将用户名和密码存储在手机上。

相反,我建议您遵循以下两种策略之一:

  • 使用持久性 cookie。 这是简单的解决方案。如果您要连接到网站,请让服务器在用户第一次登录时对其进行身份验证,然后在用户手机上设置一个永久 cookie,其中包含与用户帐户关联的(加密的)随机 128 位字符串。用户随后每次启动应用程序时,当它通过 HTTP/HTTPS 联系服务器时,客户端将发送其持久 cookie,服务器可以使用该 cookie 来验证客户端。理想情况下,您会使用 HTTPS 并使用安全 cookie。

  • 使用公钥认证。 这是更棘手的解决方案。您可以让电话应用程序生成自己的公钥/私钥对。当用户第一次登录时,应用程序可以发送公钥,服务器可以将公钥与该帐户相关联。以后每次用户启动应用程序时,应用程序都可以使用私钥向服务器验证自己。

    • 例如,如果您使用 Web 技术,您可能让客户端生成一个自签名证书,使用 HTTPS 连接到服务器,并使用其客户端证书进行身份验证。您必须测试 Android 上的 Web 视图是否支持客户端证书。

    • 或者,如果您使用自己的自定义协议连接到服务器,则通过 SSL 或 TLS 建立隧道,并使用 SSL/TLS 的客户端证书功能。

不要使用令牌的用户名/密码!

如果可以解密,则存在被解密的风险。即使大多数人知道他们不应该这样做,但他们对多项服务使用相同的密码 - 因此,即使您的服务不是特别有价值,您也有责任保护给您的任何密码。

解决问题的方法与管理 HTTP 会话相同 - 使用代理标识符(可能与会话 cookie 具有相同的值 - 但寿命更长)然后维护代理标识符的查找表,即用户发给和到期时间。

DW 的第二个选项最好通过以下更正和额外细节来实现:

  • 在用户使用正常身份验证机制成功进行身份验证后并在该经过身份验证的会话中,在应用程序上生成密钥对。
  • 在手机上生成 UUID(不要使用 OS/API 的内置设备 ID 或任何其他应用程序也可以检索的任何其他唯一标识符),对其进行加密*并存储它(*请参阅下面的应用程序数据加密最佳实践在手机上)。
  • 以编程方式使用 UUID 和一些可用电话详细信息的组合,将它们稍微混合在一起(而不是简单地连接它们)以生成只有您的应用程序知道的 AppDeviceId。
  • 通过安全通道(由真正受信任的 CA 签名的 SSL/TLS)将公钥 + AppDeviceId 发送到服务器,毫不妥协地注册设备和公钥。
  • 现在进行加密:使用 UUID(不是您用来制作 AppDeviceId 的那个)和一些可用电话详细信息的组合以编程方式生成加密密钥,将它们混合在一起(而不是简单地连接它们)。如果您可以绑定手机的锁屏密码/pin,那就更好了(在 iOS 上,这是通过钥匙串在后台完成的,IFF 用户实际上使用了锁屏密码/pin)。
  • 将您创建的用于生成加密密钥的 UUID 存储在只有您的应用程序“允许”访问的存储中(请记住,有根设备意味着任何应用程序或用户都可能无论如何都可以访问它……这是最薄弱的一点) .
  • 加密并存储您为 AppDeviceId 创建的 UUID 并加密并存储加密的私钥。再次,使用只有您的应用程序“允许”访问的存储空间(请记住,有根设备意味着任何应用程序或用户可能无论如何都可以访问它)。
  • 为了在未来进行身份验证,应用程序应该使用私钥签署应用程序和服务器都知道的有效负载,例如 AppDeviceId,并通过安全通道(SSL/TLS 等)将其发送到服务器。服务器必须使用公钥验证签名。
  • 如果服务器曾经使用给定的 AppDeviceId 接收到尝试的身份验证失败,则删除/删除/忘记注册的公钥并阻止任何进一步使用此密钥对机制进行身份验证的尝试,直到用户使用其他(通常)更安全的身份验证, 久经考验的技术(例如您正在使用这种新技术增强的身份验证过程,或亲自使用正确的文档等)。
  • 在密钥对上添加时间限制甚至更好(减轻长时间的劫持),这样用户必须不时使用更安全、久经考验的技术进行身份验证。

通过上述方法,需要对代码进行反编译和逆向工程 + 访问设备上存储的数据(物理访问设备或 root 设备上的恶意应用程序)+ 设备知识(通过一些技巧进行指纹识别或物理访问设备或控制设备上的应用程序)能够使用该密钥对和 AppDeviceId 进行身份验证。