Remove dependency on string.pack

This commit is contained in:
Miguel Oliveira 2022-10-16 19:28:56 -03:00
parent 0cd726952a
commit d4c173c713
10 changed files with 251 additions and 54 deletions

View file

@ -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

View file

@ -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

View file

@ -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),

View file

@ -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

View file

@ -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
View 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

View file

@ -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
) )

View file

@ -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

View file

@ -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 {

View file

@ -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 {