master
1const std = @import("std");
2const fmt = std.fmt;
3const testing = std.testing;
4
5const Secp256k1 = @import("../secp256k1.zig").Secp256k1;
6
7test "secp256k1 ECDH key exchange" {
8 const dha = Secp256k1.scalar.random(.little);
9 const dhb = Secp256k1.scalar.random(.little);
10 const dhA = try Secp256k1.basePoint.mul(dha, .little);
11 const dhB = try Secp256k1.basePoint.mul(dhb, .little);
12 const shareda = try dhA.mul(dhb, .little);
13 const sharedb = try dhB.mul(dha, .little);
14 try testing.expect(shareda.equivalent(sharedb));
15}
16
17test "secp256k1 ECDH key exchange including public multiplication" {
18 const dha = Secp256k1.scalar.random(.little);
19 const dhb = Secp256k1.scalar.random(.little);
20 const dhA = try Secp256k1.basePoint.mul(dha, .little);
21 const dhB = try Secp256k1.basePoint.mulPublic(dhb, .little);
22 const shareda = try dhA.mul(dhb, .little);
23 const sharedb = try dhB.mulPublic(dha, .little);
24 try testing.expect(shareda.equivalent(sharedb));
25}
26
27test "secp256k1 point from affine coordinates" {
28 const xh = "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798";
29 const yh = "483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8";
30 var xs: [32]u8 = undefined;
31 _ = try fmt.hexToBytes(&xs, xh);
32 var ys: [32]u8 = undefined;
33 _ = try fmt.hexToBytes(&ys, yh);
34 var p = try Secp256k1.fromSerializedAffineCoordinates(xs, ys, .big);
35 try testing.expect(p.equivalent(Secp256k1.basePoint));
36}
37
38test "secp256k1 test vectors" {
39 const expected = [_][]const u8{
40 "0000000000000000000000000000000000000000000000000000000000000000",
41 "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798",
42 "c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5",
43 "f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9",
44 "e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13",
45 "2f8bde4d1a07209355b4a7250a5c5128e88b84bddc619ab7cba8d569b240efe4",
46 "fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556",
47 "5cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc",
48 "2f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a01",
49 "acd484e2f0c7f65309ad178a9f559abde09796974c57e714c35f110dfc27ccbe",
50 };
51 var p = Secp256k1.identityElement;
52 for (expected) |xh| {
53 const x = p.affineCoordinates().x;
54 p = p.add(Secp256k1.basePoint);
55 var xs: [32]u8 = undefined;
56 _ = try fmt.hexToBytes(&xs, xh);
57 try testing.expectEqualSlices(u8, &x.toBytes(.big), &xs);
58 }
59}
60
61test "secp256k1 test vectors - doubling" {
62 const expected = [_][]const u8{
63 "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798",
64 "c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5",
65 "e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13",
66 "2f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a01",
67 "e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a",
68 };
69 var p = Secp256k1.basePoint;
70 for (expected) |xh| {
71 const x = p.affineCoordinates().x;
72 p = p.dbl();
73 var xs: [32]u8 = undefined;
74 _ = try fmt.hexToBytes(&xs, xh);
75 try testing.expectEqualSlices(u8, &x.toBytes(.big), &xs);
76 }
77}
78
79test "secp256k1 compressed sec1 encoding/decoding" {
80 const p = Secp256k1.random();
81 const s = p.toCompressedSec1();
82 const q = try Secp256k1.fromSec1(&s);
83 try testing.expect(p.equivalent(q));
84}
85
86test "secp256k1 uncompressed sec1 encoding/decoding" {
87 const p = Secp256k1.random();
88 const s = p.toUncompressedSec1();
89 const q = try Secp256k1.fromSec1(&s);
90 try testing.expect(p.equivalent(q));
91}
92
93test "secp256k1 public key is the neutral element" {
94 const n = Secp256k1.scalar.Scalar.zero.toBytes(.little);
95 const p = Secp256k1.random();
96 try testing.expectError(error.IdentityElement, p.mul(n, .little));
97}
98
99test "secp256k1 public key is the neutral element (public verification)" {
100 const n = Secp256k1.scalar.Scalar.zero.toBytes(.little);
101 const p = Secp256k1.random();
102 try testing.expectError(error.IdentityElement, p.mulPublic(n, .little));
103}
104
105test "secp256k1 field element non-canonical encoding" {
106 const s = [_]u8{0xff} ** 32;
107 try testing.expectError(error.NonCanonical, Secp256k1.Fe.fromBytes(s, .little));
108}
109
110test "secp256k1 neutral element decoding" {
111 try testing.expectError(error.InvalidEncoding, Secp256k1.fromAffineCoordinates(.{ .x = Secp256k1.Fe.zero, .y = Secp256k1.Fe.zero }));
112 const p = try Secp256k1.fromAffineCoordinates(.{ .x = Secp256k1.Fe.zero, .y = Secp256k1.Fe.one });
113 try testing.expectError(error.IdentityElement, p.rejectIdentity());
114}
115
116test "secp256k1 double base multiplication" {
117 const p1 = Secp256k1.basePoint;
118 const p2 = Secp256k1.basePoint.dbl();
119 const s1 = [_]u8{0x01} ** 32;
120 const s2 = [_]u8{0x02} ** 32;
121 const pr1 = try Secp256k1.mulDoubleBasePublic(p1, s1, p2, s2, .little);
122 const pr2 = (try p1.mul(s1, .little)).add(try p2.mul(s2, .little));
123 try testing.expect(pr1.equivalent(pr2));
124}
125
126test "secp256k1 scalar inverse" {
127 const expected = "08d0684a0fe8ea978b68a29e4b4ffdbd19eeb59db25301cf23ecbe568e1f9822";
128 var out: [32]u8 = undefined;
129 _ = try std.fmt.hexToBytes(&out, expected);
130
131 const scalar = try Secp256k1.scalar.Scalar.fromBytes(.{
132 0x94, 0xa1, 0xbb, 0xb1, 0x4b, 0x90, 0x6a, 0x61, 0xa2, 0x80, 0xf2, 0x45, 0xf9, 0xe9, 0x3c, 0x7f,
133 0x3b, 0x4a, 0x62, 0x47, 0x82, 0x4f, 0x5d, 0x33, 0xb9, 0x67, 0x07, 0x87, 0x64, 0x2a, 0x68, 0xde,
134 }, .big);
135 const inverse = scalar.invert();
136 try std.testing.expectEqualSlices(u8, &out, &inverse.toBytes(.big));
137}
138
139test "secp256k1 scalar parity" {
140 try std.testing.expect(Secp256k1.scalar.Scalar.zero.isOdd() == false);
141 try std.testing.expect(Secp256k1.scalar.Scalar.one.isOdd());
142 try std.testing.expect(Secp256k1.scalar.Scalar.one.dbl().isOdd() == false);
143}