Skip to main content

rabe_bn/
arith.rs

1use std::cmp::Ordering;
2use rand::Rng;
3use core::fmt;
4use byteorder::{ByteOrder, BigEndian, WriteBytesExt};
5use std::iter::FromIterator;
6#[cfg(feature = "borsh")]
7use borsh::{BorshSerialize, BorshDeserialize};
8#[cfg(feature = "serde")]
9use serde::{Serialize, Deserialize};
10
11/// 256-bit, stack allocated biginteger for use in prime field
12/// arithmetic.
13#[derive(Copy, Clone, PartialEq, Eq, Debug)]
14#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))]
15#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
16#[repr(C)]
17pub struct U256(pub [u64; 4]);
18
19impl From<[u64; 4]> for U256 {
20    fn from(d: [u64; 4]) -> Self {
21        U256(d)
22    }
23}
24
25/// 512-bit, stack allocated biginteger for use in extension
26/// field serialization and scalar interpretation.
27#[derive(Copy, Clone, PartialEq, Eq, Debug)]
28#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))]
29#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
30#[repr(C)]
31pub struct U512(pub [u64; 8]);
32
33impl U512 {
34    /// Multiplies c1 by modulo, adds c0.
35    #[allow(dead_code)]
36    pub fn from(c1: &U256, c0: &U256, modulo: &U256) -> U512 {
37        let mut res = [0; 8];
38
39        for (i, xi) in c1.0.iter().enumerate() {
40            mac_digit(&mut res[i..], &modulo.0, *xi);
41        }
42
43        let mut c0_iter = c0.0.iter();
44        let mut carry = 0;
45
46        for ai in res.iter_mut() {
47            if let Some(bi) = c0_iter.next() {
48                *ai = adc(*ai, *bi, &mut carry);
49            } else if carry != 0 {
50                *ai = adc(*ai, 0, &mut carry);
51            } else {
52                break;
53            }
54        }
55
56        debug_assert!(0 == carry);
57
58        U512(res)
59    }
60
61    /// Get a random U512
62    pub fn random<R: Rng + ?Sized>(rng: &mut R) -> U512 {
63        U512(rng.gen())
64    }
65
66    pub fn get_bit(&self, n: usize) -> Option<bool> {
67        if n >= 512 {
68            None
69        } else {
70            let part = n / 64;
71            let bit = n - (64 * part);
72
73            Some(self.0[part] & (1 << bit) > 0)
74        }
75    }
76
77    /// Divides self by modulo, returning remainder and, if
78    /// possible, a quotient smaller than the modulus.
79    pub fn divrem(&self, modulo: &U256) -> (Option<U256>, U256) {
80        let mut q = Some(U256::zero());
81        let mut r = U256::zero();
82
83        for i in (0..512).rev() {
84            // NB: modulo's first two bits are always unset
85            // so this will never destroy information
86            mul2(&mut r.0);
87            assert!(r.set_bit(0, self.get_bit(i).unwrap()));
88            if &r >= modulo {
89                sub_noborrow(&mut r.0, &modulo.0);
90                if q.is_some() && !q.as_mut().unwrap().set_bit(i, true) {
91                    q = None
92                }
93            }
94        }
95
96        if q.is_some() && (q.as_ref().unwrap() >= modulo) {
97            (None, r)
98        } else {
99            (q, r)
100        }
101    }
102
103    pub fn interpret(buf: &[u8; 64]) -> U512 {
104        let mut n = [0; 8];
105        for (l, i) in (0..8).rev().zip((0..8).map(|i| i * 8)) {
106            n[l] = BigEndian::read_u64(&buf[i..]);
107        }
108
109        U512(n)
110    }
111}
112
113impl fmt::Display for U512 {
114    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
115        let mut str = String::new();
116        for tup in self.0.iter() {
117            str.push_str(format!("{:#X?}", tup).as_ref())
118        }
119        write!(f, "{:?}", str)
120    }
121}
122
123impl FromIterator<u64> for U512 {
124    fn from_iter<I: IntoIterator<Item=u64>>(iter: I) -> Self {
125        let mut barry: Vec<u8> = Vec::new();
126        for word in iter {
127            for v in word.to_le_bytes() {
128                barry.push(v)
129            }
130        }
131        let mut array = [0u8; 64];
132        for (&x, p) in barry.iter().zip(array.iter_mut()) {
133            *p = x;
134        }
135        U512::interpret(&array)
136    }
137}
138
139impl fmt::Display for U256 {
140    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
141        let mut str = String::new();
142        for tup in self.0.iter() {
143            str.push_str(format!("{:#X?}", tup).as_ref())
144        }
145        write!(f, "{:?}", str)
146    }
147}
148
149impl Ord for U256 {
150    #[inline]
151    fn cmp(&self, other: &U256) -> Ordering {
152        for (a, b) in self.0.iter().zip(other.0.iter()).rev() {
153            if *a < *b {
154                return Ordering::Less;
155            } else if *a > *b {
156                return Ordering::Greater;
157            }
158        }
159
160        return Ordering::Equal;
161    }
162}
163
164impl PartialOrd for U256 {
165    #[inline]
166    fn partial_cmp(&self, other: &U256) -> Option<Ordering> {
167        Some(self.cmp(other))
168    }
169}
170
171/// U256/U512 errors
172#[derive(Debug)]
173pub enum Error {
174    InvalidLength { expected: usize, actual: usize },
175}
176
177impl U256 {
178    /// Initialize U256 from slice of bytes (big endian)
179    pub fn from_slice(s: &[u8]) -> Result<U256, Error> {
180        if s.len() != 32 {
181            return Err(Error::InvalidLength {
182                expected: 32,
183                actual: s.len(),
184            });
185        }
186
187        let mut n = [0; 4];
188        for (l, i) in (0..4).rev().zip((0..4).map(|i| i * 8)) {
189            n[l] = BigEndian::read_u64(&s[i..]);
190        }
191
192        Ok(U256(n))
193    }
194    #[inline]
195    pub fn zero() -> U256 {
196        U256([0, 0, 0, 0])
197    }
198
199    #[inline]
200    pub fn one() -> U256 {
201        U256([1, 0, 0, 0])
202    }
203
204    #[inline]
205    pub fn into_bytes(&self) -> Vec<u8> {
206        let mut wtr = vec![];
207        for elem in self.0 {
208            wtr.write_u64::<BigEndian>(elem).unwrap();
209        }
210        wtr
211    }
212
213    /// Produce a random number (mod `modulo`)
214    pub fn random<R: Rng + ?Sized>(rng: &mut R, modulo: &U256) -> U256 {
215        U512::random(rng).divrem(modulo).1
216    }
217
218    pub fn is_zero(&self) -> bool {
219        self.0[0] == 0 && self.0[1] == 0 && self.0[2] == 0 && self.0[3] == 0
220    }
221
222    pub fn set_bit(&mut self, n: usize, to: bool) -> bool {
223        if n >= 256 {
224            false
225        } else {
226            let part = n / 64;
227            let bit = n - (64 * part);
228
229            if to {
230                self.0[part] |= 1 << bit;
231            } else {
232                self.0[part] &= !(1 << bit);
233            }
234
235            true
236        }
237    }
238
239    pub fn get_bit(&self, n: usize) -> Option<bool> {
240        if n >= 256 {
241            None
242        } else {
243            let part = n / 64;
244            let bit = n - (64 * part);
245
246            Some(self.0[part] & (1 << bit) > 0)
247        }
248    }
249
250    /// Add `other` to `self` (mod `modulo`)
251    pub fn add(&mut self, other: &U256, modulo: &U256) {
252        add_nocarry(&mut self.0, &other.0);
253
254        if *self >= *modulo {
255            sub_noborrow(&mut self.0, &modulo.0);
256        }
257    }
258
259    /// Subtract `other` from `self` (mod `modulo`)
260    pub fn sub(&mut self, other: &U256, modulo: &U256) {
261        if *self < *other {
262            add_nocarry(&mut self.0, &modulo.0);
263        }
264
265        sub_noborrow(&mut self.0, &other.0);
266    }
267
268    /// Multiply `self` by `other` (mod `modulo`) via the Montgomery
269    /// multiplication method.
270    pub fn mul(&mut self, other: &U256, modulo: &U256, inv: u64) {
271        mul_reduce(&mut self.0, &other.0, &modulo.0, inv);
272
273        if *self >= *modulo {
274            sub_noborrow(&mut self.0, &modulo.0);
275        }
276    }
277
278    /// Turn `self` into its additive inverse (mod `modulo`)
279    pub fn neg(&mut self, modulo: &U256) {
280        if *self > Self::zero() {
281            let mut tmp = modulo.0;
282            sub_noborrow(&mut tmp, &self.0);
283
284            self.0 = tmp;
285        }
286    }
287
288    #[inline]
289    pub fn is_even(&self) -> bool {
290        self.0[0] & 1 == 0
291    }
292
293    /// Turn `self` into its multiplicative inverse (mod `modulo`)
294    pub fn invert(&mut self, modulo: &U256) {
295        // Guajardo Kumar Paar Pelzl
296        // Efficient Software-Implementation of Finite Fields with Applications to Cryptography
297        // Algorithm 16 (BEA for Inversion in Fp)
298
299        let mut u = *self;
300        let mut v = *modulo;
301        let mut b = U256::one();
302        let mut c = U256::zero();
303
304        while u != U256::one() && v != U256::one() {
305            while u.is_even() {
306                div2(&mut u.0);
307
308                if b.is_even() {
309                    div2(&mut b.0);
310                } else {
311                    add_nocarry(&mut b.0, &modulo.0);
312                    div2(&mut b.0);
313                }
314            }
315            while v.is_even() {
316                div2(&mut v.0);
317
318                if c.is_even() {
319                    div2(&mut c.0);
320                } else {
321                    add_nocarry(&mut c.0, &modulo.0);
322                    div2(&mut c.0);
323                }
324            }
325
326            if u >= v {
327                sub_noborrow(&mut u.0, &v.0);
328                b.sub(&c, modulo);
329            } else {
330                sub_noborrow(&mut v.0, &u.0);
331                c.sub(&b, modulo);
332            }
333        }
334
335        if u == U256::one() {
336            self.0 = b.0;
337        } else {
338            self.0 = c.0;
339        }
340    }
341
342    /// Return an Iterator<Item=bool> over all bits from
343    /// MSB to LSB.
344    pub fn bits(&self) -> BitIterator {
345        BitIterator { int: &self, n: 256 }
346    }
347}
348
349pub struct BitIterator<'a> {
350    int: &'a U256,
351    n: usize,
352}
353
354impl<'a> Iterator for BitIterator<'a> {
355    type Item = bool;
356
357    fn next(&mut self) -> Option<bool> {
358        if self.n == 0 {
359            None
360        } else {
361            self.n -= 1;
362
363            self.int.get_bit(self.n)
364        }
365    }
366}
367
368/// Divide by two
369#[inline]
370fn div2(a: &mut [u64; 4]) {
371    let mut t = a[3] << 63;
372    a[3] = a[3] >> 1;
373    let b = a[2] << 63;
374    a[2] >>= 1;
375    a[2] |= t;
376    t = a[1] << 63;
377    a[1] >>= 1;
378    a[1] |= b;
379    a[0] >>= 1;
380    a[0] |= t;
381}
382
383/// Multiply by two
384#[inline]
385fn mul2(a: &mut [u64; 4]) {
386    let mut last = 0;
387    for i in a {
388        let tmp = *i >> 63;
389        *i <<= 1;
390        *i |= last;
391        last = tmp;
392    }
393}
394
395#[inline(always)]
396fn split_u64(i: u64) -> (u64, u64) {
397    (i >> 32, i & 0xFFFFFFFF)
398}
399
400#[inline(always)]
401fn combine_u64(hi: u64, lo: u64) -> u64 {
402    (hi << 32) | lo
403}
404
405#[inline]
406fn adc(a: u64, b: u64, carry: &mut u64) -> u64 {
407    let (a1, a0) = split_u64(a);
408    let (b1, b0) = split_u64(b);
409    let (c, r0) = split_u64(a0 + b0 + *carry);
410    let (c, r1) = split_u64(a1 + b1 + c);
411    *carry = c;
412
413    combine_u64(r1, r0)
414}
415
416#[inline]
417fn add_nocarry(a: &mut [u64; 4], b: &[u64; 4]) {
418    let mut carry = 0;
419
420    for (a, b) in a.into_iter().zip(b.iter()) {
421        *a = adc(*a, *b, &mut carry);
422    }
423
424    debug_assert!(0 == carry);
425}
426
427#[inline]
428fn sub_noborrow(a: &mut [u64; 4], b: &[u64; 4]) {
429    #[inline]
430    fn sbb(a: u64, b: u64, borrow: &mut u64) -> u64 {
431        let (a1, a0) = split_u64(a);
432        let (b1, b0) = split_u64(b);
433        let (b, r0) = split_u64((1 << 32) + a0 - b0 - *borrow);
434        let (b, r1) = split_u64((1 << 32) + a1 - b1 - ((b == 0) as u64));
435
436        *borrow = (b == 0) as u64;
437
438        combine_u64(r1, r0)
439    }
440
441    let mut borrow = 0;
442
443    for (a, b) in a.into_iter().zip(b.iter()) {
444        *a = sbb(*a, *b, &mut borrow);
445    }
446
447    debug_assert!(0 == borrow);
448}
449
450fn mac_digit(acc: &mut [u64], b: &[u64], c: u64) {
451    #[inline]
452    fn mac_with_carry(a: u64, b: u64, c: u64, carry: &mut u64) -> u64 {
453        let (b_hi, b_lo) = split_u64(b);
454        let (c_hi, c_lo) = split_u64(c);
455
456        let (a_hi, a_lo) = split_u64(a);
457        let (carry_hi, carry_lo) = split_u64(*carry);
458        let (x_hi, x_lo) = split_u64(b_lo * c_lo + a_lo + carry_lo);
459        let (y_hi, y_lo) = split_u64(b_lo * c_hi);
460        let (z_hi, z_lo) = split_u64(b_hi * c_lo);
461        let (r_hi, r_lo) = split_u64(x_hi + y_lo + z_lo + a_hi + carry_hi);
462
463        *carry = (b_hi * c_hi) + r_hi + y_hi + z_hi;
464
465        combine_u64(r_lo, x_lo)
466    }
467
468    if c == 0 {
469        return;
470    }
471
472    let mut b_iter = b.iter();
473    let mut carry = 0;
474
475    for ai in acc.iter_mut() {
476        if let Some(bi) = b_iter.next() {
477            *ai = mac_with_carry(*ai, *bi, c, &mut carry);
478        } else if carry != 0 {
479            *ai = mac_with_carry(*ai, 0, c, &mut carry);
480        } else {
481            break;
482        }
483    }
484
485    debug_assert!(carry == 0);
486}
487
488#[inline]
489fn mul_reduce(this: &mut [u64; 4], by: &[u64; 4], modulus: &[u64; 4], inv: u64) {
490    // The Montgomery reduction here is based on Algorithm 14.32 in
491    // Handbook of Applied Cryptography
492    // <http://cacr.uwaterloo.ca/hac/about/chap14.pdf>.
493
494    let mut res = [0; 2 * 4];
495    for (i, xi) in this.iter().enumerate() {
496        mac_digit(&mut res[i..], by, *xi);
497    }
498
499    for i in 0..4 {
500        let k = inv.wrapping_mul(res[i]);
501        mac_digit(&mut res[i..], modulus, k);
502    }
503
504    this.copy_from_slice(&res[4..]);
505}
506
507#[test]
508fn setting_bits() {
509    let rng = &mut ::rand::thread_rng();
510    let modulo = U256([0xffffffffffffffff; 4]);
511
512    let a = U256::random(rng, &modulo);
513    let mut e = U256::zero();
514    for (i, b) in a.bits().enumerate() {
515        assert!(e.set_bit(255 - i, b));
516    }
517
518    assert_eq!(a, e);
519}
520
521#[test]
522fn testing_divrem() {
523    let rng = &mut ::rand::thread_rng();
524
525    let modulo = U256(
526        [
527            0x3c208c16d87cfd47,
528            0x97816a916871ca8d,
529            0xb85045b68181585d,
530            0x30644e72e131a029,
531        ],
532    );
533
534    for _ in 0..100 {
535        let c0 = U256::random(rng, &modulo);
536        let c1 = U256::random(rng, &modulo);
537
538        let c1q_plus_c0 = U512::from(&c1, &c0, &modulo);
539
540        let (new_c1, new_c0) = c1q_plus_c0.divrem(&modulo);
541
542        assert_eq!(c1, new_c1.unwrap());
543        assert_eq!(c0, new_c0);
544    }
545
546    {
547        // Modulus should become 1*q + 0
548        let a = U512(
549            [
550                0x3c208c16d87cfd47,
551                0x97816a916871ca8d,
552                0xb85045b68181585d,
553                0x30644e72e131a029,
554                0,
555                0,
556                0,
557                0,
558            ],
559        );
560
561        let (c1, c0) = a.divrem(&modulo);
562        assert_eq!(c1.unwrap(), U256::one());
563        assert_eq!(c0, U256::zero());
564    }
565
566    {
567        // Modulus squared minus 1 should be (q-1) q + q-1
568        let a = U512(
569            [
570                0x3b5458a2275d69b0,
571                0xa602072d09eac101,
572                0x4a50189c6d96cadc,
573                0x04689e957a1242c8,
574                0x26edfa5c34c6b38d,
575                0xb00b855116375606,
576                0x599a6f7c0348d21c,
577                0x0925c4b8763cbf9c,
578            ],
579        );
580
581        let (c1, c0) = a.divrem(&modulo);
582        assert_eq!(
583            c1.unwrap(),
584            U256(
585                [
586                    0x3c208c16d87cfd46,
587                    0x97816a916871ca8d,
588                    0xb85045b68181585d,
589                    0x30644e72e131a029,
590                ],
591            )
592        );
593        assert_eq!(
594            c0,
595            U256(
596                [
597                    0x3c208c16d87cfd46,
598                    0x97816a916871ca8d,
599                    0xb85045b68181585d,
600                    0x30644e72e131a029,
601                ],
602            )
603        );
604    }
605
606    {
607        // Modulus squared minus 2 should be (q-1) q + q-2
608        let a = U512(
609            [
610                0x3b5458a2275d69af,
611                0xa602072d09eac101,
612                0x4a50189c6d96cadc,
613                0x04689e957a1242c8,
614                0x26edfa5c34c6b38d,
615                0xb00b855116375606,
616                0x599a6f7c0348d21c,
617                0x0925c4b8763cbf9c,
618            ],
619        );
620
621        let (c1, c0) = a.divrem(&modulo);
622
623        assert_eq!(
624            c1.unwrap(),
625            U256(
626                [
627                    0x3c208c16d87cfd46,
628                    0x97816a916871ca8d,
629                    0xb85045b68181585d,
630                    0x30644e72e131a029,
631                ],
632            )
633        );
634        assert_eq!(
635            c0,
636            U256(
637                [
638                    0x3c208c16d87cfd45,
639                    0x97816a916871ca8d,
640                    0xb85045b68181585d,
641                    0x30644e72e131a029,
642                ],
643            )
644        );
645    }
646
647    {
648        // Ridiculously large number should fail
649        let a = U512(
650            [
651                0xffffffffffffffff,
652                0xffffffffffffffff,
653                0xffffffffffffffff,
654                0xffffffffffffffff,
655                0xffffffffffffffff,
656                0xffffffffffffffff,
657                0xffffffffffffffff,
658                0xffffffffffffffff,
659            ],
660        );
661
662        let (c1, c0) = a.divrem(&modulo);
663        assert!(c1.is_none());
664        assert_eq!(
665            c0,
666            U256(
667                [
668                    0xf32cfc5b538afa88,
669                    0xb5e71911d44501fb,
670                    0x47ab1eff0a417ff6,
671                    0x06d89f71cab8351f,
672                ],
673            )
674        );
675    }
676
677    {
678        // Modulus squared should fail
679        let a = U512(
680            [
681                0x3b5458a2275d69b1,
682                0xa602072d09eac101,
683                0x4a50189c6d96cadc,
684                0x04689e957a1242c8,
685                0x26edfa5c34c6b38d,
686                0xb00b855116375606,
687                0x599a6f7c0348d21c,
688                0x0925c4b8763cbf9c,
689            ],
690        );
691
692        let (c1, c0) = a.divrem(&modulo);
693        assert!(c1.is_none());
694        assert_eq!(c0, U256::zero());
695    }
696
697    {
698        // Modulus squared plus one should fail
699        let a = U512(
700            [
701                0x3b5458a2275d69b2,
702                0xa602072d09eac101,
703                0x4a50189c6d96cadc,
704                0x04689e957a1242c8,
705                0x26edfa5c34c6b38d,
706                0xb00b855116375606,
707                0x599a6f7c0348d21c,
708                0x0925c4b8763cbf9c,
709            ],
710        );
711
712        let (c1, c0) = a.divrem(&modulo);
713        assert!(c1.is_none());
714        assert_eq!(c0, U256::one());
715    }
716
717    {
718        let modulo = U256(
719            [
720                0x43e1f593f0000001,
721                0x2833e84879b97091,
722                0xb85045b68181585d,
723                0x30644e72e131a029,
724            ],
725        );
726
727        // Fr modulus masked off is valid
728        let a = U512(
729            [
730                0xffffffffffffffff,
731                0xffffffffffffffff,
732                0xffffffffffffffff,
733                0xffffffffffffffff,
734                0xffffffffffffffff,
735                0xffffffffffffffff,
736                0xffffffffffffffff,
737                0x07ffffffffffffff,
738            ],
739        );
740
741        let (c1, c0) = a.divrem(&modulo);
742
743        assert!(c1.unwrap() < modulo);
744        assert!(c0 < modulo);
745    }
746}