核心问题

题目是:

五个同事想计算他们的平均工资,但又不想互相公开各自的工资,怎么做?

这本质上是一个经典的 隐私求和 / 安全求平均 问题:

  • 每个人都持有自己的私有输入
  • 所有人只想知道总和或平均数
  • 不想让任何单个人知道别人的具体数值

一、原答案给出的主方法:环形加随机数

设五个人分别为 A、B、C、D、E,他们的工资分别为:

同时,每个人各自再选一个随机数:

第一步:先把随机数在一圈里传一遍

  • A 想一个随机数 ,告诉 B
  • B 再加上自己的随机数 ,把 告诉 C
  • C 再加 ,告诉 D
  • D 再加 ,告诉 E
  • E 再加 ,把总和告诉 A

到这里,A 收到的是:

第二步:再把工资逐步“替换”进去

  • A 加上自己的工资 ,并减去自己最开始加进去的随机数
  • 然后把结果传给 B
  • B 再加上自己的工资 ,减去自己加进去的
  • 依次传下去

最后传到 E 时,E 手里就得到:

再除以 5,就得到平均工资。

二、这个方法的核心思想是什么

这个方法的关键并不是“绕一圈”,而是:

先用随机数把每个人的真实工资遮住,再在传递过程中逐步把随机数换成真实工资。

这样做的结果是:

  • 中间传递值始终被随机数扰动
  • 单个人拿到某一步的数据,也很难直接反推出别人的工资
  • 最后只暴露总和(或平均数),不暴露个体值

三、这个方法的优点

原答案总结了几个好处,整理如下:

1. 单个人无法直接知道别人的具体工资

在正常执行下,每个人只看到局部中间量,看不到完整拆解。

2. 中间数据即使被截获,也不容易反推个体值

因为随机数把真实工资“掩住”了。

3. 这个方法可以推广到任意大于 2 人的情况

不局限于 5 个人。

4. 通信次数较少

是一种相对简洁的隐私求平均方案。

四、这个方法的边界

原答案也提到,这个方法并不是无条件绝对安全的。

1. 如果所有人串通,当然可以还原数据

因为所有随机数一旦全部交出来,就能把整个过程反解。

2. 如果“除一个人之外的其他所有人抱团”,最后仍可能推出那个人的工资

这是评论区后来特别补充的一个重要点。

例如:

  • 5 个人里有 4 个人私下合谋
  • 他们可以先用同样方法算出自己 4 个人工资总和
  • 再用总平均反推出第 5 个人的工资

所以更准确地说,这种方法保证的是:

在没有大规模串谋的前提下,个体工资不会被直接暴露。

而不是能抵御任意联盟攻击。

五、评论区里另一个更经典的方案:把工资拆给别人

评论区给了一个更常见、也更清晰的方案:

每个人把自己的工资拆成若干份,分别发给其他人;最后每个人把自己收到的份额求和并公开,再把这些公开数加总,得到总工资。

这是一个非常经典的秘密分享思路。

具体做法

假设第 个人工资是

他随机拆成若干份:

也就是:

  • 个人把自己的工资分拆成几份
  • 分别告诉其他人
  • 其他每个人只知道自己收到的那一份
  • 没有人单独知道完整工资

最后:

  • 每个人把自己收到的所有数字相加
  • 再把这个和公布出来
  • 所有人把这几个公开值再加总
  • 得到总工资
  • 最后除以人数就是平均工资

原文后面还把这个写成了矩阵形式,并说明:

矩阵所有元素之和,等于行和之和,也等于列和之和。

因此:

  • 行和代表每个人真实工资
  • 列和代表每个人收到的数字总和
  • 公布列和,不需要公布行和,也能算出总工资

六、这个拆分方案的优缺点

优点

  • 思路更清楚
  • 非常适合作为“秘密分享”的入门例子
  • 更容易推广成矩阵或协议形式

缺点

  • 同样挡不住“其余所有人抱团”
  • 如果 4 个人合谋,仍可能推出第 5 个人的工资

原文评论区也强调:

把工资分成更多份,并不能真正防住“剩余所有人结盟”的情况。

另外一个细节是:

  • 拆出来的数字可以取负数
  • 这样可以减少别人从“每份都非负”中推断工资下界的信息

七、一个看似简单、其实不安全的方法

原文还提到一种现实里有人真做过的方法:

  • 第一个人输入一个巨大的不规则数字
  • 然后每个人依次把自己的工资加上去
  • 最后传回第一个人
  • 第一个人减去最初那个大数字,再除以人数

这个办法虽然简单,但有明显问题:

第一个人掌握起始随机数,因此天然拥有更多信息。

如果中间过程再被截获,或者第一个人能观察更多数据,就可能推出其他人的工资。

所以这个方法不如前面两种方法安全。