Warcraft III resources & community, 2003–2006 · archived

SHA1 (an hashing algorithm)

not rated
Submitted by AltSubmitterCalculations0 downloads
Simply use SHA1core("{binary string}")

Given an ascii binary code, it will return the true SHA-1 as per FIPS #180-2 (also in NIST records).

The SHA1 code generates a 160 bit hash expressed as five 32-bit hexadecimal words.

Due to constraints on strings, I am unsure of how this would work with binary strings of length 1024 or greater, in fact, I am unsure if 1024 characters is possible. Regardless, this will compute any string of length 448 or fewer characters. According to SHA-1 standards, a 64 bit expression of the length of the message input must be appended. Additionally, this message is analyzed as a series of 512 bit chunks.

If anybody cares to write any optimization code, aside from the alternate SHA-1 format provided in FIPS #180-2 (which provides no benefit to calculation time or noticable measure against string leakage), then I request that code be submitted as a comment.

Thank you.

(Edited the comments into //comments. Sorry)

Source

//Bulk function: SHA1core and necessary components.
//Globals required:
        set udg_Pow[31] = -2147483648
        set udg_Pow[30] = 1073741824
        set udg_Pow[29] = 536870912
        set udg_Pow[28] = 268435456
        set udg_Pow[27] = 134217728
        set udg_Pow[26] = 67108864
        set udg_Pow[25] = 33554432
        set udg_Pow[24] = 16777216
        set udg_Pow[23] = 8388608
        set udg_Pow[22] = 4194304
        set udg_Pow[21] = 2097152
        set udg_Pow[20] = 1048576
        set udg_Pow[19] = 524288
        set udg_Pow[18] = 262144
        set udg_Pow[17] = 131072
        set udg_Pow[16] = 65536
        set udg_Pow[15] = 32768
        set udg_Pow[14] = 16384
        set udg_Pow[13] = 8192
        set udg_Pow[12] = 4096
        set udg_Pow[11] = 2048
        set udg_Pow[10] = 1024
        set udg_Pow[9] = 512
        set udg_Pow[8] = 256
        set udg_Pow[7] = 128
        set udg_Pow[6] = 64
        set udg_Pow[5] = 32
        set udg_Pow[4] = 16
        set udg_Pow[3] = 8
        set udg_Pow[2] = 4
        set udg_Pow[1] = 2
        set udg_Pow[0] = 1
        set udg_HEXCHAR[0] = "0"
        set udg_HEXCHAR[1] = "1"
        set udg_HEXCHAR[2] = "2"
        set udg_HEXCHAR[3] = "3"
        set udg_HEXCHAR[4] = "4"
        set udg_HEXCHAR[5] = "5"
        set udg_HEXCHAR[6] = "6"
        set udg_HEXCHAR[7] = "7"
        set udg_HEXCHAR[8] = "8"
        set udg_HEXCHAR[9] = "9"
        set udg_HEXCHAR[10] = "A"
        set udg_HEXCHAR[11] = "B"
        set udg_HEXCHAR[12] = "C"
        set udg_HEXCHAR[13] = "D"
        set udg_HEXCHAR[14] = "E"
        set udg_HEXCHAR[15] = "F"
        set udg_APPENDSHA = see note!

//~~~~~~End Globals~~~~~~
//
//udg_APPENDSHA is a string of length 1024, containing a 1 followed by 1023 zeroes.
//The function will not display properly otherwise I would have put it here in whole.
//
//~~~~~~Start Function~~~~~~

function dec2bin takes integer Dec returns string
        local integer z = Dec
        local integer i = 30
        local string Sign = "0"
        local string Bin = ""
        if ( Dec < 0 ) then
                set Sign = "1"
                set Dec = 2147483648 + Dec
                set z = Dec
        endif 
        loop
                exitwhen (i == -1 or z == 0)
                if ( z - udg_Pow[i] >= 0) then
                        set Bin  = Bin + "1"
                        set z  = z - udg_Pow[i]
                else
                        set Bin  = Bin + "0"
                endif
                set i = i - 1
        endloop
        set Sign = Sign + Bin
        set Bin = null
        return Sign + SubString(udg_APPENDSHA,1,i+2)
endfunction

function bin2dec takes string Bin returns integer
        local integer i = 2
        local integer Dec = 0
        loop
                exitwhen i == 33
                if ( SubString(Bin,i-1,i) == "1" ) then
                        set Dec = Dec + udg_Pow[32-i]
                endif
                set i = i + 1
        endloop
        if ( SubString(Bin,0,1) == "1" ) then
                return 2147483648 + Dec
        endif
        return Dec
endfunction

function XORBIN takes integer A, integer B returns integer
        local integer i = 30
        local integer C = 0
        if ( (A < 0 and B < 0) ) then
                set A = A + 2147483648
                set B = B + 2147483648
        endif
        if ( (A < 0 and B >= 0) or (B < 0 and A >= 0) ) then
                set C = -2147483648
                if ( A < 0 ) then
                        set A = A + 2147483648
                else
                        set B = B + 2147483648
                endif
        endif
        loop
                exitwhen i < 0
                if ( A >= udg_Pow[i] or B >= udg_Pow[i] ) then
                        if ( (A >= udg_Pow[i] and B < udg_Pow[i]) or (B >= udg_Pow[i] and A < udg_Pow[i]) ) then
                                set C = C + udg_Pow[i]
                        endif
                        if ( A >= udg_Pow[i] ) then
                                set A = A - udg_Pow[i]
                        endif
                        if ( B >= udg_Pow[i] ) then
                                set B = B - udg_Pow[i]
                        endif
                endif
                set i = i - 1                           
        endloop 
        return C
endfunction

function ANDBIN takes integer A, integer B returns integer
        local integer i = 30
        local integer C = 0
        if ( (A < 0 and B < 0) ) then
                set C = -2147483648
                set A = A + 2147483648
                set B = B + 2147483648
        endif
        if ( A < 0 ) then
                set A = A + 2147483648
        endif
        if ( B < 0 ) then
                set B = B + 2147483648
        endif
        loop
                exitwhen i < 0
                if ( A >= udg_Pow[i] and B >= udg_Pow[i] ) then
                        set C = C + udg_Pow[i]
                endif
                if ( A >= udg_Pow[i] ) then
                        set A = A - udg_Pow[i]
                endif
                if ( B >= udg_Pow[i] ) then
                        set B = B - udg_Pow[i]
                endif
                set i = i - 1                           
        endloop 
        return C
endfunction

function NOTBIN takes integer I returns integer
        return -1 - I
endfunction


function FUNCt takes integer b, integer c, integer d, integer t returns integer
        if ( t < 20 ) then
                return XORBIN(ANDBIN(b,c),(ANDBIN(NOTBIN(b),d)))
        endif
        if ( t < 40 or t >= 60 ) then
                return XORBIN(XORBIN(b,c),d)
        endif
        return XORBIN(XORBIN(ANDBIN(b,c),ANDBIN(b,d)),ANDBIN(c,d))
endfunction

function KONSt takes integer t returns integer
        if ( t < 20 ) then
                return 1518500249
        endif
        if ( t < 40 ) then
                return 1859775393
        endif
        if ( t < 60 ) then
                return -1894007588
        endif
        return -899497514
endfunction

function dec2hex takes integer A returns string
        local integer i = 27
        local integer c = 0
        local string Str = ""
        if ( A >= udg_Pow[28] or A < 0) then
                if ( A < 0 ) then
                        set c = c + udg_Pow[3]
                        set A = A + 2147483648
                endif
                if ( A >= udg_Pow[30] ) then
                        set c = c + udg_Pow[2]
                        set A = A - udg_Pow[30]
                endif
                if ( A >= udg_Pow[29] ) then
                        set c = c + udg_Pow[1]
                        set A = A - udg_Pow[29]
                endif
                if ( A >= udg_Pow[28] ) then
                        set c = c + udg_Pow[0]
                        set A = A - udg_Pow[28]
                endif
                if ( c < 10 ) then
                        set Str = Str + I2S(c)
                else
                        set Str = Str + udg_HEXCHAR[c]
                endif
        endif
        loop
                exitwhen i < 0
                set c = 0
                if ( A >= udg_Pow[i-3] ) then
                        if ( A >= udg_Pow[i] ) then
                                set c = c + udg_Pow[3]
                                set A = A - udg_Pow[i]
                        endif
                        if ( A >= udg_Pow[i-1] ) then
                                set c = c + udg_Pow[2]
                                set A = A - udg_Pow[i-1]
                        endif
                        if ( A >= udg_Pow[i-2] ) then
                                set c = c + udg_Pow[1]
                                set A = A - udg_Pow[i-2]
                        endif
                        if ( A >= udg_Pow[i-3] ) then
                                set c = c + udg_Pow[0]
                                set A = A - udg_Pow[i-3]
                        endif
                endif
                set Str = Str + udg_HEXCHAR[c]
                set i = i - 4
        endloop
        return Str
endfunction

function ROTATE takes integer Value, integer Amount returns integer
        local integer z = 0
        local integer i = 30
        set Amount = ModuloInteger(Amount,32)
        if ( Value < 0 ) then
                set z = udg_Pow[Amount-1]
                set Value = Value + 2147483648
        endif
        loop
                exitwhen i < 0
                if ( Value >= udg_Pow[i] ) then
                        set z = z + udg_Pow[ModuloInteger(Amount+i,32)]
                        set Value = Value - udg_Pow[i]
                endif
                set i = i - 1
        endloop
        return z
endfunction

function SHA1core takes string M returns string
        local integer i
        local integer Messages = 1
        local string array Mt
        local integer array W
        local integer array K
        local integer t = 0
        local integer TEMP = 0
        local integer lasta
        local integer lastb
        local integer lastc
        local integer lastd
        local integer laste
        local integer a =  1732584193 
        local integer b =  -271733879
        local integer c = -1732584194
        local integer d =   271733878
        local integer e = -1009589776
        set i = StringLength(M)
        if ( i >= 448 ) then 
                set Mt[0] = SubString(M,0,512) + SubString(udg_APPENDSHA,1,513-StringLength(SubString(M,0,512)))
                set Mt[1] = SubString(M,512,1024) + SubString(udg_APPENDSHA,1,513-StringLength(SubString(M,512,1024)))
                set Messages = 2
        else
                set Mt[0] = M + SubString(udg_APPENDSHA,0,480-i) + dec2bin(i)
        endif
        set M = null
        set i = 0
        loop
                exitwhen t == Messages
                        set lasta = a
                        set lastb = b
                        set lastc = c
                        set lastd = d
                        set laste = e
                        loop
                                exitwhen i == 16
                                set W[i] = bin2dec(SubString(Mt[t],i*32,i*32+32))
                                set i = i + 1
                        endloop
                        set Mt[t] = null
                        loop
                                exitwhen i == 80
                                set W[i] = ROTATE(XORBIN(W[i-16],XORBIN(W[i-14],XORBIN(W[i-8],W[i-3]))),1)
                                set i = i + 1
                                if( ModuloInteger(i,16) == 0 ) then
                                        call TriggerSleepAction( 0.001 )
                                endif
                        endloop
                        set i = 0
                        loop
                                exitwhen i == 80
                                set TEMP = ROTATE(a,5) + FUNCt(b,c,d,i) + e + KONSt(i) + W[i]
                                set e = d
                                set d = c
                                set c = ROTATE(b,30)
                                set b = a
                                set a = TEMP
                                set i = i + 1
                                if( ModuloInteger(i,10) == 0 and i != 0) then
                                        call TriggerSleepAction( 0.001 )
                                endif
                        endloop
                        set i = 0
                        set a = a + lasta
                        set b = b + lastb
                        set c = c + lastc
                        set d = d + lastd
                        set e = e + laste
                set t = t + 1
        endloop
        return dec2hex(a) + dec2hex(b) + dec2hex(c) + dec2hex(d) + dec2hex(e)
endfunction

Comments

2
Well, I have a code system, but my hashing algoritem just gets a new code, and doesn't care about collsiions. That doesn't really matter, though, because the only thing I hash is usernames, so w/e. I'm sure that would run sorta-fast if you took out the sleep statements. the 0.001 will acually sleep for 0.1, the minimum sleep. The only way to get around that, and not have it kill the loop for taking to much time, is to use a timer, that has 0.0 for it's delay, that kills itself when done. That is REALLY tedious, though, and uses global variables, or a gamecache, or whatever. I use JassShopPro, so I can make whatever globals I want, though, so that isn't a huge limitation for me. Anyway, if you do it like that, it would lock the game up, until it is done hashing. BTW, I was about to work on an MD5, but this should do, with a little touching up! GJ!
I got this working finally. Turns out this code takes upwards of 2 and a 1/2 seconds to run. I wanted to use this to protect certain codes in my map, but its awful slow.
Oh btw, I'm not positive but I think you only need 512 characters of APPENDSHA for it to work, not 1024 like is stated above.
2 questions: Does anyone know of a smaller/quicker hash that would take > 1 month to crack on todays computers? Any ideas on how to make this code run faster?

In order to get this to work I had to add callback registration to it. Something like this:
[calling code]
Set SHA1_In = (Substring((Entered chat string), 4, (Length of (Entered chat string))))
Set SHA_Callback = SHAChatDone <gen>
Trigger - Run Sha1 Hash <gen> (checking conditions)
[End calling code]
[Called code]
function Trig_Sha1_Hash_Actions takes nothing returns nothing
local trigger SHACallback = udg_SHA_Callback
set udg_SHA1_Out= SHA1core(udg_SHA1_In)
set udg_SHAComplete = true
call ConditionalTriggerExecute( udg_SHA_Callback )
endfunction


//===========================================================================
function InitTrig_Sha1_Hash takes nothing returns nothing
set gg_trg_Sha1_Hash = CreateTrigger( )
call TriggerAddAction( gg_trg_Sha1_Hash, function Trig_Sha1_Hash_Actions )
endfunction

[ End called code]

Is the hash run on all of the computers? Is there a way to run the hash
only on one of the computers and propagate the result of the hash to the other
computers without causing a desynch?

EMPY
Author of Traps & Towers TD and other maps
P.S. This site was helpful in debugging/testing the code:
http://www.cs.eku.edu/faculty/styer/460/Encrypt/JS-SHA1.html