Proof (of knowledge) of exponentiation

1. Proof of exponentiation

Proof of exponentiation时基于adaptive root assumption(充分必要条件)的。
在这里插入图片描述
在这里插入图片描述
特别适合当 x x 很大时,计算 r = x   m o d   l ,   u r r=x\ mod\ l,\ u^r 将大量节约verifier直接计算 u x u^x 的时间。
在这里插入图片描述

借助Fiat-Shamir heuristic,可将上面的交互式PoE转化为NI-PoE:
在这里插入图片描述
对应在https://github.com/dignifiedquire/rust-accumulators/blob/master/src/proofs.rs中的实现为:

/// NI-PoE Prove
/// Assumes `u^x = w`
/// All operations are `mod n`.
pub fn ni_poe_prove(x: &BigUint, u: &BigUint, w: &BigUint, n: &BigUint) -> ExponentProof {
    debug_assert!(&u.modpow(x, n) == w, "invalid input");

    // l <- H_prime(x, u, w)
    let mut to_hash = x.to_bytes_be();
    to_hash.extend(&u.to_bytes_be());
    to_hash.extend(&w.to_bytes_be());

    let l = hash_prime::<_, Blake2b>(&to_hash);

    // q <- floor(x/l)
    let q = x.div_floor(&l);

    //Prover sends Q <- u^q ∈ G to the Verifier.
    u.modpow(&q, n)
}

/// NI-PoE Verify
/// Assumes `u^x = w`
/// All operations are `mod n`.
pub fn ni_poe_verify(
    x: &BigUint,
    u: &BigUint,
    w: &BigUint,
    q: &ExponentProof,
    n: &BigUint,
) -> bool {
    // l <- H_prime(x, u, w)
    let mut to_hash = x.to_bytes_be();
    to_hash.extend(&u.to_bytes_be());
    to_hash.extend(&w.to_bytes_be());

    let l = hash_prime::<_, Blake2b>(&to_hash);

    // r <- x mod l
    let r = x.mod_floor(&l);

    // Q^l u^r == w
    &((q.modpow(&l, &n) * &u.modpow(&r, &n)) % n) == w
}

// 基于hash值来获取prime数值。
// When the proofs are made non-interactive, using the
// Fiat-Shamir heuristic the challenge is generated by hashing the previous transcript

/// Hash the given numbers to a prime number.
/// Currently uses only 128bits.
pub fn hash_prime<O: ArrayLength<u8>, D: Digest<OutputSize = O>>(input: &[u8]) -> BigUint {
    let mut y = BigUint::from_bytes_be(&D::digest(input)[..16]);

    while !probably_prime(&y, 20) {
        y = BigUint::from_bytes_be(&D::digest(&y.to_bytes_be())[..16]);
    }

    y
}

2. Proof of knowledge of exponentiation

2.1 有安全攻击隐患的PoKE

在这里插入图片描述
在这里插入图片描述
此时,verifier不需要自己计算余数 r r ,改由prover提供。同时注意,此时要求discrete logarithm base g g 必须被包含在CRS中 \Rightarrow 存在安全攻击问题,不是secure protocol:
在这里插入图片描述

2.2 基于base g g u u 的两次PoKE

对witness x x 的证明,做了两次PoKE证明,一次是base g g ,一次是base u u
在这里插入图片描述
以上,proof中包含了两个group元素 Q Q Q和Q' 。如下,通过增加一个challenge α \alpha ,可以将proof中的group元素仍然减为1个 Q Q
在这里插入图片描述
借助Fiat-Shamir heuristic,可将上面的交互式PoKE2转化为NI-PoKE2:
在这里插入图片描述
对应在https://github.com/dignifiedquire/rust-accumulators/blob/master/src/proofs.rs中的实现为:

//proof of knowledge of exponent, i.e. a proof that a computationally bounded prover knows the discrete logarithm between two elements in a group of unknown order. The proof is succinct in that the proof size and verification time is independent of the size of the discrete-log.

/// NI-PoKE2 Prove
/// assumes `u^x = w`
/// All operations are `mod n`.
pub fn ni_poke2_prove(
    x: impl Into<BigInt>,
    u: &BigUint,
    w: &BigUint,
    n: &BigUint,
) -> (BigUint, BigUint, BigInt) {
    let x: BigInt = x.into();

    debug_assert!(&modpow_uint_int(u, &x, n).unwrap() == w, "invalid input");

    // g <- H_G(u, w)
    let mut to_hash = u.to_bytes_be();
    to_hash.extend(&w.to_bytes_be());
    let g = hash_group::<_, Blake2b>(&to_hash, n);

    // z = g^x
    let z = modpow_uint_int(&g, &x, n).expect("invalid state");

    // l <- H_prime(u, w, z)
    to_hash.extend(&z.to_bytes_be());
    let l: BigInt = hash_prime::<_, Blake2b>(&to_hash).into();

    // alpha = H(u, w, z, l)
    to_hash.extend(&l.to_bytes_be().1);
    let alpha = BigUint::from_bytes_be(&Blake2b::digest(&to_hash)[..]);

    // q <- floor(x/l)
    // r <- x % l
    let (q, r) = x.div_rem(&l);

    // Q <- (ug^alpha)^q
    let q_big = modpow_uint_int(&(u * &g.modpow(&alpha, n)), &q, n).expect("invalid state");

    (z, q_big, r)
}

/// NI-PoKE2 Verify
/// assumes `u^x = w`
/// All operations are `mod n`
pub fn ni_poke2_verify(
    u: &BigUint,
    w: &BigUint,
    pi: &(BigUint, BigUint, BigInt),
    n: &BigUint,
) -> bool {
    // {z, Q, r} <- pi
    let (z, q_big, r) = pi;

    // g <- H_G(u, w)
    let mut to_hash = u.to_bytes_be();
    to_hash.extend(&w.to_bytes_be());
    let g = hash_group::<_, Blake2b>(&to_hash, n);

    // l <- H_prime(u, w, z)
    to_hash.extend(&z.to_bytes_be());
    let l = hash_prime::<_, Blake2b>(&to_hash);

    // alpha = H(u, w, z, l)
    to_hash.extend(&l.to_bytes_be());
    let alpha = BigUint::from_bytes_be(&Blake2b::digest(&to_hash)[..]);

    // Q^l(ug^alpha)^r
    let lhs: BigInt = ((q_big.modpow(&l, n)
        * modpow_uint_int(&(u * &g.modpow(&alpha, n)), &r, n).expect("invalid state"))
        % n)
        .into();

    // wz^alpha
    let z_alpha = z.modpow(&alpha, n);
    let rhs: BigInt = ((w * z_alpha) % n).into();

    lhs == rhs
}

3. Aggreating Knowledge of Co-prime Roots

在第2节中,已可证明 u x = w u^x=w ,若有一系列的co-prime roots x 1 , . . . , x n x_1,...,x_n 满足 w i x i = α i w_i^{x_i}=\alpha_i g c d ( x i , x j ) = 1 i , j [ 1 , n ] , i ! = j gcd(x_i,x_j)=1\forall i,j\in[1,n],i!=j
在这里插入图片描述
在这里插入图片描述
https://github.com/cambrian/accumulator/中也有相应的代码实现,且实现的性能要优于https://github.com/dignifiedquire/rust-accumulators/
``

#[allow(non_snake_case)]
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
/// Struct for NI-PoKCR.
pub struct Pokcr<G: Group> {
  w: G::Elem,
}

impl<G: Group> Pokcr<G> {
  /// Generates an NI-PoKCR proof.
  pub fn prove(witnesses: &[G::Elem]) -> Self {
    Self {
      w: witnesses.iter().fold(G::id(), |a, b| G::op(&a, b)),
    }
  }

  /// Verifies an NI-PoKCR proof.
  pub fn verify(alphas: &[G::Elem], x: &[Integer], proof: &Self) -> bool {
    let y = multi_exp::<G>(alphas, x);
    let lhs = G::exp(&proof.w, &x.iter().product());
    lhs == y
  }
}

参考资料:
[1] 2018年论文《Batching Techniques for Accumulators with Applications to IOPs and Stateless Blockchains
[2] 博客密码学中的各种假设——DL/SDH…

发布了154 篇原创文章 · 获赞 13 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/mutourend/article/details/103455822