125 lines
4.0 KiB
Plaintext
125 lines
4.0 KiB
Plaintext
REM SHA-256 calculation by Richard Russell in BBC BASIC for Windows
|
|
|
|
REM Must run in FLOAT64 mode:
|
|
*FLOAT64
|
|
|
|
REM Test message for validation:
|
|
message$ = "Rosetta code"
|
|
|
|
REM Initialize variables:
|
|
h0% = &6A09E667
|
|
h1% = &BB67AE85
|
|
h2% = &3C6EF372
|
|
h3% = &A54FF53A
|
|
h4% = &510E527F
|
|
h5% = &9B05688C
|
|
h6% = &1F83D9AB
|
|
h7% = &5BE0CD19
|
|
|
|
REM Create table of constants:
|
|
DIM k%(63) : k%() = \
|
|
\ &428A2F98, &71374491, &B5C0FBCF, &E9B5DBA5, &3956C25B, &59F111F1, &923F82A4, &AB1C5ED5, \
|
|
\ &D807AA98, &12835B01, &243185BE, &550C7DC3, &72BE5D74, &80DEB1FE, &9BDC06A7, &C19BF174, \
|
|
\ &E49B69C1, &EFBE4786, &0FC19DC6, &240CA1CC, &2DE92C6F, &4A7484AA, &5CB0A9DC, &76F988DA, \
|
|
\ &983E5152, &A831C66D, &B00327C8, &BF597FC7, &C6E00BF3, &D5A79147, &06CA6351, &14292967, \
|
|
\ &27B70A85, &2E1B2138, &4D2C6DFC, &53380D13, &650A7354, &766A0ABB, &81C2C92E, &92722C85, \
|
|
\ &A2BFE8A1, &A81A664B, &C24B8B70, &C76C51A3, &D192E819, &D6990624, &F40E3585, &106AA070, \
|
|
\ &19A4C116, &1E376C08, &2748774C, &34B0BCB5, &391C0CB3, &4ED8AA4A, &5B9CCA4F, &682E6FF3, \
|
|
\ &748F82EE, &78A5636F, &84C87814, &8CC70208, &90BEFFFA, &A4506CEB, &BEF9A3F7, &C67178F2
|
|
|
|
Length% = 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$(Length% >>> 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%(63)
|
|
FOR chunk% = 0 TO LEN(message$) DIV 64 - 1
|
|
|
|
FOR i% = 0 TO 15
|
|
w%(i%) = !(!^message$ + 64*chunk% + 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 sixty-four 32-bit words:
|
|
FOR i% = 16 TO 63
|
|
s0% = FNrr(w%(i%-15),7) EOR FNrr(w%(i%-15),18) EOR (w%(i%-15) >>> 3)
|
|
s1% = FNrr(w%(i%-2),17) EOR FNrr(w%(i%-2),19) EOR (w%(i%-2) >>> 10)
|
|
w%(i%) = FN32(w%(i%-16) + s0% + w%(i%-7) + s1%)
|
|
NEXT i%
|
|
|
|
REM Initialize hash value for this chunk:
|
|
a% = h0%
|
|
b% = h1%
|
|
c% = h2%
|
|
d% = h3%
|
|
e% = h4%
|
|
f% = h5%
|
|
g% = h6%
|
|
h% = h7%
|
|
|
|
REM Main loop:
|
|
FOR i% = 0 TO 63
|
|
s0% = FNrr(a%,2) EOR FNrr(a%,13) EOR FNrr(a%,22)
|
|
maj% = (a% AND b%) EOR (a% AND c%) EOR (b% AND c%)
|
|
t2% = FN32(s0% + maj%)
|
|
s1% = FNrr(e%,6) EOR FNrr(e%,11) EOR FNrr(e%,25)
|
|
ch% = (e% AND f%) EOR ((NOT e%) AND g%)
|
|
t1% = FN32(h% + s1% + ch% + k%(i%) + w%(i%))
|
|
|
|
h% = g%
|
|
g% = f%
|
|
f% = e%
|
|
e% = FN32(d% + t1%)
|
|
d% = c%
|
|
c% = b%
|
|
b% = a%
|
|
a% = FN32(t1% + t2%)
|
|
|
|
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%)
|
|
h5% = FN32(h5% + f%)
|
|
h6% = FN32(h6% + g%)
|
|
h7% = FN32(h7% + h%)
|
|
|
|
NEXT chunk%
|
|
|
|
REM Produce the final hash value (big-endian):
|
|
hash$ = FNhex(h0%) + " " + FNhex(h1%) + " " + FNhex(h2%) + " " + FNhex(h3%) + \
|
|
\ " " + FNhex(h4%) + " " + FNhex(h5%) + " " + FNhex(h6%) + " " + FNhex(h7%)
|
|
|
|
PRINT hash$
|
|
END
|
|
|
|
DEF FNrr(A%,I%) = (A% >>> I%) OR (A% << (32-I%))
|
|
|
|
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#
|