Encoding, Hashing, and Checking in LuaPosted: March 18, 2012
As soon as I want to start doing screen sharing, I have to start thinking about security, and other issues. Soon enough, I’m looking at hash codes, and other encoding stuff. So, I cast about for the likes of MD5, SHA1, SHA2, CRC32, Adler32, and even Base64.
This is ground that has been well trod, and in most cases it’s better to go with code that has been out in the wild for years and years because it’s well exercised and proven correct under usage. What I came across most of the time were interop wrappers to OpenSSL, which is probably the biggest repository of this stuff outside of proprietary implementations.
What I really want is a clean simple, all-Lua crypto library, that includes the stuff that I’m typically going to use. The OpenSSL library is a bit large to get at just base64 encoding, or SHA2-256, when that’s all I need. And, since the library’s intended use is for the implementation of SSL and TLS, it contains a lot more stuff than I actually need. So, carrying a lot of excess baggage for no particular gain.
So, I implemented my own. There were a few constraints to my implementation
- Must be pure Lua code
- Must not have any external dependencies
- Must not have any copyright or license restrictions
In the case of SHA1, I found a public domain implementation.
SHA2 was based on code from the Lua wiki, with modifications
Base64 coding was based on the public domain C implementation from the Lua code itself.
CRC32 and Adler32 we based on Wikipedia examples
In all cases, I utilized the Lua bitops library, which is in-built for both Lua 5.2 and LuaJIT.
But, although OpenSSL is mostly available everywhere, it’s not quite as readily approachable as I would like.
These routines are all now a part of the BanateCore. I still need to add HMAC support, which is not too hard. And with that, I can start to play with some secured communications.
It’s been an interesting exercise. In most cases, I could just use LuaRocks and get the appropriate package, and call it a day. For example, the LuaSocket library already includes base64 encoding. But, what if I don’t want to use the LuaSocket library? And I definitely won’t be spending my time porting OpenSSL to work on my BeagleBone. So, size does matter, and smaller is definitely better than larger in this case.
Another thing that I was exploring is how hard it is to recode something from C/C++. These particular routines are fairly straight forward. I first started out using the FFI interface to get at features that are typical of ‘C’ code, like pointer arithmetic and unsigned int and the like. Then I found that I didn’t need the specifics, and was able to recode without those dependencies. The exercise wasn’t that painful at all. As a bonus, I grabbed as many test cases as I could find, and threw them in the ensure proper usage. At least they routines work as well as the progenitors.
Usage is pretty straight forward:
local base64 = require "base64"
local encoded = base64.encode(mystring)
local decoded = base64.decode(encoded)
local hash = require "hashes"
local crc = hash.CRC32(encoded)
local adler = hash.Adler32(encoded)
CRC32 is used in a lot of places either in networking or otherwise as a simple hash. Having a ‘native’ implementation is quite useful. Similarly, Adler32 is used in zlib, and having a ‘native’ implementation of that library will be useful as well.
I am finding that in many cases, I can reduce the code size, and even speed things up, by going with a straight Lua implementation, rather than interop to a separate library. This is great because carrying a separate library, with a separate license, build process, and maintenance schedule, is quite a painful thing. I have wanted to go down the ‘pure Lua’ rabbit hole, and I’m finding the further down the hole I go, it doesn’t get curioser and curioser, but simpler and simpler, and that’s a good thing.