Elliptic curve crypto in python including secp256k1, alt_bn128, and bls12_381
—
Finite field arithmetic supporting all implemented curves with both basic and extension field operations. This module provides the fundamental mathematical operations underlying all elliptic curve computations in py-ecc.
# Import base field classes
from py_ecc.fields.field_elements import FQ, FQ2, FQ12, FQP
from py_ecc.fields.optimized_field_elements import (
FQ as optimized_FQ,
FQ2 as optimized_FQ2,
FQ12 as optimized_FQ12,
FQP as optimized_FQP
)Operations in prime finite fields Fp.
class FQ:
"""
Element of a prime finite field Fp.
"""
field_modulus: int # Prime modulus p
def __init__(self, val: int):
"""
Create a field element.
Args:
val (int): Integer value (will be reduced modulo p)
"""
def __add__(self, other):
"""Addition in the field."""
def __sub__(self, other):
"""Subtraction in the field."""
def __mul__(self, other):
"""Multiplication in the field."""
def __truediv__(self, other):
"""Division in the field (multiplication by inverse)."""
def __pow__(self, other):
"""Exponentiation in the field."""
def __eq__(self, other) -> bool:
"""Equality comparison."""
def __neg__(self):
"""Additive inverse (negation)."""
def inverse(self):
"""
Multiplicative inverse of the element.
Returns:
FQ: Multiplicative inverse (1/self)
"""
@classmethod
def zero(cls):
"""Return the additive identity (0)."""
@classmethod
def one(cls):
"""Return the multiplicative identity (1)."""Operations in quadratic extension fields Fp2 = Fp[i]/(i^2 + 1).
class FQ2:
"""
Element of quadratic extension field Fp2.
Represented as a + b*i where i^2 = -1.
"""
field_modulus: int # Base field modulus
FQ2_MODULUS_COEFFS: Tuple[int, int] # Coefficients for i^2 + 1
def __init__(self, coeffs: Sequence[int]):
"""
Create an Fp2 element.
Args:
coeffs: [a, b] representing a + b*i
"""
def __add__(self, other):
"""Addition in Fp2."""
def __sub__(self, other):
"""Subtraction in Fp2."""
def __mul__(self, other):
"""Multiplication in Fp2."""
def __truediv__(self, other):
"""Division in Fp2."""
def __pow__(self, other):
"""Exponentiation in Fp2."""
def __eq__(self, other) -> bool:
"""Equality comparison."""
def __neg__(self):
"""Additive inverse."""
def inverse(self):
"""Multiplicative inverse in Fp2."""
def norm(self):
"""Norm of the element (a^2 + b^2)."""
def conjugate(self):
"""Complex conjugate (a - b*i)."""
@classmethod
def zero(cls):
"""Additive identity in Fp2."""
@classmethod
def one(cls):
"""Multiplicative identity in Fp2."""Operations in degree-12 extension fields Fp12 used as the target group for pairings.
class FQ12:
"""
Element of degree-12 extension field Fp12.
Used as the target group GT for bilinear pairings.
"""
field_modulus: int # Base field modulus
FQ12_MODULUS_COEFFS: Tuple[int, ...] # Coefficients for the irreducible polynomial
def __init__(self, coeffs: Sequence[int]):
"""
Create an Fp12 element.
Args:
coeffs: 12 coefficients representing the polynomial
"""
def __add__(self, other):
"""Addition in Fp12."""
def __sub__(self, other):
"""Subtraction in Fp12."""
def __mul__(self, other):
"""Multiplication in Fp12."""
def __truediv__(self, other):
"""Division in Fp12."""
def __pow__(self, other):
"""Exponentiation in Fp12."""
def __eq__(self, other) -> bool:
"""Equality comparison."""
def __neg__(self):
"""Additive inverse."""
def inverse(self):
"""Multiplicative inverse in Fp12."""
@classmethod
def zero(cls):
"""Additive identity in Fp12."""
@classmethod
def one(cls):
"""Multiplicative identity in Fp12."""Base class for polynomial field extensions.
class FQP:
"""
Base class for polynomial field extensions.
"""
field_modulus: int # Base field modulus
def __init__(self, coeffs: Sequence[int]):
"""Initialize with polynomial coefficients."""
def degree(self) -> int:
"""Degree of the polynomial representation."""
def __add__(self, other):
"""Polynomial addition."""
def __sub__(self, other):
"""Polynomial subtraction."""
def __mul__(self, other):
"""Polynomial multiplication with reduction."""
def __eq__(self, other) -> bool:
"""Polynomial equality."""# BN128 curve fields
from py_ecc.fields import (
bn128_FQ, # Base field for BN128
bn128_FQ2, # Quadratic extension for BN128
bn128_FQ12, # Degree-12 extension for BN128 (GT)
bn128_FQP # General polynomial field for BN128
)
# Optimized BN128 fields
from py_ecc.fields import (
optimized_bn128_FQ,
optimized_bn128_FQ2,
optimized_bn128_FQ12,
optimized_bn128_FQP
)# BLS12-381 curve fields
from py_ecc.fields import (
bls12_381_FQ, # Base field for BLS12-381
bls12_381_FQ2, # Quadratic extension for BLS12-381
bls12_381_FQ12, # Degree-12 extension for BLS12-381 (GT)
bls12_381_FQP # General polynomial field for BLS12-381
)
# Optimized BLS12-381 fields
from py_ecc.fields import (
optimized_bls12_381_FQ,
optimized_bls12_381_FQ2,
optimized_bls12_381_FQ12,
optimized_bls12_381_FQP
)from py_ecc.fields.field_properties import field_properties
# Access curve parameters
bn128_params = field_properties["bn128"]
bls12_381_params = field_properties["bls12_381"]
# Available parameters:
# - field_modulus: Prime modulus for the base field
# - fq2_modulus_coeffs: Coefficients for Fp2 construction
# - fq12_modulus_coeffs: Coefficients for Fp12 constructionfrom py_ecc.fields import bls12_381_FQ as FQ
# Create field elements
a = FQ(123)
b = FQ(456)
# Basic operations
sum_val = a + b
diff_val = a - b
product = a * b
quotient = a / b
power = a ** 3
# Special elements
zero = FQ.zero()
one = FQ.one()
neg_a = -a
inv_a = a.inverse()
print(f"Field operations: {sum_val}, {product}, {power}")from py_ecc.fields import bls12_381_FQ2 as FQ2
# Create Fp2 elements: a + b*i
x = FQ2([1, 2]) # 1 + 2*i
y = FQ2([3, 4]) # 3 + 4*i
# Complex arithmetic
sum_xy = x + y # (1+3) + (2+4)*i = 4 + 6*i
product_xy = x * y # (1 + 2*i)(3 + 4*i) = (3-8) + (6+4)*i = -5 + 10*i
# Special operations
norm_x = x.norm() # 1^2 + 2^2 = 5
conjugate_x = x.conjugate() # 1 - 2*i
inverse_x = x.inverse() # 1/(1 + 2*i)
print(f"Fp2 operations: {sum_xy}, {product_xy}, {norm_x}")from py_ecc.fields import bls12_381_FQ12 as FQ12
# Create Fp12 elements (12 coefficients)
coeffs1 = [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] # 1
coeffs2 = [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] # generator element
gt_element1 = FQ12(coeffs1)
gt_element2 = FQ12(coeffs2)
# Target group operations (used in pairing results)
product = gt_element1 * gt_element2
power = gt_element1 ** 12345
# Check for identity
is_identity = (product == FQ12.one())
print(f"Target group operations completed: {is_identity}")from py_ecc.fields import bn128_FQ, bls12_381_FQ
# Different curves have different field moduli
bn128_element = bn128_FQ(123)
bls12_381_element = bls12_381_FQ(123)
# These are elements of different fields
print(f"BN128 field modulus: {bn128_FQ.field_modulus}")
print(f"BLS12-381 field modulus: {bls12_381_FQ.field_modulus}")
# Operations are only valid within the same field
bn128_sum = bn128_element + bn128_FQ(456)
bls12_381_sum = bls12_381_element + bls12_381_FQ(456)import time
from py_ecc.fields import bls12_381_FQ as RefFQ
from py_ecc.fields import optimized_bls12_381_FQ as OptFQ
# Performance comparison
a_ref = RefFQ(12345)
b_ref = RefFQ(67890)
a_opt = OptFQ(12345)
b_opt = OptFQ(67890)
# Time reference implementation
start = time.time()
for _ in range(10000):
result_ref = a_ref * b_ref
ref_time = time.time() - start
# Time optimized implementation
start = time.time()
for _ in range(10000):
result_opt = a_opt * b_opt
opt_time = time.time() - start
print(f"Reference time: {ref_time:.4f}s")
print(f"Optimized time: {opt_time:.4f}s")
print(f"Speedup: {ref_time/opt_time:.2f}x")from py_ecc.fields import (
bls12_381_FQ as FQ,
bls12_381_FQ2 as FQ2,
bls12_381_FQ12 as FQ12
)
# Build field extension tower: Fp -> Fp2 -> Fp12
base_element = FQ(123)
# Embed in Fp2 as constant term
fp2_element = FQ2([base_element.n, 0])
# Elements can be lifted through the tower
# but operations must respect the field structure
print(f"Field tower: Fp -> Fp2 -> Fp12")
print(f"Base: {base_element}")
print(f"In Fp2: {fp2_element}")from py_ecc.utils import prime_field_inv, deg, poly_rounded_div
def prime_field_inv(a: int, n: int) -> int:
"""
Compute modular inverse using extended Euclidean algorithm.
Args:
a (int): Element to invert
n (int): Modulus
Returns:
int: Modular inverse of a modulo n
"""
def deg(p: Sequence) -> int:
"""
Compute degree of polynomial representation.
Args:
p: Polynomial coefficients
Returns:
int: Degree of the polynomial
"""
def poly_rounded_div(a: Sequence, b: Sequence) -> Tuple:
"""
Polynomial division with rounding.
Args:
a: Dividend polynomial coefficients
b: Divisor polynomial coefficients
Returns:
Tuple: Quotient coefficients
"""Field operations may raise various exceptions:
ZeroDivisionError: Division by zero or computing inverse of zeroValueError: Invalid field element constructionTypeError: Incompatible field operationsfrom py_ecc.fields import bls12_381_FQ as FQ
try:
a = FQ(123)
b = FQ(0)
# This will raise ZeroDivisionError
result = a / b
except ZeroDivisionError:
print("Cannot divide by zero in field")
except ValueError as e:
print(f"Invalid field operation: {e}")Install with Tessl CLI
npx tessl i tessl/pypi-py-ecc