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