←  APIs and Utilities

ComputerCraft | Programmable Computers for Minecraft

»

SHA-256 in Pure Lua

GravityScore's Photo GravityScore 05 Jan 2013

Hey all,

Quite recently, I've been finding myself needing some very secure hashing functions to encrypt passwords and other data. In light of recent conversations on these forums, it seemed like SHA-1 just wasn't going to cut it.

I started searching and came across SHA-2 - a set of functions that are far more secure than SHA-1. They include SHA-244, SHA-256, SHA-384, and SHA-512. I found a pure Lua implementation of both SHA-244 and SHA-256 here, in the Lua documentation (adapted from the Pseudo code found on Wikipedia here). This seemed like it would work perfectly.

I fired it up with a test example, and found that the standard ComputerCraft bit API couldn't deal with the large numbers that were being produced by this, and also didn't have a right rotate function - so I found a custom implementation of the Lua bit32, and included it.

I vastly adapted both sources, and compiled them into easily copy and paste-able pieces of code (no need to install an API). Albeit, there may be far more speed and size efficient ways (it's around 200 lines) of implementing this, but they work.

In regards to copyright: both of these sources allow the free use of the code in them - they do not require you to include credits or licenses (to be honest, they aren't very clear about who exactly wrote them...).

SHA-256 can be downloaded from Pastebin using the ID: gsFrNjbt.
Quote

theoriginalbit's Photo theoriginalbit 05 Jan 2013

Nice job. I think I will be replacing my SHA-1 with one of these, never found any done quite like this.

On a separate note how are you testing the speed?
Quote

GravityScore's Photo GravityScore 05 Jan 2013

I just was printing them one after another, and the SHA-1 to a noticeably longer amount of time than the SHA-244 or 256. :P
Quote

CoolisTheName007's Photo CoolisTheName007 05 Jan 2013

Maybe you were using a sha1 that didn't used the bit API? I adapted one to use it, I doubt that it will be slower.

Also, doing all in one function might seem cleaner, but since each internal function is re-made (not sure exactly of the terminology) each time you call sha244, it is actually worst efficiency-wise.

I have a bench marking module (github) that generates nice-looking results and comparisons between given functions; can't really spend time doing it now with sha.
Quote

GravityScore's Photo GravityScore 05 Jan 2013

View PostCoolisTheName007, on 05 January 2013 - 01:04 PM, said:

Maybe you were using a sha1 that didn't used the bit API? I adapted one to use it, I doubt that it will be slower.

Also, doing all in one function might seem cleaner, but since each internal function is re-made (not sure exactly of the terminology) each time you call sha244, it is actually worst efficiency-wise.

I have a bench marking module (github) that generates nice-looking results and comparisons between given functions; can't really spend time doing it now with sha.

Yes the SHA1 I was using wasn't yours that used the CC bit API. Maybe that will be faster - I'm not too concerned about speed with this.

Like I said in the OP, I would have used the local CC bit API, but I couldn't because it gave me the error "number is too large (maximum allowed: 2^32-1)", and it also did not have an implementation of right rotate (rrotate). Would it be better if I stored each function in a local variable? (like local band = function(int1, int2, int3, ...)?)
Quote

theoriginalbit's Photo theoriginalbit 05 Jan 2013

View PostGravityScore, on 05 January 2013 - 09:17 PM, said:

Yes the SHA1 I was using wasn't yours that used the CC bit API. Maybe that will be faster - I'm not too concerned about speed with this.
I would have suggested a way to test for curiosity but because of the way that os.time() works in CC there went the easiest way :P not having any system time in milliseconds sucks sometimes :P



OFF TOPIC:

View PostGravityScore, on 05 January 2013 - 09:17 PM, said:

"number is too large (maximum allowed: 2^32-1)"
Yeh I had/may still have some issues (haven't overly tested it) with that atm with the Extended String Library and implementing Java's hashCode function...
Quote

CoolisTheName007's Photo CoolisTheName007 06 Jan 2013

View PostGravityScore, on 05 January 2013 - 09:17 PM, said:

Would it be better if I stored each function in a local variable? (like local band = function(int1, int2, int3, ...)?)

Yes, but outside the sha244 function, like

local function band(...

end

function sha244(...)
Quote

GravityScore's Photo GravityScore 06 Jan 2013

View PostCoolisTheName007, on 06 January 2013 - 04:22 AM, said:

View PostGravityScore, on 05 January 2013 - 09:17 PM, said:

Would it be better if I stored each function in a local variable? (like local band = function(int1, int2, int3, ...)?)

Yes, but outside the sha244 function, like

local function band(...

end

function sha244(...)

Just note this isn't supposed to be an API. I hate programs that make me install APIs. This is intended to be copied and pasted straight into code. I guess I can move the bit functions outside of the function though. I'll do it now! Thanks for the suggestion.
Quote

CoolisTheName007's Photo CoolisTheName007 06 Jan 2013

View PostGravityScore, on 06 January 2013 - 05:13 AM, said:

Just note this isn't supposed to be an API. I hate programs that make me install APIs. This is intended to be copied and pasted straight into code. I guess I can move the bit functions outside of the function though. I'll do it now! Thanks for the suggestion.

To make sure the only function exposed is sha22 to an user that copied and pasted your code into a program, surround the whole code with a do ... end block. That will keep the local functions to that block, and only sha244 will be put into the program's environment:

do
local function band(..)
..
end

function sha244(..)
..
end
end

I use this more and more to keep blocks of code contained to themselves in the same file.
Quote

DiamondOwner's Photo DiamondOwner 04 Feb 2013

How do you run the hash code for sha256?
Quote

GravityScore's Photo GravityScore 05 Feb 2013

You can run the hash function by copy and pasting the code for the SHA-256 function into you program, then do something like:
local stringToHash = "thisisapassword"
hash = sha256(stringToHash)
Quote

DiamondOwner's Photo DiamondOwner 05 Feb 2013

Thx GravityScore. Will global variables also work with the hash function? I'm planning to make my own small OS, may I use your hash code in my OS (I will give you credit.)? Are collisions with the hash "sha256" highly unlikely, unlikely, likely, or highly likely? This is to determine if encryption is required to keep people from reliably using rainbow tables to find out the password. What's the speed of the hash? This will help me determine the timer needed to hash a change to the username/password. I'm new to Lua, so can you convert a program into a string, then hash the program? This is to verify the integrity of core programs. Will this function (the hash) work in parallel.waitForAll? If you read to this part and have answered the above :D .
Quote

theoriginalbit's Photo theoriginalbit 05 Feb 2013

View PostDiamondOwner, on 05 February 2013 - 09:46 AM, said:

Thx GravityScore. Will global variables also work with the hash function? I'm planning to make my own small OS, may I use your hash code in my OS (I will give you credit.)? Are collisions with the hash "sha256" highly unlikely, unlikely, likely, or highly likely? This is to determine if encryption is required to keep people from reliably using rainbow tables to find out the password. What's the speed of the hash?
http://en.wikipedia....f_SHA_functions

View PostDiamondOwner, on 05 February 2013 - 09:46 AM, said:

I'm new to Lua, so can you convert a program into a string, then hash the program?
You just open the programs file and read the contents, thats a string. It the program is big enough it may crash the computer with a failure to yield (although I haven't tested if it will with this one, it does it with others). But be aware, you cannot do a hash of a program and then store it in itself, because then the hash will change, so the best method is to have an external program that stores all the and compares all the hashes, then store ITS own hash in a file somewhere for comparison.

View PostDiamondOwner, on 05 February 2013 - 09:46 AM, said:

Will this function (the hash) work in parallel.waitForAll? If you read to this part and have answered the above :D .
Not quite. With parallel functions you need to give it a function pointer, and since a function pointer means you can provide parameters you would need to setup a function that gets called from the parallel, which then calls the hashing.
Quote

KillaVanilla's Photo KillaVanilla 10 Feb 2013

View PostGravityScore, on 05 January 2013 - 09:17 PM, said:

-snip-

Like I said in the OP, I would have used the local CC bit API, but I couldn't because it gave me the error "number is too large (maximum allowed: 2^32-1)", and it also did not have an implementation of right rotate (rrotate). Would it be better if I stored each function in a local variable? (like local band = function(int1, int2, int3, ...)?)

I just wrote my own implementation of SHA-2, and ran into the same problem you did. Instead of doing everything with the standard operators as you did, I just used modulus on pretty much every variable in the code by (2^32-1) that was used in addition operations.

Also, as for the second question, you can simply put all of the functions used within the function inside the function body itself. Lua has no problems with functions inside of functions.
Quote

theoriginalbit's Photo theoriginalbit 10 Feb 2013

View PostKillaVanilla, on 10 February 2013 - 04:41 PM, said:

I just moduloed (spelling?) pretty much every variable in the code by (2^32-1)
I think it would be this?

I just used modulo
Or
I just used modulus
Quote

KillaVanilla's Photo KillaVanilla 10 Feb 2013

View PostTheOriginalBIT, on 10 February 2013 - 05:19 PM, said:

View PostKillaVanilla, on 10 February 2013 - 04:41 PM, said:

I just moduloed (spelling?) pretty much every variable in the code by (2^32-1)
I think it would be this?

I just used modulo
Or
I just used modulus
Okay, thanks for the insight.
Quote

bjornir90's Photo bjornir90 11 Feb 2013

To make it de-hash the msg I just have to run the function again ?
Quote

remiX's Photo remiX 11 Feb 2013

No, you can't de-hash a hashed string. To check if a typed string is equal to an already-hased string, hash the typed one and then check if they're equal
Quote

Left's Photo Left 22 Mar 2013

Hello, Gravity.

Can I use SHA256 for CUNIX root and other user password encryption? Thanks, Lin
Quote

GravityScore's Photo GravityScore 22 Mar 2013

Sure, go ahead!
Quote