| ... | @@ -843,7 +843,7 @@ const ct_protected = struct { | ... | @@ -843,7 +843,7 @@ const ct_protected = struct { |
| 843 | | 843 | |
| 844 | // Compares two big integers in constant time, returning true if x >= y. | 844 | // Compares two big integers in constant time, returning true if x >= y. |
| 845 | fn limbsCmpGeq(x: anytype, y: @TypeOf(x)) bool { | 845 | fn limbsCmpGeq(x: anytype, y: @TypeOf(x)) bool { |
| 846 | return !ct.limbsCmpLt(x, y); | 846 | return !limbsCmpLt(x, y); |
| 847 | } | 847 | } |
| 848 | | 848 | |
| 849 | // Multiplies two limbs and returns the result as a wide limb. | 849 | // Multiplies two limbs and returns the result as a wide limb. |
| ... | @@ -878,11 +878,11 @@ const ct_unprotected = struct { | ... | @@ -878,11 +878,11 @@ const ct_unprotected = struct { |
| 878 | | 878 | |
| 879 | // Compares two big integers in constant time, returning true if x < y. | 879 | // Compares two big integers in constant time, returning true if x < y. |
| 880 | fn limbsCmpLt(x: anytype, y: @TypeOf(x)) bool { | 880 | fn limbsCmpLt(x: anytype, y: @TypeOf(x)) bool { |
| 881 | assert(x.limbs_count() == y.limbs_count()); | 881 | const x_limbs = x.limbsConst(); |
| 882 | const x_limbs = x.limbs.constSlice(); | 882 | const y_limbs = y.limbsConst(); |
| 883 | const y_limbs = y.limbs.constSlice(); | 883 | assert(x_limbs.len == y_limbs.len); |
| 884 | | 884 | |
| 885 | var i = x.limbs_count(); | 885 | var i = x_limbs.len; |
| 886 | while (i != 0) { | 886 | while (i != 0) { |
| 887 | i -= 1; | 887 | i -= 1; |
| 888 | if (x_limbs[i] != y_limbs[i]) { | 888 | if (x_limbs[i] != y_limbs[i]) { |
| ... | @@ -894,7 +894,7 @@ const ct_unprotected = struct { | ... | @@ -894,7 +894,7 @@ const ct_unprotected = struct { |
| 894 | | 894 | |
| 895 | // Compares two big integers in constant time, returning true if x >= y. | 895 | // Compares two big integers in constant time, returning true if x >= y. |
| 896 | fn limbsCmpGeq(x: anytype, y: @TypeOf(x)) bool { | 896 | fn limbsCmpGeq(x: anytype, y: @TypeOf(x)) bool { |
| 897 | return !ct.limbsCmpLt(x, y); | 897 | return !limbsCmpLt(x, y); |
| 898 | } | 898 | } |
| 899 | | 899 | |
| 900 | // Multiplies two limbs and returns the result as a wide limb. | 900 | // Multiplies two limbs and returns the result as a wide limb. |
| ... | @@ -961,3 +961,28 @@ test "finite field arithmetic" { | ... | @@ -961,3 +961,28 @@ test "finite field arithmetic" { |
| 961 | try testing.expect(x_sq3.eql(x_sq4)); | 961 | try testing.expect(x_sq3.eql(x_sq4)); |
| 962 | try m.fromMontgomery(&x); | 962 | try m.fromMontgomery(&x); |
| 963 | } | 963 | } |
| | 964 | |
| | 965 | fn testCt(ct_: anytype) !void { |
| | 966 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; |
| | 967 | |
| | 968 | const l0: Limb = 0; |
| | 969 | const l1: Limb = 1; |
| | 970 | try testing.expectEqual(l1, ct_.select(true, l1, l0)); |
| | 971 | try testing.expectEqual(l0, ct_.select(false, l1, l0)); |
| | 972 | try testing.expectEqual(false, ct_.eql(l1, l0)); |
| | 973 | try testing.expectEqual(true, ct_.eql(l1, l1)); |
| | 974 | |
| | 975 | const M = Modulus(256); |
| | 976 | const m = try M.fromPrimitive(u256, 3429938563481314093726330772853735541133072814650493833233); |
| | 977 | const x = try M.Fe.fromPrimitive(u256, m, 80169837251094269539116136208111827396136208141182357733); |
| | 978 | const y = try M.Fe.fromPrimitive(u256, m, 24620149608466364616251608466389896540098571); |
| | 979 | try testing.expectEqual(false, ct_.limbsCmpLt(x.v, y.v)); |
| | 980 | try testing.expectEqual(true, ct_.limbsCmpGeq(x.v, y.v)); |
| | 981 | |
| | 982 | try testing.expectEqual(WideLimb{ .hi = 0, .lo = 0x88 }, ct_.mulWide(1 << 3, (1 << 4) + 1)); |
| | 983 | } |
| | 984 | |
| | 985 | test ct { |
| | 986 | try testCt(ct_protected); |
| | 987 | try testCt(ct_unprotected); |
| | 988 | } |