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次
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