1use crate::{
4 Curve, Error, FieldBytes, Result,
5 array::Array,
6 bigint::{AddMod, ConstOne, ConstZero, Integer, Limb, NegMod, Odd, RandomMod, SubMod, Zero},
7 ctutils::{self, CtEq, CtGt, CtLt, CtSelect},
8 field,
9 scalar::{FromUintUnchecked, IsHigh},
10};
11use base16ct::HexDisplay;
12use common::Generate;
13use core::{
14 cmp::Ordering,
15 fmt,
16 ops::{Add, AddAssign, Neg, ShrAssign, Sub, SubAssign},
17 str,
18};
19use rand_core::{CryptoRng, TryCryptoRng};
20use subtle::{
21 Choice, ConditionallySelectable, ConstantTimeEq, ConstantTimeGreater, ConstantTimeLess,
22 CtOption,
23};
24use zeroize::DefaultIsZeroes;
25
26#[cfg(feature = "arithmetic")]
27use super::{CurveArithmetic, Scalar};
28
29#[cfg(feature = "serde")]
30use serdect::serde::{Deserialize, Serialize, de, ser};
31
32#[derive(Copy, Clone, Debug, Default)]
46pub struct ScalarValue<C: Curve> {
47 inner: C::Uint,
49}
50
51impl<C> ScalarValue<C>
52where
53 C: Curve,
54{
55 pub const ZERO: Self = Self {
57 inner: C::Uint::ZERO,
58 };
59
60 pub const ONE: Self = Self {
62 inner: C::Uint::ONE,
63 };
64
65 pub const MODULUS: Odd<C::Uint> = C::ORDER;
67
68 pub fn new(uint: C::Uint) -> CtOption<Self> {
70 CtOption::new(
71 Self { inner: uint },
72 CtLt::ct_lt(&uint, &Self::MODULUS).into(),
73 )
74 }
75
76 pub fn from_bytes(bytes: &FieldBytes<C>) -> CtOption<Self> {
78 Self::new(field::bytes_to_uint::<C>(bytes))
79 }
80
81 pub fn from_slice(slice: &[u8]) -> Result<Self> {
87 let bytes = Array::try_from(slice).map_err(|_| Error)?;
88 Self::from_bytes(&bytes).into_option().ok_or(Error)
89 }
90
91 pub fn as_uint(&self) -> &C::Uint {
93 &self.inner
94 }
95
96 pub fn as_limbs(&self) -> &[Limb] {
98 self.inner.as_ref()
99 }
100
101 pub fn is_zero(&self) -> Choice {
103 self.inner.is_zero().into()
104 }
105
106 pub fn is_even(&self) -> Choice {
108 self.inner.is_even().into()
109 }
110
111 pub fn is_odd(&self) -> Choice {
113 self.inner.is_odd().into()
114 }
115
116 pub fn to_bytes(&self) -> FieldBytes<C> {
118 field::uint_to_bytes::<C>(&self.inner)
119 }
120
121 pub fn to_uint(&self) -> C::Uint {
123 self.inner
124 }
125
126 #[deprecated(since = "0.14.0", note = "use the `Generate` trait instead")]
128 pub fn random<R: CryptoRng + ?Sized>(rng: &mut R) -> Self {
129 Self::generate_from_rng(rng)
130 }
131}
132
133impl<C> From<u64> for ScalarValue<C>
134where
135 C: Curve,
136{
137 fn from(n: u64) -> Self {
138 Self {
139 inner: C::Uint::from(n),
140 }
141 }
142}
143
144impl<C> FromUintUnchecked for ScalarValue<C>
145where
146 C: Curve,
147{
148 type Uint = C::Uint;
149
150 fn from_uint_unchecked(uint: C::Uint) -> Self {
151 Self { inner: uint }
152 }
153}
154
155impl<C> Generate for ScalarValue<C>
156where
157 C: Curve,
158{
159 fn try_generate_from_rng<R: TryCryptoRng + ?Sized>(
160 rng: &mut R,
161 ) -> core::result::Result<Self, R::Error> {
162 Ok(Self {
163 inner: C::Uint::try_random_mod_vartime(rng, Self::MODULUS.as_nz_ref())?,
164 })
165 }
166}
167
168#[cfg(feature = "arithmetic")]
169impl<C> ScalarValue<C>
170where
171 C: CurveArithmetic,
172{
173 pub(super) fn to_scalar(self) -> Scalar<C> {
175 Scalar::<C>::from_uint_unchecked(self.inner)
176 }
177}
178
179impl<C> AsRef<[Limb]> for ScalarValue<C>
181where
182 C: Curve,
183{
184 fn as_ref(&self) -> &[Limb] {
185 self.as_limbs()
186 }
187}
188
189impl<C> ConditionallySelectable for ScalarValue<C>
190where
191 C: Curve,
192{
193 fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
194 Self {
195 inner: C::Uint::ct_select(&a.inner, &b.inner, choice.into()),
196 }
197 }
198}
199
200impl<C> ConstantTimeEq for ScalarValue<C>
201where
202 C: Curve,
203{
204 fn ct_eq(&self, other: &Self) -> Choice {
205 self.inner.ct_eq(&other.inner).into()
206 }
207}
208
209impl<C> ConstantTimeLess for ScalarValue<C>
210where
211 C: Curve,
212{
213 fn ct_lt(&self, other: &Self) -> Choice {
214 self.inner.ct_lt(&other.inner).into()
215 }
216}
217
218impl<C> ConstantTimeGreater for ScalarValue<C>
219where
220 C: Curve,
221{
222 fn ct_gt(&self, other: &Self) -> Choice {
223 self.inner.ct_gt(&other.inner).into()
224 }
225}
226
227impl<C> CtSelect for ScalarValue<C>
228where
229 C: Curve,
230{
231 fn ct_select(&self, other: &Self, choice: ctutils::Choice) -> Self {
232 Self {
233 inner: C::Uint::ct_select(&self.inner, &other.inner, choice),
234 }
235 }
236}
237
238impl<C> CtEq for ScalarValue<C>
239where
240 C: Curve,
241{
242 fn ct_eq(&self, other: &Self) -> ctutils::Choice {
243 self.inner.ct_eq(&other.inner)
244 }
245}
246
247impl<C> CtGt for ScalarValue<C>
248where
249 C: Curve,
250{
251 fn ct_gt(&self, other: &Self) -> ctutils::Choice {
252 self.inner.ct_gt(&other.inner)
253 }
254}
255
256impl<C> CtLt for ScalarValue<C>
257where
258 C: Curve,
259{
260 fn ct_lt(&self, other: &Self) -> ctutils::Choice {
261 self.inner.ct_lt(&other.inner)
262 }
263}
264
265impl<C: Curve> DefaultIsZeroes for ScalarValue<C> {}
266
267impl<C: Curve> Eq for ScalarValue<C> {}
268
269impl<C> PartialEq for ScalarValue<C>
270where
271 C: Curve,
272{
273 fn eq(&self, other: &Self) -> bool {
274 CtEq::ct_eq(self, other).to_bool()
275 }
276}
277
278impl<C> PartialOrd for ScalarValue<C>
279where
280 C: Curve,
281{
282 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
283 Some(self.cmp(other))
284 }
285}
286
287impl<C> Ord for ScalarValue<C>
288where
289 C: Curve,
290{
291 fn cmp(&self, other: &Self) -> Ordering {
292 self.inner.cmp(&other.inner)
293 }
294}
295
296impl<C> Add<ScalarValue<C>> for ScalarValue<C>
297where
298 C: Curve,
299{
300 type Output = Self;
301
302 fn add(self, other: Self) -> Self {
303 self.add(&other)
304 }
305}
306
307impl<C> Add<&ScalarValue<C>> for ScalarValue<C>
308where
309 C: Curve,
310{
311 type Output = Self;
312
313 fn add(self, other: &Self) -> Self {
314 Self {
315 inner: self.inner.add_mod(&other.inner, Self::MODULUS.as_nz_ref()),
316 }
317 }
318}
319
320impl<C> AddAssign<ScalarValue<C>> for ScalarValue<C>
321where
322 C: Curve,
323{
324 fn add_assign(&mut self, other: Self) {
325 *self = *self + other;
326 }
327}
328
329impl<C> AddAssign<&ScalarValue<C>> for ScalarValue<C>
330where
331 C: Curve,
332{
333 fn add_assign(&mut self, other: &Self) {
334 *self = *self + other;
335 }
336}
337
338impl<C> Sub<ScalarValue<C>> for ScalarValue<C>
339where
340 C: Curve,
341{
342 type Output = Self;
343
344 fn sub(self, other: Self) -> Self {
345 self.sub(&other)
346 }
347}
348
349impl<C> Sub<&ScalarValue<C>> for ScalarValue<C>
350where
351 C: Curve,
352{
353 type Output = Self;
354
355 fn sub(self, other: &Self) -> Self {
356 Self {
357 inner: self.inner.sub_mod(&other.inner, Self::MODULUS.as_nz_ref()),
358 }
359 }
360}
361
362impl<C> SubAssign<ScalarValue<C>> for ScalarValue<C>
363where
364 C: Curve,
365{
366 fn sub_assign(&mut self, other: Self) {
367 *self = *self - other;
368 }
369}
370
371impl<C> SubAssign<&ScalarValue<C>> for ScalarValue<C>
372where
373 C: Curve,
374{
375 fn sub_assign(&mut self, other: &Self) {
376 *self = *self - other;
377 }
378}
379
380impl<C> Neg for ScalarValue<C>
381where
382 C: Curve,
383{
384 type Output = Self;
385
386 fn neg(self) -> Self {
387 Self {
388 inner: self.inner.neg_mod(Self::MODULUS.as_nz_ref()),
389 }
390 }
391}
392
393impl<C> Neg for &ScalarValue<C>
394where
395 C: Curve,
396{
397 type Output = ScalarValue<C>;
398
399 fn neg(self) -> ScalarValue<C> {
400 -*self
401 }
402}
403
404impl<C> ShrAssign<usize> for ScalarValue<C>
405where
406 C: Curve,
407{
408 fn shr_assign(&mut self, rhs: usize) {
409 self.inner >>= rhs;
410 }
411}
412
413impl<C> IsHigh for ScalarValue<C>
414where
415 C: Curve,
416{
417 fn is_high(&self) -> Choice {
418 let n_2 = Self::MODULUS.get() >> 1u32;
419 self.inner.ct_gt(&n_2).into()
420 }
421}
422
423impl<C> fmt::Display for ScalarValue<C>
424where
425 C: Curve,
426{
427 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
428 write!(f, "{self:X}")
429 }
430}
431
432impl<C> fmt::LowerHex for ScalarValue<C>
433where
434 C: Curve,
435{
436 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
437 write!(f, "{:x}", HexDisplay(&self.to_bytes()))
438 }
439}
440
441impl<C> fmt::UpperHex for ScalarValue<C>
442where
443 C: Curve,
444{
445 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
446 write!(f, "{:X}", HexDisplay(&self.to_bytes()))
447 }
448}
449
450impl<C> str::FromStr for ScalarValue<C>
451where
452 C: Curve,
453{
454 type Err = Error;
455
456 fn from_str(hex: &str) -> Result<Self> {
457 let mut bytes = FieldBytes::<C>::default();
458 base16ct::mixed::decode(hex, &mut bytes)?;
459 Self::from_bytes(&bytes).into_option().ok_or(Error)
460 }
461}
462
463#[cfg(feature = "serde")]
464impl<C> Serialize for ScalarValue<C>
465where
466 C: Curve,
467{
468 fn serialize<S>(&self, serializer: S) -> core::result::Result<S::Ok, S::Error>
469 where
470 S: ser::Serializer,
471 {
472 serdect::array::serialize_hex_upper_or_bin(&self.to_bytes(), serializer)
473 }
474}
475
476#[cfg(feature = "serde")]
477impl<'de, C> Deserialize<'de> for ScalarValue<C>
478where
479 C: Curve,
480{
481 fn deserialize<D>(deserializer: D) -> core::result::Result<Self, D::Error>
482 where
483 D: de::Deserializer<'de>,
484 {
485 let mut bytes = FieldBytes::<C>::default();
486 serdect::array::deserialize_hex_or_bin(&mut bytes, deserializer)?;
487 Self::from_bytes(&bytes)
488 .into_option()
489 .ok_or_else(|| de::Error::custom("scalar out of range"))
490 }
491}