双密钥加密/解密?

8
我想使用PHP和MySQL存储一些相当敏感的数据,并将使用某种可逆加密来实现,因为我需要以明文形式获取数据才能使用。我将从用户的用户名/密码组合中派生加密密钥,但在密码被遗忘的(不可避免的)情况下该怎么办让我陷入了困境。我意识到加密的目的是只有使用正确的密钥才能撤销它,但这个问题肯定已经被解决过了。我试图理解公钥密码学是否适用于这个问题,但我所能想到的是私钥仍然需要正确才能解密数据。你有什么建议吗?
7个回答

5

不清楚您的具体需求,因此很难提供实现建议。

像PGP和S/MIME这样的标准会使用新的对称密钥加密每个消息。然后,这些密钥会为消息的每个接收者加密。这样,每个接收者都会得到相同的密文,而不是为每个接收者复制消息(可能非常大),只有密钥(较小)被复制,但是对于每个接收者进行了不同的加密。

也许您可以在这里做类似的事情,使用用户的密码加密密钥,并使用您的公钥加密另一个副本。如果用户忘记了他们的密码,您可以使用您的私钥(在适当的备份身份验证之后)为他们恢复消息。


4
传统的解决方案是有一个“恢复代理”:一个用户持有第二个密码,可用于解密所有数据。使用恢复密码需要严格遵守使用政策,例如将其物理放入保险柜中。
然后,要么对所有数据进行两次加密:一次使用用户密钥,一次使用恢复密钥;要么为每组数据生成一个会话密钥,并仅对数据进行一次加密,但会话密钥要进行两次加密。
为了使此方法有效,至少恢复代理的密钥必须是非对称的,因为私有部分将存储在保险柜中,公钥将存储在软件中。
作为使用相同方案的另一种替代方案:在更改密码时使用恢复密钥加密用户的密码。这种方法更简单易行,但可以恢复密码而不仅仅是数据,这可能是不可取的。

如果您想了解如何实现此功能,请查阅有关Windows上EFS工作原理的技术细节。它可以非常复杂,例如赋予不同受托人查看不同数据量的能力 - 但这意味着管理更多密钥 - 或者只需使用不同的公钥两次加密相同的密钥即可简单实现。 - SilverbackNet

3
我希望使用PHP和MySQL存储一些敏感数据,并将使用某种可逆加密来实现,因为我需要将数据以明文形式取回才能使用。以下是需要考虑的问题:
- 这是谁的数据?(你的、你的用户的还是第三方的?) - 它需要保护免受什么?(泄露、损坏(意外或有意)...) - 它需要受到谁的保护? - 不涉及的人可以不用说。 - 你是否需要/想要避免自己访问明文数据(有助于否认), - 你是否需要保护你的用户数据不被第三方看到, - 或者需要保护第三方的数据不被用户看到, - 或者需要保护你的数据不被用户或第三方看到? - 可能的攻击方式是什么? - 是否需要在服务器完全被攻破的情况下进行保护? - 是否需要防范应用层攻击,即用户仅获得部分可用数据而非全部数据(例如,访问SQL数据库但无法访问文件系统)? - 数据量是否足够小,以至于攻击者可以猜测并简单地检查自己是否猜对了?(短密码、数字、简单单词、固定格式文本是可能的候选项) - 攻击者是否拥有已知的明文来进行攻击? - 如果用户忘记密码,数据是否最好消失(或重新获取数据),还是值得冒增加曝光风险的风险?
你需要考虑这些问题来使用加密。答案将帮助你确定你需要什么和你想要什么,并可能指出正确的方向。你可能不想与我们分享所有答案。
我将从用户的用户名/密码组合中派生加密密钥,但在密码被遗忘的(不可避免的)情况下,我卡住了。我意识到加密的目的是只有使用正确的密钥才能撤销,但这个问题之前一定有人解决过。
你可能已经在没有考虑影响的情况下决定了一个解决方案。这并不意味着解决方案是错误的,但这个问题建议你思考为了安全愿意冒什么风险。有时会冒险暴露数据。
我正在努力理解公钥加密是否适用于这个问题,但我所能想到的是私钥仍然需要正确才能解密数据。

这似乎是在寻找问题的解决方案。 当你有两个(或更多)具有相互通信数据的利益相关方时,公钥密码技术非常有用。 这些参与者可以是真实的(人)或功能性的(系统组件),但没有两个参与者,就没有必要有单独的公钥和私钥。


2
基本上,如果您加密了某些内容,并且丢失了加密密钥,那么就糟糕了。
在保护数据方面,您需要考虑为什么要保护它,以及您试图保护它免受何种威胁。还有哪些权衡是值得做的——唯一真正安全的系统是完全隔离于互联网之外的系统,这对于大多数应用程序来说是自我打败的安全级别。
因此,以下是一些问题需要问自己:
1. 如果有人入侵了我的数据库,他们能够访问这些数据,这是可以接受的吗? 2. 如果有人入侵了我的整个应用程序堆栈,会怎样?
如果以上两个问题的答案都是否定的,那么关键材料必须由用户持有。如果他们丢失了密钥,将无法访问其数据。
如果您还提供手动密钥恢复选项,并且拥有一个您不存储在应用程序附近的“主密钥”,只有您持有并使用它手动重置密码,则可以提供该选项。如果这也不是一个选项(例如,只有用户才能访问数据,而不是系统管理员),那么您将不得不在某个地方做出妥协。

2
这是我自己思考过的一个问题,我认为以下几个选项可供选择(其中选项#1最安全):
  1. 不提供重置密码功能-如果他们忘记了密码,则被锁定。

  2. 生成新的安全主密钥并使用此主密钥加密和哈希用户的密钥,并将密文和哈希结果存储在数据库中。然后通过将其添加到用户下载的文件中,向用户发送电子邮件或在屏幕上显示安全主密钥来使用户知道安全密钥。要重置密码,用户必须输入此主密钥,然后对其进行哈希处理并进行比较,如果匹配,则解密数据库中的用户密钥。

  3. 在注册时要求用户提供2个安全问题和答案; 对答案进行哈希处理,并将问题和答案哈希存储在数据库中。第二个答案用作加密用户密钥的主密钥。要接收密码重置请求电子邮件,用户必须正确回答第一个问题。一旦他们单击电子邮件中的链接,网页就会询问第二个问题,如果这是正确的,并且查询字符串参数值有效,则使用第二个问题的答案来解密用户的密钥。

  4. 使用应用程序全局主密钥(可能存储在Web / UI应用程序中),并使用此密钥加密和存储用户的密钥。通过密码重置电子邮件流程验证用户后,使用应用程序全局主密钥解密用户的密钥,然后使用其新密码重新加密。

总之,每个选项的优点如下:

  1. 这是最安全的选择,如果要保持数据加密,则可能是唯一的选择。但是,在现实世界中,人们忘记密码就像太阳升起一样肯定,不提供重置密码功能可能是一个糟糕的商业决策。

  2. 这是安全的,因为主密钥不存储在前端或数据库中,因此如果平台被攻击,则需要一些重大的努力才能解密数据。但是,缺点是用户仍然可能会丢失其主密钥。

  3. 这里的弱点是如果数据库遭到攻击,则可以研究问题的答案,然后用于解密用户的加密密钥。

  4. 这种方法将应用程序密钥留在堆栈中,如果您的平台被黑客攻击,则数据容易受到攻击。您唯一的保护措施是,如果数据库服务器被黑客攻击,则数据仍然是安全的。

与软件开发世界中的大多数事物一样,您需要考虑为实现目标而选择什么,并争取正确的平衡。


1

为什么要为每个用户使用不同的密钥?

如果选择一个密钥,处理起来会更容易。

将加密密钥存储在数据库之外。

您的应用程序仍然需要访问它,但拥有数据库转储的人将无法读取加密信息。


2
如果有人最终得到了数据库转储文件,我会认为他们也有能力获取我的应用程序源代码。 - Matt

1
  1. 生成一个随机的会话密钥。
  2. 使用会话密钥加密数据。
  3. 使用任意数量的用户密码加密随机密钥。

这样,您就可以使用任何用户密码来解密数据。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接