authorgravatar for 124872+jedisct1@users.noreply.github.comFrank Denis <124872+jedisct1@users.noreply.github.com> 2026-09-07 21:03:43+02:00
committergravatar for 124872+jedisct1@users.noreply.github.comFrank Denis <124872+jedisct1@users.noreply.github.com> 2026-10-25 08:38:01+01:00
logad2225deb5b01eb751ba1882c0e9c2fc6b1fcafa
tree1f5027e02325183d1fbd4c237976103b8d8f95b9
parent720939f8c9cee80963a0089645e42ebbb4545906

crypto.ff: add a function to decode reduced field elements

Add fromBytesReduced() to accept values below 2^m.bits() (including values at or above the modulus).

1 files changed, 15 insertions(+), 0 deletions(-)

lib/std/crypto/ff.zig+15
...@@ -472,6 +472,21 @@ fn Fe_(comptime bits: comptime_int) type {...@@ -472,6 +472,21 @@ fn Fe_(comptime bits: comptime_int) type {
472 return fe;472 return fe;
473 }473 }
474474
475 /// Decodes and reduces a byte string whose value is below 2^m.bits().
476 pub fn fromBytesReduced(m: Modulus(bits), bytes: []const u8, comptime endian: Endian) OverflowError!Self {
477 var fe = Self{ .v = FeUint.zero };
478 const m_limbs_count = m.limbs_count();
479 const fe_limbs = fe.v.limbs()[0..m_limbs_count];
480 var acc = decodeBytes(fe_limbs, bytes, endian);
481
482 acc |= math.shr(Limb, fe_limbs[m_limbs_count - 1], t_bits - m.leading);
483 if (!ct.eql(acc, 0)) return error.Overflow;
484 fe.v.limbs_len = m_limbs_count;
485
486 _ = fe.v.conditionalSubWithOverflow(ct.limbsCmpGeq(fe.v, m.v), m.v);
487 return fe;
488 }
489
475 /// Converts the field element to a byte string.490 /// Converts the field element to a byte string.
476 /// Returns an error if the element is in Montgomery form.491 /// Returns an error if the element is in Montgomery form.
477 pub fn toBytes(self: Self, bytes: []u8, comptime endian: Endian) (OverflowError || RepresentationError)!void {492 pub fn toBytes(self: Self, bytes: []u8, comptime endian: Endian) (OverflowError || RepresentationError)!void {