blob: 375915c5b36ac31d849ed4faf86aa22882e7dfdc [file] [log] [blame]
purpose: PPP MD5 Message-digest routines
\ RSA Data Security, Inc. MD5 Message-Digest Algorithm
\ To form the message digest for a message M
\ (1) Initialize using md5init
\ (2) Call md5update and M for at least one M
\ (3) Call md5final
\ The message digest is now in md5digest[0...15]
[ifdef] notdef
This file was translated into Forth from md5.h and md5.c in the Linux
source code, which contained the following:
/*
***********************************************************************
** md5.h -- header file for implementation of MD5 **
** RSA Data Security, Inc. MD5 Message-Digest Algorithm **
** Created: 2/17/90 RLR **
** Revised: 12/27/90 SRD,AJ,BSK,JT Reference C version **
** Revised (for MD5): RLR 4/27/91 **
** -- G modified to have y&~z instead of y&z **
** -- FF, GG, HH modified to add in last register done **
** -- Access pattern: round 2 works mod 5, round 3 works mod 3 **
** -- distinct additive constant for each step **
** -- round 4 added, working mod 7 **
***********************************************************************
*/
/*
***********************************************************************
** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. **
** **
** License to copy and use this software is granted provided that **
** it is identified as the "RSA Data Security, Inc. MD5 Message- **
** Digest Algorithm" in all material mentioning or referencing this **
** software or this function. **
** **
** License is also granted to make and use derivative works **
** provided that such works are identified as "derived from the RSA **
** Data Security, Inc. MD5 Message-Digest Algorithm" in all **
** material mentioning or referencing the derived work. **
** **
** RSA Data Security, Inc. makes no representations concerning **
** either the merchantability of this software or the suitability **
** of this software for any particular purpose. It is provided "as **
** is" without express or implied warranty of any kind. **
** **
** These notices must be retained in any copies of any part of this **
** documentation and/or software. **
***********************************************************************
*/
[then]
\ This code only works right on 32-bit systems
decimal
headers
16 constant /digest
/digest buffer: md5digest \ contains result after MD5Final call
headerless
64 buffer: md5input \ input buffer
16 /l* buffer: md5xin \ transformation input buffer
04 /l* buffer: md5buf \ scratch buffer
0 value md5count
\ MD5 primitives
\ x y and x invert z and or
: md5F ( x y z -- n ) -rot over and -rot invert and or ;
\ z x and z invert y and or
: md5G ( x y z -- n ) tuck invert and -rot and or ;
: md5H ( x y z -- n ) xor xor ;
\ x z invert or y xor
: md5I ( x y z -- n ) invert rot or xor ;
: rotate_left ( x n -- y ) 2dup lshift -rot 32 swap - rshift or ;
\ FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4
: md5FF ( a b c d x s e -- )
swap >r + >r ( a b c d ) ( r: s x+e )
rot @ dup >r rot @ rot @ md5F ( a F ) ( r: s x+e b@ )
over @ + r> swap r> + ( a b@ first ) ( r: s )
r> rotate_left + swap !
;
: GG ( a b c d x s e - )
swap >r + >r ( a b c d ) ( r: s x+e )
rot @ dup >r rot @ rot @ md5G ( a F ) ( r: s x+e b@ )
over @ + r> swap r> + ( a b@ first ) ( r: s )
r> rotate_left + swap !
;
: HH ( a b c d x s e -- )
swap >r + >r ( a b c d ) ( r: s x+e )
rot @ dup >r rot @ rot @ md5H ( a F ) ( r: s x+e b@ )
over @ + r> swap r> + ( a b@ first ) ( r: s )
r> rotate_left + swap !
;
: II ( a b c d x s e - )
swap >r + >r ( a b c d ) ( r: s x+e )
rot @ dup >r rot @ rot @ md5I ( a F ) ( r: s x+e b@ )
over @ + r> swap r> + ( a b@ first ) ( r: s )
r> rotate_left + swap !
;
: l+! ( n a -- ) dup l@ rot + swap l! ;
\ Basic MD5 step. Transforms md5buf based on md5input.
variable md5a
variable md5b
variable md5c
variable md5d
7 constant S11
12 constant S12
17 constant S13
22 constant S14
5 constant S21
9 constant S22
14 constant S23
20 constant S24
4 constant S31
11 constant S32
16 constant S33
23 constant S34
6 constant S41
10 constant S42
15 constant S43
21 constant S44
: Transform ( buf in -- )
swap >r
r@ 0 la+ l@ md5a !
r@ 1 la+ l@ md5b !
r@ 2 la+ l@ md5c !
r@ 3 la+ l@ md5d !
>r
\ Round 1
md5a md5b md5c md5d r@ 0 la+ l@ S11 3614090360 md5FF \ 1
md5d md5a md5b md5c r@ 1 la+ l@ S12 3905402710 md5FF \ 2
md5c md5d md5a md5b r@ 2 la+ l@ S13 606105819 md5FF \ 3
md5b md5c md5d md5a r@ 3 la+ l@ S14 3250441966 md5FF \ 4
md5a md5b md5c md5d r@ 4 la+ l@ S11 4118548399 md5FF \ 5
md5d md5a md5b md5c r@ 5 la+ l@ S12 1200080426 md5FF \ 6
md5c md5d md5a md5b r@ 6 la+ l@ S13 2821735955 md5FF \ 7
md5b md5c md5d md5a r@ 7 la+ l@ S14 4249261313 md5FF \ 8
md5a md5b md5c md5d r@ 8 la+ l@ S11 1770035416 md5FF \ 9
md5d md5a md5b md5c r@ 9 la+ l@ S12 2336552879 md5FF \ 10
md5c md5d md5a md5b r@ 10 la+ l@ S13 4294925233 md5FF \ 11
md5b md5c md5d md5a r@ 11 la+ l@ S14 2304563134 md5FF \ 12
md5a md5b md5c md5d r@ 12 la+ l@ S11 1804603682 md5FF \ 13
md5d md5a md5b md5c r@ 13 la+ l@ S12 4254626195 md5FF \ 14
md5c md5d md5a md5b r@ 14 la+ l@ S13 2792965006 md5FF \ 15
md5b md5c md5d md5a r@ 15 la+ l@ S14 1236535329 md5FF \ 16
\ Round 2
md5a md5b md5c md5d r@ 1 la+ l@ S21 4129170786 GG \ 17
md5d md5a md5b md5c r@ 6 la+ l@ S22 3225465664 GG \ 18
md5c md5d md5a md5b r@ 11 la+ l@ S23 643717713 GG \ 19
md5b md5c md5d md5a r@ 0 la+ l@ S24 3921069994 GG \ 20
md5a md5b md5c md5d r@ 5 la+ l@ S21 3593408605 GG \ 21
md5d md5a md5b md5c r@ 10 la+ l@ S22 38016083 GG \ 22
md5c md5d md5a md5b r@ 15 la+ l@ S23 3634488961 GG \ 23
md5b md5c md5d md5a r@ 4 la+ l@ S24 3889429448 GG \ 24
md5a md5b md5c md5d r@ 9 la+ l@ S21 568446438 GG \ 25
md5d md5a md5b md5c r@ 14 la+ l@ S22 3275163606 GG \ 26
md5c md5d md5a md5b r@ 3 la+ l@ S23 4107603335 GG \ 27
md5b md5c md5d md5a r@ 8 la+ l@ S24 1163531501 GG \ 28
md5a md5b md5c md5d r@ 13 la+ l@ S21 2850285829 GG \ 29
md5d md5a md5b md5c r@ 2 la+ l@ S22 4243563512 GG \ 30
md5c md5d md5a md5b r@ 7 la+ l@ S23 1735328473 GG \ 31
md5b md5c md5d md5a r@ 12 la+ l@ S24 2368359562 GG \ 32
\ Round 3
md5a md5b md5c md5d r@ 5 la+ l@ S31 4294588738 HH \ 33
md5d md5a md5b md5c r@ 8 la+ l@ S32 2272392833 HH \ 34
md5c md5d md5a md5b r@ 11 la+ l@ S33 1839030562 HH \ 35
md5b md5c md5d md5a r@ 14 la+ l@ S34 4259657740 HH \ 36
md5a md5b md5c md5d r@ 1 la+ l@ S31 2763975236 HH \ 37
md5d md5a md5b md5c r@ 4 la+ l@ S32 1272893353 HH \ 38
md5c md5d md5a md5b r@ 7 la+ l@ S33 4139469664 HH \ 39
md5b md5c md5d md5a r@ 10 la+ l@ S34 3200236656 HH \ 40
md5a md5b md5c md5d r@ 13 la+ l@ S31 681279174 HH \ 41
md5d md5a md5b md5c r@ 0 la+ l@ S32 3936430074 HH \ 42
md5c md5d md5a md5b r@ 3 la+ l@ S33 3572445317 HH \ 43
md5b md5c md5d md5a r@ 6 la+ l@ S34 76029189 HH \ 44
md5a md5b md5c md5d r@ 9 la+ l@ S31 3654602809 HH \ 45
md5d md5a md5b md5c r@ 12 la+ l@ S32 3873151461 HH \ 46
md5c md5d md5a md5b r@ 15 la+ l@ S33 530742520 HH \ 47
md5b md5c md5d md5a r@ 2 la+ l@ S34 3299628645 HH \ 48
\ Round 4
md5a md5b md5c md5d r@ 0 la+ l@ S41 4096336452 II \ 49
md5d md5a md5b md5c r@ 7 la+ l@ S42 1126891415 II \ 50
md5c md5d md5a md5b r@ 14 la+ l@ S43 2878612391 II \ 51
md5b md5c md5d md5a r@ 5 la+ l@ S44 4237533241 II \ 52
md5a md5b md5c md5d r@ 12 la+ l@ S41 1700485571 II \ 53
md5d md5a md5b md5c r@ 3 la+ l@ S42 2399980690 II \ 54
md5c md5d md5a md5b r@ 10 la+ l@ S43 4293915773 II \ 55
md5b md5c md5d md5a r@ 1 la+ l@ S44 2240044497 II \ 56
md5a md5b md5c md5d r@ 8 la+ l@ S41 1873313359 II \ 57
md5d md5a md5b md5c r@ 15 la+ l@ S42 4264355552 II \ 58
md5c md5d md5a md5b r@ 6 la+ l@ S43 2734768916 II \ 59
md5b md5c md5d md5a r@ 13 la+ l@ S44 1309151649 II \ 60
md5a md5b md5c md5d r@ 4 la+ l@ S41 4149444226 II \ 61
md5d md5a md5b md5c r@ 11 la+ l@ S42 3174756917 II \ 62
md5c md5d md5a md5b r@ 2 la+ l@ S43 718787259 II \ 63
md5b md5c md5d md5a r@ 9 la+ l@ S44 3951481745 II \ 64
r> drop
md5a @ r@ 0 la+ l+!
md5b @ r@ 1 la+ l+!
md5c @ r@ 2 la+ l+!
md5d @ r> 3 la+ l+!
;
headers
\ The routine md5init initializes the message-digest context
: md5init ( -- )
0 to md5count
\ Load magic initialization constants.
md5buf
h# 67452301 over l! la1+
h# efcdab89 over l! la1+
h# 98badcfe over l! la1+
h# 10325476 swap l! ( )
;
headerless
: md5-addchar ( mdi char -- mdi' )
\ add new character to buffer, increment mdi
over md5input + c! 1+ ( mdi )
\ transform if necessary
dup h# 40 = if
drop ( )
16 0 do
md5input i la+ le-l@ md5xin i la+ l!
loop
md5buf md5xin Transform
0 ( mdi )
then
;
headers
\ The routine md5update updates the message-digest context to
\ account for the presence of each of the characters inBuf[0..inLen-1]
\ in the message whose digest is being computed.
: md5update ( inBuf inLen -- )
\ compute number of bytes mod 64
md5count h# 3f and ( inBuf inLen mdi )
\ update number of bytes
over md5count + to md5count ( inBuf inLen mdi )
-rot ( mdi inBuf inLen )
bounds ?do i c@ md5-addchar loop ( mdi )
drop
;
\ The routine md5final terminates the message-digest computation and
\ ends with the desired message digest in md5digest[0...15].
: md5final ( -- )
\ pad out length to 56 mod 64
md5count h# 3f and ( mdi )
dup 56 < if 56 else 120 then over - ( mdi padlen )
dup if
swap h# 80 md5-addchar ( padlen mdi )
swap 1- 0 ?do 0 md5-addchar loop drop
else
2drop
then
\ transfer 56 bytes to transformation input buffer
14 0 do
md5input i la+ le-l@ md5xin i la+ l!
loop
\ append original length in bits
md5count 3 lshift md5xin 14 la+ l! ( bytes )
0 md5xin 15 la+ l! ( )
\ and transform
md5buf md5xin Transform
\ copy buffer to digest
4 0 do ( )
md5buf i la+ l@ md5digest i la+ le-l!
loop
;
: md5end ( -- digest$ ) MD5Final md5digest /digest ;
: $md5digest1 ( $1 -- digest$ )
MD5Init ( a n )
MD5Update ( )
md5end ( digest$ )
;
: $md5digest2 ( $1 $2 -- digest$ )
MD5Init ( $1 $2 )
2swap MD5Update MD5Update ( )
md5end ( digest$ )
;