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

Mina Learning - Signature

liumuhui 8个月前 (01-28) 阅读数 147 #区块链
文章标签 OpenBuildMina公链

Schnorr signature

sign

输入 kp=(sk, pk), input 输出签名 sig=(s, R.x)

  1. 使用 derive_nonce(kp, msg) 生成随机数 k
  2. 计算 $R = k \cdot g$
  3. 判断 R.x 是否是偶数, 否则 k = -k
  4. 计算 e = H(pk, R.x, input)
  5. 计算签名 s = k + e * sk

verify

输入 sig, pk, msg 输出: bool

  1. 计算 e = H(pk, R.x, input)
  2. 计算 $S = s \cdot g$
  3. 计算 $R'= S - e \cdot pk $
  4. 判断 R'.y 是偶数且 R'.x=R.x

derive_nonce

  1. Blake2bVar(input, pk.x, pk.y, sk, domain_param)
  2. 将 hash 值高两位置0(因为 Scalar 是255位, 高两位置0, 能保证 hash 值一定在 Scalar域内)
  3. 将处理后的 hash 值转成 Scalar k
    /// This function uses a cryptographic hash function to create a uniformly and
    /// randomly distributed nonce.  It is crucial for security that no two different
    /// messages share the same nonce.
    fn derive_nonce(&self, kp: &Keypair, input: &H) -> ScalarField {
        let mut blake_hasher = Blake2bVar::new(32).unwrap();

        let roi = input
            .to_roinput()
            .append_field(kp.public.point().x)
            .append_field(kp.public.point().y)
            .append_scalar(*kp.secret.scalar())
            .append_bytes(&self.domain_param.clone().into_bytes());

        blake_hasher.update(&roi.to_bytes());

        let mut bytes = [0; 32];
        blake_hasher
            .finalize_variable(&mut bytes)
            .expect("incorrect output size");
        // Drop the top two bits to convert into a scalar field element
        //   N.B. Since the order of Pallas's scalar field p is very close to 2^m
        //   for some m, truncating only creates a tiny amount of bias that should
        //   be insignificant and better than reduction modulo p.
        bytes[bytes.len() - 1] &= 0b0011_1111;

        ScalarField::from_random_bytes(&bytes[..]).expect("failed to create scalar from bytes")
    }

message_hash

  1. poseidon(input, pk.x, pk.y, R.x)
  2. hash 值转成 Scalar(涉及到 Base 域的值转 Scalar 域)
    fn message_hash(&mut self, pub_key: &PubKey, rx: BaseField, input: &H) -> ScalarField {
        let schnorr_input = Message::<H> {
            input: input.clone(),
            pub_key_x: pub_key.point().x,
            pub_key_y: pub_key.point().y,
            rx,
        };

        // Squeeze and convert from base field element to scalar field element
        // Since the difference in modulus between the two fields is < 2^125, w.h.p., a
        // random value from one field will fit in the other field.
        ScalarField::from(self.hasher.hash(&schnorr_input).into_bigint())
    }

Poseidon

Mina hash 主要使用 Poseidon, 主要原因应该是 Poseidon zk-friendly, 生成电路约束较(SHA256, Keccak256 ...)少.

Mina 使用下面两种, 区别是 Poseidon 参数不同. 详细请看 params.sage.

pub(crate) fn create_legacy<H: 'static + Hashable>(domain_param: H::D) -> impl Signer<H> {
    Schnorr::<H> {
        hasher: Box::new(mina_hasher::create_legacy::<Message<H>>(
            domain_param.clone(),
        )),
        domain_param,
    }
}

pub(crate) fn create_kimchi<H: 'static + Hashable>(domain_param: H::D) -> impl Signer<H> {
    Schnorr::<H> {
        hasher: Box::new(mina_hasher::create_kimchi::<Message<H>>(
            domain_param.clone(),
        )),
        domain_param,
    }
}
版权声明

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

发表评论:

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

热门