1. Proof of exponentiation
Proof of exponentiation是基于adaptive root assumption(充分必要条件)的。


特别适合当
x
x
x很大时,计算
r
=
x
m
o
d
l
,
u
r
r=x\ mod\ l,\ u^r
r=x mod l, ur将大量节约verifier直接计算
u
x
u^x
ux的时间。

借助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
r,改由prover提供。同时注意,此时要求discrete logarithm base
g
g
g必须被包含在CRS中
⇒
\Rightarrow
⇒ 存在安全攻击问题,不是secure protocol:

2.2 基于base g g g和 u u u的两次PoKE
对witness
x
x
x的证明,做了两次PoKE证明,一次是base
g
g
g,一次是base
u
u
u。

以上,proof中包含了两个group元素
Q
和
Q
′
Q和Q'
Q和Q′。如下,通过增加一个challenge
α
\alpha
α,可以将proof中的group元素仍然减为1个
Q
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
ux=w,若有一系列的co-prime roots
x
1
,
.
.
.
,
x
n
x_1,...,x_n
x1,...,xn满足
w
i
x
i
=
α
i
w_i^{x_i}=\alpha_i
wixi=α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
gcd(xi,xj)=1∀i,j∈[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…
本文深入探讨了基于自适应根假设的幂证明(Proof of Exponentiation),包括其非交互式版本的实现,并讨论了知识证明(Proof of Knowledge of Exponentiation)的不同形式及其安全性。此外,还介绍了如何通过聚合共同素数根的知识证明来进一步优化证明过程。
537

被折叠的 条评论
为什么被折叠?



