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}