authorgravatar for 124872+jedisct1@users.noreply.github.comFrank Denis <124872+jedisct1@users.noreply.github.com> 2026-09-27 17:38:01+02:00
committergravatar for 124872+jedisct1@users.noreply.github.comFrank Denis <124872+jedisct1@users.noreply.github.com> 2026-10-01 12:06:49+02:00
logb30ccf20d34a94627aaa458c94ca191d5119b473
tree919101685f8a7cbcc129b53222c3ab9a57d66451
parent8874073a3fddd9409018a88dcc7f85076b8fdc19

Add tests for public scalar multiplication and scalar split


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

lib/std/crypto/pcurves/tests/secp256k1.zig+39
...@@ -4,6 +4,8 @@ const testing = std.testing;...@@ -4,6 +4,8 @@ const testing = std.testing;
44
5const Secp256k1 = @import("../secp256k1.zig").Secp256k1;5const Secp256k1 = @import("../secp256k1.zig").Secp256k1;
66
7const lambda: u256 = 0x5363ad4cc05c30e0a5261c028812645a122e22ea20816678df02967c1b23bd72;
8
7test "secp256k1 ECDH key exchange" {9test "secp256k1 ECDH key exchange" {
8 const io = testing.io;10 const io = testing.io;
9 const dha = Secp256k1.scalar.random(io, .little);11 const dha = Secp256k1.scalar.random(io, .little);
...@@ -138,6 +140,43 @@ test "secp256k1 double base multiplication" {...@@ -138,6 +140,43 @@ test "secp256k1 double base multiplication" {
138 try testing.expect(pr1.equivalent(pr2));140 try testing.expect(pr1.equivalent(pr2));
139}141}
140142
143test "secp256k1 public multiplication" {
144 const io = testing.io;
145 const n = Secp256k1.scalar.field_order;
146 const p = Secp256k1.random(io);
147 for ([_]u256{ 1, 2, n - 1, lambda, n - lambda, (1 << 128) - 1 }) |x| {
148 var s: [32]u8 = undefined;
149 std.mem.writeInt(u256, &s, x, .big);
150 for ([_]Secp256k1{ p, Secp256k1.basePoint }) |q| {
151 try testing.expect((try q.mulPublic(s, .big)).equivalent(try q.mul(s, .big)));
152 }
153 }
154
155 var s_n: [32]u8 = undefined;
156 std.mem.writeInt(u256, &s_n, n, .little);
157 try testing.expectError(error.NonCanonical, p.mulPublic(s_n, .little));
158}
159
160test "secp256k1 scalar split" {
161 const io = testing.io;
162 const Scalar = Secp256k1.scalar.Scalar;
163 const n = Secp256k1.scalar.field_order;
164 var lambda_s: [32]u8 = undefined;
165 std.mem.writeInt(u256, &lambda_s, lambda, .little);
166 const lambda_scalar = try Scalar.fromBytes(lambda_s, .little);
167 inline for (.{ .little, .big }) |endian| {
168 const k = Secp256k1.scalar.random(io, endian);
169 const split = try Secp256k1.Endormorphism.splitScalar(k, endian);
170 const r1 = try Scalar.fromBytes(split.r1, endian);
171 const r2 = try Scalar.fromBytes(split.r2, endian);
172 try testing.expect(r1.add(r2.mul(lambda_scalar)).equivalent(try Scalar.fromBytes(k, endian)));
173 for ([_][32]u8{ split.r1, split.r2 }) |r_s| {
174 const r = std.mem.readInt(u256, &r_s, endian);
175 try testing.expect(@min(r, n - r) < 1 << 128);
176 }
177 }
178}
179
141test "secp256k1 scalar inverse" {180test "secp256k1 scalar inverse" {
142 const expected = "08d0684a0fe8ea978b68a29e4b4ffdbd19eeb59db25301cf23ecbe568e1f9822";181 const expected = "08d0684a0fe8ea978b68a29e4b4ffdbd19eeb59db25301cf23ecbe568e1f9822";
143 var out: [32]u8 = undefined;182 var out: [32]u8 = undefined;