如何使用未存储在任何地方且只有所有者知道的密钥加密前端/后端中的数据?

信息安全 加密 密码学 javascript AES pbkdf2
2021-08-24 04:10:02

我已经阅读了一堆关于客户端密码学如何不是一个好主意的答案和教程,因为主要在Javascript Cryptography Considered Harmful文章中列出了许多原因。一些事实

  1. 该应用程序将使用 HTTPS
  2. 将有服务器和客户端验证
  3. 用户密码与以下场景之间没有联系
  4. 服务器端是一个 RESTful Web 服务(没有任何会话)
  5. 后端向用户发布 JWT
  6. 后端可能同时允许用户/密码以及 oauth(即 fb、twitter 等)

我想在客户端加密什么?

用户将通过前端应用程序(即 Vue.js、Angular、React 等)输入一些个人信息(即姓名、地址、电话号码)。

我怎么想象这会起作用?

用户选择字段(即个人信息的点点滴滴),然后点击加密。用户将提供一个加密密钥。前端将使用一些js crypto library加密信息替换它们DOM并通知用户备份加密密钥。

如何将此信息传达给服务器?

前端将向服务器发出带有个人信息(无论是纯文本还是乱码)的 HTTPPUTPOST请求。服务器不关心传入的数据(即除了sql或其他形式的注入)并立即将其存储在数据库中。此请求将不包含encryption key但是,可能包含一个标志以指定哪些字段已加密。

如何解密?

当用户请求信息时,后端会按原样返回服务器中的任何内容。如果加密的信息将显示gibberish给用户。使用标志,系统将为他们提供decrypt选项并单击将要求他们输入encryption key并在本地进行解密。

终极目的?

首先,将尽一切努力确保服务器和数据库以及一切都是防弹的,但是,如果由于某种原因服务器被黑客入侵,那么黑客最终会得到大量与胡言乱语的个人信息相关的信息。

终极问题

Javascript强烈建议不要通过互联网阅读密码学,因此,我的问题

  1. 考虑到上述场景和要求,上述实施有哪些风险?
  2. 您是否推荐一种方法,只有用户可以控制密钥,而不是存储在任何地方?
  3. 如果我要在后端加密此信息,我如何encrypt key与用户进行安全通信也许使用密钥加密信息xyz,然后为用户提供一个安全链接以单击并查看xyz加密密钥,...?
  4. 对于前端、基于后端的加密,还有哪些其他建议?

我想让用户相信只有他们知道如何解密密钥。我怎样才能以更有效的方式实现这一目标?无需存储和管理加密密钥?

2018 年 7 月 17 日更新

根据接受的答案,我写了一篇关于我如何实现解决方案的中等帖子是链接https://medium.com/@rhamedy/encryption-decryption-of-data-based-on-users-password-using- pbkdf2-aes-算法-592f8c1bb79a

1个回答

在初始用户注册时,使用密码安全的伪随机数生成器生成强加密密钥;此密钥将用作数据加密密钥 (DEK) 来加密用户的数据。但是您不想将 DEK 存储在任何地方,至少以明文形式存储。您想使用密钥派生函数(例如 PBKDF2)从用户密码派生加密密钥。使用从用户密码派生的密钥(密钥加密密钥或 KEK)加密 DEK。然后您可以安全地将该 DEK的密文存储在数据库中。

每次用户随后登录时,您不仅必须对他们进行身份验证,还必须从他们的密码中重新派生 KEK,然后使用派生的密钥来解密 DEK 的密文。将 DEK 存储在会话中在服务器上,而不是在客户端。现在你在做生意;只要会话处于活动状态,您就可以使用 DEK 在服务器端解密信息,但不能在会话到期后解密。这样做的好处是用户不必盯着一些 gobbledegook 密文。您可以改为使用占位符容器 DOM 元素说“已加密”或其他内容,并可能监听对该元素的点击,然后调用对 API 端点的调用,该端点从数据库中获取密文,在服务器上使用 DEK 对其进行解密您存储在会话中,然后将其作为纯文本立即返回给客户端,您可以在其中将其注入 UI 以供用户查看。客户端不需要存储敏感数据,也不需要在客户端执行任何加密操作。这种方法还具有额外的好处,即 DEK 可以随着时间的推移保持不变。如果用户更改了他的密码,只需从新密码中派生一个 KEK,并使用新的 KEK 重新加密与以前相同的 DEK,并像以前一样将 DEK 的新密文存储在数据库中。