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
impl BigInt
Sourcepub fn from_limbs(limbs: &[u64; 4]) -> Self
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 bitslimbs[1]is bits 64-127limbs[2]is bits 128-191limbs[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]);Sourcepub fn from_bytes(bytes: &[u8; 32]) -> Self
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 bytebytes[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.
Sourcepub fn from_u64(value: u64) -> Self
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.
Sourcepub fn to_bytes(&self) -> [u8; 32]
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
Sourcepub fn limbs(&self) -> [u64; 4]
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
Sourcepub fn mul(&self, rhs: &Self) -> Self
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.
Sourcepub fn mul_wide(&self, rhs: &Self) -> (Self, Self)
pub fn mul_wide(&self, rhs: &Self) -> (Self, Self)
Wide multiplication returning the full 512-bit result as (low, high) BigInts.
Sourcepub fn square_wide(&self) -> (Self, Self)
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.
Sourcepub fn div_rem(&self, divisor: &Self) -> (Self, Self)
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.
Sourcepub fn ct_cmp(&self, rhs: &Self) -> Ordering
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.
Sourcepub fn ct_select(a: &Self, b: &Self, flag: u64) -> Self
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.
Sourcepub fn get_bit(&self, bit_position: u32) -> u64
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).
Sourcepub fn bit_length(&self) -> u32
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.
Sourcepub fn to_u64(&self) -> Option<u64>
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 u64Noneif 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.
Sourcepub fn and(&self, rhs: &Self) -> Self
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.
Sourcepub fn checked_shl(&self, bits: u32) -> Option<Self>
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 overflowNoneif 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.
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 mul_wide(&self, rhs: &Self) -> (Self, Self)
fn mul_wide(&self, rhs: &Self) -> (Self, Self)
Delegates to BigInt::mul_wide for wide multiplication.
Source§fn square_wide(&self) -> (Self, Self)
fn square_wide(&self) -> (Self, Self)
Delegates to BigInt::square_wide for optimized wide squaring.
Source§fn cmp(&self, rhs: &Self) -> Ordering
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
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
fn ct_select(a: &Self, b: &Self, flag: u64) -> Self
Delegates to BigInt::ct_select for constant-time conditional selection.
Source§fn get_bit(&self, bit_position: u32) -> u64
fn get_bit(&self, bit_position: u32) -> u64
Delegates to BigInt::get_bit for constant-time bit extraction.
Source§fn bit_length(&self) -> u32
fn bit_length(&self) -> u32
Delegates to BigInt::bit_length for bit length calculation.
Source§impl ConfigurableArithmetic for BigInt
impl ConfigurableArithmetic for BigInt
Source§fn mul_with_config(&self, rhs: &Self, config: &MultiplicationConfig) -> Self
fn mul_with_config(&self, rhs: &Self, config: &MultiplicationConfig) -> Self
Source§fn pow_with_config(&self, exp: &BigInt, _config: &ExponentiationConfig) -> Self
fn pow_with_config(&self, exp: &BigInt, _config: &ExponentiationConfig) -> Self
Source§impl MontgomeryOps for BigInt
impl MontgomeryOps for BigInt
Source§impl Ord for BigInt
Implements total ordering for BigInt.
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§impl PartialEq for BigInt
Implements equality comparison for BigInt.
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§impl PartialOrd for BigInt
Implements partial ordering for BigInt.
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§impl Shl<u32> for BigInt
Implements the left shift operator (<<) for BigInt.
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§impl Sub for BigInt
Implements the subtraction operator (-) for BigInt.
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));impl Copy for BigInt
impl Eq for BigInt
Marks BigInt as having total equality.
BigInt equality is reflexive, symmetric, and transitive, satisfying
the requirements for the Eq trait.