-- Copyright (c) 2015 Phil Leblanc -- see LICENSE file ------------------------------------------------------------ --[[ Poly1305 message authentication (MAC) created by Dan Bernstein ... ]] ----------------------------------------------------------- -- poly1305 local sunp = string.unpack local bit32 = bit32 -- alias local function poly_init(k) -- k: 32-byte key as a string -- initialize internal state local st = { r = { bit32.band(sunp('= 16 do -- 16 = poly1305_block_size -- h += m[i] (in rfc: a += n with 0x01 byte) h0 = h0 + bit32.band(sunp('= 16 then poly_blocks(st, m) end --handle remaining bytes if st.bytes == 0 then -- no bytes left -- nothing to do? no add 0x01? - apparently not. else local buffer = string.sub(m, st.midx) .. '\x01' .. string.rep('\0', 16 - st.bytes -1) assert(#buffer == 16) st.final = true -- this is the last block --~ p16(buffer) poly_blocks(st, buffer) end -- return st end --poly_update local function poly_finish(st) -- local c, mask --u32 local f --u64 -- fully carry h local h0 = st.h[1] local h1 = st.h[2] local h2 = st.h[3] local h3 = st.h[4] local h4 = st.h[5] -- c = bit32.rshift(h1,26); h1 = bit32.band(h1, 0x3ffffff) h2 = h2 + c; c = bit32.rshift(h2, 26); h2 = bit32.band(h2, 0x3ffffff) h3 = h3 + c; c = bit32.rshift(h3, 26); h3 = bit32.band(h3, 0x3ffffff) h4 = h4 + c; c = bit32.rshift(h4, 26); h4 = bit32.band(h4, 0x3ffffff) h0 = h0 + (c*5); c = bit32.rshift(h0, 26); h0 = bit32.band(h0, 0x3ffffff) h1 = h1 + c -- --compute h + -p local g0 = (h0 + 5) ; c = bit32.rshift(g0, 26); g0 = bit32.band(g0, 0x3ffffff) local g1 = (h1 + c) ; c = bit32.rshift(g1, 26); g1 = bit32.band(g1, 0x3ffffff) local g2 = (h2 + c) ; c = bit32.rshift(g2, 26); g2 = bit32.band(g2, 0x3ffffff) local g3 = (h3 + c) ; c = bit32.rshift(g3, 26); g3 = bit32.band(g3, 0x3ffffff) local g4 = bit32.band(h4 + c - 0x4000000, 0xffffffff) -- (1 << 26) -- -- select h if h < p, or h + -p if h >= p mask = bit32.band(bit32.rshift(g4, 31) - 1, 0xffffffff) -- g0 = bit32.band(g0, mask) g1 = bit32.band(g1, mask) g2 = bit32.band(g2, mask) g3 = bit32.band(g3, mask) g4 = bit32.band(g4, mask) -- mask = bit32.band(bit32.bnot(mask), 0xffffffff) h0 = bit32.bor(bit32.band(h0, mask), g0) h1 = bit32.bor(bit32.band(h1, mask), g1) h2 = bit32.bor(bit32.band(h2, mask), g2) h3 = bit32.bor(bit32.band(h3, mask), g3) h4 = bit32.bor(bit32.band(h4, mask), g4) -- --h = h % (2^128) h0 = bit32.band(bit32.bor((h0), bit32.lshift(h1, 26)), 0xffffffff) h1 = bit32.band(bit32.bor(bit32.rshift(h1, 6), bit32.lshift(h2, 20)), 0xffffffff) h2 = bit32.band(bit32.bor(bit32.rshift(h2, 12), bit32.lshift(h3, 14)), 0xffffffff) h3 = bit32.band(bit32.bor(bit32.rshift(h3, 18), bit32.lshift(h4, 8)), 0xffffffff) -- -- mac = (h + pad) % (2^128) f = h0 + st.pad[1] ; h0 = bit32.band(f, 0xffffffff) f = h1 + st.pad[2] + bit32.rshift(f, 32) ; h1 = bit32.band(f, 0xffffffff) f = h2 + st.pad[3] + bit32.rshift(f, 32) ; h2 = bit32.band(f, 0xffffffff) f = h3 + st.pad[4] + bit32.rshift(f, 32) ; h3 = bit32.band(f, 0xffffffff) -- local mac = string.pack('