我正在开发Node.js应用程序,该应用程序要求用户从第三方服务输入他的API密钥(该服务不允许通过oauth登录(。现在我将这些存储在.env文件中,因此需要在安装时输入。我希望用户能够在用户界面中设置一次密钥(使用密码(,然后将其持久存储,这样当退出应用程序并重新启动时,密钥仍然存在。我该怎么做?我是否加密密钥并将其存储在数据库中?还有其他方法吗?
一般来说,这对您的用户和您作为服务提供商来说都是太大的风险。如果这些是您想要存储的有价值的api密钥,那么您的服务将成为一个很好的目标。正如你也注意到的,这就是oauth的发明目的。
如果你仍然决定这样做,你可以用一些ux来换取更多的安全性。您肯定应该加密api密钥,但将加密密钥存储在哪里以使其真正有意义始终是个问题。
想想攻击者是如何获得这些api密钥(威胁(的,这将有助于提供足够的保护(缓解这些威胁(。
例如,攻击者可能直接或离线访问数据库,比如从备份中访问,或者通过受损的数据库服务器访问。为此,dbms提供的标准静态加密是很好的,尤其是如果您使用AWS和KMS之类的东西来存储加密密钥。所以你需要在休息时进行加密,但这还不够。
攻击者也可能会危害您的应用程序,因此透明加密没有帮助。例如,您可以在应用程序级别加密敏感字段(即api密钥(,使用与每个用户关联的唯一密钥,安全地存储在适当的服务中(如HSM或AWS中的Secrets Manager(。这可能仍然允许攻击者访问,但这变得越来越困难,而且您可以对密钥访问进行更多的控制和可审计性。
更进一步,您可以使用适当的密钥派生函数(如pbkdf2或类似函数(从用户密码中派生密钥,并且永远不要将它们存储在数据库中,只存储在内存中。这意味着,如果登录用户可以访问服务器内存和/或服务器端的网络通信(在tls终止后(,他们的秘密仍然可能被攻击者泄露,但脱机用户的秘密仍然是安全的,因为即使你没有解密它们的密钥。当然,只有当你只需要访问他们的api密钥时,只要他们存在,这才有效。