Org.BouncyCastle.Math.BinPoly.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).
Factories for IBinPolyInv instances (multiplicative inversion in
GF(2^n)), the inversion-specialised sibling of 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.
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.
Compute z = z + x as polynomial addition over GF(2) (limb-wise XOR into
the accumulator). See Add
for the reduction-independence rationale.
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.
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.
Copy a polynomial: z[zOff..zOff + size] = x[xOff..xOff + size]. No
secret-wipe semantics — value-level move.
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.
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.
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.
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.
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.
Number of ulong limbs required to hold a polynomial of bit length n.
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.