| author | |
| committer | |
| log | 735e31ad99bc87621f68dc99806743f64c5128a6 |
| tree | d18553d6e52c2b13cd4edfbab7a0660687e532c1 |
| parent | 16126cf14165bf97ed3c588fbc10f13c1970f22f |
On P-256 and P-384 (a = -3), the curve equation at x = 0 reduces to
y^2 = B. B is a quadratic residue mod p on both curves, so the
points (0, +/-sqrt(B)) exist, are valid, and lie in the prime-order
group since the cofactor is 1.
The final select only checks , so for q = (0, +/-sqrt(B))
it discards the correct sum and returns p.4 files changed, 32 insertions(+), 2 deletions(-)
lib/std/crypto/pcurves/p256.zig+1-1| ... | @@ -215,7 +215,7 @@ pub const P256 = struct { | ... | @@ -215,7 +215,7 @@ pub const P256 = struct { |
| 215 | .y = Y3, | 215 | .y = Y3, |
| 216 | .z = Z3, | 216 | .z = Z3, |
| 217 | }; | 217 | }; |
| 218 | ret.cMov(p, @intFromBool(q.x.isZero())); | 218 | ret.cMov(p, @intFromBool(q.x.isZero() and q.y.isZero())); |
| 219 | return ret; | 219 | return ret; |
| 220 | } | 220 | } |
| 221 | 221 |
lib/std/crypto/pcurves/p384.zig+1-1| ... | @@ -215,7 +215,7 @@ pub const P384 = struct { | ... | @@ -215,7 +215,7 @@ pub const P384 = struct { |
| 215 | .y = Y3, | 215 | .y = Y3, |
| 216 | .z = Z3, | 216 | .z = Z3, |
| 217 | }; | 217 | }; |
| 218 | ret.cMov(p, @intFromBool(q.x.isZero())); | 218 | ret.cMov(p, @intFromBool(q.x.isZero() and q.y.isZero())); |
| 219 | return ret; | 219 | return ret; |
| 220 | } | 220 | } |
| 221 | 221 |
lib/std/crypto/pcurves/tests/p256.zig+15| ... | @@ -145,3 +145,18 @@ test "p256 scalar parity" { | ... | @@ -145,3 +145,18 @@ test "p256 scalar parity" { |
| 145 | try std.testing.expect(P256.scalar.Scalar.one.isOdd()); | 145 | try std.testing.expect(P256.scalar.Scalar.one.isOdd()); |
| 146 | try std.testing.expect(P256.scalar.Scalar.one.dbl().isOdd() == false); | 146 | try std.testing.expect(P256.scalar.Scalar.one.dbl().isOdd() == false); |
| 147 | } | 147 | } |
| 148 | |||
| 149 | test "p256 with x = 0 point" { | ||
| 150 | const yh = "66485c780e2f83d72433bd5d84a06bb6541c2af31dae871728bf856a174f93f4"; | ||
| 151 | var ys: [32]u8 = undefined; | ||
| 152 | _ = try fmt.hexToBytes(&ys, yh); | ||
| 153 | const y = try P256.Fe.fromBytes(ys, .big); | ||
| 154 | |||
| 155 | const p = P256.basePoint.dbl(); | ||
| 156 | const q = try P256.fromAffineCoordinates(.{ .x = .zero, .y = y }); | ||
| 157 | const want = p.add(q); | ||
| 158 | const got = p.addMixed(.{ .x = .zero, .y = y }); | ||
| 159 | |||
| 160 | try std.testing.expect(!got.equivalent(p)); | ||
| 161 | try std.testing.expect(got.equivalent(want)); | ||
| 162 | } |
lib/std/crypto/pcurves/tests/p384.zig+15| ... | @@ -155,3 +155,18 @@ test "p384 scalar parity" { | ... | @@ -155,3 +155,18 @@ test "p384 scalar parity" { |
| 155 | try std.testing.expect(P384.scalar.Scalar.one.isOdd()); | 155 | try std.testing.expect(P384.scalar.Scalar.one.isOdd()); |
| 156 | try std.testing.expect(P384.scalar.Scalar.one.dbl().isOdd() == false); | 156 | try std.testing.expect(P384.scalar.Scalar.one.dbl().isOdd() == false); |
| 157 | } | 157 | } |
| 158 | |||
| 159 | test "p384 with x = 0 point" { | ||
| 160 | const yh = "c306610fb0ae5a159cf45c06069f22a6c5eb3641c602d42dea2c4b4f75550793406d80d2b91ad54f9048bd487af1ade1"; | ||
| 161 | var ys: [48]u8 = undefined; | ||
| 162 | _ = try fmt.hexToBytes(&ys, yh); | ||
| 163 | const y = try P384.Fe.fromBytes(ys, .big); | ||
| 164 | |||
| 165 | const p = P384.basePoint.dbl(); | ||
| 166 | const q = try P384.fromAffineCoordinates(.{ .x = .zero, .y = y }); | ||
| 167 | const want = p.add(q); | ||
| 168 | const got = p.addMixed(.{ .x = .zero, .y = y }); | ||
| 169 | |||
| 170 | try std.testing.expect(!got.equivalent(p)); | ||
| 171 | try std.testing.expect(got.equivalent(want)); | ||
| 172 | } |