1use crate::impls::inner_types::*;
2use crate::*;
3use rand::Rng;
4use rand_core::{CryptoRng, RngCore};
5use subtle::CtOption;
6
7#[derive(PartialEq, Eq, serde::Serialize, serde::Deserialize)]
9pub enum ProofCommitment<C: BlsSignatureImpl> {
10 Basic(
12 #[serde(serialize_with = "traits::signature::serialize::<C, _>")]
14 #[serde(deserialize_with = "traits::signature::deserialize::<C, _>")]
15 <C as Pairing>::Signature,
16 ),
17 MessageAugmentation(
19 #[serde(serialize_with = "traits::signature::serialize::<C, _>")]
21 #[serde(deserialize_with = "traits::signature::deserialize::<C, _>")]
22 <C as Pairing>::Signature,
23 ),
24 ProofOfPossession(
26 #[serde(serialize_with = "traits::signature::serialize::<C, _>")]
28 #[serde(deserialize_with = "traits::signature::deserialize::<C, _>")]
29 <C as Pairing>::Signature,
30 ),
31}
32
33impl<C: BlsSignatureImpl> Default for ProofCommitment<C> {
34 fn default() -> Self {
35 Self::ProofOfPossession(<C as Pairing>::Signature::default())
36 }
37}
38
39impl<C: BlsSignatureImpl> Display for ProofCommitment<C> {
40 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
41 match self {
42 Self::Basic(s) => write!(f, "Basic({})", s),
43 Self::MessageAugmentation(s) => write!(f, "MessageAugmentation({})", s),
44 Self::ProofOfPossession(s) => write!(f, "ProofOfPossession({})", s),
45 }
46 }
47}
48
49impl<C: BlsSignatureImpl> fmt::Debug for ProofCommitment<C> {
50 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
51 match self {
52 Self::Basic(s) => write!(f, "Basic({:?})", s),
53 Self::MessageAugmentation(s) => write!(f, "MessageAugmentation({:?})", s),
54 Self::ProofOfPossession(s) => write!(f, "ProofOfPossession({:?})", s),
55 }
56 }
57}
58
59impl<C: BlsSignatureImpl> Copy for ProofCommitment<C> {}
60
61impl<C: BlsSignatureImpl> Clone for ProofCommitment<C> {
62 fn clone(&self) -> Self {
63 *self
64 }
65}
66
67impl<C: BlsSignatureImpl> subtle::ConditionallySelectable for ProofCommitment<C> {
68 fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
69 match (a, b) {
70 (Self::Basic(a), Self::Basic(b)) => {
71 Self::Basic(<C as Pairing>::Signature::conditional_select(a, b, choice))
72 }
73 (Self::MessageAugmentation(a), Self::MessageAugmentation(b)) => {
74 Self::MessageAugmentation(<C as Pairing>::Signature::conditional_select(
75 a, b, choice,
76 ))
77 }
78 (Self::ProofOfPossession(a), Self::ProofOfPossession(b)) => {
79 Self::ProofOfPossession(<C as Pairing>::Signature::conditional_select(a, b, choice))
80 }
81 _ => panic!("Cannot conditional select between different proof commitments"),
82 }
83 }
84}
85
86impl_from_derivatives_generic!(ProofCommitment);
87
88impl<C: BlsSignatureImpl> From<&ProofCommitment<C>> for Vec<u8> {
89 fn from(value: &ProofCommitment<C>) -> Self {
90 serde_bare::to_vec(value).unwrap()
91 }
92}
93
94impl<C: BlsSignatureImpl> TryFrom<&[u8]> for ProofCommitment<C> {
95 type Error = BlsError;
96
97 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
98 let len = C::Signature::default().to_bytes().as_ref().len() + 1;
99 if value.len() != len {
100 return Err(BlsError::InvalidInputs(format!(
101 "Invalid length, expected {}, got {}",
102 len,
103 value.len()
104 )));
105 }
106 serde_bare::from_slice(value).map_err(|e| BlsError::InvalidInputs(e.to_string()))
107 }
108}
109
110impl<C: BlsSignatureImpl> ProofCommitment<C> {
111 pub fn generate<B: AsRef<[u8]>>(
114 msg: B,
115 signature: Signature<C>,
116 ) -> BlsResult<(Self, ProofCommitmentSecret<C>)> {
117 match signature {
118 Signature::Basic(_) => {
119 let (u, x) = <C as BlsSignatureProof>::generate_commitment(
120 msg,
121 <C as BlsSignatureBasic>::DST,
122 )?;
123 Ok((Self::Basic(u), ProofCommitmentSecret(x)))
124 }
125 Signature::MessageAugmentation(_) => {
126 let (u, x) = <C as BlsSignatureProof>::generate_commitment(
127 msg,
128 <C as BlsSignatureMessageAugmentation>::DST,
129 )?;
130 Ok((Self::MessageAugmentation(u), ProofCommitmentSecret(x)))
131 }
132 Signature::ProofOfPossession(_) => {
133 let (u, x) = <C as BlsSignatureProof>::generate_commitment(
134 msg,
135 <C as BlsSignaturePop>::SIG_DST,
136 )?;
137 Ok((Self::ProofOfPossession(u), ProofCommitmentSecret(x)))
138 }
139 }
140 }
141
142 pub fn finalize(
145 self,
146 x: ProofCommitmentSecret<C>,
147 y: ProofCommitmentChallenge<C>,
148 sig: Signature<C>,
149 ) -> BlsResult<ProofOfKnowledge<C>> {
150 match (self, sig) {
151 (Self::Basic(u), Signature::Basic(s)) => {
152 let (u, v) = <C as BlsSignatureProof>::generate_proof(u, x.0, y.0, s)?;
153 Ok(ProofOfKnowledge::Basic { u, v })
154 }
155 (Self::MessageAugmentation(u), Signature::MessageAugmentation(s)) => {
156 let (u, v) = <C as BlsSignatureProof>::generate_proof(u, x.0, y.0, s)?;
157 Ok(ProofOfKnowledge::MessageAugmentation { u, v })
158 }
159 (Self::ProofOfPossession(u), Signature::ProofOfPossession(s)) => {
160 let (u, v) = <C as BlsSignatureProof>::generate_proof(u, x.0, y.0, s)?;
161 Ok(ProofOfKnowledge::ProofOfPossession { u, v })
162 }
163 (_, _) => Err(BlsError::InvalidProof),
164 }
165 }
166}
167
168#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
170pub struct ProofCommitmentSecret<C: BlsSignatureImpl>(
171 #[serde(serialize_with = "traits::scalar::serialize::<C, _>")]
173 #[serde(deserialize_with = "traits::scalar::deserialize::<C, _>")]
174 pub <<C as Pairing>::PublicKey as Group>::Scalar,
175);
176
177impl_from_derivatives_generic!(ProofCommitmentSecret);
178
179impl<C: BlsSignatureImpl> From<&ProofCommitmentSecret<C>> for Vec<u8> {
180 fn from(value: &ProofCommitmentSecret<C>) -> Self {
181 scalar_to_be_bytes::<C, SECRET_KEY_BYTES>(value.0).to_vec()
182 }
183}
184
185impl<C: BlsSignatureImpl> TryFrom<&[u8]> for ProofCommitmentSecret<C> {
186 type Error = BlsError;
187
188 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
189 let bytes = <[u8; 32]>::try_from(value)
190 .map_err(|_| BlsError::InvalidInputs("Invalid secret key bytes".to_string()))?;
191 let value = scalar_from_be_bytes::<C, SECRET_KEY_BYTES>(&bytes).map(Self);
192 Option::from(value)
193 .ok_or_else(|| BlsError::InvalidInputs("Invalid secret key bytes".to_string()))
194 }
195}
196
197impl<C: BlsSignatureImpl> ProofCommitmentSecret<C> {
198 pub fn to_be_bytes(&self) -> [u8; SECRET_KEY_BYTES] {
200 scalar_to_be_bytes::<C, SECRET_KEY_BYTES>(self.0)
201 }
202
203 pub fn to_le_bytes(&self) -> [u8; SECRET_KEY_BYTES] {
205 scalar_to_le_bytes::<C, SECRET_KEY_BYTES>(self.0)
206 }
207
208 pub fn from_be_bytes(bytes: &[u8; SECRET_KEY_BYTES]) -> CtOption<Self> {
210 scalar_from_be_bytes::<C, SECRET_KEY_BYTES>(bytes).map(Self)
211 }
212
213 pub fn from_le_bytes(bytes: &[u8; SECRET_KEY_BYTES]) -> CtOption<Self> {
215 scalar_from_le_bytes::<C, SECRET_KEY_BYTES>(bytes).map(Self)
216 }
217}
218
219#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
222pub struct ProofCommitmentChallenge<C: BlsSignatureImpl>(
223 #[serde(serialize_with = "traits::scalar::serialize::<C, _>")]
225 #[serde(deserialize_with = "traits::scalar::deserialize::<C, _>")]
226 pub <<C as Pairing>::PublicKey as Group>::Scalar,
227);
228
229impl_from_derivatives_generic!(ProofCommitmentChallenge);
230
231impl<C: BlsSignatureImpl> From<&ProofCommitmentChallenge<C>> for Vec<u8> {
232 fn from(value: &ProofCommitmentChallenge<C>) -> Self {
233 scalar_to_be_bytes::<C, SECRET_KEY_BYTES>(value.0).to_vec()
234 }
235}
236
237impl<C: BlsSignatureImpl> TryFrom<&[u8]> for ProofCommitmentChallenge<C> {
238 type Error = BlsError;
239
240 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
241 let bytes = <[u8; 32]>::try_from(value)
242 .map_err(|_| BlsError::InvalidInputs("Invalid secret key bytes".to_string()))?;
243 let value = scalar_from_be_bytes::<C, SECRET_KEY_BYTES>(&bytes).map(Self);
244 Option::from(value)
245 .ok_or_else(|| BlsError::InvalidInputs("Invalid secret key bytes".to_string()))
246 }
247}
248
249impl<C: BlsSignatureImpl> ProofCommitmentChallenge<C> {
250 pub fn new() -> Self {
252 Self::random(get_crypto_rng())
253 }
254
255 pub fn from_hash<B: AsRef<[u8]>>(data: B) -> Self {
257 Self(<C as HashToScalar>::hash_to_scalar(
258 data.as_ref(),
259 KEYGEN_SALT,
260 ))
261 }
262
263 pub fn random(mut rng: impl RngCore + CryptoRng) -> Self {
265 Self(<C as HashToScalar>::hash_to_scalar(
266 rng.r#gen::<[u8; SECRET_KEY_BYTES]>(),
267 KEYGEN_SALT,
268 ))
269 }
270
271 pub fn to_be_bytes(&self) -> [u8; SECRET_KEY_BYTES] {
273 scalar_to_be_bytes::<C, SECRET_KEY_BYTES>(self.0)
274 }
275
276 pub fn to_le_bytes(&self) -> [u8; SECRET_KEY_BYTES] {
278 scalar_to_le_bytes::<C, SECRET_KEY_BYTES>(self.0)
279 }
280
281 pub fn from_be_bytes(bytes: &[u8; SECRET_KEY_BYTES]) -> CtOption<Self> {
283 scalar_from_be_bytes::<C, SECRET_KEY_BYTES>(bytes).map(Self)
284 }
285
286 pub fn from_le_bytes(bytes: &[u8; SECRET_KEY_BYTES]) -> CtOption<Self> {
288 scalar_from_le_bytes::<C, SECRET_KEY_BYTES>(bytes).map(Self)
289 }
290}