闽公网安备 35020302035485号
假设你是一名外交官,得知了某个重大机密。政府高层共有 16 位关键人物,你可以向他们发送消息,而你希望从中选出 5 人,并且要求至少 3 人同时在场才能解密这条消息。举个例子:你不想让总统知道,但希望军方首脑和 4 名立法机构负责人能够获取这条信息。在普通加密中,你可以把消息单独发给每个人,但你无法强制设定一个 “最少参与解密人数” 的门槛。门限加密的核心思想就是:总共有 N 个人,他们的公钥被放在同一个数据块里。任何人都可以从中选出 L 个人,用他们的公钥生成一个加密密钥,然后指定一个门限值 T,对消息加密后发送给这 L 个接收者。
每个接收者只进行部分解密。这一步可以非常复杂,也可以做得很简单,取决于具体场景的实现方式。比如,你可以让解密操作在同一台计算机上完成,所有达到法定人数的人依次在这台机器上输入自己的口令;或者让每个人把自己的部分解密结果发给指定人员,由他合并后完成最终解密。一旦达到门限人数的人都完成了自己的部分,就可以执行最后一步,解开整条消息。
门限加密背后的数学原理相当深奥。想了解细节可以查阅美国国家标准与技术研究院(NIST)的文档。我也用代码实现过这套算法,并附上了数学说明和源码。真正有趣的是门限加密的潜在应用场景。理解数学固然有用,但探索它能用来做什么,是更有挑战性也更有价值的事。在这套算法里,N 通常取 2 的整数次幂。这一点并非硬性要求,因为你可以加入虚拟用户来补齐数量,但它会影响公钥数据块的整体大小。消息加密所面向的人数(也就是上面说的 L)必须小于或等于 N。
.如果 T = 1,就相当于一个广播系统:一条加密消息发给所有人,每个人都可以单独解密。
为了让数学逻辑成立,T 必须小于等于 L。如果你想让列表里所有人都必须参与解密,只需设置 T = L。回到前面外交官的例子:你可以把消息发给 5 个人,并要求5 人全部在场才能解密,以此分担机密曝光带来的冲击。
第一步是初始化(Setup),用于确定安全等级和最多支持的用户总数 N。如果之后需要增加更多用户,就要从这里重新开始,使用 2N 来生成一个所谓的公共参考串(CRS)。CRS 是一组向量和矩阵,大小由 N 决定。生成 CRS 之后,每个人生成自己的私钥,并由此推导出公钥。我个人很认同一种设计:私钥永不存储,而是始终通过口令的哈希值重新生成。借助椭圆曲线算法,这一点很容易实现。每个用户的完整公钥包含 4N 个点,因此比标准公钥算法的公钥要大得多。
选定消息接收者的步骤叫作预处理(Preprocess)。发送者选出 L 个接收者,算法会把他们的公钥合并成一个加密密钥,以及一个叫作聚合密钥的向量。加密密钥依赖于列表 L 中的用户,聚合密钥则是列表内、外密钥的组合。这两个密钥会被用于下一步。加密步骤会使用若干随机数,结合 CRS 和加密密钥来隐藏消息。消息本身是一个数字,但任何字符串都可以轻松转换成合法数字,因为数值空间非常大。我写的示例程序使用 520 字节长度的数字。在梳理代码逻辑时我发现,可以对多组 520 字节块使用同一个隐藏值,因此理论上可以隐藏任意长度的消息。不过更简便的做法,通常是把这 520 字节当作对称加密算法的密钥。
当足够多的用户提交了部分解密结果后,就可以解密消息了。到这里,数学运算会变得非常复杂:所有随机数被约去,公钥相互合并,再用逆矩阵消去 CRS 中的一组秘密数值。如果你喜欢数学,会觉得这部分相当精妙。这套数学体系基于椭圆曲线配对。目前,还没有已知的经典算法可以破解它(也就是椭圆曲线离散对数问题)。已有理论算法可以在量子计算机上运行,但需要大约 2³² 个托佛利门。只要单个托佛利门被造出,量子计算的 “摩尔定律” 就会开始生效。如果翻倍周期是一年,那么还需要 32 年才有可能破解 128 位安全强度的椭圆曲线。
如果你需要把信息保密 50 年,那确实需要担心 40 年后量子计算机可能破解你的消息。但由于量子计算的 “时钟” 尚未真正启动,可能要等 60 年,才有人能破解今天的椭圆曲线算法。