PyCryptodome is a self-contained Python package of low-level cryptographic 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.
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)."""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 = 1from 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()}")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})")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 == messagefrom 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()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()}")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)}")PyCryptodome automatically selects the best available big integer implementation:
pow(base, exp, mod) instead of (base ** exp) % modInteger objects for repeated operations to avoid conversion overheadInteger objectsInteger objects handle memory automaticallyCrypto.RandomValueError: Invalid mathematical operations (e.g., division by zero, no modular inverse)TypeError: Incompatible types for operationsOverflowError: Results too large for representation (rare with arbitrary precision)ZeroDivisionError: Division or modulus by zeroInstall with Tessl CLI
npx tessl i tessl/pypi-pycryptodome