]> gitweb.factorcode.org Git - factor.git/blob - basis/checksums/md5/md5.factor
Merge branch 'master' of git://factorcode.org/git/factor
[factor.git] / basis / checksums / md5 / md5.factor
1 ! Copyright (C) 2006, 2008 Doug Coleman.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: kernel io io.binary io.files io.streams.byte-array math
4 math.functions math.parser namespaces splitting grouping strings
5 sequences byte-arrays locals sequences.private macros fry
6 io.encodings.binary math.bitwise checksums
7 checksums.common checksums.stream combinators ;
8 IN: checksums.md5
9
10 ! See http://www.faqs.org/rfcs/rfc1321.html
11
12 <PRIVATE
13
14 SYMBOLS: a b c d old-a old-b old-c old-d ;
15
16 : T ( N -- Y )
17     sin abs 32 2^ * >integer ; foldable
18
19 : initialize-md5 ( -- )
20     0 bytes-read set
21     HEX: 67452301 dup a set old-a set
22     HEX: efcdab89 dup b set old-b set
23     HEX: 98badcfe dup c set old-c set
24     HEX: 10325476 dup d set old-d set ;
25
26 : update-md ( -- )
27     old-a a update-old-new
28     old-b b update-old-new
29     old-c c update-old-new
30     old-d d update-old-new ;
31
32 :: (ABCD) ( x a b c d k s i func -- )
33     #! a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s)
34     a [
35         b get c get d get func call w+
36         k x nth-unsafe w+
37         i T w+
38         s bitroll-32
39         b get w+
40     ] change ; inline
41
42 : F ( X Y Z -- FXYZ )
43     #! F(X,Y,Z) = XY v not(X) Z
44     pick bitnot bitand [ bitand ] [ bitor ] bi* ;
45
46 : G ( X Y Z -- GXYZ )
47     #! G(X,Y,Z) = XZ v Y not(Z)
48     dup bitnot rot bitand [ bitand ] [ bitor ] bi* ;
49
50 : H ( X Y Z -- HXYZ )
51     #! H(X,Y,Z) = X xor Y xor Z
52     bitxor bitxor ;
53
54 : I ( X Y Z -- IXYZ )
55     #! I(X,Y,Z) = Y xor (X v not(Z))
56     rot swap bitnot bitor bitxor ;
57
58 CONSTANT: S11 7
59 CONSTANT: S12 12
60 CONSTANT: S13 17
61 CONSTANT: S14 22
62 CONSTANT: S21 5
63 CONSTANT: S22 9
64 CONSTANT: S23 14
65 CONSTANT: S24 20
66 CONSTANT: S31 4
67 CONSTANT: S32 11
68 CONSTANT: S33 16
69 CONSTANT: S34 23
70 CONSTANT: S41 6
71 CONSTANT: S42 10
72 CONSTANT: S43 15
73 CONSTANT: S44 21
74
75 MACRO: with-md5-round ( ops func -- )
76     '[ [ _ (ABCD) ] compose ] map '[ _ cleave ] ;
77
78 : (process-md5-block-F) ( block -- )
79     {
80         [ a b c d 0  S11 1  ]
81         [ d a b c 1  S12 2  ]
82         [ c d a b 2  S13 3  ]
83         [ b c d a 3  S14 4  ]
84         [ a b c d 4  S11 5  ]
85         [ d a b c 5  S12 6  ]
86         [ c d a b 6  S13 7  ]
87         [ b c d a 7  S14 8  ]
88         [ a b c d 8  S11 9  ]
89         [ d a b c 9  S12 10 ]
90         [ c d a b 10 S13 11 ]
91         [ b c d a 11 S14 12 ]
92         [ a b c d 12 S11 13 ]
93         [ d a b c 13 S12 14 ]
94         [ c d a b 14 S13 15 ]
95         [ b c d a 15 S14 16 ]
96     } [ F ] with-md5-round ;
97
98 : (process-md5-block-G) ( block -- )
99     {
100         [ a b c d 1  S21 17 ]
101         [ d a b c 6  S22 18 ]
102         [ c d a b 11 S23 19 ]
103         [ b c d a 0  S24 20 ]
104         [ a b c d 5  S21 21 ]
105         [ d a b c 10 S22 22 ]
106         [ c d a b 15 S23 23 ]
107         [ b c d a 4  S24 24 ]
108         [ a b c d 9  S21 25 ]
109         [ d a b c 14 S22 26 ]
110         [ c d a b 3  S23 27 ]
111         [ b c d a 8  S24 28 ]
112         [ a b c d 13 S21 29 ]
113         [ d a b c 2  S22 30 ]
114         [ c d a b 7  S23 31 ]
115         [ b c d a 12 S24 32 ]
116     } [ G ] with-md5-round ;
117
118 : (process-md5-block-H) ( block -- )
119     {
120         [ a b c d 5  S31 33 ]
121         [ d a b c 8  S32 34 ]
122         [ c d a b 11 S33 35 ]
123         [ b c d a 14 S34 36 ]
124         [ a b c d 1  S31 37 ]
125         [ d a b c 4  S32 38 ]
126         [ c d a b 7  S33 39 ]
127         [ b c d a 10 S34 40 ]
128         [ a b c d 13 S31 41 ]
129         [ d a b c 0  S32 42 ]
130         [ c d a b 3  S33 43 ]
131         [ b c d a 6  S34 44 ]
132         [ a b c d 9  S31 45 ]
133         [ d a b c 12 S32 46 ]
134         [ c d a b 15 S33 47 ]
135         [ b c d a 2  S34 48 ]
136     } [ H ] with-md5-round ;
137
138 : (process-md5-block-I) ( block -- )
139     {
140         [ a b c d 0  S41 49 ]
141         [ d a b c 7  S42 50 ]
142         [ c d a b 14 S43 51 ]
143         [ b c d a 5  S44 52 ]
144         [ a b c d 12 S41 53 ]
145         [ d a b c 3  S42 54 ]
146         [ c d a b 10 S43 55 ]
147         [ b c d a 1  S44 56 ]
148         [ a b c d 8  S41 57 ]
149         [ d a b c 15 S42 58 ]
150         [ c d a b 6  S43 59 ]
151         [ b c d a 13 S44 60 ]
152         [ a b c d 4  S41 61 ]
153         [ d a b c 11 S42 62 ]
154         [ c d a b 2  S43 63 ]
155         [ b c d a 9  S44 64 ]
156     } [ I ] with-md5-round ;
157
158 : (process-md5-block) ( block -- )
159     4 <groups> [ le> ] map {
160         [ (process-md5-block-F) ]
161         [ (process-md5-block-G) ]
162         [ (process-md5-block-H) ]
163         [ (process-md5-block-I) ]
164     } cleave
165
166     update-md ;
167
168 : process-md5-block ( str -- )
169     dup length [ bytes-read [ + ] change ] keep 64 = [
170         (process-md5-block)
171     ] [
172         f bytes-read get pad-last-block
173         [ (process-md5-block) ] each
174     ] if ;
175     
176 : stream>md5 ( -- )
177     64 read [ process-md5-block ] keep
178     length 64 = [ stream>md5 ] when ;
179
180 : get-md5 ( -- str )
181     [ a b c d ] [ get 4 >le ] map concat >byte-array ;
182
183 PRIVATE>
184
185 SINGLETON: md5
186
187 INSTANCE: md5 stream-checksum
188
189 M: md5 checksum-stream ( stream -- byte-array )
190     drop [ initialize-md5 stream>md5 get-md5 ] with-input-stream ;