crypto_bigint/lib.rs
1#![no_std]
2#![cfg_attr(docsrs, feature(doc_cfg))]
3#![doc = include_str!("../README.md")]
4#![doc(
5 html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg",
6 html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg"
7)]
8#![deny(unsafe_code)]
9#![warn(
10 clippy::unwrap_used,
11 missing_docs,
12 missing_debug_implementations,
13 missing_copy_implementations,
14 rust_2018_idioms,
15 trivial_casts,
16 trivial_numeric_casts,
17 unused_qualifications
18)]
19
20//! ## Usage
21//!
22//! This crate defines a [`UInt`] type which is const generic around an inner
23//! [`Limb`] array, where a [`Limb`] is a newtype for a word-sized integer.
24//! Thus large integers are represented as a arrays of smaller integers which
25//! are sized appropriately for the CPU, giving us some assurances of how
26//! arithmetic operations over those smaller integers will behave.
27//!
28//! To obtain appropriately sized integers regardless of what a given CPU's
29//! word size happens to be, a number of portable type aliases are provided for
30//! integer sizes commonly used in cryptography, for example:
31//! [`U128`], [`U384`], [`U256`], [`U2048`], [`U3072`], [`U4096`].
32//!
33//! ### `const fn` usage
34//!
35//! The [`UInt`] type provides a number of `const fn` inherent methods which
36//! can be used for initializing and performing arithmetic on big integers in
37//! const contexts:
38//!
39//! ```
40//! use crypto_bigint::U256;
41//!
42//! // Parse a constant from a big endian hexadecimal string.
43//! pub const MODULUS: U256 =
44//! U256::from_be_hex("ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551");
45//!
46//! // Compute `MODULUS` shifted right by 1 at compile time
47//! pub const MODULUS_SHR1: U256 = MODULUS.shr_vartime(1);
48//! ```
49//!
50//! ### Trait-based usage
51//!
52//! The [`UInt`] type itself does not implement the standard arithmetic traits
53//! such as [`Add`], [`Sub`], [`Mul`], and [`Div`].
54//!
55//! To use these traits you must first pick a wrapper type which determines
56//! overflow behavior: [`Wrapping`] or [`Checked`].
57//!
58//! #### Wrapping arithmetic
59//!
60//! ```
61//! use crypto_bigint::{U256, Wrapping};
62//!
63//! let a = Wrapping(U256::MAX);
64//! let b = Wrapping(U256::ONE);
65//! let c = a + b;
66//!
67//! // `MAX` + 1 wraps back around to zero
68//! assert_eq!(c.0, U256::ZERO);
69//! ```
70//!
71//! #### Checked arithmetic
72//!
73//! ```
74//! use crypto_bigint::{U256, Checked};
75//!
76//! let a = Checked::new(U256::ONE);
77//! let b = Checked::new(U256::from(2u8));
78//! let c = a + b;
79//! assert_eq!(c.0.unwrap(), U256::from(3u8))
80//! ```
81//!
82//! ### Modular arithmetic
83//!
84//! This library has initial support for modular arithmetic in the form of the
85//! [`AddMod`], [`SubMod`], [`NegMod`], and [`MulMod`] traits, as well as the
86//! support for the [`Rem`] trait when used with a [`NonZero`] operand.
87//!
88//! ```
89//! use crypto_bigint::{AddMod, U256};
90//!
91//! // mod 3
92//! let modulus = U256::from(3u8);
93//!
94//! // 1 + 1 mod 3 = 2
95//! let a = U256::ONE.add_mod(&U256::ONE, &modulus);
96//! assert_eq!(a, U256::from(2u8));
97//!
98//! // 2 + 1 mod 3 = 0
99//! let b = a.add_mod(&U256::ONE, &modulus);
100//! assert_eq!(b, U256::ZERO);
101//! ```
102//!
103//! ### Random number generation
104//!
105//! When the `rand_core` or `rand` features of this crate are enabled, it's
106//! possible to generate random numbers using any [`CryptoRng`] by using the
107//! [`Random`] trait:
108//!
109//! ```
110//! # #[cfg(feature = "rand")]
111//! # {
112//! use crypto_bigint::{Random, U256, rand_core::OsRng};
113//!
114//! let n = U256::random(&mut OsRng);
115//! # }
116//! ```
117//!
118//! #### Modular random number generation
119//!
120//! The [`RandomMod`] trait supports generating random numbers with a uniform
121//! distribution around a given [`NonZero`] modulus.
122//!
123//! ```
124//! # #[cfg(feature = "rand")]
125//! # {
126//! use crypto_bigint::{NonZero, RandomMod, U256, rand_core::OsRng};
127//!
128//! let modulus = NonZero::new(U256::from(3u8)).unwrap();
129//! let n = U256::random_mod(&mut OsRng, &modulus);
130//! # }
131//! ```
132//!
133//! [`Add`]: core::ops::Add
134//! [`Div`]: core::ops::Div
135//! [`Mul`]: core::ops::Mul
136//! [`Rem`]: core::ops::Rem
137//! [`Sub`]: core::ops::Sub
138//! [`CryptoRng`]: rand_core::CryptoRng
139
140#[cfg(all(feature = "alloc", test))]
141extern crate alloc;
142
143#[macro_use]
144mod nlimbs;
145
146#[cfg(feature = "generic-array")]
147mod array;
148mod checked;
149mod limb;
150mod non_zero;
151mod traits;
152mod uint;
153mod wrapping;
154
155pub use crate::{
156 checked::Checked,
157 limb::{Limb, WideWord, Word},
158 non_zero::NonZero,
159 traits::*,
160 uint::*,
161 wrapping::Wrapping,
162};
163pub use subtle;
164
165// TODO(tarcieri): remove these in the next breaking release
166#[allow(deprecated)]
167pub use crate::limb::{LimbUInt, WideLimbUInt};
168
169pub(crate) use limb::{SignedWord, WideSignedWord};
170
171#[cfg(feature = "generic-array")]
172pub use {
173 crate::array::{ArrayDecoding, ArrayEncoding, ByteArray},
174 generic_array::{self, typenum::consts},
175};
176
177#[cfg(feature = "rand_core")]
178pub use rand_core;
179
180#[cfg(feature = "rlp")]
181pub use rlp;
182
183#[cfg(feature = "zeroize")]
184pub use zeroize;
185
186/// Import prelude for this crate: includes important traits.
187pub mod prelude {
188 pub use crate::traits::*;
189
190 #[cfg(feature = "generic-array")]
191 pub use crate::array::{ArrayDecoding, ArrayEncoding};
192}
193
194#[cfg(sidefuzz)]
195#[no_mangle]
196pub extern "C" fn fuzz() {
197 let input = sidefuzz::fetch_input(32); // 32 bytes of of fuzzing input as a &[u8]
198 sidefuzz::black_box(my_hopefully_constant_fn(input));
199}