ccryptolib/x25519.lua
2022-03-30 21:52:52 -03:00

60 lines
1.5 KiB
Lua

--- The X25519 key exchange scheme.
--
-- @module x25519
--
local expect = require "cc.expect".expect
local fp = require "ccryptolib.internal.fp"
local mont = require "ccryptolib.internal.curve25519"
-- TODO This function feels out of place anywhere I try putting it on.
local function bits(str)
-- Decode.
local bytes = {str:byte(1, 32)}
local out = {}
for i = 1, 32 do
local byte = bytes[i]
for j = -7, 0 do
local bit = byte % 2
out[8 * i + j] = bit
byte = (byte - bit) / 2
end
end
-- Clamp.
out[256] = 0
out[255] = 1
-- We remove the 3 lowest bits since the ladder already multiplies by 8.
return {unpack(out, 4)}
end
local mod = {}
--- Computes the public key from a secret key.
--
-- @tparam string sk A random 32-byte secret key.
-- @treturn string The matching public key.
--
function mod.publicKey(sk)
expect(1, sk, "string")
assert(#sk == 32, "secret key length must be 32")
return fp.encode(mont.ladder8(fp.kmul, 9, bits(sk)))
end
--- Performs the key exchange.
--
-- @tparam string sk A secret key.
-- @tparam string pk A public key, usually derived from a second secret key.
-- @treturn string The 32-byte shared secret between both keys.
--
function mod.exchange(sk, pk)
expect(1, sk, "string")
assert(#sk == 32, "secret key length must be 32")
expect(2, pk, "string")
assert(#pk == 32, "public key length must be 32")
return fp.encode(mont.ladder8(fp.mul, fp.decode(pk), bits(sk)))
end
return mod