RosettaCodeData/Task/SHA-1/BBC-BASIC/sha-1-2.basic

103 lines
2.8 KiB
Plaintext

*FLOAT64
PRINT FNsha1("Rosetta Code")
END
DEF FNsha1(message$)
LOCAL a%, b%, c%, d%, e%, f%, i%, j%, k%, l%, t%
LOCAL h0%, h1%, h2%, h3%, h4%, w%()
REM Initialize variables:
h0% = &67452301
h1% = &EFCDAB89
h2% = &98BADCFE
h3% = &10325476
h4% = &C3D2E1F0
l% = LEN(message$)*8
REM Pre-processing:
REM append the bit '1' to the message:
message$ += CHR$&80
REM append k bits '0', where k is the minimum number >= 0 such that
REM the resulting message length (in bits) is congruent to 448 (mod 512)
WHILE (LEN(message$) MOD 64) <> 56
message$ += CHR$0
ENDWHILE
REM append length of message (before pre-processing), in bits, as
REM 64-bit big-endian integer
FOR i% = 56 TO 0 STEP -8
message$ += CHR$(l% >>> i%)
NEXT
REM Process the message in successive 512-bit chunks:
REM break message into 512-bit chunks, for each chunk
REM break chunk into sixteen 32-bit big-endian words w[i], 0 <= i <= 15
DIM w%(79)
FOR j% = 0 TO LEN(message$) DIV 64 - 1
FOR i% = 0 TO 15
w%(i%) = !(!^message$ + 64*j% + 4*i%)
SWAP ?(^w%(i%)+0),?(^w%(i%)+3)
SWAP ?(^w%(i%)+1),?(^w%(i%)+2)
NEXT i%
REM Extend the sixteen 32-bit words into eighty 32-bit words:
FOR i% = 16 TO 79
w%(i%) = w%(i%-3) EOR w%(i%-8) EOR w%(i%-14) EOR w%(i%-16)
w%(i%) = (w%(i%) << 1) OR (w%(i%) >>> 31)
NEXT i%
REM Initialize hash value for this chunk:
a% = h0%
b% = h1%
c% = h2%
d% = h3%
e% = h4%
REM Main loop:
FOR i% = 0 TO 79
CASE TRUE OF
WHEN 0 <= i% AND i% <= 19
f% = (b% AND c%) OR ((NOT b%) AND d%)
k% = &5A827999
WHEN 20 <= i% AND i% <= 39
f% = b% EOR c% EOR d%
k% = &6ED9EBA1
WHEN 40 <= i% AND i% <= 59
f% = (b% AND c%) OR (b% AND d%) OR (c% AND d%)
k% = &8F1BBCDC
WHEN 60 <= i% AND i% <= 79
f% = b% EOR c% EOR d%
k% = &CA62C1D6
ENDCASE
t% = FN32(((a% << 5) OR (a% >>> 27)) + f% + e% + k% + w%(i%))
e% = d%
d% = c%
c% = (b% << 30) OR (b% >>> 2)
b% = a%
a% = t%
NEXT i%
REM Add this chunk's hash to result so far:
h0% = FN32(h0% + a%)
h1% = FN32(h1% + b%)
h2% = FN32(h2% + c%)
h3% = FN32(h3% + d%)
h4% = FN32(h4% + e%)
NEXT j%
= FNhex(h0%) + FNhex(h1%) + FNhex(h2%) + FNhex(h3%) + FNhex(h4%)
DEF FNhex(A%) = RIGHT$("0000000"+STR$~A%,8)
DEF FN32(n#)
WHILE n# > &7FFFFFFF : n# -= 2^32 : ENDWHILE
WHILE n# < &80000000 : n# += 2^32 : ENDWHILE
= n#