Remove dependency on string.pack
This commit is contained in:
parent
0cd726952a
commit
d4c173c713
15
aead.lua
15
aead.lua
|
@ -4,9 +4,12 @@
|
||||||
--
|
--
|
||||||
|
|
||||||
local expect = require "cc.expect".expect
|
local expect = require "cc.expect".expect
|
||||||
|
local packing = require "ccryptolib.internal.packing"
|
||||||
local chacha20 = require "ccryptolib.chacha20"
|
local chacha20 = require "ccryptolib.chacha20"
|
||||||
local poly1305 = require "ccryptolib.poly1305"
|
local poly1305 = require "ccryptolib.poly1305"
|
||||||
|
|
||||||
|
local p8x1, fmt8x1 = packing.compilePack("<I8")
|
||||||
|
local u4x4, fmt4x4 = packing.compileUnpack("<I4I4I4I4")
|
||||||
local bxor = bit32.bxor
|
local bxor = bit32.bxor
|
||||||
local bor = bit32.bor
|
local bor = bit32.bor
|
||||||
|
|
||||||
|
@ -39,8 +42,8 @@ local function encrypt(key, nonce, message, aad, rounds)
|
||||||
-- Authenticate.
|
-- Authenticate.
|
||||||
local pad1 = ("\0"):rep(-#aad % 16)
|
local pad1 = ("\0"):rep(-#aad % 16)
|
||||||
local pad2 = ("\0"):rep(-#ciphertext % 16)
|
local pad2 = ("\0"):rep(-#ciphertext % 16)
|
||||||
local aadLen = ("<I8"):pack(#aad)
|
local aadLen = p8x1("<I8", #aad)
|
||||||
local ctxLen = ("<I8"):pack(#ciphertext)
|
local ctxLen = p8x1("<I8", #ciphertext)
|
||||||
local combined = aad .. pad1 .. ciphertext .. pad2 .. aadLen .. ctxLen
|
local combined = aad .. pad1 .. ciphertext .. pad2 .. aadLen .. ctxLen
|
||||||
local tag = poly1305.mac(authKey, combined)
|
local tag = poly1305.mac(authKey, combined)
|
||||||
|
|
||||||
|
@ -77,11 +80,11 @@ local function decrypt(key, nonce, tag, ciphertext, aad, rounds)
|
||||||
-- Check tag.
|
-- Check tag.
|
||||||
local pad1 = ("\0"):rep(-#aad % 16)
|
local pad1 = ("\0"):rep(-#aad % 16)
|
||||||
local pad2 = ("\0"):rep(-#ciphertext % 16)
|
local pad2 = ("\0"):rep(-#ciphertext % 16)
|
||||||
local aadLen = ("<I8"):pack(#aad)
|
local aadLen = p8x1(fmt8x1, #aad)
|
||||||
local ctxLen = ("<I8"):pack(#ciphertext)
|
local ctxLen = p8x1(fmt8x1, #ciphertext)
|
||||||
local combined = aad .. pad1 .. ciphertext .. pad2 .. aadLen .. ctxLen
|
local combined = aad .. pad1 .. ciphertext .. pad2 .. aadLen .. ctxLen
|
||||||
local t1, t2, t3, t4 = ("<I4I4I4I4"):unpack(tag)
|
local t1, t2, t3, t4 = u4x4(fmt4x4, tag, 1)
|
||||||
local u1, u2, u3, u4 = ("<I4I4I4I4"):unpack(poly1305.mac(authKey, combined))
|
local u1, u2, u3, u4 = u4x4(fmt4x4, poly1305.mac(authKey, combined), 1)
|
||||||
local eq = bor(bxor(t1, u1), bxor(t2, u2), bxor(t3, u3), bxor(t4, u4))
|
local eq = bor(bxor(t1, u1), bxor(t2, u2), bxor(t3, u3), bxor(t4, u4))
|
||||||
if eq == 0 then return message end
|
if eq == 0 then return message end
|
||||||
end
|
end
|
||||||
|
|
20
blake3.lua
20
blake3.lua
|
@ -3,11 +3,15 @@
|
||||||
-- @module blake3
|
-- @module blake3
|
||||||
--
|
--
|
||||||
|
|
||||||
local expect = require "cc.expect".expect
|
local expect = require "cc.expect".expect
|
||||||
|
local packing = require "ccryptolib.internal.packing"
|
||||||
|
|
||||||
local unpack = unpack or table.unpack
|
local unpack = unpack or table.unpack
|
||||||
local bxor = bit32.bxor
|
local bxor = bit32.bxor
|
||||||
local rol = bit32.lrotate
|
local rol = bit32.lrotate
|
||||||
|
local p16x4, fmt16x4 = packing.compilePack("<I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4")
|
||||||
|
local u16x4 = packing.compileUnpack(fmt16x4)
|
||||||
|
local u8x4, fmt8x4 = packing.compileUnpack("<I4I4I4I4I4I4I4I4")
|
||||||
|
|
||||||
local CHUNK_START = 0x01
|
local CHUNK_START = 0x01
|
||||||
local CHUNK_END = 0x02
|
local CHUNK_END = 0x02
|
||||||
|
@ -129,7 +133,7 @@ local function expand(state, len, offset)
|
||||||
for i = 0, len / 64 do
|
for i = 0, len / 64 do
|
||||||
local n = offset + i
|
local n = offset + i
|
||||||
local md = compress(state.cv, state.m, n, state.n, state.f, true)
|
local md = compress(state.cv, state.m, n, state.n, state.f, true)
|
||||||
out[i + 1] = ("<I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4"):pack(unpack(md))
|
out[i + 1] = p16x4(fmt16x4, unpack(md))
|
||||||
end
|
end
|
||||||
|
|
||||||
return table.concat(out):sub(1, len)
|
return table.concat(out):sub(1, len)
|
||||||
|
@ -150,7 +154,7 @@ local function update(state, message)
|
||||||
-- Digest complete blocks.
|
-- Digest complete blocks.
|
||||||
for i = 1, #blocks, 64 do
|
for i = 1, #blocks, 64 do
|
||||||
-- Compress the block.
|
-- Compress the block.
|
||||||
local block = {("<I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4"):unpack(blocks, i)}
|
local block = {u16x4(fmt16x4, blocks, i)}
|
||||||
local stateFlags = state.f + state.s + state.e
|
local stateFlags = state.f + state.s + state.e
|
||||||
state.cv = compress(state.cv, block, state.t, 64, stateFlags)
|
state.cv = compress(state.cv, block, state.t, 64, stateFlags)
|
||||||
state.s = 0
|
state.s = 0
|
||||||
|
@ -188,7 +192,7 @@ local function finalize(state)
|
||||||
-- Pad the last message block.
|
-- Pad the last message block.
|
||||||
local lastLen = #state.m
|
local lastLen = #state.m
|
||||||
local padded = state.m .. ("\0"):rep(64)
|
local padded = state.m .. ("\0"):rep(64)
|
||||||
local last = {("<I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4"):unpack(padded)}
|
local last = {u16x4(fmt16x4, padded, 1)}
|
||||||
|
|
||||||
-- Prepare output expansion state.
|
-- Prepare output expansion state.
|
||||||
if state.t > 0 then
|
if state.t > 0 then
|
||||||
|
@ -267,13 +271,13 @@ end
|
||||||
function mod.newKeyed(key)
|
function mod.newKeyed(key)
|
||||||
expect(1, key, "string")
|
expect(1, key, "string")
|
||||||
assert(#key == 32, "key length must be 32")
|
assert(#key == 32, "key length must be 32")
|
||||||
return new({("<I4I4I4I4I4I4I4I4"):unpack(key)}, KEYED_HASH)
|
return new({u8x4(fmt8x4, key, 1)}, KEYED_HASH)
|
||||||
end
|
end
|
||||||
|
|
||||||
function mod.newDk(context)
|
function mod.newDk(context)
|
||||||
expect(1, context, "string")
|
expect(1, context, "string")
|
||||||
local iv = new(IV, DERIVE_KEY_CONTEXT):update(context):finalize():expand(32)
|
local iv = new(IV, DERIVE_KEY_CONTEXT):update(context):finalize():expand(32)
|
||||||
return new({("<I4I4I4I4I4I4I4I4"):unpack(iv)}, DERIVE_KEY_MATERIAL)
|
return new({u8x4(fmt8x4, iv, 1)}, DERIVE_KEY_MATERIAL)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Hashes data using BLAKE3.
|
--- Hashes data using BLAKE3.
|
||||||
|
@ -304,7 +308,7 @@ function mod.digestKeyed(key, message, len)
|
||||||
expect(3, len, "number", "nil")
|
expect(3, len, "number", "nil")
|
||||||
len = len or 32
|
len = len or 32
|
||||||
assert(len % 1 == 0 and len >= 1, "length must be a positive integer")
|
assert(len % 1 == 0 and len >= 1, "length must be a positive integer")
|
||||||
local h = new({("<I4I4I4I4I4I4I4I4"):unpack(key)}, KEYED_HASH)
|
local h = new({u8x4(fmt8x4, key, 1)}, KEYED_HASH)
|
||||||
return h:update(message):finalize():expand(len)
|
return h:update(message):finalize():expand(len)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -322,7 +326,7 @@ function mod.deriveKey(context)
|
||||||
expect(2, len, "number", "nil")
|
expect(2, len, "number", "nil")
|
||||||
len = len or 32
|
len = len or 32
|
||||||
assert(len % 1 == 0 and len >= 1, "length must be a positive integer")
|
assert(len % 1 == 0 and len >= 1, "length must be a positive integer")
|
||||||
local h = new({("<I4I4I4I4I4I4I4I4"):unpack(iv)}, DERIVE_KEY_MATERIAL)
|
local h = new({u8x4(fmt8x4, iv, 1)}, DERIVE_KEY_MATERIAL)
|
||||||
return h:update(material):finalize():expand(len)
|
return h:update(material):finalize():expand(len)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
15
chacha20.lua
15
chacha20.lua
|
@ -3,10 +3,15 @@
|
||||||
-- @module chacha20
|
-- @module chacha20
|
||||||
--
|
--
|
||||||
|
|
||||||
local expect = require "cc.expect".expect
|
local expect = require "cc.expect".expect
|
||||||
|
local packing = require "ccryptolib.internal.packing"
|
||||||
|
|
||||||
local bxor = bit32.bxor
|
local bxor = bit32.bxor
|
||||||
local rol = bit32.lrotate
|
local rol = bit32.lrotate
|
||||||
|
local u8x4, fmt8x4 = packing.compileUnpack("<I4I4I4I4I4I4I4I4")
|
||||||
|
local u3x4, fmt3x4 = packing.compileUnpack("<I4I4I4")
|
||||||
|
local p16x4, fmt16x4 = packing.compilePack("<I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4")
|
||||||
|
local u16x4 = packing.compileUnpack(fmt16x4)
|
||||||
|
|
||||||
local mod = {}
|
local mod = {}
|
||||||
|
|
||||||
|
@ -36,8 +41,8 @@ function mod.crypt(key, nonce, message, rounds, offset)
|
||||||
|
|
||||||
-- Build the state block.
|
-- Build the state block.
|
||||||
local i0, i1, i2, i3 = 0x61707865, 0x3320646e, 0x79622d32, 0x6b206574
|
local i0, i1, i2, i3 = 0x61707865, 0x3320646e, 0x79622d32, 0x6b206574
|
||||||
local k0, k1, k2, k3, k4, k5, k6, k7 = ("<I4I4I4I4I4I4I4I4"):unpack(key)
|
local k0, k1, k2, k3, k4, k5, k6, k7 = u8x4(fmt8x4, key, 1)
|
||||||
local cr, n0, n1, n2 = offset, ("<I4I4I4"):unpack(nonce)
|
local cr, n0, n1, n2 = offset, u3x4(fmt3x4, nonce, 1)
|
||||||
|
|
||||||
-- Pad the message.
|
-- Pad the message.
|
||||||
local padded = message .. ("\0"):rep(-#message % 64)
|
local padded = message .. ("\0"):rep(-#message % 64)
|
||||||
|
@ -101,10 +106,10 @@ function mod.crypt(key, nonce, message, rounds, offset)
|
||||||
|
|
||||||
m00, m01, m02, m03, m04, m05, m06, m07,
|
m00, m01, m02, m03, m04, m05, m06, m07,
|
||||||
m08, m09, m10, m11, m12, m13, m14, m15, idx =
|
m08, m09, m10, m11, m12, m13, m14, m15, idx =
|
||||||
("<I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4"):unpack(padded, idx)
|
u16x4(fmt16x4, padded, idx)
|
||||||
|
|
||||||
-- Feed-forward and combine.
|
-- Feed-forward and combine.
|
||||||
out[i] = ("<I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4"):pack(
|
out[i] = p16x4(fmt16x4,
|
||||||
bxor(m00, s00 + i0), bxor(m01, s01 + i1),
|
bxor(m00, s00 + i0), bxor(m01, s01 + i1),
|
||||||
bxor(m02, s02 + i2), bxor(m03, s03 + i3),
|
bxor(m02, s02 + i2), bxor(m03, s03 + i3),
|
||||||
bxor(m04, s04 + k0), bxor(m05, s05 + k1),
|
bxor(m04, s04 + k0), bxor(m05, s05 + k1),
|
||||||
|
|
|
@ -10,7 +10,10 @@
|
||||||
-- @module[kind=internal] internal.fp
|
-- @module[kind=internal] internal.fp
|
||||||
--
|
--
|
||||||
|
|
||||||
|
local packing = require "ccryptolib.inernal.packing"
|
||||||
|
|
||||||
local unpack = unpack or table.unpack
|
local unpack = unpack or table.unpack
|
||||||
|
local ufp, fmtfp = packing.compileUnpack("<I3I3I2I3I3I2I3I3I2I3I3I2")
|
||||||
|
|
||||||
--- The modular square root of -1.
|
--- The modular square root of -1.
|
||||||
local I = {
|
local I = {
|
||||||
|
@ -751,7 +754,7 @@ end
|
||||||
--
|
--
|
||||||
local function decode(b)
|
local function decode(b)
|
||||||
local w00, w01, w02, w03, w04, w05, w06, w07, w08, w09, w10, w11 =
|
local w00, w01, w02, w03, w04, w05, w06, w07, w08, w09, w10, w11 =
|
||||||
("<I3I3I2I3I3I2I3I3I2I3I3I2"):unpack(b)
|
ufp(fmtfp, b, 1)
|
||||||
|
|
||||||
w11 = w11 % 2 ^ 15
|
w11 = w11 % 2 ^ 15
|
||||||
|
|
||||||
|
|
|
@ -10,10 +10,15 @@
|
||||||
-- @module[kind=internal] internal.fq
|
-- @module[kind=internal] internal.fq
|
||||||
--
|
--
|
||||||
|
|
||||||
local mp = require "ccryptolib.internal.mp"
|
local mp = require "ccryptolib.internal.mp"
|
||||||
local util = require "ccryptolib.internal.util"
|
local util = require "ccryptolib.internal.util"
|
||||||
|
local packing = require "ccryptolib.internal.packing"
|
||||||
|
|
||||||
local unpack = unpack or table.unpack
|
local unpack = unpack or table.unpack
|
||||||
|
local pfq, fmtfq = packing.compilePack("<I3I3I3I3I3I3I3I3I3I3I2")
|
||||||
|
local ufq = packing.compileUnpack(fmtfq)
|
||||||
|
local ufql, fmtfql = packing.compileUnpack("<I3I3I3I3I3I3I3I3I3I3I3")
|
||||||
|
local ufqh, fmtfqh = packing.compileUnpack("<I3I3I3I3I3I3I3I3I3I3I1")
|
||||||
|
|
||||||
--- The scalar field's order, q.
|
--- The scalar field's order, q.
|
||||||
local Q = {
|
local Q = {
|
||||||
|
@ -180,7 +185,7 @@ end
|
||||||
-- @treturn string The 32-byte string encoding of a.
|
-- @treturn string The 32-byte string encoding of a.
|
||||||
--
|
--
|
||||||
local function encode(a)
|
local function encode(a)
|
||||||
return ("<I3I3I3I3I3I3I3I3I3I3I2"):pack(unpack(demontgomery(a)))
|
return pfq(fmtfq, unpack(demontgomery(a)))
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Decodes a scalar.
|
--- Decodes a scalar.
|
||||||
|
@ -189,7 +194,7 @@ end
|
||||||
-- @treturn {number...} 2²⁶⁴ × a mod q as 11 limbs in [0..2²⁴).
|
-- @treturn {number...} 2²⁶⁴ × a mod q as 11 limbs in [0..2²⁴).
|
||||||
--
|
--
|
||||||
local function decode(str)
|
local function decode(str)
|
||||||
local dec = {("<I3I3I3I3I3I3I3I3I3I3I2"):unpack(str)} dec[12] = nil
|
local dec = {ufq(fmtfq, str, 1)} dec[12] = nil
|
||||||
return montgomery(dec)
|
return montgomery(dec)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -199,8 +204,8 @@ end
|
||||||
-- @treturn {number...} 2²⁶⁴ × a mod q as 11 limbs in [0..2²⁴).
|
-- @treturn {number...} 2²⁶⁴ × a mod q as 11 limbs in [0..2²⁴).
|
||||||
--
|
--
|
||||||
local function decodeWide(str)
|
local function decodeWide(str)
|
||||||
local low = {("<I3I3I3I3I3I3I3I3I3I3I3"):unpack(str)} low[12] = nil
|
local low = {ufql(fmtfql, str, 1)} low[12] = nil
|
||||||
local high = {("<I3I3I3I3I3I3I3I3I3I3I1"):unpack(str, 34)} high[12] = nil
|
local high = {ufqh(fmtfqh, str, 34)} high[12] = nil
|
||||||
return add(montgomery(low), montgomery(montgomery(high)))
|
return add(montgomery(low), montgomery(montgomery(high)))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -211,7 +216,7 @@ end
|
||||||
--
|
--
|
||||||
local function decodeClamped(str)
|
local function decodeClamped(str)
|
||||||
-- Decode.
|
-- Decode.
|
||||||
local words = {("<I3I3I3I3I3I3I3I3I3I3I2"):unpack(str)} words[12] = nil
|
local words = {ufq(fmtfq, str, 1)} words[12] = nil
|
||||||
|
|
||||||
-- Clamp.
|
-- Clamp.
|
||||||
words[1] = bit32.band(words[1], 0xfffff8)
|
words[1] = bit32.band(words[1], 0xfffff8)
|
||||||
|
@ -229,7 +234,7 @@ end
|
||||||
--
|
--
|
||||||
local function decodeClamped8(str)
|
local function decodeClamped8(str)
|
||||||
-- Decode.
|
-- Decode.
|
||||||
local words = {("<I3I3I3I3I3I3I3I3I3I3I2"):unpack(str)} words[12] = nil
|
local words = {ufq(fmtfq, str, 1)} words[12] = nil
|
||||||
|
|
||||||
-- Clamp.
|
-- Clamp.
|
||||||
words[1] = bit32.band(words[1], 0xfffff8)
|
words[1] = bit32.band(words[1], 0xfffff8)
|
||||||
|
|
166
internal/packing.lua
Normal file
166
internal/packing.lua
Normal file
|
@ -0,0 +1,166 @@
|
||||||
|
--- High-performance binary packing of integers.
|
||||||
|
--
|
||||||
|
-- :::note Internal Module
|
||||||
|
-- This module is meant for internal use within the library. Its API is unstable
|
||||||
|
-- and subject to change without major version bumps.
|
||||||
|
-- :::
|
||||||
|
--
|
||||||
|
-- <br />
|
||||||
|
--
|
||||||
|
-- :::warning
|
||||||
|
-- For performance reasons, **the generated functions do not check types,
|
||||||
|
-- lengths, nor ranges**. You must ensure that the passed arguments are
|
||||||
|
-- well-formed and respect the format string yourself.
|
||||||
|
-- :::
|
||||||
|
--
|
||||||
|
-- <br />
|
||||||
|
--
|
||||||
|
-- @module[kind=internal] internal.packing
|
||||||
|
--
|
||||||
|
|
||||||
|
local fmt = string.format
|
||||||
|
|
||||||
|
local function mkPack(words, BE)
|
||||||
|
local out = "local C=string.char return function(_,"
|
||||||
|
local nb = 0
|
||||||
|
for i = 1, #words do
|
||||||
|
out = out .. fmt("n%d,", i)
|
||||||
|
nb = nb + words[i]
|
||||||
|
end
|
||||||
|
out = out:sub(1, -2) .. ")local "
|
||||||
|
for i = 1, nb do
|
||||||
|
out = out .. fmt("b%d,", i)
|
||||||
|
end
|
||||||
|
out = out:sub(1, -2) .. " "
|
||||||
|
local bi = 1
|
||||||
|
for i = 1, #words do
|
||||||
|
for _ = 1, words[i] - 1 do
|
||||||
|
out = out .. fmt("b%d=n%d%%2^8 n%d=(n%d-b%d)*2^-8 ", bi, i, i, i, bi)
|
||||||
|
bi = bi + 1
|
||||||
|
end
|
||||||
|
bi = bi + 1
|
||||||
|
end
|
||||||
|
out = out .. "return C("
|
||||||
|
bi = 1
|
||||||
|
if not BE then
|
||||||
|
for i = 1, #words do
|
||||||
|
for _ = 1, words[i] - 1 do
|
||||||
|
out = out .. fmt("b%d,", bi)
|
||||||
|
bi = bi + 1
|
||||||
|
end
|
||||||
|
out = out .. fmt("n%d%%2^8,", i)
|
||||||
|
bi = bi + 1
|
||||||
|
end
|
||||||
|
else
|
||||||
|
for i = 1, #words do
|
||||||
|
out = out .. fmt("n%d%%2^8,", i)
|
||||||
|
bi = bi + words[i] - 2
|
||||||
|
for _ = 1, words[i] - 1 do
|
||||||
|
out = out .. fmt("b%d,", bi)
|
||||||
|
bi = bi - 1
|
||||||
|
end
|
||||||
|
bi = bi + words[i] + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
out = out:sub(1, -2) .. ")end"
|
||||||
|
return load(out)()
|
||||||
|
end
|
||||||
|
|
||||||
|
local function mkUnpack(words, BE)
|
||||||
|
local out = "local B=string.byte return function(_,s,i)local "
|
||||||
|
local bi = 1
|
||||||
|
if not BE then
|
||||||
|
for i = 1, #words do
|
||||||
|
for _ = 1, words[i] do
|
||||||
|
out = out .. fmt("b%d,", bi)
|
||||||
|
bi = bi + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
for i = 1, #words do
|
||||||
|
bi = bi + words[i] - 1
|
||||||
|
for _ = 1, words[i] do
|
||||||
|
out = out .. fmt("b%d,", bi)
|
||||||
|
bi = bi - 1
|
||||||
|
end
|
||||||
|
bi = bi + words[i] + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
out = out:sub(1, -2) .. fmt("=B(s,i,i+%d)return ", bi - 2)
|
||||||
|
bi = 1
|
||||||
|
for i = 1, #words do
|
||||||
|
out = out .. fmt("b%d", bi)
|
||||||
|
bi = bi + 1
|
||||||
|
for j = 2, words[i] do
|
||||||
|
out = out .. fmt("+b%d*2^%d", bi, 8 * j - 8)
|
||||||
|
bi = bi + 1
|
||||||
|
end
|
||||||
|
out = out .. ","
|
||||||
|
end
|
||||||
|
out = out .. fmt("i+%d end", bi - 1)
|
||||||
|
return load(out)()
|
||||||
|
end
|
||||||
|
|
||||||
|
local mod = {}
|
||||||
|
|
||||||
|
-- Check whether string.pack is implemented in a high-speed language.
|
||||||
|
if not string.pack or pcall(string.dump, string.pack) then
|
||||||
|
local function compile(fmt, fn)
|
||||||
|
local e = assert(fmt:match("^([><])I[I%d]+$"), "invalid format string")
|
||||||
|
local w = {}
|
||||||
|
for i in fmt:gmatch("I([%d]+)") do
|
||||||
|
local n = tonumber(i) or 4
|
||||||
|
assert(n > 0 and n <= 4, "integral size out of limits")
|
||||||
|
w[#w + 1] = n
|
||||||
|
end
|
||||||
|
return fn(w, e == ">")
|
||||||
|
end
|
||||||
|
|
||||||
|
local packCache = {}
|
||||||
|
local unpackCache = {}
|
||||||
|
|
||||||
|
--- (`string.pack == nil`) Compiles a binary packing function.
|
||||||
|
-- @tparam string fmt A string matched by `^([><])I[I%d]+$`.
|
||||||
|
-- @treturn function A high-performance function that behaves like an unsafe
|
||||||
|
-- version of `string.pack` for the given format string. Note that the third
|
||||||
|
-- argument isn't optional.
|
||||||
|
-- @treturn string fmt
|
||||||
|
-- @throws If the string is invalid or has an invalid integral size.
|
||||||
|
-- @throws If the compiled function is too large.
|
||||||
|
function mod.compilePack(fmt)
|
||||||
|
if not packCache[fmt] then
|
||||||
|
packCache[fmt] = compile(fmt, mkPack)
|
||||||
|
end
|
||||||
|
return packCache[fmt], fmt
|
||||||
|
end
|
||||||
|
|
||||||
|
--- (`string.pack == nil`) Compiles a binary unpacking function.
|
||||||
|
-- @tparam string fmt A string matched by `^([><])I[I%d]+$`.
|
||||||
|
-- @treturn function A high-performance function that behaves like an unsafe
|
||||||
|
-- version of `string.unpack` for the given format string.
|
||||||
|
-- @treturn string fmt
|
||||||
|
-- @throws If the string is invalid or has an invalid integral size.
|
||||||
|
-- @throws If the compiled function is too large.
|
||||||
|
function mod.compileUnpack(fmt)
|
||||||
|
if not unpackCache[fmt] then
|
||||||
|
unpackCache[fmt] = compile(fmt, mkUnpack)
|
||||||
|
end
|
||||||
|
return unpackCache[fmt], fmt
|
||||||
|
end
|
||||||
|
|
||||||
|
return mod
|
||||||
|
else
|
||||||
|
--- (`string.pack ~= nil`) Compiles a binary packing function.
|
||||||
|
-- @tparam string fmt
|
||||||
|
-- @treturn function `string.pack`
|
||||||
|
-- @treturn string fmt
|
||||||
|
mod.compilePack = function(fmt) return string.pack, fmt end
|
||||||
|
|
||||||
|
--- (`string.pack ~= nil`) Compiles a binary unpacking function.
|
||||||
|
-- @tparam string fmt
|
||||||
|
-- @treturn function `string.unpack`
|
||||||
|
-- @treturn string fmt
|
||||||
|
mod.compileUnpack = function(fmt) return string.unpack, fmt end
|
||||||
|
end
|
||||||
|
|
||||||
|
return mod
|
|
@ -10,13 +10,17 @@
|
||||||
-- @module[kind=internal] internal.sha512
|
-- @module[kind=internal] internal.sha512
|
||||||
--
|
--
|
||||||
|
|
||||||
local expect = require "cc.expect".expect
|
local expect = require "cc.expect".expect
|
||||||
|
local packing = require "ccryptolib.internal.packing"
|
||||||
|
|
||||||
local shl = bit32.lshift
|
local shl = bit32.lshift
|
||||||
local shr = bit32.rshift
|
local shr = bit32.rshift
|
||||||
local bxor = bit32.bxor
|
local bxor = bit32.bxor
|
||||||
local bnot = bit32.bnot
|
local bnot = bit32.bnot
|
||||||
local band = bit32.band
|
local band = bit32.band
|
||||||
|
local p1x16, fmt1x16 = packing.compilePack(">I16")
|
||||||
|
local p16x4, fmt16x4 = packing.compilePack(">I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4")
|
||||||
|
local u32x4, fmt32x4 = packing.compileUnpack(">I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4")
|
||||||
|
|
||||||
local function carry64(a1, a0)
|
local function carry64(a1, a0)
|
||||||
local r0 = a0 % 2 ^ 32
|
local r0 = a0 % 2 ^ 32
|
||||||
|
@ -65,9 +69,7 @@ local function digest(data)
|
||||||
-- Pad input.
|
-- Pad input.
|
||||||
local bitlen = #data * 8
|
local bitlen = #data * 8
|
||||||
local padlen = -(#data + 17) % 128
|
local padlen = -(#data + 17) % 128
|
||||||
data = data .. "\x80" .. ("\0"):rep(padlen) .. (">I16"):pack(bitlen)
|
data = data .. "\x80" .. ("\0"):rep(padlen) .. p1x16(fmt1x16, bitlen)
|
||||||
local dataWords = {(">" .. ("I4"):rep(#data / 4)):unpack(data)}
|
|
||||||
dataWords[#dataWords] = nil
|
|
||||||
|
|
||||||
-- Initialize state.
|
-- Initialize state.
|
||||||
local h01, h00 = 0x6a09e667, 0xf3bcc908
|
local h01, h00 = 0x6a09e667, 0xf3bcc908
|
||||||
|
@ -80,12 +82,8 @@ local function digest(data)
|
||||||
local h71, h70 = 0x5be0cd19, 0x137e2179
|
local h71, h70 = 0x5be0cd19, 0x137e2179
|
||||||
|
|
||||||
-- Digest.
|
-- Digest.
|
||||||
local w = {}
|
for i = 1, #data, 128 do
|
||||||
for i = 1, #dataWords, 32 do
|
local w = {u32x4(fmt32x4, data, i)}
|
||||||
local index = i - 1
|
|
||||||
for j = 1, 32 do
|
|
||||||
w[j] = dataWords[index + j]
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Message schedule.
|
-- Message schedule.
|
||||||
for j = 33, 160, 2 do
|
for j = 33, 160, 2 do
|
||||||
|
@ -172,7 +170,7 @@ local function digest(data)
|
||||||
h71, h70 = carry64(h71 + h1, h70 + h0)
|
h71, h70 = carry64(h71 + h1, h70 + h0)
|
||||||
end
|
end
|
||||||
|
|
||||||
return (">I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4"):pack(
|
return p16x4(fmt16x4,
|
||||||
h01, h00, h11, h10, h21, h20, h31, h30,
|
h01, h00, h11, h10, h21, h20, h31, h30,
|
||||||
h41, h40, h51, h50, h61, h60, h71, h70
|
h41, h40, h51, h50, h61, h60, h71, h70
|
||||||
)
|
)
|
||||||
|
|
16
poly1305.lua
16
poly1305.lua
|
@ -3,8 +3,12 @@
|
||||||
-- @module poly1305
|
-- @module poly1305
|
||||||
--
|
--
|
||||||
|
|
||||||
local expect = require "cc.expect".expect
|
local expect = require "cc.expect".expect
|
||||||
local random = require "ccryptolib.random"
|
local random = require "ccryptolib.random"
|
||||||
|
local packing = require "ccryptolib.internal.packing"
|
||||||
|
|
||||||
|
local u4x4, fmt4x4 = packing.compileUnpack("<I4I4I4I4")
|
||||||
|
local p4x4 = packing.compilePack(fmt4x4)
|
||||||
|
|
||||||
local mod = {}
|
local mod = {}
|
||||||
|
|
||||||
|
@ -27,7 +31,7 @@ function mod.mac(key, message)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Decode r.
|
-- Decode r.
|
||||||
local R0, R1, R2, R3 = ("<I4I4I4I4"):unpack(key)
|
local R0, R1, R2, R3 = u4x4(fmt4x4, key, 1)
|
||||||
|
|
||||||
-- Clamp and shift.
|
-- Clamp and shift.
|
||||||
R0 = R0 % 2 ^ 28
|
R0 = R0 % 2 ^ 28
|
||||||
|
@ -55,7 +59,7 @@ function mod.mac(key, message)
|
||||||
|
|
||||||
for i = 1, #message, 16 do
|
for i = 1, #message, 16 do
|
||||||
-- Decode message block.
|
-- Decode message block.
|
||||||
local m0, m1, m2, m3 = ("<I4I4I4I4"):unpack(message, i)
|
local m0, m1, m2, m3 = u4x4(fmt4x4, message, i)
|
||||||
|
|
||||||
-- Shift message and add.
|
-- Shift message and add.
|
||||||
local x0 = h0 + h1 + m0
|
local x0 = h0 + h1 + m0
|
||||||
|
@ -119,7 +123,7 @@ function mod.mac(key, message)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Decode s.
|
-- Decode s.
|
||||||
local s0, s1, s2, s3 = ("<I4I4I4I4"):unpack(key, 17)
|
local s0, s1, s2, s3 = u4x4(fmt4x4, key, 17)
|
||||||
|
|
||||||
-- Add.
|
-- Add.
|
||||||
local t0 = s0 + c0 + c1 local u0 = t0 % 2 ^ 32
|
local t0 = s0 + c0 + c1 local u0 = t0 % 2 ^ 32
|
||||||
|
@ -128,7 +132,7 @@ function mod.mac(key, message)
|
||||||
local t3 = t2 - u2 + s3 * 2 ^ 96 + c6 + c7 local u3 = t3 % 2 ^ 128
|
local t3 = t2 - u2 + s3 * 2 ^ 96 + c6 + c7 local u3 = t3 % 2 ^ 128
|
||||||
|
|
||||||
-- Encode.
|
-- Encode.
|
||||||
return ("<I4I4I4I4"):pack(u0, u1 / 2 ^ 32, u2 / 2 ^ 64, u3 / 2 ^ 96)
|
return p4x4(fmt4x4, u0, u1 / 2 ^ 32, u2 / 2 ^ 64, u3 / 2 ^ 96)
|
||||||
end
|
end
|
||||||
|
|
||||||
local mac = mod.mac
|
local mac = mod.mac
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
local blake3 = require "ccryptolib.blake3"
|
local blake3 = require "ccryptolib.blake3"
|
||||||
local chacha20 = require "ccryptolib.chacha20"
|
local chacha20 = require "ccryptolib.chacha20"
|
||||||
|
local packing = require "ccryptolib.internal.packing"
|
||||||
|
|
||||||
|
local u1x4, fmt1x4 = packing.compileUnpack("<I4")
|
||||||
|
|
||||||
-- Initialize from local context.
|
-- Initialize from local context.
|
||||||
local ctx = {
|
local ctx = {
|
||||||
|
@ -55,7 +58,7 @@ end
|
||||||
stir(512)
|
stir(512)
|
||||||
|
|
||||||
-- Save.
|
-- Save.
|
||||||
math.randomseed(("I4"):unpack(random(4)))
|
math.randomseed(u1x4(fmt1x4, random(4), 1))
|
||||||
save()
|
save()
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
22
sha256.lua
22
sha256.lua
|
@ -3,7 +3,8 @@
|
||||||
-- @module sha256
|
-- @module sha256
|
||||||
--
|
--
|
||||||
|
|
||||||
local expect = require "cc.expect".expect
|
local expect = require "cc.expect".expect
|
||||||
|
local packing = require "ccryptolib.internal.packing"
|
||||||
|
|
||||||
local rol = bit32.lrotate
|
local rol = bit32.lrotate
|
||||||
local shr = bit32.rshift
|
local shr = bit32.rshift
|
||||||
|
@ -11,6 +12,11 @@ local bxor = bit32.bxor
|
||||||
local bnot = bit32.bnot
|
local bnot = bit32.bnot
|
||||||
local band = bit32.band
|
local band = bit32.band
|
||||||
local unpack = unpack or table.unpack
|
local unpack = unpack or table.unpack
|
||||||
|
local p1x8, fmt1x8 = packing.compilePack(">I8")
|
||||||
|
local p16x4, fmt16x4 = packing.compilePack(">I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4")
|
||||||
|
local u16x4 = packing.compileUnpack(fmt16x4)
|
||||||
|
local p8x4, fmt8x4 = packing.compilePack(">I4I4I4I4I4I4I4I4")
|
||||||
|
local u8x4 = packing.compileUnpack(fmt8x4)
|
||||||
|
|
||||||
local function primes(n, exp)
|
local function primes(n, exp)
|
||||||
local out = {}
|
local out = {}
|
||||||
|
@ -82,15 +88,15 @@ local function digest(data)
|
||||||
-- Pad input.
|
-- Pad input.
|
||||||
local bitlen = #data * 8
|
local bitlen = #data * 8
|
||||||
local padlen = -(#data + 9) % 64
|
local padlen = -(#data + 9) % 64
|
||||||
data = data .. "\x80" .. ("\0"):rep(padlen) .. (">I8"):pack(bitlen)
|
data = data .. "\x80" .. ("\0"):rep(padlen) .. p1x8(fmt1x8, bitlen)
|
||||||
|
|
||||||
-- Digest.
|
-- Digest.
|
||||||
local h = h0
|
local h = h0
|
||||||
for i = 1, #data, 64 do
|
for i = 1, #data, 64 do
|
||||||
h = compress(h, {(">I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4"):unpack(data, i)})
|
h = compress(h, {u16x4(fmt16x4, data, i)})
|
||||||
end
|
end
|
||||||
|
|
||||||
return (">I4I4I4I4I4I4I4I4"):pack(unpack(h))
|
return p8x4(fmt8x4, unpack(h))
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Hashes a password using PBKDF2-HMAC-SHA256.
|
--- Hashes a password using PBKDF2-HMAC-SHA256.
|
||||||
|
@ -110,7 +116,7 @@ local function pbkdf2(password, salt, iter)
|
||||||
-- Pad password.
|
-- Pad password.
|
||||||
if #password > 64 then password = digest(password) end
|
if #password > 64 then password = digest(password) end
|
||||||
password = password .. ("\0"):rep(-#password % 64)
|
password = password .. ("\0"):rep(-#password % 64)
|
||||||
password = {(">I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4"):unpack(password)}
|
password = {u16x4(fmt16x4, password, 1)}
|
||||||
|
|
||||||
-- Compute password blocks.
|
-- Compute password blocks.
|
||||||
local ikp = {}
|
local ikp = {}
|
||||||
|
@ -127,8 +133,8 @@ local function pbkdf2(password, salt, iter)
|
||||||
local pad96 = {2 ^ 31, 0, 0, 0, 0, 0, 0, 0x300}
|
local pad96 = {2 ^ 31, 0, 0, 0, 0, 0, 0, 0x300}
|
||||||
|
|
||||||
-- First iteration.
|
-- First iteration.
|
||||||
local pre = (">I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4I4"):pack(unpack(ikp))
|
local pre = p16x4(fmt16x4, unpack(ikp))
|
||||||
local hs = {(">I4I4I4I4I4I4I4I4"):unpack(digest(pre .. salt .. "\0\0\0\1"))}
|
local hs = {u8x4(fmt8x4, digest(pre .. salt .. "\0\0\0\1"), 1)}
|
||||||
for i = 1, 8 do hs[i + 8] = pad96[i] end
|
for i = 1, 8 do hs[i + 8] = pad96[i] end
|
||||||
hs = compress(hokp, hs)
|
hs = compress(hokp, hs)
|
||||||
|
|
||||||
|
@ -142,7 +148,7 @@ local function pbkdf2(password, salt, iter)
|
||||||
for i = 1, 8 do out[i] = bxor(out[i], hs[i]) end
|
for i = 1, 8 do out[i] = bxor(out[i], hs[i]) end
|
||||||
end
|
end
|
||||||
|
|
||||||
return (">I4I4I4I4I4I4I4I4"):pack(unpack(out))
|
return p8x4(fmt8x4, unpack(out))
|
||||||
end
|
end
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
Loading…
Reference in a new issue