博客

  • Shamir 秘密分享:任意两点确定一条直线

    有些秘密重要到不能让一个人独占,也重要到不能因为一个人消失就丢失。

    公司想要至少三个高管同时在场才能用主密钥。家庭想要账户恢复需要不止一个信封。团队想要一份备份能在某个成员失联时仍然能恢复,又不至于把整把钥匙交给任何单一个人。

    Adi Shamir(RSA 中的那个 S)在 1979 年提出了一个优雅的解决方案:把秘密拆成 N 份,任意 K 份能恢复出原始秘密,少于 K 份则完全无法推出任何信息。注意是”完全无法推出”,不是”很难破解”。

    核心思想一页纸就讲完。

    两点确定一条直线。一个点不行——经过单一点的直线有无穷多条,每条与纵轴的交点都不同。

    现在把秘密藏在某条直线与纵轴的交点。假设秘密是 7。画一条经过 (0, 7) 的随机斜率直线,斜率本身不重要——它只是用来”遮住”秘密的随机量。

    给每个人这条直线上的一个点(不是直线本身)。一个人拿到一个点,他能想象出无穷条经过这个点的直线,每条都对应一个不同的”秘密”。他手里那个点,对所有可能的秘密都”兼容”,所以单独看什么都不告诉他。

    两个人凑在一起,直线就唯一确定了。然后秘密就是直线在 x=0 时的 y 值。

    这就是 2-of-n 方案。想要更高门槛,就换更”弯”的曲线——抛物线需要三个点确定,三次曲线需要四个点。一般地,门槛 k 对应 k-1 次多项式。

    工程实现里会用有限域算术替代普通实数运算,但形状还是同一个:秘密在 x=0,随机系数遮住它,每份 share 就是多项式上的一个点。

    它真正的价值不是”少于 k 份算起来很难”,而是”少于 k 份在数学上完全没有信息”——少一份,每个可能的秘密都仍然成立。

  • 用”无聊”的语言配 LLM

    有一个反直觉的观察:大语言模型会放大不一致的技术,悄悄地强化一致的技术。

    写代码这件事,把推理当成一次”用 token 下注”。下注在那些有强一致 embedding 的语言和框架上,得到的输出更可预测;下注在生态碎片化严重的技术上,输出会忽好忽坏。

    最典型的反例是 JavaScript 生态。几个生产级框架功能高度重叠,每年都有”新的最佳实践”,训练语料里同一个问题被以五种不同写法各表达过几百万次。模型读完这些,看到一个需求时不知道该输出哪一种,于是哪种都来一点。Python 也好不到哪去——pip / poetry / uv 的包管理之争、async vs Celery、Django vs FastAPI,每个分叉都是模型选择困难的源头。

    反过来看 Rails。”约定优于配置”这个核心理念对人类是 UX 提升,对机器是训练信号的去噪。整个 Rails 社区基本只有一种写法,模型看到 “controller” 就知道下一步是什么。

    Go 是另一个意外赢家。它在很多语言特性上”故意保守”——长期拒绝泛型,并发只有 goroutine,格式化只有 gofmt——结果就是训练语料的方差极小。模型生成的 Go 代码出错率明显低于 Python,标准库覆盖度足够大,连 footgun 的种类都是有限的。

    如果你在搭建 agent 编排框架、CLI 工具、后端服务这类典型场景,认真考虑一下 Go 或类似的”无聊”语言。审美上无聊,工程上稳定。

  • 用 AI 写代码:更慢,但更好

    很多人默认 AI 编程工具的存在意义就是”快速生成低质量代码”。但其实可以反过来用——把它当成一种更系统、更注重质量的开发方式的辅助。

    最近实验了一种工作流:让多个不同的模型并行 review 同一个 PR。Claude 一遍、Codex 一遍、其他模型再一遍,各自按严重程度排序提出问题,再把结果聚合起来。

    这样做的关键洞察是:模型越多越不一样,幻觉和误报就越少。一个模型自信地说有 bug,另一个模型完全没提,那大概率是假阳。三个模型都指向同一处代码,那基本就是真的需要看。

    这个流程”快”吗?显然不快。每个 PR 的 review 时间从几分钟变成半小时。但产出不是更多行代码,而是更深的理解:哪些路径没 考虑、哪些边界条件容易漏、哪些命名其实在暗示别的语义。

    讽刺的是,这种用法对原本就习惯”慢工出细活”的开发者最友好。如果你以前就喜欢花时间看清楚再动手,AI 在这里是放大器;如果你只想拼输出速度,那它反而拖你后腿。

    工具的”快”或”慢”,从来都是用法决定的。