8个版本 (破坏性)

0.8.0 2023年9月20日
0.7.0 2023年7月24日
0.6.0 2023年4月16日
0.5.0 2023年3月12日
0.1.0 2022年9月24日

#951 in 密码学

每月下载量 36次

MIT许可证

170KB
3.5K SLoC

Cait-Sith

Cait-Sith是一个新的阈值ECDSA协议(和实现),它比流行的替代方案更简单、性能更高。

该协议支持任意数量的参与方和阈值。

警告

这是一款实验性加密软件,除非你是头上顶着扩音器的巨猫,否则我会谨慎行事。

  • 该协议没有正式的安全证明。
  • 该库尚未经过任何形式的审计。

设计

Cait-Sith的主要设计原则是尽可能将工作卸载到与密钥无关的预处理阶段。这种方法的优点是,这个预处理阶段可以在需要签名之前提前进行,甚至可以在确定要签名的密钥之前执行这一阶段的成果。

一个有用的场景是当在多个密钥上运行阈值托管服务时,这些预处理结果可以执行,并且可以根据需要使用,而不管最终使用哪个密钥更频繁。

详细规范可在此仓库中找到,但我们也会在这里提供一些细节。

Cait-Sith设计的核心涉及一个已提交的Beaver三元组。它们的形式为

$$ ([a], [b], [c]), (A = a \cdot G, B = b \cdot G, C = c \cdot G) $$

其中$a, b, c$是满足$a \cdot b = c$的标量,并在多个参与者之间秘密共享,因此没有人知道它们的实际值。此外,与标准Beaver三元组不同,我们还有对这些秘密值的公开承诺,这有助于在线协议。

协议的流程首先需要一种生成三元组的方法

  • 运行一次设置协议,允许各方高效地生成三元组。
  • 各方现在可以通过分布式协议生成任意数量的三元组。

然后,各方需要生成一个密钥对,以便它们可以签名消息

  • 各方运行分布式密钥生成协议来设置新的密钥对,该密钥对可用于多个签名。

当各方想要使用给定的密钥进行签名时

  • 在知道要签名的消息之前,各方可以使用私钥份额创建一个预签名
  • 一旦他们知道这条消息,他们就可以使用预签名创建完整的签名。

重要的是,预签名和三元组决不重复使用。

刷新和重新共享

除了密钥生成之外,cait-sith 还支持密钥刷新和密钥重新共享

密钥刷新为每个参与者生成新的份额,同时保持相同的参与者列表和阈值。

密钥重新共享执行同样的操作,但还允许更改阈值和参与者列表(只要足够多的旧参与者存在,以满足旧阈值)。

API 设计

在内部,API 尽可能地简单,尽可能地将细节抽象到简单的接口中。

此接口有两个方法

pub trait Protocol {
    type Output;

    fn poke(&mut self) -> Result<Action<Self::Output>, ProtocolError>;
    fn message(&mut self, from: Participant, data: MessageData);
}

给定此特质的实例,它表示参与协议的单个参与者,您可以做两件事

  • 您可以提供来自其他某个参与者的新消息。
  • 您可以“戳”协议以查看它是否需要您执行某种操作,或者是否发生错误。

此操作可以是以下之一

  • 协议告诉您已完成,返回类型为 Output 的值。
  • 协议要求您将消息发送给所有其他参与者。
  • 协议要求您向一个参与者私下发送消息。
  • 协议通知您,除非它接收到新消息,否则无法取得更多进展。

特别是,关于轮次和消息序列化的详细信息被抽象化,并全部在内部执行。实际上,协议不是围绕“轮次”设计的,其中一些更复杂的协议甚至可以在内部具有并行执行线程。

基准测试

以下是针对 Secp256k1 曲线,在 Intel Core i5-4690K CPU 上执行的基准测试。

> cargo bench -F k256

setup 3
time:   [94.689 ms 95.057 ms 95.449 ms]

triple generation (3, 3)
time:   [36.610 ms 36.682 ms 36.757 ms]

keygen (3,3)
time:   [3.0901 ms 3.1095 ms 3.1297 ms]

presign (3,3)
time:   [2.5531 ms 2.5640 ms 2.5761 ms]

sign (3,3)
time:   [446.79 µs 447.89 µs 449.02 µs]

这些测试是在同一台机器上运行 3 个参与者,且没有通信成本的情况下执行的。

请注意,对于每个签名,三元组生成需要执行两次。此外,与其他协议相比,三元组生成对带宽的需求相对较高,但这在基准测试中并未反映出来,因为网络速度不受限制。尽管如此,这种成本并不那么重要,因为它可以提前执行,且与密钥无关。

因此,应考虑预签名 + 签名的成本。这种成本足够低,很可能是网络性能的瓶颈。

网络基准测试

该库还有一个示例,运行一个模拟网络延迟和带宽限制的基准测试。请注意,在这些示例中,使用了多个线程,因此更好地反映了计算在各个节点之间并行化的实际情况。然而,我运行这些基准测试的 CPU 只具有 4 个核心,因此对大参与者基准测试要持保留态度。

以下是一个有 3 个参与者的示例,它们之间的延迟为 100ms,每个的出向链路为 10 MB/s。

> cargo run --release -F k256 --example network-benches -- 3 100 10000000  

Triple Setup 3 [100 ms, 10000000 B/S]
time:   304.884093ms
up:      10322 B
down:    10322 B

Triple Gen 3 [100 ms, 10000000 B/S]
time:   740.041888ms
up:      106202 B
down:    106202 B

Keygen (3, 3) [100 ms, 10000000 B/S]
time:   207.137969ms
up:      1068 B
down:    1068 B

Presign (3, 3) [100 ms, 10000000 B/S]
time:   104.090877ms
up:      961 B
down:    961 B

Sign (3, 3) [100 ms, 10000000 B/S]
time:   100.606562ms
up:      151 B
down:    151 B

以下是一个极端情况,有 100 个参与者,它们之间的延迟为 300ms,每个的出向链路为 1 MB/s。

> cargo run --release --example network-benches -- 100 300 1000000

Triple Setup 100 [300 ms, 1000000 B/S]
time:   51.269278194s
up:      510843 B
down:    510843 B

Triple Gen 100 [300 ms, 1000000 B/S]
time:   32.959644915s
up:      6765025 B
down:    6765025 B

Keygen (100, 100) [300 ms, 1000000 B/S]
time:   5.871460998s
up:      551527 B
down:    551527 B

Presign (100, 100) [300 ms, 1000000 B/S]
time:   2.891458487s
up:      546835 B
down:    546835 B

Sign (100, 100) [300 ms, 1000000 B/S]
time:   359.795393ms
up:      7859 B
down:    7859 B

通用曲线

该库支持通用曲线和哈希。

通用曲线的支持是通过自定义的 CSCurve 特质实现的,该特质可以轻松地针对 RustCrypto elliptic-curves 套件库中的任何曲线实现。

根据以下表格,此包还提供了一些现有曲线的实现,作为特性的实现

曲线 特性
Secp256k1 k256

为了支持任何消息哈希,API 要求用户在直接将消息作为标量进行签名时提供消息的哈希。

缺点

目前,协议及其实现确实存在一些已知的缺点。

  • 该协议确实需要预先生成三元组,但这些可以不依赖于私钥来生成。
  • 该协议不尝试提供可识别的中断。

我们也不打算在Cait-Sith本身中添加可识别的中断。虽然在某些情况下这可能是有吸引力的,但我们不满意当前对可识别中断属性建模的方式,并正在努力改进此模型。

依赖项

~8–17MB
~238K SLoC