核心问题
题目是:
五个同事想计算他们的平均工资,但又不想互相公开各自的工资,怎么做?
这本质上是一个经典的 隐私求和 / 安全求平均 问题:
- 每个人都持有自己的私有输入
- 所有人只想知道总和或平均数
- 不想让任何单个人知道别人的具体数值
一、原答案给出的主方法:环形加随机数
设五个人分别为 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 个人的工资
原文评论区也强调:
把工资分成更多份,并不能真正防住“剩余所有人结盟”的情况。
另外一个细节是:
- 拆出来的数字可以取负数
- 这样可以减少别人从“每份都非负”中推断工资下界的信息
七、一个看似简单、其实不安全的方法
原文还提到一种现实里有人真做过的方法:
- 第一个人输入一个巨大的不规则数字
- 然后每个人依次把自己的工资加上去
- 最后传回第一个人
- 第一个人减去最初那个大数字,再除以人数
这个办法虽然简单,但有明显问题:
第一个人掌握起始随机数,因此天然拥有更多信息。
如果中间过程再被截获,或者第一个人能观察更多数据,就可能推出其他人的工资。
所以这个方法不如前面两种方法安全。