ccryptolib/internal/util.lua
2022-04-08 11:56:03 -03:00

73 lines
1.8 KiB
Lua

--- Converts a little-endian array from one power-of-two base to another.
--
-- @tparam {number...} a The array to convert, in little-endian.
-- @tparam number base1 The base to convert from. Must be a power of 2.
-- @tparam number base2 The base to convert to. Must be a power of 2.
-- @treturn {number...}
--
local function rebaseLE(a, base1, base2) -- TODO Write contract properly.
local out = {}
local outlen = 1
local acc = 0
local mul = 1
for i = 1, #a do
acc = acc + a[i] * mul
mul = mul * base1
while mul >= base2 do
local rem = acc % base2
acc = (acc - rem) / base2
mul = mul / base2
out[outlen] = rem
outlen = outlen + 1
end
end
if mul > 0 then
out[outlen] = acc
end
return out
end
--- Decodes bits with X25519/Ed25519 exponent clamping.
--
-- @taparm string str The 32-byte encoded exponent.
-- @treturn {number...} The decoded clamped bits.
--
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[1] = 0
out[2] = 0
out[3] = 0
out[255] = 1
out[256] = 0
-- We remove the 3 lowest bits since the ladder already multiplies by 8.
return out
end
--- Decodes bits with X25519/Ed25519 exponent clamping and division by 8.
--
-- @taparm string str The 32-byte encoded exponent.
-- @treturn {number...} The decoded clamped bits, divided by 8.
--
local function bits8(str)
return {unpack(bits(str), 4)}
end
return {
rebaseLE = rebaseLE,
bits = bits,
bits8 = bits8,
}