master
1const std = @import("std");
2const fmt = std.fmt;
3const testing = std.testing;
4
5const P384 = @import("../p384.zig").P384;
6
7test "p384 ECDH key exchange" {
8 const dha = P384.scalar.random(.little);
9 const dhb = P384.scalar.random(.little);
10 const dhA = try P384.basePoint.mul(dha, .little);
11 const dhB = try P384.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 "p384 point from affine coordinates" {
18 const xh = "aa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7";
19 const yh = "3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f";
20 var xs: [48]u8 = undefined;
21 _ = try fmt.hexToBytes(&xs, xh);
22 var ys: [48]u8 = undefined;
23 _ = try fmt.hexToBytes(&ys, yh);
24 var p = try P384.fromSerializedAffineCoordinates(xs, ys, .big);
25 try testing.expect(p.equivalent(P384.basePoint));
26}
27
28test "p384 test vectors" {
29 const expected = [_][]const u8{
30 "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
31 "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7",
32 "08D999057BA3D2D969260045C55B97F089025959A6F434D651D207D19FB96E9E4FE0E86EBE0E64F85B96A9C75295DF61",
33 "077A41D4606FFA1464793C7E5FDC7D98CB9D3910202DCD06BEA4F240D3566DA6B408BBAE5026580D02D7E5C70500C831",
34 "138251CD52AC9298C1C8AAD977321DEB97E709BD0B4CA0ACA55DC8AD51DCFC9D1589A1597E3A5120E1EFD631C63E1835",
35 "11DE24A2C251C777573CAC5EA025E467F208E51DBFF98FC54F6661CBE56583B037882F4A1CA297E60ABCDBC3836D84BC",
36 "627BE1ACD064D2B2226FE0D26F2D15D3C33EBCBB7F0F5DA51CBD41F26257383021317D7202FF30E50937F0854E35C5DF",
37 "283C1D7365CE4788F29F8EBF234EDFFEAD6FE997FBEA5FFA2D58CC9DFA7B1C508B05526F55B9EBB2040F05B48FB6D0E1",
38 "1692778EA596E0BE75114297A6FA383445BF227FBE58190A900C3C73256F11FB5A3258D6F403D5ECE6E9B269D822C87D",
39 "8F0A39A4049BCB3EF1BF29B8B025B78F2216F7291E6FD3BAC6CB1EE285FB6E21C388528BFEE2B9535C55E4461079118B",
40 "A669C5563BD67EEC678D29D6EF4FDE864F372D90B79B9E88931D5C29291238CCED8E85AB507BF91AA9CB2D13186658FB",
41 };
42 var p = P384.identityElement;
43 for (expected) |xh| {
44 const x = p.affineCoordinates().x;
45 p = p.add(P384.basePoint);
46 var xs: [48]u8 = undefined;
47 _ = try fmt.hexToBytes(&xs, xh);
48 try testing.expectEqualSlices(u8, &x.toBytes(.big), &xs);
49 }
50}
51
52test "p384 test vectors - doubling" {
53 const expected = [_][]const u8{
54 "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7",
55 "08D999057BA3D2D969260045C55B97F089025959A6F434D651D207D19FB96E9E4FE0E86EBE0E64F85B96A9C75295DF61",
56 "138251CD52AC9298C1C8AAD977321DEB97E709BD0B4CA0ACA55DC8AD51DCFC9D1589A1597E3A5120E1EFD631C63E1835",
57 "1692778EA596E0BE75114297A6FA383445BF227FBE58190A900C3C73256F11FB5A3258D6F403D5ECE6E9B269D822C87D",
58 };
59 var p = P384.basePoint;
60 for (expected) |xh| {
61 const x = p.affineCoordinates().x;
62 p = p.dbl();
63 var xs: [48]u8 = undefined;
64 _ = try fmt.hexToBytes(&xs, xh);
65 try testing.expectEqualSlices(u8, &x.toBytes(.big), &xs);
66 }
67}
68
69test "p384 compressed sec1 encoding/decoding" {
70 const p = P384.random();
71 const s0 = p.toUncompressedSec1();
72 const s = p.toCompressedSec1();
73 try testing.expectEqualSlices(u8, s0[1..49], s[1..49]);
74 const q = try P384.fromSec1(&s);
75 try testing.expect(p.equivalent(q));
76}
77
78test "p384 uncompressed sec1 encoding/decoding" {
79 const p = P384.random();
80 const s = p.toUncompressedSec1();
81 const q = try P384.fromSec1(&s);
82 try testing.expect(p.equivalent(q));
83}
84
85test "p384 public key is the neutral element" {
86 const n = P384.scalar.Scalar.zero.toBytes(.little);
87 const p = P384.random();
88 try testing.expectError(error.IdentityElement, p.mul(n, .little));
89}
90
91test "p384 public key is the neutral element (public verification)" {
92 const n = P384.scalar.Scalar.zero.toBytes(.little);
93 const p = P384.random();
94 try testing.expectError(error.IdentityElement, p.mulPublic(n, .little));
95}
96
97test "p384 field element non-canonical encoding" {
98 const s = [_]u8{0xff} ** 48;
99 try testing.expectError(error.NonCanonical, P384.Fe.fromBytes(s, .little));
100}
101
102test "p384 neutral element decoding" {
103 try testing.expectError(error.InvalidEncoding, P384.fromAffineCoordinates(.{ .x = P384.Fe.zero, .y = P384.Fe.zero }));
104 const p = try P384.fromAffineCoordinates(.{ .x = P384.Fe.zero, .y = P384.Fe.one });
105 try testing.expectError(error.IdentityElement, p.rejectIdentity());
106}
107
108test "p384 double base multiplication" {
109 const p1 = P384.basePoint;
110 const p2 = P384.basePoint.dbl();
111 const s1 = [_]u8{0x01} ** 48;
112 const s2 = [_]u8{0x02} ** 48;
113 const pr1 = try P384.mulDoubleBasePublic(p1, s1, p2, s2, .little);
114 const pr2 = (try p1.mul(s1, .little)).add(try p2.mul(s2, .little));
115 try testing.expect(pr1.equivalent(pr2));
116}
117
118test "p384 double base multiplication with large scalars" {
119 const p1 = P384.basePoint;
120 const p2 = P384.basePoint.dbl();
121 const s1 = [_]u8{0xee} ** 48;
122 const s2 = [_]u8{0xdd} ** 48;
123 const pr1 = try P384.mulDoubleBasePublic(p1, s1, p2, s2, .little);
124 const pr2 = (try p1.mul(s1, .little)).add(try p2.mul(s2, .little));
125 try testing.expect(pr1.equivalent(pr2));
126}
127
128test "p384 scalar inverse" {
129 const expected = "a3cc705f33b5679a66e76ce66e68055c927c5dba531b2837b18fe86119511091b54d733f26b2e7a0f6fa2e7ea21ca806";
130 var out: [48]u8 = undefined;
131 _ = try std.fmt.hexToBytes(&out, expected);
132
133 const scalar = try P384.scalar.Scalar.fromBytes(.{
134 0x94, 0xa1, 0xbb, 0xb1, 0x4b, 0x90, 0x6a, 0x61, 0xa2, 0x80, 0xf2, 0x45, 0xf9, 0xe9, 0x3c, 0x7f,
135 0x3b, 0x4a, 0x62, 0x47, 0x82, 0x4f, 0x5d, 0x33, 0xb9, 0x67, 0x07, 0x87, 0x64, 0x2a, 0x68, 0xde,
136 0x38, 0x36, 0xe8, 0x0f, 0xa2, 0x84, 0x6b, 0x4e, 0xf3, 0x9a, 0x02, 0x31, 0x24, 0x41, 0x22, 0xca,
137 }, .big);
138 const inverse = scalar.invert();
139 const inverse2 = inverse.invert();
140 try testing.expectEqualSlices(u8, &out, &inverse.toBytes(.big));
141 try testing.expect(inverse2.equivalent(scalar));
142
143 const sq = scalar.sq();
144 const sqr = try sq.sqrt();
145 try testing.expect(sqr.equivalent(scalar));
146}
147
148test "p384 scalar parity" {
149 try std.testing.expect(P384.scalar.Scalar.zero.isOdd() == false);
150 try std.testing.expect(P384.scalar.Scalar.one.isOdd());
151 try std.testing.expect(P384.scalar.Scalar.one.dbl().isOdd() == false);
152}