#schnorr-signature #signature-scheme #elliptic-curve #schnorr #signatures #signature #zk-snarks

无std dusk-schnorr

这是一个纯Rust实现的施诺尔签名,并附带一个PLONK电路模块。

20个版本 (11个破坏性版本)

0.18.0 2024年1月3日
0.17.0 2023年12月13日
0.16.0 2023年11月22日
0.13.0 2023年6月28日
0.8.0-rc.02021年7月14日

#1136 in 密码学


4 个crate中使用 (3个直接使用)

MPL-2.0 许可证

60KB
654

dusk-schnorr

Build Status Repository Documentation

此crate提供了一个用于JubJub椭圆曲线群的施诺尔签名方案的Rust实现,使用Poseidon哈希函数。此实现由Dusk团队设计。

关于

施诺尔签名方案,以它的创造者克劳斯·施诺尔命名,是一种以简单著称的数字签名方案。该方案提供了一种创建短签名的简单方法。

实现使用了jubjub椭圆曲线和Poseidon哈希函数,其论文可在此处找到。

签名方案是在Phoenix事务模型中实现的,基于施诺尔Sigma协议,并与Fiat-Shamir变换一起编译,作为非交互式签名方案。具体来说,Phoenix协议使用一种变体,该变体利用双施诺尔签名,通过双公钥进行验证,允许在协议的后期阶段进行计算过程的委托。

库结构

库分为以下组件

  • 密钥:包含用于签名消息的密钥结构,以及用于验证的公钥和双公钥结构。
  • 签名:包含标准和双签名结构以及验证施诺尔签名和双施诺尔签名的函数。
  • 设备:包含用于在电路中验证施诺尔签名和双施诺尔签名的Plonk设备。

签名方案描述

符号

以下

  • 点$P$乘以标量$s$表示将$P$加到自身$s$次。
  • $\mathbb{F}_q$是阶为$q$的素数有限域
  • 对于素数$q$:$\mathbb{F}_q^× = \mathbb{F}_q \setminus 0$包含$\mathbb{F}_q$的所有非零元素。

单签名

设置

在这个库中,我们在 jubjub 椭圆曲线上实现了我们的 Schnorr 签名方案,具体来说,我们有以下内容

  • 一个有限域 $\mathbb{F}_q$,该域的基数是素数 $q$,在此实现中,该域对应于椭圆曲线 BLS12-381 的标量域
  • 一个椭圆曲线 $E / \mathbb{F}_q$,在我们的情况下,这是 jubjub 椭圆曲线
  • 一个曲线点子群 $\mathbb{G} \in E(\mathbb{F}_q)$,其阶为素数 $p$
  • 一个固定的生成点 $G \in \mathbb{G}$
  • 一个加密哈希函数 $H : {0 , 1}^∗ \rightarrow \mathbb{F}_p$,其中 $\mathbb{F}_p$ 是 jubjub 椭圆曲线的标量域。

密钥生成

  • 选择一个私钥签名密钥,$sk \in \mathbb{F}_p^×$。
  • 公共验证密钥是 $PK = skG \in \mathbb{G}$。

签名

要对消息 $m \in \mathbb{F}_q^×$ 进行签名

  • 选择一个随机的私钥随机数 $r \in \mathbb{F}_p^×$。
  • 计算随机数点 $R = rG \in \mathbb{G}$。
  • 计算挑战哈希 $c = H(R \parallel m) \in \mathbb{F}_p$,其中 $\parallel$ 表示连接,并且 $R$ 表示为位字符串。
  • 计算 $u = r − sk \cdot c \in \mathbb{F}_p$。

签名是元组 $(u, R) \in \mathbb{F}_p \times \mathbb{G}$。

验证

  • 计算挑战哈希 $c = H(R \parallel m) \in \mathbb{F}_p$。
  • 验证 $uG + cPK = R$。

如果签名是用与 $PK$ 对应的密钥签名的,这将成立,因为

$$ uG + cPK = (r - sk\cdot c)G + (sk\cdot c)G = (r - sk\cdot c + sk\cdot c)G = rG = R $$

双重签名

设置

与上述单签名相同,只是增加了另一个生成点 $G' \in \mathbb{G}$,该点不同于 $G$,且与 $G$ 的离散对数关系未知。

密钥生成

  • 选择一个私钥签名密钥,$sk \in \mathbb{F}_p^×$。
  • 公共验证密钥是元组 $(PK, PK')$,其中 $PK = skG \in \mathbb{G}$ 和 $PK' = skG' \in \mathbb{G}$。

签名

要对消息 $m \in \mathbb{F}_q^×$ 进行签名

  • 选择一个随机的私钥随机数 $r \in \mathbb{F}_p^×$。
  • 计算随机数点 $R = rG \in \mathbb{G}$ 和 $R' = rG' \in \mathbb{G}$。
  • 计算挑战哈希 $c = H(R \parallel R' \parallel m) \in \mathbb{F}_p$,其中 $\parallel$ 表示连接,并且 $R, R'$ 表示为位字符串。
  • 计算 $u = r − sk \cdot c \in \mathbb{F}_p$。

签名是元组 $(u, R, R') \in \mathbb{F}_p \times \mathbb{G} \times \mathbb{G}$。

验证

  • 计算挑战哈希 $c = H(R \parallel R' \parallel m) \in \mathbb{F}_p$。
  • 验证 $rG + cPK = R$ 和 $uG' + cPK' = R'$。

如果签名是用正确的私钥签名的,这将成立,因为

$$ uG + cPK = (r - sk\cdot c)G + (sk\cdot c)G = (r - sk\cdot c + sk\cdot c)G = rG = R $$

$$ uG' + cPK' = (r - sk\cdot c)G' + (sk\cdot c)G' = (r - sk\cdot c + sk\cdot c)G' = rG' = R' $$

关于安全性和实现的说明

所实现的签名方案在随机预言模型下,假设离散对数问题的难度,在选言攻击下是存在不可伪造的。这一特性在 Katz 和 Lindell 的《现代密码学导论》第 12.5.1 节中有详细描述。

尽管基本的 Schnorr 签名方案是一个广泛认可的构造,但 Phoenix 所使用的双密钥变体是一种新颖的引入。在交易协议的背景下,这允许在不泄露签名者密钥的机密性的情况下委托证明计算。

用法

要将 dusk-schnorr 软件包集成到您的项目中,请使用以下命令添加它

cargo add dusk-schnorr

一个基本的示例,展示如何生成和验证 Schnorr 签名

use dusk_bls12_381::BlsScalar;
use dusk_schnorr::{SecretKey, PublicKey};
use rand::rngs::StdRng;
use rand::SeedableRng;
use ff::Field;

fn main() {
    // Setup
    let mut rng = StdRng::seed_from_u64(1234u64);
    let message = BlsScalar::random(&mut rng);

    // Key generation
    let sk = SecretKey::random(&mut rng);

    // Standard Dusk-Schnorr signature scheme:
    let pk = PublicKey::from(&sk);
    let signature = sk.sign(&mut rng, message);
    assert!(pk.verify(&signature, message), "The signature should be valid.");

    // Double Dusk-Schnorr signature scheme:
    #[cfg(features = "double")]
    {
        let pk = dusk_schnorr::PublicKeyDouble::from(&sk);
        let signature = sk.sign_double(&mut rng, message);
        assert!(pk.verify(&signature, message), "The signature should be valid.");
    }

    // Dusk-Schnorr signature scheme with variable generator:
    #[cfg(features = "var_generator")]
    {
        let generator = dusk_jubjub::GENERATOR_EXTENDED * JubJubScalar::from(42u64);
        let sk = sk.with_variable_generator(generator);
        let pk = dusk_schnorr::PublicKeyVarGen::from(&sk);
        let signature = sk.sign(&mut rng, message);
        assert!(pk.verify(&signature, message), "The signature should be valid.");
    }
}

许可

此源代码形式受 Mozilla 公共许可证第 2.0 版的条款约束。如果此文件未附带 MPL 复制品,您可以在此处获得一个:http://mozilla.org/MPL/2.0/

版权所有 (c) DUSK 网络。保留所有权利。

依赖关系

~7MB
~143K SLoC