110 lines
3.2 KiB
Plaintext
110 lines
3.2 KiB
Plaintext
PRINT FN_MD5("")
|
|
PRINT FN_MD5("a")
|
|
PRINT FN_MD5("abc")
|
|
PRINT FN_MD5("message digest")
|
|
PRINT FN_MD5("abcdefghijklmnopqrstuvwxyz")
|
|
PRINT FN_MD5("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")
|
|
PRINT FN_MD5(STRING$(8,"1234567890"))
|
|
END
|
|
|
|
DEF FN_MD5(message$)
|
|
LOCAL a%, b%, c%, d%, f%, g%, h0%, h1%, h2%, h3%, i%, bits%, chunk%, temp%
|
|
LOCAL r&(), k%(), w%()
|
|
DIM r&(63), k%(63), w%(15)
|
|
|
|
REM r specifies the per-round shift amounts:
|
|
r&() = 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, \
|
|
\ 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, \
|
|
\ 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, \
|
|
\ 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21
|
|
|
|
REM Use binary integer part of the sines of integers (Radians) as constants:
|
|
FOR i% = 0 TO 63
|
|
k%(i%) = FN32(INT(ABS(SIN(i% + 1.0#)) * 2^32))
|
|
NEXT
|
|
|
|
REM Initialize variables:
|
|
h0% = &67452301
|
|
h1% = &EFCDAB89
|
|
h2% = &98BADCFE
|
|
h3% = &10325476
|
|
|
|
bits% = LEN(message$)*8
|
|
|
|
REM Append '1' bit to message:
|
|
message$ += CHR$&80
|
|
|
|
REM Append '0' bits until message length in bits = 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 little-endian integer:
|
|
FOR i% = 0 TO 56 STEP 8
|
|
message$ += CHR$(bits% >>> i%)
|
|
NEXT
|
|
|
|
REM Process the message in successive 512-bit chunks:
|
|
FOR chunk% = 0 TO LEN(message$) DIV 64 - 1
|
|
|
|
REM Break chunk into sixteen 32-bit little-endian words:
|
|
FOR i% = 0 TO 15
|
|
w%(i%) = !(PTR(message$) + 64*chunk% + 4*i%)
|
|
NEXT i%
|
|
|
|
REM Initialize hash value for this chunk:
|
|
a% = h0%
|
|
b% = h1%
|
|
c% = h2%
|
|
d% = h3%
|
|
|
|
REM Main loop:
|
|
FOR i% = 0 TO 63
|
|
CASE TRUE OF
|
|
WHEN i% <= 15:
|
|
f% = d% EOR (b% AND (c% EOR d%))
|
|
g% = i%
|
|
WHEN 16 <= i% AND i% <= 31:
|
|
f% = c% EOR (d% AND (b% EOR c%))
|
|
g% = (5 * i% + 1) MOD 16
|
|
WHEN 32 <= i% AND i% <= 47:
|
|
f% = b% EOR c% EOR d%
|
|
g% = (3 * i% + 5) MOD 16
|
|
OTHERWISE:
|
|
f% = c% EOR (b% OR (NOT d%))
|
|
g% = (7 * i%) MOD 16
|
|
ENDCASE
|
|
|
|
temp% = d%
|
|
d% = c%
|
|
c% = b%
|
|
b% = FN32(b% + FNlrot(FN32(a% + f%) + FN32(k%(i%) + w%(g%)), r&(i%)))
|
|
a% = temp%
|
|
|
|
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%)
|
|
|
|
NEXT chunk%
|
|
|
|
= FNrevhex(h0%) + FNrevhex(h1%) + FNrevhex(h2%) + FNrevhex(h3%)
|
|
|
|
DEF FNrevhex(A%)
|
|
SWAP ?(^A%+0),?(^A%+3)
|
|
SWAP ?(^A%+1),?(^A%+2)
|
|
= RIGHT$("0000000"+STR$~A%,8)
|
|
|
|
DEF FNlrot(n#, r%)
|
|
n# = FN32(n#)
|
|
= (n# << r%) OR (n# >>> (32 - r%))
|
|
|
|
DEF FN32(n#)
|
|
WHILE n# > &7FFFFFFF : n# -= 2^32 : ENDWHILE
|
|
WHILE n# < &80000000 : n# += 2^32 : ENDWHILE
|
|
= n#
|