CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-pycryptodome

PyCryptodome is a self-contained Python package of low-level cryptographic primitives

Pending
Overview
Eval results
Files

mathematical-primitives.mddocs/

Mathematical Primitives

Mathematical operations and data structures that form the foundation of PyCryptodome's cryptographic implementations. Provides big integer arithmetic, primality testing, and mathematical utilities optimized for cryptographic computations.

Capabilities

Big Integer Arithmetic

High-precision integer arithmetic supporting arbitrarily large numbers with optimized implementations for cryptographic operations.

class Integer:
    """
    Big integer class with cryptographic optimizations.
    Auto-selects best available implementation (GMP, custom, or native).
    """
    
    def __init__(self, value):
        """
        Initialize Integer from various sources.
        
        Parameters:
        - value: int, bytes, hex string, or another Integer
        """
    
    # Arithmetic operations
    def __add__(self, other) -> 'Integer':
        """Addition: self + other"""
    
    def __sub__(self, other) -> 'Integer':
        """Subtraction: self - other"""
    
    def __mul__(self, other) -> 'Integer':
        """Multiplication: self * other"""
    
    def __pow__(self, exponent, modulus=None) -> 'Integer':
        """
        Exponentiation: self ** exponent [mod modulus]
        Optimized for cryptographic use with Montgomery ladder.
        """
    
    def __floordiv__(self, other) -> 'Integer':
        """Floor division: self // other"""
    
    def __mod__(self, other) -> 'Integer':
        """Modulus: self % other"""
    
    def __divmod__(self, other) -> tuple:
        """Division with remainder: divmod(self, other)"""
    
    # Bitwise operations
    def __and__(self, other) -> 'Integer':
        """Bitwise AND: self & other"""
    
    def __or__(self, other) -> 'Integer':
        """Bitwise OR: self | other"""
    
    def __xor__(self, other) -> 'Integer':
        """Bitwise XOR: self ^ other"""
    
    def __lshift__(self, n: int) -> 'Integer':
        """Left shift: self << n"""
    
    def __rshift__(self, n: int) -> 'Integer':
        """Right shift: self >> n"""
    
    # Comparison operations
    def __eq__(self, other) -> bool:
        """Equality: self == other"""
    
    def __lt__(self, other) -> bool:
        """Less than: self < other"""
    
    def __le__(self, other) -> bool:
        """Less than or equal: self <= other"""
    
    # Modular arithmetic
    def inverse(self, modulus) -> 'Integer':
        """
        Compute modular multiplicative inverse.
        
        Parameters:
        - modulus (Integer): Modulus value
        
        Returns:
        Integer: self^(-1) mod modulus
        
        Raises:
        ValueError: If inverse doesn't exist (gcd(self, modulus) != 1)
        """
    
    def gcd(self, other) -> 'Integer':
        """
        Compute greatest common divisor using Euclidean algorithm.
        
        Parameters:
        - other (Integer): Other integer
        
        Returns:
        Integer: gcd(self, other)
        """
    
    def lcm(self, other) -> 'Integer':
        """
        Compute least common multiple.
        
        Parameters:
        - other (Integer): Other integer
        
        Returns:
        Integer: lcm(self, other)
        """
    
    # Utility methods
    def size_in_bits(self) -> int:
        """Number of bits needed to represent this integer."""
    
    def size_in_bytes(self) -> int:
        """Number of bytes needed to represent this integer."""
    
    def is_odd(self) -> bool:
        """Check if integer is odd."""
    
    def is_even(self) -> bool:
        """Check if integer is even."""
    
    # Conversion methods
    def to_bytes(self, length=None, byteorder='big') -> bytes:
        """
        Convert to bytes representation.
        
        Parameters:
        - length (int): Target byte length (None for minimal)
        - byteorder (str): 'big' or 'little' endian
        
        Returns:
        bytes: Binary representation
        """
    
    @staticmethod
    def from_bytes(data: bytes, byteorder='big') -> 'Integer':
        """
        Create Integer from bytes.
        
        Parameters:
        - data (bytes): Binary data
        - byteorder (str): 'big' or 'little' endian
        
        Returns:
        Integer: Integer representation of bytes
        """
    
    def __int__(self) -> int:
        """Convert to Python int (may lose precision for very large numbers)."""
    
    def __str__(self) -> str:
        """Decimal string representation."""
    
    def __repr__(self) -> str:
        """Representation string."""
    
    def __hex__(self) -> str:
        """Hexadecimal string representation."""
    
    def __bool__(self) -> bool:
        """Boolean value (False only for zero)."""

Primality Testing

Probabilistic and deterministic algorithms for testing whether integers are prime, essential for key generation and validation.

def miller_rabin_test(candidate, iterations, randfunc=None):
    """
    Miller-Rabin probabilistic primality test.
    
    Parameters:
    - candidate (int): Integer to test for primality
    - iterations (int): Number of test iterations (higher = more accurate)
    - randfunc (callable): Random function for choosing test bases
    
    Returns:
    int: 0 if composite, 1 if probably prime
    """

def lucas_test(candidate):
    """
    Lucas probabilistic primality test.
    
    Parameters:
    - candidate (int): Odd integer to test (must be > 2)
    
    Returns:
    int: 0 if composite, 1 if probably prime
    """

def test_probable_prime(candidate, randfunc=None):
    """
    Combined primality test using multiple algorithms.
    
    Parameters:
    - candidate (int): Integer to test
    - randfunc (callable): Random function
    
    Returns:
    int: PROBABLY_PRIME if likely prime, COMPOSITE if definitely composite
    """

# Primality test result constants
COMPOSITE = 0
PROBABLY_PRIME = 1

Usage Examples

Big Integer Operations

from Crypto.Math.Numbers import Integer

# Create integers from different sources
a = Integer(12345)
b = Integer("0xABCDEF", 16)  # From hex string
c = Integer(b"Hello", 256)   # From bytes

# Arithmetic operations
sum_val = a + b
product = a * b
power = a ** 100

# Modular arithmetic (common in cryptography)
modulus = Integer(2**256 - 1)  # Large prime-like number
mod_power = pow(a, b, modulus)  # Fast modular exponentiation
inverse = a.inverse(modulus)    # Modular inverse

# Bitwise operations
xor_result = a ^ b
shifted = a << 10

# Size operations
print(f"Bits needed: {a.size_in_bits()}")
print(f"Bytes needed: {a.size_in_bytes()}")

RSA Key Generation Mathematics

from Crypto.Math.Numbers import Integer
from Crypto.Math.Primality import test_probable_prime
from Crypto.Random import get_random_bytes

def generate_rsa_primes(bits):
    """Generate two RSA primes of specified bit length."""
    while True:
        # Generate random candidate
        random_bytes = get_random_bytes(bits // 8)
        candidate = Integer.from_bytes(random_bytes)
        
        # Ensure odd and correct bit length
        candidate |= (1 << (bits - 1))  # Set MSB
        candidate |= 1                  # Set LSB (make odd)
        
        # Test for primality
        if test_probable_prime(candidate) == PROBABLY_PRIME:
            return candidate

# Generate 1024-bit RSA primes
p = generate_rsa_primes(1024)
q = generate_rsa_primes(1024)
n = p * q  # RSA modulus

# Compute private exponent
e = Integer(65537)  # Common public exponent
phi_n = (p - 1) * (q - 1)
d = e.inverse(phi_n)  # Private exponent

print(f"Public key: (n={n}, e={e})")
print(f"Private key: (n={n}, d={d})")

Modular Exponentiation for Encryption

from Crypto.Math.Numbers import Integer

# RSA encryption/decryption example
n = Integer("0x9A7B2C3D...")  # RSA modulus
e = Integer(65537)            # Public exponent
d = Integer("0x1F2E3D...")   # Private exponent

# Message as integer (after proper padding)
message = Integer(b"Hello, World!")

# Encryption: ciphertext = message^e mod n
ciphertext = pow(message, e, n)

# Decryption: plaintext = ciphertext^d mod n  
decrypted = pow(ciphertext, d, n)

assert decrypted == message

Elliptic Curve Point Operations

from Crypto.Math.Numbers import Integer

# Simplified elliptic curve point addition (conceptual)
class ECPoint:
    def __init__(self, x, y, curve_p):
        self.x = Integer(x)
        self.y = Integer(y)
        self.p = Integer(curve_p)  # Prime modulus
    
    def double(self):
        """Point doubling on elliptic curve."""
        # Simplified formula: slope = (3*x^2) / (2*y) mod p
        numerator = (Integer(3) * self.x * self.x) % self.p
        denominator = (Integer(2) * self.y) % self.p
        slope = (numerator * denominator.inverse(self.p)) % self.p
        
        # New coordinates
        x3 = (slope * slope - Integer(2) * self.x) % self.p
        y3 = (slope * (self.x - x3) - self.y) % self.p
        
        return ECPoint(x3, y3, self.p)

# Example with P-256 curve
p256_prime = Integer(2**256 - 2**224 + 2**192 + 2**96 - 1)
point = ECPoint(
    0x6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296,
    0x4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5,
    p256_prime
)
doubled_point = point.double()

Primality Testing in Practice

from Crypto.Math.Primality import miller_rabin_test, test_probable_prime
from Crypto.Math.Numbers import Integer

# Generate and test potential primes
def find_next_prime(start_value):
    """Find next probable prime after start_value."""
    candidate = Integer(start_value)
    if candidate.is_even():
        candidate += 1  # Make odd
    
    while True:
        # Quick test with small iterations
        if miller_rabin_test(candidate, 10) == PROBABLY_PRIME:
            # More thorough test
            if test_probable_prime(candidate) == PROBABLY_PRIME:
                return candidate
        candidate += 2  # Check next odd number

# Find large prime
large_prime = find_next_prime(2**512)
print(f"Found prime: {large_prime}")
print(f"Bit length: {large_prime.size_in_bits()}")

Number Conversion and Encoding

from Crypto.Math.Numbers import Integer

# Various ways to create and convert integers
num = Integer(12345)

# Convert to different formats
hex_string = hex(num)           # "0x3039"
decimal_string = str(num)       # "12345"
bytes_big = num.to_bytes(4, 'big')      # b'\x00\x009'
bytes_little = num.to_bytes(4, 'little') # b'9\x00\x00'

# Reconstruct from bytes
from_big = Integer.from_bytes(bytes_big, 'big')
from_little = Integer.from_bytes(bytes_little, 'little')

assert from_big == num
assert from_little == num

# Handle large numbers
large_num = Integer(2**1024 - 1)
large_bytes = large_num.to_bytes()  # Minimal byte representation
print(f"Large number byte length: {len(large_bytes)}")

Performance Considerations

Implementation Selection

PyCryptodome automatically selects the best available big integer implementation:

  1. GMP (GNU Multiple Precision): Fastest, requires libgmp
  2. Custom C: Fast, pure C implementation included with PyCryptodome
  3. Pure Python: Fallback, slower but always available

Optimization Tips

  • Use modular exponentiation pow(base, exp, mod) instead of (base ** exp) % mod
  • Prefer Integer objects for repeated operations to avoid conversion overhead
  • Use appropriate bit sizes for your security requirements
  • Cache frequently used constants (like moduli) as Integer objects

Memory Management

  • Integer objects handle memory automatically
  • Very large numbers may consume significant memory
  • Consider the trade-off between precision and memory usage

Security Considerations

Cryptographic Quality

  • Primality tests are probabilistic with configurable accuracy
  • Use sufficient iterations for security-critical applications
  • Miller-Rabin test with 64+ iterations provides high confidence

Side-Channel Resistance

  • Modular exponentiation uses Montgomery ladder for timing attack resistance
  • Constant-time operations where possible
  • Consider implementation-specific side-channel protections

Random Number Dependencies

  • Primality tests require cryptographically secure randomness
  • Use system-provided randomness or Crypto.Random
  • Ensure proper entropy for key generation

Error Handling

  • ValueError: Invalid mathematical operations (e.g., division by zero, no modular inverse)
  • TypeError: Incompatible types for operations
  • OverflowError: Results too large for representation (rare with arbitrary precision)
  • ZeroDivisionError: Division or modulus by zero

Install with Tessl CLI

npx tessl i tessl/pypi-pycryptodome

docs

cryptographic-hashing.md

cryptographic-protocols.md

digital-signatures.md

index.md

input-output-operations.md

mathematical-primitives.md

public-key-cryptography.md

symmetric-encryption.md

utility-functions.md

tile.json