如何将个人身份与个人数据分开?

时间:2010-09-11 14:32:25

标签: hash database-security sensitive-data

我正在编写一个应用程序,其主要目的是保留用户列表 购买。

我想确保即使我作为开发人员(或任何有完整的人) 访问数据库)无法计算出多少钱 特定的人已经花了或者他买了什么。

我最初想出了以下方案:

    --------------+------------+-----------
    user_hash     | item       | price
    --------------+------------+-----------
    a45cd654fe810 | Strip club |     400.00
    a45cd654fe810 | Ferrari    | 1510800.00
    54da2241211c2 | Beer       |       5.00
    54da2241211c2 | iPhone     |     399.00
  • 用户使用用户名和密码登录。
  • 从密码计算user_hash(可能还有盐腌等)。
  • 使用哈希通过普通的SQL查询访问用户数据。

如果有足够的用户,几乎不可能知道多少 一个特定用户通过知道他的名字而花费的钱。

这是一件明智的事吗,还是我完全愚蠢?

7 个答案:

答案 0 :(得分:4)

我担心,如果您的应用程序可以将某个人与其数据相关联,那么任何开发人员/管理员都可以。

你唯一能做的就是让链接变得更难,减慢开发人员/管理员的速度,但是如果你把用户与数据联系起来更加困难,那么你的服务器也会变得更难。


基于@no想法的想法:

您可以使用经典的用户/密码登录您的应用程序(哈希密码或其他),以及用于保证数据安全的特殊“通行证”。此“通行证”不会存储在您的数据库中。

当您的客户登录您的应用程序时,我必须提供用户/密码/通行证。使用数据库检查用户/密码,该传递将用于加载/写入数据。

当您需要编写数据时,您可以对“用户名/密码”对进行哈希处理,并将其存储为将客户端与数据相关联的密钥。

当您需要加载数据时,您可以对“username / pass”对进行哈希处理,并加载与此哈希匹配的每个数据。

这样就无法在您的数据和用户之间建立链接。

另一方面,(正如我在对@no的评论中所说)小心碰撞。此外,如果您的用户写了一个错误的“通行证”,您将无法检查它。


更新:对于最后一部分,我有另一个想法,你可以在你的数据库中存储你的“通行证/密码”夫妇的哈希值,这样你就可以检查你的“通行证”是否合适。

答案 1 :(得分:2)

  1. 使用以下命令创建用户表:
    1. user_id:标识列(自动生成的ID)
    2. 用户名
    3. 密码:确保它是哈希!
  2. 像示例中一样创建一个产品表:
    1. user_hash
    2. 项目
  3. user_hash将基于永远不会更改的user_id。用户名和密码可根据需要随意更改。当用户登录时,您将比较用户名/密码以获取user_id。您可以在会话期间将user_hash发送回客户端,或者加密/间接版本的哈希(可以是会话ID,服务器将user_hash存储在会话中)。

    现在您需要一种方法将user_id哈希到user_hash并保护它。

    1. 如果您在@no建议的情况下在客户端执行此操作,则客户端需要具有user_id。大安全漏洞(特别是如果它是一个Web应用程序),哈希很容易被篡改,并且算法可以免费向公众提供。
    2. 您可以将其作为数据库中的函数。不好的想法,因为数据库中包含了连接记录的所有部分。
    3. 对于网站或客户端/服务器应用程序,您可以在服务器端代码上使用它。好多了,但是一个开发人员可以访问哈希算法和数据。
    4. 让另一位开发人员编写散列算法(您无权访问)并将其作为TCP / Web服务粘贴到另一台服务器(您也无权访问)上。然后,您的服务器端代码将传递用户ID并返回哈希值。您不会拥有该算法,但您可以发送所有用户ID以获取所有哈希值。虽然该服务可以进行日志记录,但尝试将风险降至最低,但#3并没有带来很多好处。
    5. 如果它只是一个客户端数据库应用程序,那么您只有#1和2的选择。我强烈建议添加另一个服务器端的[业务]层,与数据库服务器分开。
    6. 修改 这与以前的一些要点重叠。有3台服务器:

      • 身份验证服务器:员工A具有访问权限。维护用户表。具有采用用户/密码组合的Web服务(具有加密通信)。哈希密码,在表中查找user_id,生成user_hash。这样您就不能简单地发送所有user_ids并返回哈希值。您必须拥有未存储在任何地方的密码,并且只能在身份验证过程中使用。
      • 主数据库服务器:员工B具有访问权限。仅存储user_hash。没有用户ID,没有密码。您可以使用user_hash链接数据,但实际的用户信息位于其他位置。
      • 网站服务器:员工B可以访问。获取登录信息,传递给身份验证服务器,获取哈希值,然后处理登录信息。在会话中保留哈希以写入/查询数据库。

      因此,员工A具有user_id,用户名,密码和算法。员工B具有user_hash和数据。除非员工B修改网站以存储原始用户/密码,否则他无法链接到真实用户。

      使用SQL分析,Employee A将获得user_id,用户名和密码哈希(因为user_hash稍后在代码中生成)。员工B将获得user_hash和数据。

答案 2 :(得分:1)

确保数据无法连接到其所属人员的唯一方法是不首先记录身份信息(使所有内容都匿名)。但是,这样做很可能会使您的应用毫无意义。你可以让这更难做,但你不能让它变得不可能。

将用户数据和识别信息存储在单独的数据库中(可能在不同的服务器上),并将两者与ID号相关联,这可能是您可以做的最接近的事情。这样,您已尽可能隔离了两个数据集。您仍然必须保留该ID号作为它们之间的链接;否则,您将无法检索用户的数据。

此外,我不建议使用散列密码作为唯一标识符。当用户更改其密码时,您必须通过并更新所有数据库,以使用新的密码ID替换旧的哈希密码ID。使用不基于任何用户信息的唯一ID通常要容易得多(以帮助确保它保持静态)。

这最终成为一个社会问题,而不是技术问题。最好的解决方案将是社交解决方案。在强化系统以防止未经授权的访问(黑客等)之后,您可能会获得更好的里程,与您的用户建立信任并实施有关数据安全的策略和程序系统。对滥用客户信息的员工包含特定处罚。由于单一的客户信任破坏足以破坏您的声誉并驱使您的所有用户离开,因此具有“顶级”访问权限的人滥用此数据的诱惑比您想象的要少(因为公司通常会崩溃)超过任何收益)。

答案 3 :(得分:1)

请记住,即使没有将人的识别信息实际存储在任何地方,仅仅将足够的信息与相同的密钥相关联,也可以让您找出与某些信息相关联的人的身份。举个简单的例子,你可以打电话给脱衣舞俱乐部,询问哪个顾客驾驶法拉利。

出于这个原因,当您取消识别医疗记录(用于研究等)时,您必须删除89岁以上人群的生日(因为那些老年人很少,特定的出生日期可能指向单个人)并删除任何指定包含少于20,000人的区域的地理编码。 (见http://privacy.med.miami.edu/glossary/xd_deidentified_health_info.htm

AOL在发布搜索数据时发现了一种艰难的方式,只需了解与匿名人士相关的搜索内容即可识别人员。 (见http://www.fi.muni.cz/kd/events/cikhaj-2007-jan/slides/kumpost.pdf

答案 4 :(得分:0)

问题是如果有人已经拥有对数据库的完全访问权限,那么将记录链接到特定人员只是时间问题。在数据库的某个位置(或应用程序本身),您必须在用户和项目之间建立关系。如果有人具有完全访问权限,那么他们将可以访问该机制。

绝对没有办法阻止这种情况。

现实情况是,通过完全访问,我们处于信任的位置。这意味着公司经理必须相信即使您可以看到数据,也不会以任何方式对其进行操作。这就是道德这样的小事情发挥作用的地方。

现在,据说,许多公司将开发和生产人员分开。目的是将开发与直播(即:真实)数据直接联系。这具有许多优点,安全性和数据可靠性处于最重要的位置。

唯一真正的缺点是某些开发人员认为他们无法在没有生产访问权限的情况下解决问题。然而,事实并非如此。

然后,生产人员将是唯一可以访问实时服务器的人员。他们通常会接受更大程度的审查(犯罪记录和其他背景调查),这与您必须保护的数据类型相关。

所有这一切的重点在于这是一个人事问题;而不是一个可以用技术手段真正解决的问题。


<强>更新

其他人似乎错过了一个非常重要且非常重要的难题。即,由于某种原因数据正被输入系统。这个原因几乎普遍存在,因此可以共享。在费用报告的情况下,输入该数据,以便会计可以知道谁应该回报。

这意味着系统在某种程度上必须匹配用户和项目,而不会登录数据录入人员(即:销售人员)。

因为这些数据必须捆绑在一起而没有所有相关方站在那里输入安全代码来“释放”数据,然后DBA绝对能够查看查询日志以确定谁是谁。无论你想要投入多少哈希标记,我都可以轻松添加。三重DES也不会拯救你。

在一天结束时,您所做的就是让开发变得更加困难,绝对没有安全保障。我不能强调这一点:从dba中隐藏数据的唯一方法是1.要使输入它的人能够访问 的数据,或者2.存在于第一位。

关于选项1,如果唯一可以访问它的人是输入它的人......那么,它就没有必要在公司数据库中。

答案 5 :(得分:0)

实际上,有一种方法可以做你正在谈论的事情......

您可以让用户在运行纯客户端脚本的表单中键入他的名称和密码,该脚本根据名称和pw生成哈希。该哈希用作用户的唯一ID,并发送到服务器。这样,服务器只通过哈希而不是名称来了解用户。

为了使其工作,散列必须与普通密码散列不同,并且用户需要在服务器具有任何“内存”之前额外输入其名称/密码。有人买了。

服务器可以记住该人在会话期间购买的内容然后“忘记”,因为数据库中不包含用户帐户和敏感信息之间的链接。

修改

回应那些说客户端散列是安全风险的人:如果你做得对,那就不是了。应该假设哈希算法是已知的或可知的。否则说是“通过默默无闻的安全”。散列不涉及任何私钥,动态散列可用于防止篡改。

例如,你采用这样的哈希生成器:

http://baagoe.com/en/RandomMusings/javascript/Mash.js

// From http://baagoe.com/en/RandomMusings/javascript/
// Johannes Baagoe <baagoe@baagoe.com>, 2010
function Mash() {
  var n = 0xefc8249d;

  var mash = function(data) {
    data = data.toString();
    for (var i = 0; i < data.length; i++) {
      n += data.charCodeAt(i);
      var h = 0.02519603282416938 * n;
      n = h >>> 0;
      h -= n;
      h *= n;
      n = h >>> 0;
      h -= n;
      n += h * 0x100000000; // 2^32
    }
    return (n >>> 0) * 2.3283064365386963e-10; // 2^-32
  };

  mash.version = 'Mash 0.9';
  return mash;
}

了解n如何更改,每次散列字符串时都会得到不同的内容。

  • 使用普通哈希算法哈希用户名+密码。这将与数据库中“secret”表的键相同,但不会与数据库中的其他任何内容匹配。
  • 将散列传递附加到用户名并使用上述算法对其进行散列。
  • Base-16编码var n并将其附加到带有分隔符的原始哈希中。

这将创建一个唯一哈希(每次都不同),系统可以根据数据库中的每一列进行检查。系统可以设置为仅允许一次特定的唯一哈希(例如,每年一次),防止MITM攻击,并且没有用户的信息通过网络传递。除非我遗漏了什么,否则没有什么不安全感。

答案 6 :(得分:0)

看起来你正好跟着这个,但你只是在思考它(或者我根本就不理解它)

根据输入编写一个构建新字符串的函数(这将是他们的用户名或其他不能随时改变的东西)

在构建用户哈希时使用返回的字符串作为salt(同样我会使用userID或username作为哈希构建器的输入,因为它们不会像用户的密码或电子邮件那样更改)

将所有用户操作与用户哈希相关联。

没有只有数据库访问权限的人可以确定用户哈希到底是什么意思。即使尝试通过尝试不同的种子,盐组合强制它也会最终无用,因为盐被确定为用户名的变体。

我认为您已经在初次发帖时回答了自己的问题。