-
Notifications
You must be signed in to change notification settings - Fork 15
/
double_pop.rs
180 lines (159 loc) · 6.72 KB
/
double_pop.rs
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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
//! ## Implementation of ProofofPossion trait for Double BLS public keys using
//! the scheme described in [https://eprint.iacr.org/2022/1611] which also
//! complies with the proof of possession proposed in
//! [draft-irtf-cfrg-bls-signature-05](https://www.ietf.org/archive/id/draft-irtf-cfrg-bls-signature-05.html)
use crate::engine::EngineBLS;
use crate::{Message, ProofOfPossession, ProofOfPossessionGenerator};
use crate::double::DoublePublicKey;
use crate::serialize::SerializableToBytes;
use crate::single::Keypair;
use alloc::vec::Vec;
use constcat;
use digest::DynDigest;
use ark_ec::Group;
use ark_ff::field_hashers::{DefaultFieldHasher, HashToField};
const PROOF_OF_POSSESSION_CONTEXT: &'static [u8] = b"POP_";
const BLS_CONTEXT: &'static [u8] = b"BLS_";
/// Proof Of Possession of the secret key as the secret scaler genarting both public
/// keys in G1 and G2 by generating a BLS Signature of public key (in G2)
pub struct BLSPoP<E: EngineBLS>(pub E::SignatureGroup);
impl<E: EngineBLS> BLSPoP<E> {
fn bls_pop_context<H: DynDigest + Default + Clone>() -> Vec<u8> {
[
<BLSPoP<E> as ProofOfPossession<E, H, DoublePublicKey<E>>>::POP_DOMAIN_SEPARATION_TAG,
E::CURVE_NAME,
E::SIG_GROUP_NAME,
E::CIPHER_SUIT_DOMAIN_SEPARATION,
PROOF_OF_POSSESSION_CONTEXT,
]
.concat()
}
}
//The bls proof of possession for single or double public key schemes are the same
impl<E: EngineBLS, H: DynDigest + Default + Clone>
ProofOfPossessionGenerator<E, H, DoublePublicKey<E>, BLSPoP<E>> for Keypair<E>
{
fn generate_pok(&mut self) -> BLSPoP<E> {
//We simply classicaly BLS sign public key in G2 based on https://eprint.iacr.org/2022/1611
let public_key_as_bytes = self.public.to_bytes();
let sigma_pop = self.sign(&Message::new(
<BLSPoP<E>>::bls_pop_context::<H>().as_slice(),
&public_key_as_bytes.as_slice(),
));
BLSPoP::<E>(sigma_pop.0)
}
}
/// The verification process for verifying both possession of one secret key
/// for two public key is different.
impl<E: EngineBLS, H: DynDigest + Default + Clone> ProofOfPossession<E, H, DoublePublicKey<E>>
for BLSPoP<E>
{
const POP_DOMAIN_SEPARATION_TAG: &'static [u8] =
constcat::concat_bytes!(BLS_CONTEXT, PROOF_OF_POSSESSION_CONTEXT,);
//can't constcat generic parameter trait's const :-(
//E::CURVE_NAME, E::SIG_GROUP_NAME, E::CIPHER_SUIT_DOMAIN_SEPARATION,
// will do in runtime.
/// verify the validity of PoP by performing the following Pairing
/// e(H_pop(pk_2) + t.g_1, pk_2) = e(sign(H_pop(pk_2))+ t.pk_1, g_2)
/// we verifying by calling the verify_prepared ⎈function from the
/// engine.
fn verify(&self, public_key_of_prover: &DoublePublicKey<E>) -> bool {
//First we need to generate our randomness in a way that
//prover is unable to predict. We assume g1 and g2 are fixed.
let public_key_as_bytes =
<E as EngineBLS>::public_key_point_to_byte(&public_key_of_prover.1);
let public_key_in_signature_group = public_key_of_prover.0;
let public_key_in_signature_group_as_bytes =
E::signature_point_to_byte(&public_key_in_signature_group);
let public_key_hashed_to_signature_group = Message::new(
<BLSPoP<E>>::bls_pop_context::<H>().as_slice(),
&public_key_as_bytes,
)
.hash_to_signature_curve::<E>();
let public_key_hashed_to_signature_group_as_bytes =
E::signature_point_to_byte(&public_key_hashed_to_signature_group);
let random_oracle_seed = [
public_key_hashed_to_signature_group_as_bytes,
public_key_as_bytes,
public_key_in_signature_group_as_bytes,
E::signature_point_to_byte(&self.0),
]
.concat();
let hasher = <DefaultFieldHasher<H> as HashToField<
<<E as EngineBLS>::PublicKeyGroup as Group>::ScalarField,
>>::new(&[]);
let randomization_coefficient: E::Scalar =
hasher.hash_to_field(random_oracle_seed.as_slice(), 1)[0];
let mut randomized_pub_in_g1 = public_key_in_signature_group;
randomized_pub_in_g1 *= randomization_coefficient;
let signature = E::prepare_signature(self.0 + randomized_pub_in_g1);
let prepared_public_key = E::prepare_public_key(public_key_of_prover.1);
let prepared = [
(
prepared_public_key.clone(),
E::prepare_signature(public_key_hashed_to_signature_group),
),
(
prepared_public_key.clone(),
E::prepare_signature(E::generator_of_signature_group() * randomization_coefficient),
),
];
E::verify_prepared(signature, prepared.iter())
}
}
#[cfg(all(test, feature = "std"))]
mod tests {
use crate::double::DoublePublicKeyScheme;
use crate::engine::ZBLS;
use crate::single::Keypair;
use crate::{double_pop::BLSPoP, DoublePublicKey};
use crate::{ProofOfPossession, ProofOfPossessionGenerator};
use rand::thread_rng;
use sha2::Sha256;
#[test]
fn nugget_bls_pop_sign() {
let mut keypair = Keypair::<ZBLS>::generate(thread_rng());
<Keypair<ZBLS> as ProofOfPossessionGenerator<
ZBLS,
Sha256,
DoublePublicKey<ZBLS>,
BLSPoP<ZBLS>,
>>::generate_pok(&mut keypair);
}
#[test]
fn nugget_bls_pop_sign_and_verify() {
let mut keypair = Keypair::<ZBLS>::generate(thread_rng());
let proof_pair = <dyn ProofOfPossessionGenerator<
ZBLS,
Sha256,
DoublePublicKey<ZBLS>,
BLSPoP<ZBLS>,
>>::generate_pok(&mut keypair);
assert!(
ProofOfPossession::<ZBLS, Sha256, DoublePublicKey::<ZBLS>>::verify(
&proof_pair,
&DoublePublicKeyScheme::into_double_public_key(&keypair)
),
"valid pok does not verify"
);
}
#[test]
fn nugget_bls_pop_of_random_public_key_should_fail() {
use crate::{ProofOfPossession, ProofOfPossessionGenerator};
let mut keypair_good = Keypair::<ZBLS>::generate(thread_rng());
let proof_pair = <dyn ProofOfPossessionGenerator<
ZBLS,
Sha256,
DoublePublicKey<ZBLS>,
BLSPoP<ZBLS>,
>>::generate_pok(&mut keypair_good);
let keypair_bad = Keypair::<ZBLS>::generate(thread_rng());
assert!(
!ProofOfPossession::<ZBLS, Sha256, DoublePublicKey::<ZBLS>>::verify(
&proof_pair,
&DoublePublicKeyScheme::into_double_public_key(&keypair_bad)
),
"invalid pok of unrelated public key should not verify"
);
}
}