【问题标题】:Comparing two email address lists anonymously匿名比较两个电子邮件地址列表
【发布时间】:2014-02-15 19:09:25
【问题描述】:

给定两个列表:

A公司:

user1@example.com

user2@example.com

user3@example.com

user4@example.com

B公司:

user2@example.com

user4@example.com

user5@example.com

有没有办法匿名比较它们以获得共同的电子邮件地址数量(即 2 个),而无需任何一家公司知道哪些地址是共同的?

背景:

假设公司 A 和公司 B 想知道他们的用户群的哪一部分是共同的。为简单起见,他们只是将其基于电子邮件地址,而不关心使用多个地址或不同地址变体的人(user+misc@example.com)。

为了保护隐私,两家公司都不能向对方提供电子邮件地址的简单列表。如果他们使用相同的简单哈希,例如MD5,每个公司都可以很容易地知道哪些成员是共同的(不需要)。如果他们使用带有公司特定秘密的哈希值,则地址将不再具有可比性,因此无法回答问题。

是否有一些使用密钥加密或其他数学方法来完成我想要做的事情的技巧?

【问题讨论】:

  • 你可以雇佣第三者 :-) [不是开玩笑,这就是 CA 的全部内容]
  • 如果 2 家公司还没有准备好分享详细信息,他们如何与第 3 方分享,这可能会通过获取两者的详细信息而受益,如果对第 3 方没有用处,它甚至可以传播它们在市场上造福他人?
  • 感谢其他不被接受的答案和 cmet 通过让第三方进行比较来减少技术问题。这绝对是一种可行的方法,但它可能会导致额外的业务方面的复杂性。 Razvan 的答案是我在技术方面所寻找的。谢谢!

标签: email hash comparison


【解决方案1】:

我相信在密码学领域可以更好地理解这个问题。

secure multi-party computation的问题。

我不知道这个问题的任何防弹解决方案,但我可以想到以下几点:

  1. 选择一个可交换散列函数 (H):

    H(H(string, seed1), seed2) = H(H(string, seed2), seed1)

  2. 各方(A 公司和 B 公司)必须选择一个秘密种子:

    SEED_A, SEED_B

  3. A 公司使用SEED_A 对所有电子邮件地址进行哈希处理,B 公司使用SEED_B 对所有电子邮件地址进行哈希处理。

  4. 他们交换哈希值。

  5. 每家公司对从对方收到的集合再次应用哈希函数。

  6. 此时数据应该已经是乱码,公司应该无法识别他们自己的电子邮件地址(因为它们已经被哈希了两次 - 第二次使用未知密钥)。

  7. 所有邮件地址都应公开布局,具有相同哈希值的邮件地址应计为属于两家公司的邮件地址(除非两家公司都无法告知哈希值的来源)。

这就是理论。希望我没有遗漏任何东西,算法也没有缺陷。

至于实现,这是我能提供的最简单的 PHP 脚本:

$a = array("user1@example.com", "user2@example.com", "user3@example.com", "user4@example.com");
$b = array("user2@example.com", "user4@example.com", "user5@example.com");

function enc($str, $seed) {
    for ($i = strlen($str) - 1; $i >= 0; $i--) {
        $str[$i] = $str[$i] ^ $seed[$i % strlen($seed)];
    }
    
    return $str;
}

/* Company A */
$hashesForB = array();
$SEED_A = 'SALT FOR COMPANY A';

foreach ($a as $address) {
    $hashesForB[] = enc($address, $SEED_A);
}

/* Company B */
$hashesForA = array();
$SALT_B = 'THIS IS THE SALT FOR COMPANY B';

foreach ($b as $address) {
    $hashesForA[] = enc($address, $SALT_B);
}

/* Company A */
$hashesForB_2 = array();

foreach ($hashesForA as $hash) {
    $hashesForB_2[] = enc($hash, $SEED_A);
}

/* Company B */
$hashesForA_2 = array();

foreach ($hashesForB as $hash) {
    $hashesForA_2[] = enc($hash, $SALT_B);
}

$common = count(array_intersect($hashesForA_2, $hashesForB_2));

print $common; // it will output 2

Click here for the DEMO

正如您在上面的代码中看到的,我使用 XOR 算法进行(伪)散列(实际上,任何基于加法的散列函数都可以完成这项工作)。

显然,这不是最佳选择,原因有很多:

  • XOR 将在使用相同盐的新调用时返回原始输入
  • 熵并不是你所希望的最好的
  • 数据未被截断

不过,您可以使用建议 herehereherehere 来实现自己的哈希函数。

【讨论】:

  • 多么棒的答案,拉兹万!这就是我一直在考虑的路径,每个公司都将自己的秘密应用于数据,但我被困在散列部分,只提出了一个基于 ORD() 的粗略加法编码人物。这好多了,我也会探索那些非常有用的链接。
  • @Razvan 我们如何在没有人知道两个种子的情况下提出可交换种子对?
  • 您可以查看我在底部提到的 4 个链接。基本上,您可以采用任何可交换的数学运算,它就可以解决问题。最简单的可能是乘法(参见第三个链接)。例如:电子邮件 * 种子 1 * 种子 2 = 电子邮件 * 种子 2 * 种子 1。
【解决方案2】:

隐私协议禁止共享电子邮件地址是否存在隐私问题?或者这是一个竞争问题?

如果您只是想了解重叠百分比,那么我认为电子邮件地址的简单编码可能会起作用。例如,对每个列表进行重复数据删除,对每个电子邮件地址进行 Base64 编码,然后运行比较以获得重叠,然后报告数字。

一个简单的 NDA 可以减少技术问题。

【讨论】:

    【解决方案3】:

    这取决于您要使用的语言。

    在 python 中,你可以使用这个脚本:

    listA = ('user1@example.com', 'user2@example.com', 'user3@example.com')
    listB = ('user1@example.com', 'user2@example.com')
    
    result = [x for x in listA if x in listB]
    print(len(result))
    

    为了安全起见,您可以将此脚本托管在外部服务器中,两家公司都可以将其放入列表中,然后检查结果。

    【讨论】:

      猜你喜欢
      • 2019-04-28
      • 2014-07-12
      • 1970-01-01
      • 2017-07-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多