Skip to main content

abstract_integers/
abstract_int.rs

1#[macro_export]
2macro_rules! abstract_int {
3    ($name:ident, $bits:literal, $signed:literal) => {
4        #[derive(Clone, Copy)]
5        pub struct $name {
6            b: [u8; ($bits + 7) / 8],
7            sign: Sign,
8            signed: bool,
9        }
10
11        impl $name {
12            fn max() -> BigInt {
13                BigInt::from(1u32).shl($bits) - BigInt::one()
14            }
15
16            pub fn max_value() -> Self {
17                Self::from(Self::max())
18            }
19
20            fn hex_string_to_bytes(s: &str) -> Vec<u8> {
21                let s = if s.len() % 2 != 0 {
22                    let mut x = "0".to_string();
23                    x.push_str(s);
24                    x
25                } else {
26                    s.to_string()
27                };
28                assert!(s.len() % 2 == 0, "length of hex string {}: {}",s, s.len());
29                let b: Result<Vec<u8>, ParseIntError> = (0..s.len())
30                    .step_by(2)
31                    .map(|i| u8::from_str_radix(&s[i..i + 2], 16))
32                    .collect();
33                b.expect("Error parsing hex string")
34            }
35
36            #[allow(dead_code)]
37            pub fn from_literal(x: u128) -> Self {
38                let big_x = BigInt::from(x);
39                if big_x > $name::max().into() {
40                    panic!("literal {} too big for type {}", x, stringify!($name));
41                }
42                big_x.into()
43            }
44
45            #[allow(dead_code)]
46            pub fn from_signed_literal(x: i128) -> Self {
47                let big_x = BigInt::from(x as u128);
48                if big_x > $name::max().into() {
49                    panic!("literal {} too big for type {}", x, stringify!($name));
50                }
51                big_x.into()
52            }
53
54            /// Returns 2 to the power of the argument
55            #[allow(dead_code)]
56            pub fn pow2(x: usize) -> $name {
57                BigInt::from(1u32).shl(x).into()
58            }
59
60            /// Gets the `i`-th least significant bit of this integer.
61            #[allow(dead_code)]
62            pub fn bit(self, i: usize) -> bool {
63                assert!(
64                    i < self.b.len() * 8,
65                    "the bit queried should be lower than the size of the integer representation: {} < {}",
66                    i,
67                    self.b.len() * 8
68                );
69                let bigint : BigInt = self.into();
70                let tmp: BigInt = bigint >> i;
71                (tmp & BigInt::one()).to_bytes_le().1[0] == 1
72            }
73        }
74
75        impl From<BigUint> for $name {
76            fn from(x: BigUint) -> $name {
77                Self::from(BigInt::from(x))
78            }
79        }
80
81        impl From<BigInt> for $name {
82            fn from(x: BigInt) -> $name {
83                let max_value = Self::max();
84                assert!(x <= max_value, "{} is too large for type {}!", x, stringify!($name));
85                let (sign, repr) = x.to_bytes_be();
86                if sign == Sign::Minus && (!$signed) {
87                    panic!("Trying to convert a negative number into an unsigned integer!")
88                }
89                if repr.len() > ($bits + 7) / 8 {
90                    panic!("{} is too large for type {}", x, stringify!($name))
91                }
92                let mut out = [0u8; ($bits + 7) / 8];
93                let upper = out.len();
94                let lower = upper - repr.len();
95                out[lower..upper].copy_from_slice(&repr);
96                $name {
97                    b: out,
98                    sign: sign,
99                    signed: $signed,
100                }
101            }
102        }
103
104        impl Default for $name {
105            fn default() -> $name {
106                $name {
107                    b: [0u8; ($bits + 7) / 8],
108                    sign: Sign::Plus,
109                    signed: $signed,
110                }
111            }
112        }
113
114        impl Into<BigInt> for $name {
115            fn into(self) -> BigInt {
116                BigInt::from_bytes_be(self.sign, &self.b)
117            }
118        }
119
120        impl Into<BigUint> for $name {
121            fn into(self) -> BigUint {
122                BigUint::from_bytes_be(&self.b)
123            }
124        }
125
126        impl core::fmt::Display for $name {
127            fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
128                let uint: BigInt = (*self).into();
129                write!(f, "{}", uint)
130            }
131        }
132
133        impl core::fmt::Debug for $name {
134            fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
135                let uint: BigInt = (*self).into();
136                write!(f, "{}", uint)
137            }
138        }
139
140        impl core::fmt::LowerHex for $name {
141            fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
142                let val: BigInt = (*self).into();
143                core::fmt::LowerHex::fmt(&val, f)
144            }
145        }
146    };
147}
148
149#[macro_export]
150macro_rules! abstract_public {
151    ($name:ident) => {
152        impl $name {
153            #[allow(dead_code)]
154            pub fn inv(self, modval: Self) -> Self {
155                let biguintmodval: BigInt = modval.into();
156                let m = &biguintmodval - BigInt::from(2u32);
157                let s: BigInt = (self).into();
158                s.modpow(&m, &biguintmodval).into()
159            }
160
161            #[allow(dead_code)]
162            pub fn pow_felem(self, exp: Self, modval: Self) -> Self {
163                let a: BigInt = self.into();
164                let b: BigInt = exp.into();
165                let m: BigInt = modval.into();
166                let c: BigInt = a.modpow(&b, &m);
167                c.into()
168            }
169            /// Returns self to the power of the argument.
170            /// The exponent is a u128.
171            #[allow(dead_code)]
172            pub fn pow(self, exp: u128, modval: Self) -> Self {
173                self.pow_felem(BigInt::from(exp).into(), modval)
174            }
175
176            fn rem(self, n: Self) -> Self {
177                self % n
178            }
179        }
180
181        /// **Warning**: panics on overflow.
182        impl Add for $name {
183            type Output = $name;
184            fn add(self, rhs: $name) -> $name {
185                let a: BigInt = self.into();
186                let b: BigInt = rhs.into();
187                let c = a + b;
188                if c > $name::max() {
189                    panic!("bounded addition overflow for type {}", stringify!($name));
190                }
191                c.into()
192            }
193        }
194
195        /// **Warning**: panics on underflow.
196        impl Sub for $name {
197            type Output = $name;
198            fn sub(self, rhs: $name) -> $name {
199                let a: BigInt = self.into();
200                let b: BigInt = rhs.into();
201                let c = if self.signed {
202                    a - b
203                } else {
204                    a.checked_sub(&b).unwrap_or_else(|| {
205                        panic!(
206                            "bounded substraction underflow for type {}",
207                            stringify!($name)
208                        )
209                    })
210                };
211                c.into()
212            }
213        }
214
215        /// **Warning**: panics on overflow.
216        impl Mul for $name {
217            type Output = $name;
218            fn mul(self, rhs: $name) -> $name {
219                let a: BigInt = self.into();
220                let b: BigInt = rhs.into();
221                let c = a * b;
222                if c > $name::max() {
223                    panic!(
224                        "bounded multiplication overflow for type {}",
225                        stringify!($name)
226                    );
227                }
228                c.into()
229            }
230        }
231
232        /// **Warning**: panics on division by 0.
233        impl Div for $name {
234            type Output = $name;
235            fn div(self, rhs: $name) -> $name {
236                let a: BigInt = self.into();
237                let b: BigInt = rhs.into();
238                if b == BigInt::zero() {
239                    panic!("dividing by zero in type {}", stringify!($name));
240                }
241                let c = a / b;
242                c.into()
243            }
244        }
245
246        /// **Warning**: panics on division by 0.
247        impl Rem for $name {
248            type Output = $name;
249            fn rem(self, rhs: $name) -> $name {
250                let a: BigInt = self.into();
251                let b: BigInt = rhs.into();
252                if b == BigInt::zero() {
253                    panic!("dividing by zero in type {}", stringify!($name));
254                }
255                let c = a % b;
256                c.into()
257            }
258        }
259
260        impl Not for $name {
261            type Output = $name;
262            fn not(self) -> Self::Output {
263                unimplemented!();
264            }
265        }
266
267        impl BitOr for $name {
268            type Output = $name;
269            fn bitor(self, rhs: Self) -> Self::Output {
270                let a: BigInt = self.into();
271                let b: BigInt = rhs.into();
272                (a | b).into()
273            }
274        }
275
276        impl BitXor for $name {
277            type Output = $name;
278            fn bitxor(self, rhs: Self) -> Self::Output {
279                let a: BigInt = self.into();
280                let b: BigInt = rhs.into();
281                (a ^ b).into()
282            }
283        }
284
285        impl BitAnd for $name {
286            type Output = $name;
287            fn bitand(self, rhs: Self) -> Self::Output {
288                let a: BigInt = self.into();
289                let b: BigInt = rhs.into();
290                (a & b).into()
291            }
292        }
293
294        impl Shr<usize> for $name {
295            type Output = $name;
296            fn shr(self, rhs: usize) -> Self::Output {
297                let a: BigInt = self.into();
298                let b = rhs as usize;
299                (a >> b).into()
300            }
301        }
302
303        impl Shl<usize> for $name {
304            type Output = $name;
305            fn shl(self, rhs: usize) -> Self::Output {
306                let a: BigInt = self.into();
307                let b = rhs as usize;
308                (a << b).into()
309            }
310        }
311
312        impl PartialEq for $name {
313            fn eq(&self, rhs: &$name) -> bool {
314                let a: BigInt = (*self).into();
315                let b: BigInt = (*rhs).into();
316                a == b
317            }
318        }
319
320        impl Eq for $name {}
321
322        impl PartialOrd for $name {
323            fn partial_cmp(&self, other: &$name) -> Option<core::cmp::Ordering> {
324                let a: BigInt = (*self).into();
325                let b: BigInt = (*other).into();
326                a.partial_cmp(&b)
327            }
328        }
329
330        impl Ord for $name {
331            fn cmp(&self, other: &$name) -> core::cmp::Ordering {
332                self.partial_cmp(other).unwrap()
333            }
334        }
335    };
336}
337
338#[macro_export]
339macro_rules! abstract_unsigned {
340    ($name:ident, $bits:literal) => {
341        abstract_int!($name, $bits, false);
342
343        impl $name {
344            #[allow(dead_code)]
345            pub fn from_hex(s: &str) -> Self {
346                BigInt::from_bytes_be(Sign::Plus, &Self::hex_string_to_bytes(s)).into()
347            }
348
349            #[allow(dead_code)]
350            pub fn from_be_bytes(v: &[u8]) -> Self {
351                debug_assert!(
352                    v.len() <= ($bits + 7) / 8,
353                    "from_be_bytes: lenght of bytes should be lesser than the lenght of the canvas"
354                );
355                let mut repr = [0u8; ($bits + 7) / 8];
356                let upper = repr.len();
357                let lower = upper - v.len();
358                repr[lower..upper].copy_from_slice(&v);
359                $name {
360                    b: repr,
361                    sign: Sign::Plus,
362                    signed: false,
363                }
364            }
365
366            #[allow(dead_code)]
367            pub fn from_le_bytes(v: &[u8]) -> Self {
368                debug_assert!(
369                    v.len() <= ($bits + 7) / 8,
370                    "from_be_bytes: lenght of bytes should be lesser than the lenght of the canvas"
371                );
372                let mut repr = [0u8; ($bits + 7) / 8];
373                let upper = repr.len();
374                let lower = upper - v.len();
375                repr[lower..upper].copy_from_slice(&v);
376                BigInt::from_bytes_le(Sign::Plus, &repr).into()
377            }
378
379            #[allow(dead_code)]
380            pub fn to_be_bytes(self) -> [u8; ($bits + 7) / 8] {
381                self.b
382            }
383
384            #[allow(dead_code)]
385            pub fn to_le_bytes(self) -> [u8; ($bits + 7) / 8] {
386                let x = BigInt::from_bytes_be(Sign::Plus, &self.b);
387                let (_, x_s) = x.to_bytes_le();
388                let mut repr = [0u8; ($bits + 7) / 8];
389                repr[0..x_s.len()].copy_from_slice(&x_s);
390                repr
391            }
392
393            /// Produces a new integer which is all ones if the two arguments are equal and
394            /// all zeroes otherwise.
395            /// **NOTE:** This is not constant time but `BigInt` generally isn't.
396            #[inline]
397            pub fn comp_eq(self, rhs: Self) -> Self {
398                let a: BigInt = self.into();
399                let b: BigInt = rhs.into();
400                if a == b {
401                    let one = Self::from_literal(1);
402                    (one << ($bits - 1)) - one
403                } else {
404                    Self::default()
405                }
406            }
407
408            /// Produces a new integer which is all ones if the first argument is different from
409            /// the second argument, and all zeroes otherwise.
410            /// **NOTE:** This is not constant time but `BigInt` generally isn't.
411            #[inline]
412            pub fn comp_ne(self, rhs: Self) -> Self {
413                let a: BigInt = self.into();
414                let b: BigInt = rhs.into();
415                if a != b {
416                    let one = Self::from_literal(1);
417                    (one << ($bits - 1)) - one
418                } else {
419                    Self::default()
420                }
421            }
422
423            /// Produces a new integer which is all ones if the first argument is greater than or
424            /// equal to the second argument, and all zeroes otherwise.
425            /// **NOTE:** This is not constant time but `BigInt` generally isn't.
426            #[inline]
427            pub fn comp_gte(self, rhs: Self) -> Self {
428                let a: BigInt = self.into();
429                let b: BigInt = rhs.into();
430                if a >= b {
431                    let one = Self::from_literal(1);
432                    (one << ($bits - 1)) - one
433                } else {
434                    Self::default()
435                }
436            }
437
438            /// Produces a new integer which is all ones if the first argument is strictly greater
439            /// than the second argument, and all zeroes otherwise.
440            /// **NOTE:** This is not constant time but `BigInt` generally isn't.
441            #[inline]
442            pub fn comp_gt(self, rhs: Self) -> Self {
443                let a: BigInt = self.into();
444                let b: BigInt = rhs.into();
445                if a > b {
446                    let one = Self::from_literal(1);
447                    (one << ($bits - 1)) - one
448                } else {
449                    Self::default()
450                }
451            }
452
453            /// Produces a new integer which is all ones if the first argument is less than or
454            /// equal to the second argument, and all zeroes otherwise.
455            /// **NOTE:** This is not constant time but `BigInt` generally isn't.
456            #[inline]
457            pub fn comp_lte(self, rhs: Self) -> Self {
458                let a: BigInt = self.into();
459                let b: BigInt = rhs.into();
460                if a <= b {
461                    let one = Self::from_literal(1);
462                    (one << ($bits - 1)) - one
463                } else {
464                    Self::default()
465                }
466            }
467
468            /// Produces a new integer which is all ones if the first argument is strictly less than
469            /// the second argument, and all zeroes otherwise.
470            /// **NOTE:** This is not constant time but `BigInt` generally isn't.
471            #[inline]
472            pub fn comp_lt(self, rhs: Self) -> Self {
473                let a: BigInt = self.into();
474                let b: BigInt = rhs.into();
475                if a < b {
476                    let one = Self::from_literal(1);
477                    (one << ($bits - 1)) - one
478                } else {
479                    Self::default()
480                }
481            }
482        }
483    };
484}
485
486#[macro_export]
487macro_rules! abstract_signed {
488    ($name:ident, $bits:literal) => {
489        abstract_int!($name, $bits, true);
490
491        impl $name {
492            #[allow(dead_code)]
493            pub fn from_hex(sign: &str, s: &str) -> Self {
494                let sign = match sign {
495                    "+" => Sign::Plus,
496                    "-" => Sign::Minus,
497                    "" => Sign::NoSign,
498                    _ => panic!("from_hex requires the first argument to be + or -"),
499                };
500                BigInt::from_bytes_be(sign, &Self::hex_string_to_bytes(s)).into()
501            }
502        }
503    };
504}
505
506#[macro_export]
507macro_rules! abstract_unsigned_public_integer {
508    ($name:ident, $bits:literal) => {
509        abstract_unsigned!($name, $bits);
510        abstract_public!($name);
511    };
512}
513
514#[macro_export]
515macro_rules! abstract_signed_public_integer {
516    ($name:ident, $bits:literal) => {
517        abstract_signed!($name, $bits);
518        abstract_public!($name);
519    };
520}
521
522// FIXME: Implement ct algorithms.
523#[macro_export]
524macro_rules! abstract_secret {
525    ($name:ident, $bits:literal) => {
526        impl $name {
527            pub fn declassify(self) -> BigInt {
528                self.into()
529            }
530
531            fn rem(self, n: Self) -> Self {
532                let a: BigInt = self.into();
533                let b: BigInt = n.into();
534                if b == BigInt::zero() {
535                    panic!("dividing by zero in type {}", stringify!($name));
536                }
537                let c = a % b;
538                c.into()
539            }
540        }
541
542        /// **Warning**: panics on overflow.
543        impl Add for $name {
544            type Output = $name;
545            fn add(self, rhs: $name) -> $name {
546                let a: BigInt = self.into();
547                let b: BigInt = rhs.into();
548                let c = a + b;
549                if c > $name::max() {
550                    panic!("bounded addition overflow for type {}", stringify!($name));
551                }
552                c.into()
553            }
554        }
555
556        /// **Warning**: panics on underflow.
557        impl Sub for $name {
558            type Output = $name;
559            fn sub(self, rhs: $name) -> $name {
560                let a: BigInt = self.into();
561                let b: BigInt = rhs.into();
562                let c = a.checked_sub(&b).unwrap_or_else(|| {
563                    panic!(
564                        "bounded substraction underflow for type {}",
565                        stringify!($name)
566                    )
567                });
568                c.into()
569            }
570        }
571
572        /// **Warning**: panics on overflow.
573        impl Mul for $name {
574            type Output = $name;
575            fn mul(self, rhs: $name) -> $name {
576                let a: BigInt = self.into();
577                let b: BigInt = rhs.into();
578                let c = a * b;
579                if c > $name::max() {
580                    panic!(
581                        "bounded multiplication overflow for type {}",
582                        stringify!($name)
583                    );
584                }
585                c.into()
586            }
587        }
588
589        impl Not for $name {
590            type Output = $name;
591            fn not(self) -> Self::Output {
592                unimplemented!();
593            }
594        }
595
596        impl BitOr for $name {
597            type Output = $name;
598            fn bitor(self, rhs: Self) -> Self::Output {
599                let a: BigInt = self.into();
600                let b: BigInt = rhs.into();
601                (a | b).into()
602            }
603        }
604
605        impl BitXor for $name {
606            type Output = $name;
607            fn bitxor(self, rhs: Self) -> Self::Output {
608                let a: BigInt = self.into();
609                let b: BigInt = rhs.into();
610                (a ^ b).into()
611            }
612        }
613
614        impl BitAnd for $name {
615            type Output = $name;
616            fn bitand(self, rhs: Self) -> Self::Output {
617                let a: BigInt = self.into();
618                let b: BigInt = rhs.into();
619                (a & b).into()
620            }
621        }
622
623        impl Shr<usize> for $name {
624            type Output = $name;
625            fn shr(self, rhs: usize) -> Self::Output {
626                let a: BigInt = self.into();
627                (a >> rhs).into()
628            }
629        }
630
631        impl Shl<usize> for $name {
632            type Output = $name;
633            fn shl(self, rhs: usize) -> Self::Output {
634                let a: BigInt = self.into();
635                (a << rhs).into()
636            }
637        }
638    };
639}
640
641#[macro_export]
642macro_rules! abstract_unsigned_secret_integer {
643    ($name:ident, $bits:literal) => {
644        abstract_unsigned!($name, $bits);
645        abstract_secret!($name, $bits);
646    };
647}
648
649#[macro_export]
650macro_rules! abstract_signed_secret_integer {
651    ($name:ident, $bits:literal) => {
652        abstract_signed!($name, $bits);
653        abstract_secret!($name, $bits);
654    };
655}
656
657// ============ Legacy API ============
658
659/// Defines a bounded natural integer with regular arithmetic operations, checked for overflow
660/// and underflow.
661#[macro_export]
662macro_rules! define_abstract_integer_checked {
663    ($name:ident, $bits:literal) => {
664        abstract_unsigned_public_integer!($name, $bits);
665    };
666}