在数据库中保存加密的私人消息

信息安全 密码学
2021-08-12 20:12:46

我不确定这个问题是否更适合 StackOverflowSE 或 CryptoSE,但我认为这是正确的地方。

在一个在线社区门户中,我想将用户的私人消息加密保存在数据库中,这样如果有人访问数据库,信息就不会泄露。但我不知道如何管理密钥。

发送消息时,应将其加密保存在数据库中,并且只有在其中一个参与者请求消息时才能解密。密钥显然不能保存在数据库中,因为这会使整个事情变得毫无意义。

我想出的方法是使用对称密钥算法保存消息,并为每个参与者保存使用公钥算法加密的密钥(每个用户都有一个公钥)。

当请求消息时,使用用户的私钥对其进行解密以获取对称密钥。但是我不知道如何创建/保存私钥。它不能在数据库中,并且由于应用程序是多平台的(网络、移动访问),我无法将其保存在用户的设备上,并且必须使用来自用户的常量动态生成,而不是保存在数据库的某处。我能想到的唯一常量是用户的密码。但是,如果密码丢失/忘记,则无法再访问这些消息。

我的问题:还有其他方法可以做到这一点吗?或者你知道另一个仍然是私有的常量吗?

编辑/更新: 感谢您的回答。这是一个更新:

如何将私钥保存在使用随机字符串加密的 db 中,该字符串在注册时通过邮件发送给用户建议用户不要删除该邮件。如果她仍然这样做(似乎很有可能),那么我可以责怪她,没有 j/k,但这至少是恢复消息的一种方法。

这里有一个子问题:应用程序只能通过 HTTPS 或 TCP/IP+SSL API 访问。是否可以保存在服务器上对消息进行加密/解密并通过 SSL 以普通方式发送它?否则,我将不得不为所有平台(浏览器、移动设备、桌面)寻找实现(如 GPG)。这需要在用户登录时将私钥存储在 ram 中(密码在会话开始/登录时发送)。当然,如果有人获得对服务器的写访问权(更改应用程序)或对 ram(o0)的读访问权,他可以嗅探密钥,但我认为这不太可能。

无论如何,消息必须在服务器上*加密*(意味着以明文形式发送),因为它可能需要由服务器推送到移动设备。(这是否安全并不重要,我想确保没有人可以使用数据库转储 - 如果 Apple 或类似公司可以在交付时读取它,则不然)。

可能我不需要这些,因为我的用户很可能不会互相发送秘密消息,但万一发生泄漏,他们不会高兴的。这是一个本地学生社区,你永远不知道无聊的 CS 学生在做什么;)。

4个回答

如果进行密码恢复的唯一方法涉及回答问题,您可以使用密码加密私钥一次,然后使用秘密答案再加密一次,并将两个加密版本存储在数据库中。然后,如果用户忘记密码并使用秘密答案进行恢复,您可以访问私钥并使用新密码重新加密(正常使用)。如果正在更改秘密答案,则应请求密码,以便可以重新生成使用答案加密的版本。

这确实有(至少)两个问题。“秘密”的答案通常并不难破解。这可以通过使用具有大量迭代的 PBKDF2 来部分解决(因为该选项将不经常使用)。显然,另一个问题是,如果出于某种原因您想手动重置用户的密码(即他们在不知道秘密答案的情况下说服了您他们的身份),那么您将无法恢复这些消息。但是,尽管存在这些问题,但取决于您愿意做出的妥协,它仍然可能有用。

在数据库中加密,因此如果有人访问数据库,信息就不会泄露。但我不知道如何管理密钥。

推荐你看两本书:

数据库中的密码学本书讨论了如何管理密钥和管理加密服务提供者。提供的代码是 Java,但它看起来对 .NET 相当友好。这本书的目的是安全,隐私无关紧要。

半透明数据库本书旨在使数据对授权用户有用和可用,但对小偷和窥探者无用。这本书更多地关注隐私,安全紧随其后。我有旧版。

我能想到的唯一常量是用户的密码。但是,如果密码丢失/忘记,则无法再访问这些消息。

这个答案克服了忘记密码后需要手动恢复消息的问题。如果您需要一些仍然保持出色安全级别的自动化方式,那么您可能不走运。这是由管理员手动恢复。

您可以存储使用密码生成的密钥的非对称加密副本。

(一般来说)用于加密密码生成密钥的非对称加密密钥”不能被逆向工程。

因此,您确实需要在某处存储“用于访问密码生成密钥的非对称解密密钥”。

您可以将其存储在纸上或带锁盒子内的闪存驱动器上。

这可以完全防止某人获得只读访问权限,除非他们在您的交换或堆或核心转储中找到消息。如果您有足够的 RAM 并且足够多疑,则可以考虑禁用交换,如果您从不使用堆或核心转储,不妨也禁用它们。

具有读写能力的人可能能够更改您的程序以在消息被解密时永久存储或发送消息。如果您想解决这个问题,您将需要存储所有可执行文件(甚至操作系统?)的校验和,并在每次校验和更改时手动验证它是您所做的,而不是闯入。这可以让您有机会在大量数据泄漏之前消除损坏。

对此有许多复杂的可能答案,但我将为您提供一个简单的答案,它不依赖于正常登录过程之外的用户交互:

当用户登录时,通过带有某种盐值的 PBDKF2 使用他们的密码生成对称加密密钥。

下一部分是关于在哪里存储该密钥的安全问题权衡问题。我更愿意将它作为 cookie 存储在用户的机器上,只要他们的登录凭据持续存在。鉴于密钥是用随机盐制成的,该盐保存在服务器上并且永远不会泄露,并且解密只能通过身份验证进行,它不会使用户遭受对其密码的合理离线暴力攻击。

最后,与任何其他常见登录会话相比,它不会使用户面临访问其数据的更大风险。如果他们的计算机被占用并且他们已登录,则可以访问。如果他们的计算机被没收而他们没有登录,则无法访问。如果传票要求他们的数据,则在没有用户(希望是强密码)生成适当密钥的情况下,释放数据将无助于对其进行解密。此外,如果您感觉特别刻薄,您可能无法透露盐分,除非传票涵盖了这一点,或者您的机器实际上被没收了。

关于另一个私有常量?不存在。您不能对自己保密并可供用户更换。如果他们丢失了密码,您要么将密钥保存在托管中以解密,要么如果他们丢失了密钥/密码,他们就会不走运。其他任何事情都涉及复杂的箍,例如SSSS和说服朋友保证您就是您并且应该能够阅读内容。然后你必须相信他们。