ecrust-fp 0.1.0

Finite field arithmetic over Fp for the ecrust library
Documentation

ecRust

A Rust library for finite-field arithmetic, elliptic-curve operations, isogeny scaffolding, and higher-level elliptic-curve protocols.

The project is organized as a layered set of crates:

protocol       ← ECDH / EC-ElGamal helpers built on curve points
  ↓
isogeny        ← isogeny and kernel abstractions (work in progress)
  ↓
ec             ← elliptic-curve models and point arithmetic
  ↓
fp             ← finite fields: Fp, Fp^m, F2, F2^m
  ↓
crypto-bigint  ← multi-precision integers / Montgomery arithmetic

Workspace crates

fp

Finite-field arithmetic.

Main building blocks:

  • FieldOps: common trait implemented by field elements.
  • FpElement<MOD, LIMBS>: prime-field elements over Fp.
  • FpExt<MOD, LIMBS, M, P>: extension-field elements over Fp^M.
  • F2Element: the prime field F2.
  • F2Ext<LIMBS, P>: binary extension fields F2^m.
  • IrreduciblePoly / BinaryIrreducible: marker traits used to define extension fields.

ec

Elliptic-curve abstractions and affine Weierstrass arithmetic.

Main building blocks:

  • CurveOps: generic curve-model trait.
  • PointOps: generic point/group API.

isogeny

Kernel and isogeny structs.

Current status:

  • KernelSubgroup<C> exists.
  • Isogeny<C> exists as the main abstraction.
  • evaluation formulas are still TODO.

protocol

Small protocol layer on top of ec.

Current modules:

  • SecretScalar<LIMBS>
  • Ecdh
  • EcElGamal

Current status

This workspace is usable for experiments and API exploration, with the following caveats:

  • fp is the most complete and best-tested layer.
  • ec supports affine Weierstrass arithmetic and scalar multiplication, but some methods still contain exceptional-case branching and should not yet be treated as hardened production code.
  • isogeny is currently scaffolding.
  • protocol examples are functional API examples, not production-ready constructions.

Build and test

cargo build --workspace
cargo test --workspace

Quick start

1. Instantiate a prime field (FieldOps via FpElement)

use crypto_bigint::{Uint, const_prime_monty_params};
use fp::field_ops::FieldOps;
use fp::fp_element::FpElement;

const_prime_monty_params!(Fp19Mod, Uint<1>, "0000000000000013", 2);
type F19 = FpElement<Fp19Mod, 1>;

let a = F19::from_u64(7);
let b = F19::from_u64(8);
let c = a * b;
assert_eq!(c.as_limbs()[0], 18); // 56 mod 19 = 18

let inv = a.invert().into_option().unwrap();
assert!((a * inv).is_one().into());

2. Instantiate an extension field (FieldOps via FpExt)

use fp::field_ops::FieldOps;
use fp::fp_element::FpElement;
use fp::fp_ext::{FpExt, IrreduciblePoly};

struct QuadPoly;

impl IrreduciblePoly<Fp19Mod, 1, 2> for QuadPoly {
    fn modulus() -> [F19; 2] {
        [F19::one(), F19::zero()] // x² + 1
    }
}

struct TSQuad;
impl TonelliShanksConstants<Fp19Mod, 1, 2, 1> for TSQuad {
    // p^2 - 1
    const ORDER: Uint<1> = Uint::<1>::from_u64(360);
    // (p^2 - 1) / 2
    const HALF_ORDER: Uint<1> = Uint::<1>::from_u64(180);
    // p^2 - 1 = 2^S * T with T odd
    const S: u64 = 3;
    const T: Uint<1> = Uint::<1>::from_u64(45);
    // (T - 1) / 2
    const PROJENATOR_EXP: Uint<1> = Uint::<1>::from_u64(22);
    // 2^(S - 1)
    const TWOSM1: Uint<1> = Uint::<1>::from_u64(4);
    // 2^S root of unity 
    fn root_of_unity() -> [FpElement<Fp19Mod, 1>; 2] {
        [Fp19::from_u64(3), Fp19::from_u64(3)]
    }
}

type F19_2 = FpExt<Fp19Mod, 1, 2, 1, QuadPoly, TSQuad>;

let x = F19_2::new([F19::from_u64(3), F19::from_u64(2)]); // 3 + 2u
let y = x.invert().into_option().unwrap();
assert!(FieldOps::mul(&x, &y).is_one().into());

3. Instantiate a curve (Curve) and a point (PointOps)

use ec::curve_weierstrass::WeierstrassCurve;
use ec::point_weierstrass::AffinePoint;

let curve = WeierstrassCurve::new_short(F19::from_u64(2), F19::from_u64(3));
let p = AffinePoint::new(F19::from_u64(1), F19::from_u64(5));

assert!(curve.contains(&p.x, &p.y));
let q = p.double(&curve);
let r = p.add(&q, &curve);
let s = p.scalar_mul(&[5], &curve);

Examples and demos

See DEMO.md for several concrete examples showing how to instantiate the main traits and concrete types in this workspace:

  • FieldOps with FpElement
  • FieldOps with FpExt
  • FieldOps with F2Ext
  • Curve / PointOps with WeierstrassCurve and AffinePoint
  • SecretScalar, Ecdh, and EcElGamal
  • generic helper functions written against traits instead of concrete types

Repository layout

ecrust/
├── Cargo.toml
├── README.md
├── DEMO.md
├── fp/
│   ├── src/
│   │   ├── field_ops.rs
│   │   ├── fp_element.rs
│   │   ├── fp_ext.rs
│   │   ├── f2_element.rs
│   │   └── f2_ext.rs
│   └── tests/
├── ec/
│   ├── src/
│   │   ├── curve_ops.rs
│   │   ├── point_ops.rs
│   │   ├── curve_weierstrass.rs
│   │   └── point_weierstrass.rs
│   └── tests/
├── isogeny/
│   ├── src/
│   │   ├── kernel.rs
│   │   └── isogeny.rs
│   └── tests/
└── protocol/
    ├── src/
    │   ├── scalar.rs
    │   ├── ecdh.rs
    │   └── elgamal.rs
    └── tests/

Disclaimer

Disclaimer. This software is currently in an alpha stage. We are actively working toward constant-time implementations across the project, but achieving this systematically remains an ongoing effort. At this stage, the code should be treated as experimental, and it must not be assumed to provide full side-channel resistance or production-grade security guarantees.

Authors

  • Gustavo Banegas
  • Martin Azon
  • Sam Frengley

License

Apache License 2.0. See LICENSE.