authorgravatar for 124872+jedisct1@users.noreply.github.comFrank Denis <124872+jedisct1@users.noreply.github.com> 2026-10-03 14:36:13+02:00
committergravatar for 124872+jedisct1@users.noreply.github.comFrank Denis <124872+jedisct1@users.noreply.github.com> 2026-10-03 14:36:13+02:00
logc31cb992737dd9eb7d910caeaa5259a65eac5b6e
tree9a36b2d674187279dcc815e90dc4db9dd9eb66fd
parent4258dce9198b851be2f99f0c9e682ef00d33b7b5
parenta57cf67863683c83506e864aef9cb0157d8d8d41

Merge pull request 'crypto.ff: don't compare elements with different representations' (#37038) from jedisct1/zig:ff-fixes8 into master

Reviewed-on: https://codeberg.org/ziglang/zig/pulls/37038

1 files changed, 10 insertions(+), 4 deletions(-)

lib/std/crypto/ff.zig+10-4
...@@ -482,12 +482,15 @@ fn Fe_(comptime bits: comptime_int) type {...@@ -482,12 +482,15 @@ fn Fe_(comptime bits: comptime_int) type {
482 }482 }
483483
484 /// Returns `true` if the field elements are equal, in constant time.484 /// Returns `true` if the field elements are equal, in constant time.
485 /// Elements in different representations compare unequal; convert them to the same form to compare values.
485 pub fn eql(x: Self, y: Self) bool {486 pub fn eql(x: Self, y: Self) bool {
486 return x.v.eql(y.v);487 const values_equal = x.v.eql(y.v);
488 return x.montgomery == y.montgomery and values_equal;
487 }489 }
488490
489 /// Compares two field elements in constant time.491 /// Compares two field elements in constant time.
490 pub fn compare(x: Self, y: Self) math.Order {492 pub fn compare(x: Self, y: Self) math.Order {
493 assert(!x.montgomery and !y.montgomery);
491 return x.v.compare(y.v);494 return x.v.compare(y.v);
492 }495 }
493496
...@@ -497,7 +500,9 @@ fn Fe_(comptime bits: comptime_int) type {...@@ -497,7 +500,9 @@ fn Fe_(comptime bits: comptime_int) type {
497 }500 }
498501
499 /// Returns `true` is the element is odd.502 /// Returns `true` is the element is odd.
503 /// Requires plain form because Montgomery encoding doesn't preserve parity.
500 pub fn isOdd(self: Self) bool {504 pub fn isOdd(self: Self) bool {
505 assert(!self.montgomery);
501 return self.v.isOdd();506 return self.v.isOdd();
502 }507 }
503 };508 };
...@@ -576,6 +581,7 @@ pub fn Modulus(comptime max_bits: comptime_int) type {...@@ -576,6 +581,7 @@ pub fn Modulus(comptime max_bits: comptime_int) type {
576 const Self = @This();581 const Self = @This();
577582
578 /// A field element, representing a value within the field defined by this modulus.583 /// A field element, representing a value within the field defined by this modulus.
584 /// Use elements only with the modulus that created them, even if another modulus has the same size.
579 pub const Fe = Fe_(max_bits);585 pub const Fe = Fe_(max_bits);
580586
581 const FeUint = Fe.FeUint;587 const FeUint = Fe.FeUint;
...@@ -1172,7 +1178,7 @@ test "finite field arithmetic" {...@@ -1172,7 +1178,7 @@ test "finite field arithmetic" {
1172 const M = Modulus(256);1178 const M = Modulus(256);
1173 const m = try M.fromPrimitive(u256, 3429938563481314093726330772853735541133072814650493833233);1179 const m = try M.fromPrimitive(u256, 3429938563481314093726330772853735541133072814650493833233);
1174 var x = try M.Fe.fromPrimitive(u256, m, 80169837251094269539116136208111827396136208141182357733);1180 var x = try M.Fe.fromPrimitive(u256, m, 80169837251094269539116136208111827396136208141182357733);
1175 var y = try M.Fe.fromPrimitive(u256, m, 24620149608466364616251608466389896540098571);1181 const y = try M.Fe.fromPrimitive(u256, m, 24620149608466364616251608466389896540098571);
11761182
1177 const x_ = try x.toPrimitive(u256);1183 const x_ = try x.toPrimitive(u256);
1178 try testing.expect((try M.Fe.fromPrimitive(@TypeOf(x_), m, x_)).eql(x));1184 try testing.expect((try M.Fe.fromPrimitive(@TypeOf(x_), m, x_)).eql(x));
...@@ -1243,10 +1249,10 @@ test "finite field arithmetic" {...@@ -1243,10 +1249,10 @@ test "finite field arithmetic" {
1243 try testing.expect(add_nm_m.eql(add_m_nm));1249 try testing.expect(add_nm_m.eql(add_m_nm));
12441250
1245 // Non-montgomery - montgomery1251 // Non-montgomery - montgomery
1246 const sub_nm_m = m.sub(x, y);
1247 try testing.expect(!sub_nm_m.montgomery);
1248 var y_mont = y;1252 var y_mont = y;
1249 try m.toMontgomery(&y_mont);1253 try m.toMontgomery(&y_mont);
1254 const sub_nm_m = m.sub(x, y_mont);
1255 try testing.expect(!sub_nm_m.montgomery);
1250 var sub_m_nm = m.sub(x_mont, y);1256 var sub_m_nm = m.sub(x_mont, y);
1251 try testing.expect(sub_m_nm.montgomery);1257 try testing.expect(sub_m_nm.montgomery);
1252 try m.fromMontgomery(&sub_m_nm);1258 try m.fromMontgomery(&sub_m_nm);