Mina Learning - Signature
Schnorr signature
sign
输入 kp=(sk, pk), input 输出签名 sig=(s, R.x)
- 使用 derive_nonce(kp, msg) 生成随机数 k
- 计算 $R = k \cdot g$
- 判断 R.x 是否是偶数, 否则 k = -k
- 计算 e = H(pk, R.x, input)
- 计算签名 s = k + e * sk
verify
输入 sig, pk, msg 输出: bool
- 计算 e = H(pk, R.x, input)
- 计算 $S = s \cdot g$
- 计算 $R'= S - e \cdot pk $
- 判断 R'.y 是偶数且 R'.x=R.x
derive_nonce
- Blake2bVar(input, pk.x, pk.y, sk, domain_param)
- 将 hash 值高两位置0(因为 Scalar 是255位, 高两位置0, 能保证 hash 值一定在 Scalar域内)
- 将处理后的 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
- poseidon(input, pk.x, pk.y, R.x)
- 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,
}
}
版权声明
本文仅代表作者观点,不代表区块链技术网立场。
本文系作者授权本站发表,未经许可,不得转载。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。