Lua 3 point crossover help to start - lua

I want to implement a 3 point crossover for genetic programming but I don't know how to do it and where to start.
My input is:
a = {(first pair), (second pair), ... etc.}
For example a = {(12345,67890), (09876,54321)} (those are numbers, not strings)
Output: Something like this:
Example: a_1 = {(12895), (67340)} also numbers.
Thanks for reply and sorry for my bad English.

Here is my quick implementation of k-point crossover for integers using mostly integer arithmetic. Starting with this, you can extend it to crossover your chromosomes of many pairs of integers using a loop.
math.randomseed(111)
-- math.randomseed(os.time())
a = 12345
b = 67890
len = 5 -- number of digits
function split(mum, dad, len, base)
local split = math.pow(base, math.random(len))
local son = math.floor(dad / split) * split + mum % split
local daughter = math.floor(mum / split) * split + dad % split
return son, daughter
end
function kpoint(mum, dad, len, base, k)
for i=1, k do
mum, dad = split(mum, dad, len, base)
end
return mum, dad
end
s, d = kpoint(a, b, len, 10, 3) -- 3 point crossover in base 10
print(s) -- 67395
print(d) -- 12840
-- binary, (crossover binary representation)
s, d = kpoint(tonumber("10001", 2), tonumber("10110", 2), 5, 2, 3)
print(s) -- 23 which is (10111) in base 2
print(d) -- 16 which is (10000) in base 2
-- binary, (crossover base 10, but interpret as binary)
s, d = kpoint(1101, 1010, 4, 10, 3)
print(s) -- 1001
print(d) -- 1110

Related

Reliable way of getting the exact decimals from any number

I'm having problem returning spesific amount of decimal numbers from this function, i would like it to get that info from "dec" argument, but i'm stuck with this right now.
Edit: Made it work with the edited version bellow but isn't there a better way?
local function remove_decimal(t, dec)
if type(dec) == "number" then
for key, num in pairs(type(t) == "table" and t or {}) do
if type(num) == "number" then
local num_to_string = tostring(num)
local mod, d = math.modf(num)
-- find only decimal numbers
local num_dec = num_to_string:sub(#tostring(mod) + (mod == 0 and num < 0 and 3 or 2))
if dec <= #num_dec then
-- return amount of deciamls in the num by dec
local r = d < 0 and "-0." or "0."
local r2 = r .. num_dec:sub(1, dec)
t[key] = mod + tonumber(r2)
end
end
end
end
return t
end
By passing the function bellow i want a result like this:
result[1] > 0.12
result[2] > -0.12
result[3] > 123.45
result[4] > -1.23
local result = remove_decimal({0.123, -0.123, 123.456, -1.234}, 2)
print(result[1])
print(result[2])
print(result[3])
print(result[4])
I tried this but it seems to only work with one integer numbers and if number is 12.34 instead of 1.34 e.g, the decimal place will be removed and become 12.3. Using other methods
local d = dec + (num < 0 and 2 or 1)
local r = tonumber(num_to_string:sub(1, -#num_to_string - d)) or 0
A good approach is to find the position of the decimal point (the dot, .) and then extract a substring starting from the first character to the dot's position plus how many digits you want:
local function truncate(number, dec)
local strnum = tostring(number)
local i, j = string.find(strnum, '%.')
if not i then
return number
end
local strtrn = string.sub(strnum, 1, i+dec)
return tonumber(strtrn)
end
Call it like this:
print(truncate(123.456, 2))
print(truncate(1234567, 2))
123.45
1234567
To bulk-truncate a set of numbers:
local function truncate_all(t, dec)
for key, value in pairs(t) do
t[key] = truncate(t[key], dec)
end
return t
end
Usage:
local result = truncate_all({0.123, -0.123, 123.456, -1.234}, 2)
for key, value in pairs(result) do
print(key, value)
end
1 0.12
2 -0.12
3 123.45
4 -1.23
One could use the function string.format which is similar to the printf functions from C language. If one use the format "%.2f" the resulting string will contain 2 decimals, if one use "%.3f" the resulting string will be contain 3 decimals, etc. The idea is to dynamically create the format "%.XXXf" corresponding to the number of decimal needed by the function. Then call the function string.format with the newly created format string to generate the string "123.XXX". The last step would be to convert back the string to a number with the function tonumber.
Note that if one want the special character % to be preserved when string.format is called, you need to write %%.
function KeepDecimals (Number, DecimalCount)
local FloatFormat = string.format("%%.%df", DecimalCount)
local String = string.format(FloatFormat, Number)
return tonumber(String)
end
The behavior seems close to what the OP is looking for:
for Count = 1, 5 do
print(KeepDecimals(1.123456789, Count))
end
This code should print the following:
1.1
1.12
1.123
1.1235
1.12346
Regarding the initial code, it's quite straight-forward to integrate the provided solution. Note that I renamed the function to keep_decimal because in my understanding, the function will keep the requested number of decimals, and discard the rest.
function keep_decimal (Table, Count)
local NewTable = {}
local NewIndex = 1
for Index = 1, #Table do
NewTable[NewIndex] = KeepDecimal(Table[Index], Count)
NewIndex = NewIndex + 1
end
return NewTable
end
Obviously, the code could be tested easily, simply by copy and pasting into a Lua interpreter.
Result = keep_decimal({0.123, -0.123, 123.456, -1.234}, 2)
for Index = 1, #Result do
print(Result[Index])
end
This should print the following:
0.12
-0.12
123.46
-1.23
Edit due to the clarification of the need of truncate:
function Truncate (Number, Digits)
local Divider = Digits * 10
local TruncatedValue = math.floor(Number * Divider) / Divider
return TruncatedValue
end
On my computer, the code is working as expected:
> Truncate(123.456, 2)
123.45

Adaptation of SHA2 512 gives incorrect results

I am trying to adapt the pure Lua implementation of the SecureHashAlgorithm found here for SHA2 512 instead of SHA2 256. When I try to use the adaptation, it does not give the correct answer.
Here is the adaptation:
--
-- UTILITY FUNCTIONS
--
-- transform a string of bytes in a string of hexadecimal digits
local function str2hexa (s)
local h = string.gsub(s, ".", function(c)
return string.format("%02x", string.byte(c))
end)
return h
end
-- transforms number 'l' into a big-endian sequence of 'n' bytes
--(coded as a string)
local function num2string(l, n)
local s = ""
for i = 1, n do
--most significant byte of l
local remainder = l % 256
s = string.char(remainder) .. s
--remove from l the bits we have already transformed
l = (l-remainder) / 256
end
return s
end
-- transform the big-endian sequence of eight bytes starting at
-- index 'i' in 's' into a number
local function s264num (s, i)
local n = 0
for i = i, i + 7 do
n = n*256 + string.byte(s, i)
end
return n
end
--
-- MAIN SECTION
--
-- FIRST STEP: INITIALIZE HASH VALUES
--(second 32 bits of the fractional parts of the square roots of the first 9th through 16th primes 23..53)
local HH = {}
local function initH512(H)
H = {0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1, 0x510e527fade682d1, 0x9b05688c2b3e6c1f, 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179}
return H
end
-- SECOND STEP: INITIALIZE ROUND CONSTANTS
--(first 80 bits of the fractional parts of the cube roots of the first 80 primes 2..409)
local k = {
0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc, 0x3956c25bf348b538,
0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118, 0xd807aa98a3030242, 0x12835b0145706fbe,
0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2, 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235,
0xc19bf174cf692694, 0xe49b69c19ef14ad2, 0xefbe4786384f25e3, 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65,
0x2de92c6f592b0275, 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5, 0x983e5152ee66dfab,
0xa831c66d2db43210, 0xb00327c898fb213f, 0xbf597fc7beef0ee4, 0xc6e00bf33da88fc2, 0xd5a79147930aa725,
0x06ca6351e003826f, 0x142929670a0e6e70, 0x27b70a8546d22ffc, 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed,
0x53380d139d95b3df, 0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, 0x92722c851482353b,
0xa2bfe8a14cf10364, 0xa81a664bbc423001, 0xc24b8b70d0f89791, 0xc76c51a30654be30, 0xd192e819d6ef5218,
0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8, 0x19a4c116b8d2d0c8, 0x1e376c085141ab53,
0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8, 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, 0x5b9cca4f7763e373,
0x682e6ff3d6b2b8a3, 0x748f82ee5defb2fc, 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec,
0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, 0xc67178f2e372532b, 0xca273eceea26619c,
0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, 0x06f067aa72176fba, 0x0a637dc5a2c898a6,
0x113f9804bef90dae, 0x1b710b35131c471b, 0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc,
0x431d67c49c100d4c, 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817
}
-- THIRD STEP: PRE-PROCESSING (padding)
local function preprocess(toProcess, len)
--append a single '1' bit
--append K '0' bits, where K is the minimum number >= 0 such that L + 1 + K = 896mod1024
local extra = 128 - (len + 9) % 128
len = num2string(8 * len, 8)
toProcess = toProcess .. "\128" .. string.rep("\0", extra) .. len
assert(#toProcess % 128 == 0)
return toProcess
end
local function rrotate(rot, n)
return (rot >> n) | ((rot << 64 - n))
end
local function digestblock(msg, i, H)
local w = {}
for j = 1, 16 do w[j] = s264num(msg, i + (j - 1)*4) end
for j = 17, 80 do
local v = w[j - 15]
local s0 = rrotate(v, 1) ~ rrotate(v, 8) ~ (v >> 7)
v = w[j - 2]
w[j] = w[j - 16] + s0 + w[j - 7] + ((rrotate(v, 19) ~ rrotate(v, 61)) ~ (v >> 6))
end
local a, b, c, d, e, f, g, h = H[1], H[2], H[3], H[4], H[5], H[6], H[7], H[8]
for i = 1, 80 do
a, b, c, d, e, f, g, h = a , b , c , d , e , f , g , h
local s0 = rrotate(a, 28) ~ (rrotate(a, 34) ~ rrotate(a, 39))
local maj = ((a & b) ~ (a & c)) ~ (b & c)
local t2 = s0 + maj
local s1 = rrotate(e, 14) ~ (rrotate(e, 18) ~ rrotate(e, 41))
local ch = (e & f) ~ (~e & g)
local t1 = h + s1 + ch + k[i] + w[i]
h, g, f, e, d, c, b, a = g, f, e, d + t1, c, b, a, t1 + t2
end
H[1] = (H[1] + a)
H[2] = (H[2] + b)
H[3] = (H[3] + c)
H[4] = (H[4] + d)
H[5] = (H[5] + e)
H[6] = (H[6] + f)
H[7] = (H[7] + g)
H[8] = (H[8] + h)
end
local function finalresult512 (H)
-- Produce the final hash value:
return
str2hexa(num2string(H[1], 8)..num2string(H[2], 8)..num2string(H[3], 8)..num2string(H[4], 8)..
num2string(H[5], 8)..num2string(H[6], 8)..num2string(H[7], 8)..num2string(H[8], 8))
end
-- Returns the hash512 for the given string.
local function hash512 (msg)
msg = preprocess(msg, #msg)
local H = initH512(HH)
-- Process the message in successive 1024-bit (128 bytes) chunks:
for i = 1, #msg, 128 do
digestblock(msg, i, H)
end
return finalresult512(H)
end
Given hash512("a"):
Expect: 1f40fc92da241694750979ee6cf582f2d5d7d28e18335de05abc54d0560e0f5302860c652bf08d560252aa5e74210546f369fbbbce8c12cfc7957b2652fe9a75
Actual: e0b9623f2194cb81f2a62616a183edbe390be0d0b20430cadc3371efc237fa6bf7f8b48311f2fa249131c347fee3e8cde6acfdab286d648054541f92102cfc9c
I know that I am creating a message of the correct bit size (1024 bits) and also working in 1024-bit chunks, or at least I believe I am.
I am not sure if it has to do with the handling of the integers (the standard requires unsigned integers) or whether I made a mistake in one of the utility functions, or both. If it is indeed an issue with the handling of the integers, how would I go about taking care of the problem. I was able to resolve this when working on the 256-bit version of the adaptation by using mod 2^32 when working with numbers in the digestblock method. I attempted to do mod 2^64 and 2^63 with the 512-bit version and it does not correct the problem. I am stumped.
I should mention that I cannot use one of the many library implementations as I am using a sandboxed Lua that does not provide this access, which is why I need a pure lua implementation. Thanks in advance.
Unfortunately, after introducing integers in Lua 5.3 writing scripts for Lua becomes a more complicated task.
You must always think about transformations between integers and floating point numbers.
ALWAYS. Yes, that's boring.
One of your mistakes is an excellent example of this "dark corner of Lua".
local remainder = l % 256
s = string.char(remainder) .. s
--remove from l the bits we have already transformed
l = (l-remainder) / 256
Your value l is initially a 64-bit integer.
After cutting off its first byte l contains (64-8) = 56 bits, but now it's a floating point-number (with 53-bit precision, of course).
Possible solution: use l = l >> 8 or l = l // 256 instead of l = (l-remainder) / 256
Another mistake is using s264num(msg, i + (j - 1) * 4) instead of s264num(msg, i + (j - 1) * 8)
One more mistake is in the following line:
local extra = 128 - (len + 9) % 128
The correct code is
local extra = - (len + 17) % 128 + 8
(Please note that -a%m+b is not the same as b-a%m due to operator precedence)
After fixing these 3 mistakes your code works correctly.

"Bitwise AND" in Lua

I'm trying to translate a code from C to Lua and I'm facing a problem.
How can I translate a Bitwise AND in Lua?
The source C code contains:
if ((command&0x80)==0)
...
How can this be done in Lua?
I am using Lua 5.1.4-8
Implementation of bitwise operations in Lua 5.1 for non-negative 32-bit integers
OR, XOR, AND = 1, 3, 4
function bitoper(a, b, oper)
local r, m, s = 0, 2^31
repeat
s,a,b = a+b+m, a%m, b%m
r,m = r + m*oper%(s-a-b), m/2
until m < 1
return r
end
print(bitoper(6,3,OR)) --> 7
print(bitoper(6,3,XOR)) --> 5
print(bitoper(6,3,AND)) --> 2
Here is a basic, isolated bitwise-and implementation in pure Lua 5.1:
function bitand(a, b)
local result = 0
local bitval = 1
while a > 0 and b > 0 do
if a % 2 == 1 and b % 2 == 1 then -- test the rightmost bits
result = result + bitval -- set the current bit
end
bitval = bitval * 2 -- shift left
a = math.floor(a/2) -- shift right
b = math.floor(b/2)
end
return result
end
usage:
print(bitand(tonumber("1101", 2), tonumber("1001", 2))) -- prints 9 (1001)
Here's an example of how i bitwise-and a value with a constant 0x8000:
result = (value % 65536) - (value % 32768) -- bitwise and 0x8000
In case you use Adobe Lightroom Lua, Lightroom SDK contains LrMath.bitAnd() method for "bitwise AND" operation:
-- x = a AND b
local a = 11
local b = 6
local x = import 'LrMath'.bitAnd(a, b)
-- x is 2
And there are also LrMath.bitOr(a, b) and LrMath.bitXor(a, b) methods for "bitwise OR" and "biwise XOR" operations.
This answer is specifically for Lua 5.1.X
you can use
if( (bit.band(command,0x80)) == 0) then
...
in Lua 5.3.X and onwards it's very straight forward...
print(5 & 6)
hope that helped 😉

Format string to number with minimum length in lua

For example I need number with minimum 3 digit
"512" --> 512
"24" --> 24.0
"5" --> 5.00
One option is write small function. Using answers here for my case it will be something like this
function f(value, w)
local p = math.ceil(math.log10(value))
local prec = value <= 1 and w - 1 or p > w and 0 or w - p
return string.format('%.' .. prec .. 'f', value)
end
print(f(12, 3))
But may be it is possible just using string.format() or any other simple way?
Ok, it seems this case beyond the string.format power. Thanks to #Schollii, this is my current variant
function f(value, w)
local p = math.ceil(math.log10(value))
local prec = value <= 1 and w - 1 or p > w and 0 or w - p
return string.format('%.' .. prec .. 'f', value)
end
print(f(12, 3))
There is no format code specifically for this since string.format uses printf minus a few codes (like * which would hace simplified the solution I give below). So you have to implement yourself, for example:
function f(num, w)
-- get number of digits before decimal
local intWidth = math.ceil(math.log10(num))
-- if intWidth > w then ... end -- may need this
local fmt='%'..w..'.' .. (w-intWidth) .. 'f'
return string.format(fmt, num)
end
print(f(12, 4))
print(f(12, 3))
print(f(12, 2))
print(f(512, 3))
print(f(24, 3))
print(f(5, 3))
You should probably handle case where integer part doesn't fit in field width given (return ceil or floor?).
You can't. Maximum you can reach - specify floating point precision or digit number, but you can't force output to be like your example. Lua uses C like printf with few limitations reference. Look here for full specifiers list link. Remember unsupported ones.
Writing a function would be the best and only solution, especially as your task looks strange, as it doesn't count decimal dot.

Pure Lua hashing method

This has been bothering be for a while now, I cannot seem to find a pure Lua implementation of a popular hashing method like SHA256, SHA512, or Whirlpool. I need it as I will be hashing the password client side before sending it of to a server. Speed isn't a worry here, I don't care if it takes 10 or so seconds to hash 10,000 times, I will be running it on a thread.
I have tried a couple before, which seemed like they worked perfectly fine at first, but when I tried a different input strings (usually longer ones), the hash comes out as a totally incorrect hash output.
I am using the LuaJIT version of Love2D, so it already has the BitOp library implemented. If any of you know any good implementations of these hashing methods or any similar secure ones then please let me know!
Thank you!
UPDATE: Here are some results!
Firstly this is the test code I am using.
https://github.com/JustAPerson/LuaCrypt
INPUT: Test string
OUTPUT: a3e49d843df13c2e2a7786f6ecd7e0d184f45d718d1ac1a8a63e570466e489dd
EXPECTED: a3e49d843df13c2e2a7786f6ecd7e0d184f45d718d1ac1a8a63e570466e489dd
INPUT: This is a test string to hash
OUTPUT: 05b4ac920d4130cb9d9bb046cac7476f35d7404cf116dc8d6d4a113c3c79d904
EXPECTED: f70b476ff948472f8e4e52793a5a2779e636c20dd5336d3a8a4455374318db35
https://bitbucket.org/Boolsheet/sil/raw/tip/hash.lua
INPUT: Test string
OUTPUT: 8f1a5b37fbe986953c343d5b839b14843c6c29d47a6a7e52f263cd82ad6141a3
EXPECTED: a3e49d843df13c2e2a7786f6ecd7e0d184f45d718d1ac1a8a63e570466e489dd
INPUT: This is a test string to hash
OUTPUT: 167bf7b9000442419b3016a6e1edfcc7c8d40b5f0b80518a31ddb0bbd388e87ac
EXPECTED: f70b476ff948472f8e4e52793a5a2779e636c20dd5336d3a8a4455374318db35
I would recommend against using SHA256 for passwords. They are easy to bruteforce nowadays, and the way you are using them is vulnerable to replay attacks.
Also if you must use SHA256, use the version from OpenSSL if possible (especially if your program already depends on OpenSSL.)
But if you must use it (and cannot link with OpenSSL, but can use FFI) here is a LuaJIT version of SHA256 (only) that I am using in one of my projects.
local bit = require 'bit'
local ffi = require 'ffi'
local type = type
local band, bnot, bswap, bxor, rol, ror, rshift, tobit =
bit.band, bit.bnot, bit.bswap, bit.bxor, bit.rol, bit.ror, bit.rshift, bit.tobit
local min, max = math.min, math.max
local C = ffi.C
local istype, new, fill, copy, cast, sizeof, ffi_string =
ffi.istype, ffi.new, ffi.fill, ffi.copy, ffi.cast, ffi.sizeof, ffi.string
local sha256 = {}
ffi.cdef [[
void *malloc(size_t size);
void free(void *ptr);
]]
local ctHashState = ffi.typeof 'uint32_t[8]'
local cbHashState = ffi.sizeof(ctHashState)
local ctBlock = ffi.typeof 'uint32_t[64]'
local cbBlock = ffi.sizeof(ctBlock)
local ctpu8 = ffi.typeof 'uint8_t *'
local ctpcu8 = ffi.typeof 'const uint8_t *'
local ctpu32 = ffi.typeof 'uint32_t *'
local ctpu64 = ffi.typeof 'uint64_t *'
-- This struct is used by the 'preprocess' iterator function. It keeps track
-- of the end of the input string + the total input length in bits + a pointer
-- to the block buffer (where expansion takes place.)
local ctBlockIter
local cmtBlockIter = {}
function cmtBlockIter.__sub(a, b)
if istype(ctBlockIter, a) then a = a.limit end
if istype(ctBlockIter, b) then b = b.limit end
return a - b
end
function cmtBlockIter:__tostring()
return string.format("<ctBlockIter: limit=%s; keyLength=%s>",
tostring(self.base), tostring(self.keyLength))
end
ctBlockIter = ffi.metatype([[
struct {
const uint8_t *limit;
uint32_t *blockBuffer;
uint64_t keyLength;
}
]], cmtBlockIter)
-- Initial state of the hash
local init_h = new('const uint32_t[8]', {
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
})
-- Constants used in the add step of the compression function
local k = new('const uint32_t[64]', {
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
})
-- Expand block from 512 to 2048 bits
local function expand(w)
for i = 16, 63 do
local s0 = bxor(ror(w[i-15], 7), ror(w[i-15], 18), rshift(w[i-15], 3))
local s1 = bxor(ror(w[i-2], 17), ror(w[i-2], 19), rshift(w[i-2], 10))
w[i] = w[i-16] + s0 + w[i-7] + s1
end
end
-- Process one expanded block and update the hash state
local function compress(hh, w)
local a, b, c, d, e, f, g, h =
hh[0],hh[1],hh[2],hh[3],hh[4],hh[5],hh[6],hh[7]
for i = 0, 63 do
local S1 = bxor(ror(e, 6), ror(e, 11), ror(e, 25))
local ch = bxor(band(e, f), band(bnot(e), g))
local t = tobit(h + S1 + ch + k[i] + w[i])
local S0 = bxor(ror(a, 2), ror(a, 13), ror(a, 22))
local maj = bxor(band(a, bxor(b, c)), band(b, c))
a, b, c, d, e, f, g, h =
tobit(t + S0 + maj),
a, b, c,
tobit(d + t),
e, f, g
end
hh[0],hh[1],hh[2],hh[3],hh[4],hh[5],hh[6],hh[7] =
hh[0]+a, hh[1]+b, hh[2]+c, hh[3]+d,
hh[4]+e, hh[5]+f, hh[6]+g, hh[7]+h
end
-- Take a 512-bit chunk from the input.
-- If it is the final chunk, also add padding
local keyLengthOfs = ffi.offsetof(ctBlockIter, 'keyLength')
local function nextBlock(state, input)
local w = state.blockBuffer
local cLen = min(state - input, 64)
if cLen < -8 then return nil end
fill(w, 256, 0)
copy(w, input, max(0, cLen))
if 0 <= cLen and cLen < 64 then
copy(cast(ctpu8, w)+cLen, '\128', 1)
end
for i = 0, 15 do w[i] = bswap(w[i]) end
if cLen <= (64-8-1) then
copy(cast(ctpu64, w) + 7, cast(ctpu8, state) + keyLengthOfs, 8)
w[14], w[15] = w[15], w[14]
end
input = input + 64
return input
end
-- Iterator that yields one block (possibly padded) at a time from the input
local function preprocess(input, len, w)
len = len or (type(input) == 'string' and #input or sizeof(input))
input = cast(ctpu8, input)
local it = new(ctBlockIter)
it.blockBuffer = w
it.limit = input+len
it.keyLength = len*8
return nextBlock, it, input
end
-- Compute a binary hash (32-byte binary string) from the input
function sha256.binFromBin(input, len)
local h = new(ctHashState)
local w = cast(ctpu32, C.malloc(cbBlock))
copy(h, init_h, cbHashState)
for _ in preprocess(input, len, w) do
expand(w)
compress(h, w)
end
for i = 0, 7 do h[i] = bswap(h[i]) end
C.free(w)
return ffi_string(h, 32)
end
local hexDigits = new('char[16]', "0123456789abcdef")
local hexOut = new('char[65]')
-- Compute the hash and convert to hexadecimal
function sha256.hexFromBin(input, len)
local h = new(ctHashState)
local w = cast(ctpu32, C.malloc(cbBlock))
copy(h, init_h, cbHashState)
for _ in preprocess(input, len, w) do
expand(w)
compress(h, w)
end
for i = 0, 7 do
local w = h[i]
for j = 0, 3 do
w = rol(w, 8)
hexOut[i*8 + j*2] = hexDigits[band(rshift(w, 4), 15)]
hexOut[i*8 + j*2 + 1] = hexDigits[band(w, 15)]
end
end
C.free(w)
return ffi_string(hexOut, 64)
end
return sha256
There is an implementation of SHA256 at the Lua User's Wiki. The page observes it is Lua 5.2. I would imagine that it would be practical to make that work in LuaJIT without too much trouble.
Do pay attention to the larger security issues surrounding passwords and authentication. The usual advice applies; rolling your own security rather than using an existing tested and supported implementation is not something to be done lightly.
Since you are using LuaJIT, you should be able to leverage its very powerful FFI capabilities to use crypto supplied on your native platform. That will likely require writing some FFI-flavored Lua that is platform specific to each platform on which your client expects to run, but from what I've seen by lurking in the LuaJIT mailing list that shouldn't be too painful.

Resources