BigInt

Struct BigInt 

Source
pub struct BigInt { /* private fields */ }
Expand description

BigInt implementation using clock-bigint’s U256 type. This is the default backend when the “bigint-backend” feature is enabled. Provides high-performance, heap-allocated arithmetic with optimized assembly implementations for common operations. Suitable for general-purpose cryptographic computations and applications requiring variable-precision arithmetic. Automatically selected when “bigint-backend” feature is enabled. 256-bit multi-precision integer for cryptographic arithmetic.

BigInt provides constant-time multi-precision arithmetic operations essential for elliptic curve cryptography, modular exponentiation, and other cryptographic primitives. It wraps clock-bigint’s U256 type with additional cryptographic security features and performance optimizations.

§Memory Layout

  • 4 × 64-bit limbs: Little-endian storage (limb[0] is least significant)
  • 32-byte alignment: Optimized for cache lines and SIMD operations
  • Copy semantics: Efficient stack-based operations without heap allocation

§Security Properties

  • Constant-time operations: All arithmetic executes in time independent of values
  • Side-channel resistance: Designed to prevent timing and cache attacks
  • No secret-dependent branches: Control flow independent of sensitive data
  • Secure comparisons: Constant-time equality and ordering operations

§Performance Characteristics

  • Stack-allocated: No heap allocation for arithmetic operations
  • SIMD-friendly: 32-byte alignment enables vectorized operations
  • Branch-free algorithms: All operations use conditional moves and masks
  • Optimized multiplication: Custom schoolbook multiplication with u128 intermediates

§Usage Examples

use clock_curve_math::bigint::BigInt;

// Create from small values
let a = BigInt::from_u64(42);
let b = BigInt::from_u64(123);

// Arithmetic operations (all constant-time)
let sum = a.add(&b);
let product = a.mul(&b);

// Wide multiplication for modular reduction
let (low, high) = a.mul_wide(&b);

// Secure comparison
let ordering = a.ct_cmp(&b);

// Bit manipulation
let shifted = a.shl(8);
let bit = a.get_bit(0);

§Cryptographic Applications

  • Elliptic curve arithmetic: Point operations over prime fields
  • Modular exponentiation: RSA and Diffie-Hellman implementations
  • Finite field operations: Custom modulus arithmetic
  • Cryptographic protocols: Digital signatures and key exchange

§Implementation Details

  • Backend: Uses clock-bigint’s U256 for low-level operations
  • Alignment: #[repr(align(32))] for cache line and AVX compatibility
  • Traits: Implements standard Rust traits (PartialEq, PartialOrd, etc.)
  • Operators: Supports << (shl) and - (sub) operators

§Thread Safety

BigInt is Copy and contains no interior mutability, making it safe to share across thread boundaries without synchronization.

Implementations§

Source§

impl BigInt

Source

pub fn from_limbs(limbs: &[u64; 4]) -> Self

Creates a BigInt from four 64-bit limbs in little-endian order.

The limbs are interpreted as a multi-precision integer where:

  • limbs[0] is the least significant 64 bits
  • limbs[1] is bits 64-127
  • limbs[2] is bits 128-191
  • limbs[3] is the most significant 64 bits
§Parameters
  • limbs - Array of four u64 values in little-endian limb order
§Returns

A new BigInt with the specified limb values

§Examples
use clock_curve_math::bigint::BigInt;

// Create 2^64 (1 << 64)
let big_num = BigInt::from_limbs(&[0, 1, 0, 0]);

// Create a large number
let large = BigInt::from_limbs(&[0x123456789ABCDEF0, 0xFEDCBA9876543210, 0, 0]);
Source

pub fn from_bytes(bytes: &[u8; 32]) -> Self

Creates a BigInt from 32 bytes in little-endian byte order.

The bytes are interpreted as a 256-bit big-endian integer, with:

  • bytes[0] being the least significant byte
  • bytes[31] being the most significant byte

This is the standard byte representation for cryptographic values.

§Parameters
  • bytes - Array of 32 bytes in little-endian order
§Returns

A new BigInt with the value represented by the bytes

§Examples
use clock_curve_math::bigint::BigInt;

// Create from 32-byte array (all zeros except first byte = 1)
let bytes = [1u8; 32];
let num = BigInt::from_bytes(&bytes);

// Create from hex representation
let hex_bytes = hex::decode("0100000000000000000000000000000000000000000000000000000000000000")?;
let big_endian_num = BigInt::from_bytes(hex_bytes.as_slice().try_into()?);
§Note

This method uses little-endian byte order, which is standard for most cryptographic protocols and matches the internal limb representation.

Source

pub fn from_u64(value: u64) -> Self

Creates a BigInt from a 64-bit unsigned integer value.

This is a convenience constructor for creating BigInt values from small integers, scalars, or other u64 values commonly used in cryptographic computations.

§Parameters
  • value - The u64 value to convert to BigInt
§Returns

A new BigInt with the specified value in the least significant limb

§Examples
use clock_curve_math::bigint::BigInt;

let zero = BigInt::from_u64(0);
let one = BigInt::from_u64(1);
let max_u64 = BigInt::from_u64(u64::MAX);

// Common cryptographic constants
let curve_order = BigInt::from_u64(0xFFFFFFFFFFFFFFFF); // secp256k1 order approximation
§Performance

This is the most efficient way to create small BigInt values.

Source

pub fn to_bytes(&self) -> [u8; 32]

Converts the BigInt to a 32-byte array in little-endian byte order.

Returns the BigInt value as bytes, with the least significant byte first. This is the standard representation for cryptographic values and matches the byte order expected by most cryptographic protocols.

§Returns

A 32-byte array containing the BigInt value in little-endian order

§Examples
use clock_curve_math::bigint::BigInt;

let num = BigInt::from_u64(0x123456789ABCDEF0);
let bytes = num.to_bytes();

// bytes[0] = 0xF0, bytes[1] = 0xDE, bytes[2] = 0xBC, etc.
assert_eq!(bytes[0], 0xF0);
assert_eq!(bytes[1], 0xBC);
§Use Cases
  • Serializing BigInt values for network transmission
  • Storing cryptographic keys or parameters
  • Interfacing with other cryptographic libraries
  • Debugging and logging BigInt values
Source

pub fn limbs(&self) -> [u64; 4]

Returns the four 64-bit limbs of the BigInt in little-endian order.

The limbs represent the BigInt as: value = limbs[0] + limbs[1] * 2^64 + limbs[2] * 2^128 + limbs[3] * 2^192

§Returns

An array of four u64 values where limbs[0] is the least significant limb

§Examples
use clock_curve_math::bigint::BigInt;

let num = BigInt::from_u64(0x123456789ABCDEF0);
let limbs = num.limbs();

assert_eq!(limbs[0], 0x123456789ABCDEF0); // LSB
assert_eq!(limbs[1], 0);
assert_eq!(limbs[2], 0);
assert_eq!(limbs[3], 0); // MSB
§Use Cases
  • Implementing custom arithmetic operations
  • Interfacing with low-level cryptographic primitives
  • Debugging multi-precision arithmetic
  • Converting to/from other big integer representations
Source

pub fn add(&self, rhs: &Self) -> Self

Constant-time addition.

Source

pub fn sub(&self, rhs: &Self) -> Self

Constant-time subtraction.

Source

pub fn mul(&self, rhs: &Self) -> Self

Constant-time multiplication with proper overflow handling.

Returns the full 256-bit product. For modular arithmetic, the caller is responsible for reduction if needed.

Source

pub fn mul_wide(&self, rhs: &Self) -> (Self, Self)

Wide multiplication returning the full 512-bit result as (low, high) BigInts.

Source

pub fn square_wide(&self) -> (Self, Self)

Wide squaring returning the full 512-bit result as (low, high) BigInts.

This is optimized compared to mul_wide(self, self) since we only compute each cross term a[i]*a[j] once and double it appropriately, reducing redundant computations.

Performance improvement: ~10-15% faster than general multiplication.

Source

pub fn div_rem(&self, divisor: &Self) -> (Self, Self)

Division with remainder using binary long division.

Returns (quotient, remainder) where self = quotient * divisor + remainder. This implementation uses binary long division which is much more efficient than repeated subtraction.

Source

pub fn shl(&self, bits: u32) -> Self

Constant-time left shift.

Source

pub fn shr(&self, bits: u32) -> Self

Constant-time right shift.

Source

pub fn cmp(&self, rhs: &Self) -> Ordering

Constant-time comparison.

Source

pub fn ct_cmp(&self, rhs: &Self) -> Ordering

Constant-time comparison that prevents timing leaks.

This comparison always processes all limbs regardless of their values, ensuring constant execution time and preventing timing-based side-channel attacks.

The implementation uses constant-time operations to compare limbs from most significant to least significant, accumulating the result without any early returns or branches based on intermediate results.

Source

pub fn ct_select(a: &Self, b: &Self, flag: u64) -> Self

Constant-time conditional selection between two BigInts.

Returns a if flag == 0, b if flag == 1. Executes in constant time regardless of input values.

§Safety

flag must be either 0 or 1. Other values may leak timing information.

Source

pub fn is_zero(&self) -> bool

Constant-time zero check.

Source

pub fn get_bit(&self, bit_position: u32) -> u64

Get the bit at the specified position (constant-time).

Returns 1 if the bit is set, 0 otherwise. Bit positions start from 0 (least significant bit).

Source

pub fn bit_length(&self) -> u32

Get the number of bits needed to represent this BigInt.

Returns the position of the highest set bit plus one. Returns 0 for zero.

Source

pub fn to_u64(&self) -> Option<u64>

Attempts to convert the BigInt to a u64 value.

Returns the value as a u64 if it fits within the range [0, 2^64 - 1], otherwise returns None. This is useful for converting small BigInt values back to primitive types for compatibility with other libraries.

§Returns
  • Some(value) if the BigInt value fits in a u64
  • None if the value is too large (requires more than 64 bits)
§Examples
use clock_curve_math::bigint::BigInt;

let small = BigInt::from_u64(42);
assert_eq!(small.to_u64(), Some(42));

let large = BigInt::from_limbs(&[0, 1, 0, 0]); // 2^64
assert_eq!(large.to_u64(), None); // Too large for u64
§Performance

O(1) check of the upper limbs to determine if conversion is possible.

Source

pub fn and(&self, rhs: &Self) -> Self

Performs bitwise AND operation between two BigInts.

Computes self & rhs by performing bitwise AND on each corresponding limb of the two BigInts. This is useful for masking operations and extracting specific bit patterns from large integers.

§Parameters
  • rhs - The BigInt to AND with self
§Returns

A new BigInt with the result of the bitwise AND operation

§Examples
use clock_curve_math::bigint::BigInt;

let a = BigInt::from_u64(0b11001100);
let b = BigInt::from_u64(0b10101010);
let result = a.and(&b);

assert_eq!(result.to_u64(), Some(0b10001000)); // 0b11001100 & 0b10101010
§Performance

O(1) - performs four 64-bit AND operations.

§Security

Constant-time operation, safe for use with cryptographic secrets.

Source

pub fn checked_shl(&self, bits: u32) -> Option<Self>

Performs checked left shift operation with overflow detection.

Shifts the BigInt left by the specified number of bits. If the shift amount would cause overflow (shift >= 256 bits), returns None. Otherwise returns the shifted value.

§Parameters
  • bits - Number of bits to shift left (0 ≤ bits < 256)
§Returns
  • Some(result) if the shift is valid and doesn’t overflow
  • None if the shift would overflow (bits >= 256)
§Examples
use clock_curve_math::bigint::BigInt;

let num = BigInt::from_u64(1);

// Valid shifts
assert_eq!(num.checked_shl(0).unwrap().to_u64(), Some(1));    // 1 << 0 = 1
assert_eq!(num.checked_shl(1).unwrap().to_u64(), Some(2));    // 1 << 1 = 2
assert_eq!(num.checked_shl(63).unwrap().to_u64(), Some(1 << 63)); // Max u64

// Invalid shift (would overflow)
assert_eq!(num.checked_shl(256), None);
§Security

Constant-time operation when shift amount is within bounds. Use this instead of shl() when shift amount might be untrusted.

Trait Implementations§

Source§

impl BigIntOps for BigInt

Implementation of BigIntOps for the BigInt type.

This implementation provides constant-time multi-precision arithmetic operations for cryptographic applications. All operations delegate to the underlying BigInt implementation while ensuring constant-time properties.

§Security Guarantees

All operations maintain constant-time execution characteristics, making them safe for use with cryptographic secrets and private keys.

§Performance Characteristics

Operations are optimized for the specific limb size and architecture, providing efficient multi-precision arithmetic for cryptographic workloads.

Source§

fn add(&self, rhs: &Self) -> Self

Delegates to BigInt::add for constant-time addition.

Source§

fn sub(&self, rhs: &Self) -> Self

Delegates to BigInt::sub for constant-time subtraction.

Source§

fn mul(&self, rhs: &Self) -> Self

Delegates to BigInt::mul for constant-time multiplication.

Source§

fn mul_wide(&self, rhs: &Self) -> (Self, Self)

Delegates to BigInt::mul_wide for wide multiplication.

Source§

fn square_wide(&self) -> (Self, Self)

Delegates to BigInt::square_wide for optimized wide squaring.

Source§

fn shl(&self, bits: u32) -> Self

Delegates to BigInt::shl for constant-time left shift.

Source§

fn shr(&self, bits: u32) -> Self

Delegates to BigInt::shr for constant-time right shift.

Source§

fn cmp(&self, rhs: &Self) -> Ordering

Delegates to BigInt::cmp for standard comparison. Warning: This may leak timing information - use ct_cmp for crypto.

Source§

fn ct_cmp(&self, rhs: &Self) -> Ordering

Delegates to BigInt::ct_cmp for constant-time comparison.

Source§

fn ct_select(a: &Self, b: &Self, flag: u64) -> Self

Delegates to BigInt::ct_select for constant-time conditional selection.

Source§

fn is_zero(&self) -> bool

Delegates to BigInt::is_zero for constant-time zero check.

Source§

fn get_bit(&self, bit_position: u32) -> u64

Delegates to BigInt::get_bit for constant-time bit extraction.

Source§

fn bit_length(&self) -> u32

Delegates to BigInt::bit_length for bit length calculation.

Source§

impl Clone for BigInt

Source§

fn clone(&self) -> BigInt

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl ConfigurableArithmetic for BigInt

Source§

fn mul_with_config(&self, rhs: &Self, config: &MultiplicationConfig) -> Self

Multiply with configuration.
Source§

fn pow_with_config(&self, exp: &BigInt, _config: &ExponentiationConfig) -> Self

Compute power with configuration.
Source§

impl Debug for BigInt

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for BigInt

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl MontgomeryOps for BigInt

Source§

fn montgomery_reduce(t: &BigInt) -> BigInt

Perform Montgomery reduction. Read more
Source§

fn montgomery_mul(a: &BigInt, b: &BigInt) -> BigInt

Perform Montgomery multiplication. Read more
Source§

fn to_montgomery(a: &BigInt) -> BigInt

Convert to Montgomery form. Read more
Source§

fn from_montgomery(a: &BigInt) -> BigInt

Convert from Montgomery form. Read more
Source§

impl Ord for BigInt

Implements total ordering for BigInt.

BigInt values have a total ordering (any two values can be compared), making BigInt suitable for use as keys in ordered collections like BTreeMap.

§Security Note

This uses the standard comparison method which may leak timing information. For cryptographic applications requiring constant-time comparison, use ct_cmp().

Source§

fn cmp(&self, other: &Self) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 · Source§

fn max(self, other: Self) -> Self
where Self: Sized,

Compares and returns the maximum of two values. Read more
1.21.0 · Source§

fn min(self, other: Self) -> Self
where Self: Sized,

Compares and returns the minimum of two values. Read more
1.50.0 · Source§

fn clamp(self, min: Self, max: Self) -> Self
where Self: Sized,

Restrict a value to a certain interval. Read more
Source§

impl PartialEq for BigInt

Implements equality comparison for BigInt.

Two BigInts are equal if all their limbs are equal. This implementation compares limbs directly for efficiency, which is constant-time since all BigInts have exactly 4 limbs.

§Security Note

This comparison is constant-time and safe for use with cryptographic secrets. It compares all limbs regardless of the actual values.

Source§

fn eq(&self, other: &Self) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl PartialOrd for BigInt

Implements partial ordering for BigInt.

Provides comparison operations using the cmp() method. Since BigInt represents integers with total ordering, this always returns Some(Ordering).

§Security Note

This uses the standard comparison method which may leak timing information. For cryptographic applications, use ct_cmp() instead.

Source§

fn partial_cmp(&self, other: &Self) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 · Source§

fn lt(&self, other: &Rhs) -> bool

Tests less than (for self and other) and is used by the < operator. Read more
1.0.0 · Source§

fn le(&self, other: &Rhs) -> bool

Tests less than or equal to (for self and other) and is used by the <= operator. Read more
1.0.0 · Source§

fn gt(&self, other: &Rhs) -> bool

Tests greater than (for self and other) and is used by the > operator. Read more
1.0.0 · Source§

fn ge(&self, other: &Rhs) -> bool

Tests greater than or equal to (for self and other) and is used by the >= operator. Read more
Source§

impl Shl<u32> for BigInt

Implements the left shift operator (<<) for BigInt.

Allows using the << operator for left shift operations on owned BigInt values. Delegates to the shl() method for the actual implementation.

§Examples

use clock_curve_math::bigint::BigInt;

let num = BigInt::from_u64(1);
let shifted = num << 8; // Equivalent to num.shl(8)
assert_eq!(shifted.to_u64(), Some(256));
Source§

type Output = BigInt

The resulting type after applying the << operator.
Source§

fn shl(self, rhs: u32) -> Self::Output

Performs the << operation. Read more
Source§

impl Sub for BigInt

Implements the subtraction operator (-) for BigInt.

Allows using the - operator for subtraction operations on owned BigInt values. Delegates to the sub() method for the actual implementation.

§Examples

use clock_curve_math::bigint::BigInt;

let a = BigInt::from_u64(10);
let b = BigInt::from_u64(3);
let result = a - b; // Equivalent to a.sub(&b)
assert_eq!(result.to_u64(), Some(7));
Source§

type Output = BigInt

The resulting type after applying the - operator.
Source§

fn sub(self, rhs: Self) -> Self::Output

Performs the - operation. Read more
Source§

impl Copy for BigInt

Source§

impl Eq for BigInt

Marks BigInt as having total equality.

BigInt equality is reflexive, symmetric, and transitive, satisfying the requirements for the Eq trait.

Auto Trait Implementations§

§

impl Freeze for BigInt

§

impl RefUnwindSafe for BigInt

§

impl Send for BigInt

§

impl Sync for BigInt

§

impl Unpin for BigInt

§

impl UnwindSafe for BigInt

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.