From 8a28d6f7eaaab7fd812e958aad4cfef6320918fd Mon Sep 17 00:00:00 2001 From: Miguel Oliveira Date: Wed, 14 Dec 2022 20:27:47 -0300 Subject: [PATCH] Add ecc unit tests and fix Ed25519 --- ccryptolib/ed25519.lua | 4 +- ccryptolib/internal/edwards25519.lua | 1 + spec/ed25519_spec.lua | 75 ++++++++++++++++++++++++++++ spec/x25519_spec.lua | 65 ++++++++++++++++++++++++ 4 files changed, 143 insertions(+), 2 deletions(-) create mode 100644 spec/ed25519_spec.lua create mode 100644 spec/x25519_spec.lua diff --git a/ccryptolib/ed25519.lua b/ccryptolib/ed25519.lua index a5d7b5c..75d43a5 100644 --- a/ccryptolib/ed25519.lua +++ b/ccryptolib/ed25519.lua @@ -54,7 +54,7 @@ function mod.sign(sk, pk, msg) -- Response. local m = fq.decodeWide(random.random(64)) - local s = fq.add(fq.add(k, fq.neg(fq.mul(fq.add(x, m), e))), fq.mul(m, e)) + local s = fq.add(fq.add(k, fq.mul(fq.add(x, m), e)), fq.mul(m, e)) local sStr = fq.encode(s) return rStr .. sStr @@ -84,7 +84,7 @@ function mod.verify(pk, msg, sig) local gs = ed.mulG(fq.bits(fq.decode(sStr))) local ye = ed.mul(y, fq.bits(e)) - local rv = ed.add(gs, ed.niels(ye)) + local rv = ed.sub(gs, ed.niels(ye)) return ed.encode(rv) == rStr end diff --git a/ccryptolib/internal/edwards25519.lua b/ccryptolib/internal/edwards25519.lua index 6604dfa..c61d0a7 100644 --- a/ccryptolib/internal/edwards25519.lua +++ b/ccryptolib/internal/edwards25519.lua @@ -274,6 +274,7 @@ end return { double = double, add = add, + sub = sub, niels = niels, encode = encode, decode = decode, diff --git a/spec/ed25519_spec.lua b/spec/ed25519_spec.lua new file mode 100644 index 0000000..53ff5a7 --- /dev/null +++ b/spec/ed25519_spec.lua @@ -0,0 +1,75 @@ +--- Test vector specification for Ed25519. +-- +-- Derived from RFC 8032. +-- + +local util = require "spec.util" +local ed25519 = require "ccryptolib.ed25519" + +describe("ed25519.verify", function() + it("passes the section 7.1 test 1", function() + local pk = util.hexcat { + "d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a", + } + + local m = "" + + local sig = util.hexcat { + "e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e06522490155", + "5fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b", + } + + expect(ed25519.verify(pk, m, sig)):eq(true) + end) + + it("passes the section 7.1 test 2", function() + local pk = util.hexcat { + "3d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660c", + } + + local m = util.hexcat { + "72", + } + + local sig = util.hexcat { + "92a009a9f0d4cab8720e820b5f642540a2b27b5416503f8fb3762223ebdb69da", + "085ac1e43e15996e458f3613d0f11d8c387b2eaeb4302aeeb00d291612bb0c00", + } + + expect(ed25519.verify(pk, m, sig)):eq(true) + end) + + it("passes the section 7.1 test 3", function() + local pk = util.hexcat { + "fc51cd8e6218a1a38da47ed00230f0580816ed13ba3303ac5deb911548908025", + } + + local m = util.hexcat { + "af82", + } + + local sig = util.hexcat { + "6291d657deec24024827e69c3abe01a30ce548a284743a445e3680d7db5ac3ac", + "18ff9b538d16f290ae67f760984dc6594a7c15e9716ed28dc027beceea1ec40a", + } + + expect(ed25519.verify(pk, m, sig)):eq(true) + end) + + it("returns false on an invalid signature", function() + local pk = util.hexcat { + "fc51cd8e6218a1a38da47ed00230f0580816ed13ba3303ac5deb911548908025", + } + + local m = util.hexcat { + "af83", -- Bit flip + } + + local sig = util.hexcat { + "6291d657deec24024827e69c3abe01a30ce548a284743a445e3680d7db5ac3ac", + "18ff9b538d16f290ae67f760984dc6594a7c15e9716ed28dc027beceea1ec40a", + } + + expect(ed25519.verify(pk, m, sig)):eq(false) + end) +end) diff --git a/spec/x25519_spec.lua b/spec/x25519_spec.lua new file mode 100644 index 0000000..d0f0122 --- /dev/null +++ b/spec/x25519_spec.lua @@ -0,0 +1,65 @@ +--- Test vector specification for X25519. +-- +-- Derived from RFC 7748. +-- + +local util = require "spec.util" +local x25519 = require "ccryptolib.x25519" + +describe("x25519.exchange", function() + it("passes the section 5.2 test vector #1", function() + local x = util.hexcat { + "a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4", + } + + local p = util.hexcat { + "e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c", + } + + local q = util.hexcat { + "c3da55379de9c6908e94ea4df28d084f32eccf03491c71f754b4075577a28552", + } + + expect(x25519.exchange(x, p)):eq(q) + end) + + it("passes the section 5.2 test vector #2", function() + local x = util.hexcat { + "4b66e9d4d1b4673c5ad22691957d6af5c11b6421e0ea01d42ca4169e7918ba0d", + } + + local p = util.hexcat { + "e5210f12786811d3f4b7959d0538ae2c31dbe7106fc03c3efc4cd549c715a493", + } + + local q = util.hexcat { + "95cbde9476e8907d7aade45cb4b873f88b595a68799fa152e6f8f7647aac7957", + } + + expect(x25519.exchange(x, p)):eq(q) + end) + + it("passes the section 5.2 test vector #3 (1k iterations)", function() + local k = util.hexcat { + "0900000000000000000000000000000000000000000000000000000000000000", + } + + local u = k + local u2 = util.hexcat { + "422c8e7a6227d7bca1350b3e2bb7279f7897b87bb6854b783c60e80311ae3079", + } + + expect(x25519.exchange(k, u)):eq(u2) + + for _ = 1, 1000 do + k, u = x25519.exchange(k, u), k + sleep() + end + + local k1000 = util.hexcat { + "684cf59ba83309552800ef566f2f4d3c1c3887c49360e3875f2eb94d99532c51", + } + + expect(k):eq(k1000) + end) +end)