<PackageReference Include="BouncyCastle.Cryptography" Version="2.7.0" />

Org.BouncyCastle.Math.BinPoly.BinPolys

static class BinPolys
Static entry point for binary-polynomial helpers. Reducer-independent ops ( Size, Create, Add, AddTo) sit at the top level; IBinPolyMul factories classified by reduction polynomial shape live under the nested Mul sub-class, and inversion factories under Inv (Itoh-Tsujii today; safegcd a possible future sibling).
public static class Inv

Factories for IBinPolyInv instances (multiplicative inversion in GF(2^n)), the inversion-specialised sibling of Mul.

public static class Mul

Factories for IBinPolyMul instances, classified by reduction polynomial shape: Binomial for x^n + 1, Trinomial for x^n + x^k + 1, and Pentanomial for x^n + x^k3 + x^k2 + x^k1 + 1.

public static void Add(int size, ulong[] x, int xOff, ulong[] y, int yOff, ulong[] z, int zOff)

Compute z = x + y as polynomial addition over GF(2) (limb-wise XOR). Independent of any reduction polynomial: degree-<n stays degree-<n automatically (no carry, no reduction). Operates on size-limb slices starting at the given offsets.

public static void AddTo(int size, ulong[] x, int xOff, ulong[] z, int zOff)

Compute z = z + x as polynomial addition over GF(2) (limb-wise XOR into the accumulator). See Add for the reduction-independence rationale.

public static int BitLengthVar(int size, ulong[] x, int xOff)

Variable-time bit length of the polynomial in x[xOff..xOff + size]: the position of its most significant set bit plus one (i.e. degree + 1), or 0 for the zero polynomial. The Var suffix flags the data-dependent running time — it scans from the top limb down to the first non-zero one and takes that limb's leading-zero count — so it must not be used where the polynomial is secret and timing is observable.

public static void Clear(int size, ulong[] z, int zOff)

Secret-wipe: actively erase z[zOff..zOff + size]. Forwards to Arrays.ZeroMemory, which is JIT-non-elidable by contract (via CryptographicOperations.ZeroMemory on .NET Core / 5+). Use this — not Zero — at sites where the buffer carried partial-product / key material that must be wiped under the project's side-channel discipline.

public static void Copy(int size, ulong[] x, int xOff, ulong[] z, int zOff)

Copy a polynomial: z[zOff..zOff + size] = x[xOff..xOff + size]. No secret-wipe semantics — value-level move.

public static ulong[] Create(int size)

Allocate a fresh limb array of length size (in ulong limbs, as returned by Size), initialised to zero. Caller-side bit- length-to-limb-count conversion sits at Size; this helper takes the already-converted limb count, matching the shape of Add / AddTo and the Nat.Create64(int len) convention.

public static ulong EqualTo(int size, ulong[] x, int xOff, ulong[] y, int yOff)

Constant-time equality test: returns ulong.MaxValue if x[xOff..xOff + size] equals y[yOff..yOff + size] limb-for-limb, and 0UL otherwise. Forwards to Nat.EqualTo64; the bitwise OR across limbs makes the running cost independent of the data, so this is safe to use on secret-bearing polynomials.

public static ulong EqualToOne(int size, ulong[] x, int xOff)

Constant-time test for the multiplicative identity: returns ulong.MaxValue if x[xOff..xOff + size] is the polynomial 1 (low bit set, all other bits clear), and 0UL otherwise. Forwards to Nat.EqualToOne64; the bitwise OR across limbs makes the running cost independent of the data, so this is safe to use on secret-bearing polynomials.

public static ulong EqualToZero(int size, ulong[] x, int xOff)

Constant-time test for the zero element: returns ulong.MaxValue if every limb of x[xOff..xOff + size] is zero, and 0UL otherwise. Forwards to Nat.EqualToZero64; the bitwise OR across limbs makes the running cost independent of the data, so this is safe to use on secret-bearing polynomials.

public static void One(int size, ulong[] z, int zOff)

Set the polynomial to 1 (the multiplicative identity in GF(2)[x] / r(x) for any r(x) with a non-zero constant term — true for all binomial / trinomial / pentanomial reductions this subsystem supports). This is the polynomial 1 (low bit set, all other bits clear), not "all bits set". Value-level — see Zero for the rationale.

public static int Size(int n)

Number of ulong limbs required to hold a polynomial of bit length n.

public static void Zero(int size, ulong[] z, int zOff)

Set the polynomial to the zero element of the ring: write 0 to every limb in z[zOff..zOff + size]. Value-level — for initialising accumulators and similar. The JIT may legitimately elide this write if the buffer becomes dead afterward (the *value* isn't observed). For wiping secret-bearing intermediate buffers, use Clear instead.