1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
use ark_ec::pairing::Pairing;
use ark_ff::Zero;
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
use crate::{params::PublicParams, signature::Signature, Curve};
#[derive(Clone, PartialEq, Eq, CanonicalSerialize, CanonicalDeserialize)]
pub struct PublicKey<C>
where
C: Curve,
{
// pk = (p2^x1,...,p2^xl) where (x1,...,xl) is the secret key
pub(crate) bx: Vec<C::G2>,
}
impl<C> PublicKey<C>
where
C: Curve,
{
/// Length of the public key.
pub fn length(&self) -> usize {
self.bx.len()
}
/// Convert the public key.
/// This function converts the public key to a new public key that is equivalent to the original public key.
/// The input scalar `p` must be the same as the one used in the conversion of the secret key and the signature.
///
/// ## Example
///
/// ```rust
/// use mercurial_signature::{Curve, CurveBls12_381, PublicParams, change_representation};
/// use ark_std::UniformRand;
/// use rand::thread_rng;
///
/// type G1 = <CurveBls12_381 as Curve>::G1;
/// type Fr = <CurveBls12_381 as Curve>::Fr;
///
/// let mut rng = rand::thread_rng();
/// let pp = PublicParams::new(&mut rng);
/// let (mut pk, mut sk) = pp.key_gen(&mut rng, 10);
/// let message = (0..10).map(|_| G1::rand(&mut rng)).collect::<Vec<G1>>();
/// let mut sig = sk.sign(&mut rng, &pp, &message);
///
/// let p = Fr::rand(&mut rng);
/// pk.convert(p);
/// sk.convert(p);
/// sig.convert(&mut rng, p);
/// assert!(pk.verify(&pp, &message, &sig));
/// ```
pub fn verify(&self, pp: &PublicParams<C>, message: &[C::G1], sig: &Signature<C>) -> bool {
// check length l
if self.bx.len() < message.len() {
return false;
}
// e(y1, p2) == e(p1, y2)
let lhs = C::F::pairing(sig.y1, pp.p2);
let rhs = C::F::pairing(pp.p1, sig.y2);
if lhs != rhs {
return false;
}
// e(z, y2) == e(m1, bx1) * ... * e(ml, bxl)
let lhs = C::F::pairing(sig.z, sig.y2);
let rhs = message.iter().zip(self.bx.iter()).fold(
C::F::pairing(C::G1::zero(), C::G2::zero()),
|acc, (m, bxi)| acc + C::F::pairing(*m, *bxi),
);
lhs == rhs
}
/// Convert the public key.
/// This function converts the public key to a new public key that is equivalent to the original public key.
/// The input scalar `p` must be the same as the one used in the conversion of the secret key and the signature.
///
/// ## Example
///
/// ```rust
/// use mercurial_signature::{Curve, CurveBls12_381, PublicParams, change_representation};
/// use ark_std::UniformRand;
/// use rand::thread_rng;
///
/// type G1 = <CurveBls12_381 as Curve>::G1;
/// type Fr = <CurveBls12_381 as Curve>::Fr;
///
/// let mut rng = rand::thread_rng();
/// let pp = PublicParams::new(&mut rng);
/// let (mut pk, mut sk) = pp.key_gen(&mut rng, 10);
/// let message = (0..10).map(|_| G1::rand(&mut rng)).collect::<Vec<G1>>();
/// let mut sig = sk.sign(&mut rng, &pp, &message);
///
/// let p = Fr::rand(&mut rng);
/// pk.convert(p);
/// sk.convert(p);
/// sig.convert(&mut rng, p);
/// assert!(pk.verify(&pp, &message, &sig));
/// ```
pub fn convert(&mut self, p: C::Fr) {
self.bx.iter_mut().for_each(|bxi| *bxi *= p);
}
}