区块链 区块链技术 比特币公众号手机端

设计即安全与保持精简:通过自动化提供形式化密码学证明

我仍然感到惊讶的是,安全性没有被嵌入到系统设计中,而且无法在真正意义上证明一个系统是安全的。总的来说,设计者经常把一些本应安全的程序片段组合在一起,然后就假设整个系统是安全的。这引出了许多问题。我们如何确信正在使用的模块在数学上确实正确?又如何确信,当所有这些模块组合到一起时,解决方案仍然是正确的?

问题

如今,密码学论文似乎变得越来越复杂,尤其是在 AI 正在攻破密码方法的领域。当某个漏洞被提出时,可能会引起一些混乱,而头条新闻往往把“方法被攻破”当作事实——尽管该论文实际上并未经过同行评审。其中一个例子就与 DCP 问题被攻破有关,见此处:

图:此处

这样一来,Dihedral Coset Problem 就可以与 Module-LWE(定义 ML-KEM 的基础困难性问题)联系起来。如果这一证明成立,它将为近似最短向量问题以及 LWE(带误差学习,Learning With Errors)生成一个多项式时间的量子算法,而 LWE 正是抗量子密码学中使用的许多格基方法的基础。但就在本周,我们看到一篇新论文驳斥了这一说法,见此处:

那么,研究人员究竟该如何以某种形式化分析来证明他们的方法,而不必深入钻研证明中的数学呢?嗯,越来越多的研究人员开始为此转向 Lean 编程语言。

Lean 编程语言

Lean 是一种相对较新的开源编程语言,能够对数学和软件进行形式化证明。这使得开发人员可以证明他们的程序符合某种数学形式。在密码学中,这可以用来证明程序在数学上能够匹配 SHA-256 哈希方法,或者证明程序符合 AES 加密方法。

那么,让我们来尝试一个基本示例。为此,我们可以使用如下公式:

y^2 = a (mod p)

在这里,我们必须证明 $y$ 的平方等于 $a$ 对 $p$ 取模。例如,我们可以有:

$$1031^2 = 35 \pmod{97}$$

在 Python 中,我们可以证明这是正确的:

>>> pow(1031,2,97)
35

对于 Lean,我们可以使用 % 运算符(用于取模)来编写,也可以使用内置的数学函数:

import Mathlib
example : (1031^2) % 97 = 35 := by
 norm_num

example : Nat.ModEq 97 (1031 ^2) 35 := by
 norm_num [Nat.ModEq]

然后我们可以运行:

lake env lean square.lean

如果没有错误,就说明我们已经证明了该数学等式。如果我们使用一个不正确的关系式:

import Mathlib

example : Nat.ModEq 97 (1031^2) 32 := by
  norm_num [Nat.ModEq]

我们会得到:

square.lean:3:38: error: unsolved goals
⊢ False

接下来,我们可以为我们的等式创建一个定理:

import Mathlib

theorem square_root_mod_p
    (y a p : Nat)
    (h : y^2 % p = a % p) :
    Nat.ModEq p (y^2) a := by
  exact h

-- 证明 35 是 1031 对 97 取模的一个平方根

example : Nat.ModEq 97 (1031^2) 35 := by

  apply square_root_mod_p 1031 35 97

  norm_num

如果我们运行:

lake env lean square2.lean

我们不会得到任何错误,但如果给出一个不正确的证明:

import Mathlib

theorem square_root_mod_p
    (y a p : Nat)
    (h : y^2 % p = a % p) :
    Nat.ModEq p (y^2) a := by
  exact h

-- 证明 35 是 1031 对 97 取模的一个平方根

example : Nat.ModEq 97 (1031^2) 32 := by

  apply square_root_mod_p 1031 32 97

  norm_num

我们会得到一个错误:

square2.lean:12:38: error: unsolved goals
⊢ False

这难道不是非常漂亮吗?

我们还可以定义一个所需的假设($h$),然后调用该定理:

import Mathlib

theorem square_root_mod_p
    (y a p : Nat)
    (h : y^2 % p = a % p) :
    Nat.ModEq p (y^2) a := by
  exact h

example : Nat.ModEq 97 (1031^2) 35 := by

  have h : 1031^2 % 97 = 35  % 97 := by
    norm_num

  exact square_root_mod_p 1031 35 97 h

同样,这不会产生任何错误,因此该假设得到了证明。我们还可以针对给定的 $a$ 和 $p$ 值求解平方根:

$$y^2 = a \pmod{p}$$

在下面的示例中,我们可以找到以下方程的平方根:

$$y^2 = 2 \pmod{97}$$

其中一个解为 $y=14$。还有:

$$y^2 = 5 \pmod{31}$$

其中一个解为 $y=6$。还有:

$$y^2 = 3 \pmod{19}$$

没有任何解。Lean 代码如下:

import Mathlib

/-
  检查 y 是否是以 p 为模时 a 的平方根。
-/
def isSquareRootMod (y a p : Nat) : Bool :=
  (y * y) % p == a % p

/-
  在 y = 0, 1, ..., p-1 中搜索 a 对 p 取模的平方根。

  返回:
    some y   如果 y² ≡ a (mod p)
    none     否则
-/
def findSquareRootMod (a p : Nat) : Option Nat :=
  if p = 0 then
    none
  else
    (List.range p).find? fun y =>
      (y * y) % p = a % p

##eval findSquareRootMod 2 97
##eval findSquareRootMod 5 31
##eval findSquareRootMod 3 19

运行结果为:

some 14
some 6
none

我们还可以找到给定素数的平方根。对于 $p=97$,我们可以定义:

import Mathlib

def quadraticResidues (p : Nat) : List Nat :=
  (List.range p).map (fun x => (x * x) % p) |>.eraseDups

##eval quadraticResidues 97

运行后,我们会得到如下的二次剩余:

[0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 3, 24, 47, 72, 2, 31, 62, 95, 33, 70, 12, 53, 96, 44, 91, 43, 94, 50, 8, 65, 27, 88, 54, 22, 89, 61, 35, 11, 86, 66, 48, 32, 18, 6, 93, 85, 79, 75, 73]

因此:

$$y^2 = a \pmod{97}$$

对于 $a=1, 2, 4, 6, 9$ 等值有解。但对于 $a=5$、$a=7$ 或 $a=10$ 没有解。我们可以在此证明:https://asecuritysite.com/primes/modsq?aval=5&pval=97。

那又怎样?

嗯,我们开始看到 Lean 被用于证明新方法满足一组数学定义,例如在 zk.golf 站点上,见这里:

而研究人员现在正提供 Lean 4 代码来证明或反驳各种方法:

在这种情况下,以下是通过 Lean 4 代码进行的反驳,见此处:

结论

Lean 是软件开发领域一项令人惊叹的进步,我强烈建议团队使用它来进行形式化证明,以证实他们的代码确实能够匹配给定的规范。

  • 原文链接: billatnapier.medium.com/...
  • 鸿途知科网 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
版权声明

本文仅代表作者观点,不代表区块链技术网立场。
本文系作者授权本站发表,未经许可,不得转载。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门