2 -author('tony@erix.ericsson.se').
3 %%% --------------------------------------------------------------------
5 %%% Author : Tony Rogvall <tony@erix.ericsson.se>
6 %%% Purpose : Implementation of MD5 in erlang
7 %%% Created : 30 Oct 1997 by Tony Rogvall <tony@erix.ericsson.se>
8 %%% ====================================================================
9 %%% License to copy and use this software is granted provided that it
10 %%% is identified as the "RSA Data Security, Inc. MD5 Message-Digest
11 %%% Algorithm" in all material mentioning or referencing this software
14 %%% License is also granted to make and use derivative works provided
15 %%% that such works are identified as "derived from the RSA Data
16 %%% Security, Inc. MD5 Message-Digest Algorithm" in all material
17 %%% mentioning or referencing the derived work.
18 %%% ====================================================================
19 %%% Adopted : 17 Aug 1998 by tobbe@serc.rmit.edu.au
20 %%% Made it into an epop module and cleaned it up a bit.
21 %%% --------------------------------------------------------------------
24 -import(lists
, [reverse
/1]).
28 state
= { 16#
67452301, 16#efcdab89
, 16#
98badcfe
, 16#
10325476 },
29 count
= 0, %% number of bits (64 bit)
30 buffer
= [] %% input buffer (16 bytes)
50 %% F, G, H and I are basic MD5 functions.
52 -define(F(X
, Y
, Z
), (((X
) band (Y
)) bor ((bnot (X
)) band (Z
)))).
53 -define(G(X
, Y
, Z
), (((X
) band (Z
)) bor ((Y
) band (bnot (Z
))))).
54 -define(H(X
, Y
, Z
), ((X
) bxor (Y
) bxor (Z
))).
55 -define(I(X
, Y
, Z
), ((Y
) bxor ((X
) bor (bnot (Z
))))).
57 -define(U32(X
), ((X
) band
16#ffffffff
)).
59 -define(ROTATE_LEFT(X
,N
), rotate_left(X
,N
)).
61 %% FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
62 %% Rotation is separate from addition to prevent recomputation.
64 -define(FF(A
, B
, C
, D
, X
, S
, AC
),
65 ?
ROTATE_LEFT(A
+ ?
F((B
), (C
), (D
)) + (X
) + (AC
),(S
)) + (B
)).
67 -define(GG(A
, B
, C
, D
, X
, S
, AC
),
68 ?
ROTATE_LEFT(A
+ ?
G((B
), (C
), (D
)) + (X
) + (AC
),(S
)) + (B
)).
70 -define( HH(A
, B
, C
, D
, X
, S
, AC
),
71 ?
ROTATE_LEFT(A
+ ?
H((B
), (C
), (D
)) + (X
) + (AC
),(S
)) + (B
)).
73 -define(II(A
, B
, C
, D
, X
, S
, AC
),
74 ?
ROTATE_LEFT(A
+ ?
I((B
), (C
), (D
)) + (X
) + (AC
),(S
)) + (B
)).
76 %% ---------------------------------
77 %% Exported function: string/1
78 %% Do a message digest on a string
79 %% ---------------------------------
82 format(final(update(init(), Str
))).
85 [hex(X bsr
4), hex(X
) | format(Xs
)];
90 if X4
< 10 -> X4
+ $
0;
98 Buffer
= CTX#md5_ctx
.buffer
,
100 Len
= LenI
+ length(Buffer
),
101 update(Buffer
++ Input
, Len
,CTX#md5_ctx
.state
,
102 CTX#md5_ctx
.count
+(LenI bsl
3)).
105 %% update state, count reflects number of bytes
106 %% including bytes in buffer
108 update(Buf0
, Len0
, State0
, Count
) when Len0
>= 64 ->
109 {Xs
,Buf1
} = decode(Buf0
, 64),
110 State1
= transform(State0
, Xs
),
111 update(Buf1
, Len0
- 64, State1
, Count
);
112 update(Buf0
, Len0
, State0
, Count
) ->
113 #md5_ctx
{ state
= State0
, count
= Count
, buffer
= Buf0
}.
117 %% pad out to a length 56 (we later add a count that makes 64)
118 Count
= CTX#md5_ctx
.count
, %% number of bits
119 Index
= (Count bsr
3) rem
64, %% number of bytes
120 PadLen
= if Index
< 56 ->
124 CTX1
= update(CTX
, padding(PadLen
,[])),
125 CTX2
= update(CTX1
, encode([?
U32(Count
), ?
U32(Count bsr
32)])),
126 encode(tuple_to_list(CTX2#md5_ctx
.state
)).
128 %% generate padding info to final
129 padding(0,Acc
) -> Acc
;
130 padding(1,Acc
) -> [16#
80 | Acc
];
131 padding(N
,Acc
) -> padding(N
-1, [0 | Acc
]).
133 %% rotate X as 32-bit unsigned left N bits
135 ?
U32(X bsl N
) bor (?
U32(X
) bsr (32 - N
)).
138 %% decodes Len number of bytes into 32 bit integers
139 %% returns {Xs, Tail}
142 decode(Buf
, Len
, []).
144 decode(Buf
, 0, Acc
) ->
146 decode([A0
,A1
,A2
,A3
| Buf
], N
, Acc
) ->
147 decode(Buf
, N
-4, [ A0
+ (A1 bsl
8) + (A2 bsl
16) + (A3 bsl
24) | Acc
]).
150 %% Encodes input 32-bit ints into byte buffer output.
152 encode(Xs
) -> encode(Xs
, []).
154 encode([X
| Xs
], Acc
) ->
155 encode(Xs
, [(X bsr
24) band
16#ff
,
156 (X bsr
16) band
16#ff
,
157 (X bsr
8) band
16#ff
,
158 X band
16#ff
| Acc
]);
159 encode([], Acc
) -> reverse(Acc
).
162 transform({A0
,B0
,C0
,D0
}, Xs
) ->
163 [X0
,X1
,X2
,X3
,X4
,X5
,X6
,X7
,X8
,X9
,X10
,X11
,X12
,X13
,X14
,X15
] = Xs
,
166 A1
= ?
FF (A0
, B0
, C0
, D0
, X0
, ?S11
, 16#d76aa478
),
167 D1
= ?
FF (D0
, A1
, B0
, C0
, X1
, ?S12
, 16#e8c7b756
),
168 C1
= ?
FF (C0
, D1
, A1
, B0
, X2
, ?S13
, 16#
242070db
),
169 B1
= ?
FF (B0
, C1
, D1
, A1
, X3
, ?S14
, 16#c1bdceee
),
171 A2
= ?
FF (A1
, B1
, C1
, D1
, X4
, ?S11
, 16#f57c0faf
),
172 D2
= ?
FF (D1
, A2
, B1
, C1
, X5
, ?S12
, 16#
4787c62a
),
173 C2
= ?
FF (C1
, D2
, A2
, B1
, X6
, ?S13
, 16#a8304613
),
174 B2
= ?
FF (B1
, C2
, D2
, A2
, X7
, ?S14
, 16#fd469501
),
176 A3
= ?
FF (A2
, B2
, C2
, D2
, X8
, ?S11
, 16#
698098d8
),
177 D3
= ?
FF (D2
, A3
, B2
, C2
, X9
, ?S12
, 16#
8b44f7af
),
178 C3
= ?
FF (C2
, D3
, A3
, B2
, X10
, ?S13
, 16#ffff5bb1
),
179 B3
= ?
FF (B2
, C3
, D3
, A3
, X11
, ?S14
, 16#
895cd7be
),
181 A4
= ?
FF (A3
, B3
, C3
, D3
, X12
, ?S11
, 16#
6b901122
),
182 D4
= ?
FF (D3
, A4
, B3
, C3
, X13
, ?S12
, 16#fd987193
),
183 C4
= ?
FF (C3
, D4
, A4
, B3
, X14
, ?S13
, 16#a679438e
),
184 B4
= ?
FF (B3
, C4
, D4
, A4
, X15
, ?S14
, 16#
49b40821
),
187 A5
= ?
GG (A4
, B4
, C4
, D4
, X1
, ?S21
, 16#f61e2562
),
188 D5
= ?
GG (D4
, A5
, B4
, C4
, X6
, ?S22
, 16#c040b340
),
189 C5
= ?
GG (C4
, D5
, A5
, B4
, X11
, ?S23
, 16#
265e5a51
),
190 B5
= ?
GG (B4
, C5
, D5
, A5
, X0
, ?S24
, 16#e9b6c7aa
),
192 A6
= ?
GG (A5
, B5
, C5
, D5
, X5
, ?S21
, 16#d62f105d
),
193 D6
= ?
GG (D5
, A6
, B5
, C5
, X10
, ?S22
, 16#
2441453),
194 C6
= ?
GG (C5
, D6
, A6
, B5
, X15
, ?S23
, 16#d8a1e681
),
195 B6
= ?
GG (B5
, C6
, D6
, A6
, X4
, ?S24
, 16#e7d3fbc8
),
197 A7
= ?
GG (A6
, B6
, C6
, D6
, X9
, ?S21
, 16#
21e1cde6
),
198 D7
= ?
GG (D6
, A7
, B6
, C6
, X14
, ?S22
, 16#c33707d6
),
199 C7
= ?
GG (C6
, D7
, A7
, B6
, X3
, ?S23
, 16#f4d50d87
),
200 B7
= ?
GG (B6
, C7
, D7
, A7
, X8
, ?S24
, 16#
455a14ed
),
202 A8
= ?
GG (A7
, B7
, C7
, D7
, X13
, ?S21
, 16#a9e3e905
),
203 D8
= ?
GG (D7
, A8
, B7
, C7
, X2
, ?S22
, 16#fcefa3f8
),
204 C8
= ?
GG (C7
, D8
, A8
, B7
, X7
, ?S23
, 16#
676f02d9
),
205 B8
= ?
GG (B7
, C8
, D8
, A8
, X12
, ?S24
, 16#
8d2a4c8a
),
208 A9
= ?
HH (A8
, B8
, C8
, D8
, X5
, ?S31
, 16#fffa3942
),
209 D9
= ?
HH (D8
, A9
, B8
, C8
, X8
, ?S32
, 16#
8771f681
),
210 C9
= ?
HH (C8
, D9
, A9
, B8
, X11
, ?S33
, 16#
6d9d6122
),
211 B9
= ?
HH (B8
, C9
, D9
, A9
, X14
, ?S34
, 16#fde5380c
),
213 A10
= ?
HH (A9
, B9
, C9
, D9
, X1
, ?S31
, 16#a4beea44
),
214 D10
= ?
HH (D9
, A10
, B9
, C9
, X4
, ?S32
, 16#
4bdecfa9
),
215 C10
= ?
HH (C9
, D10
, A10
, B9
, X7
, ?S33
, 16#f6bb4b60
),
216 B10
= ?
HH (B9
, C10
, D10
, A10
, X10
, ?S34
, 16#bebfbc70
),
218 A11
= ?
HH (A10
, B10
, C10
, D10
, X13
, ?S31
, 16#
289b7ec6
),
219 D11
= ?
HH (D10
, A11
, B10
, C10
, X0
, ?S32
, 16#eaa127fa
),
220 C11
= ?
HH (C10
, D11
, A11
, B10
, X3
, ?S33
, 16#d4ef3085
),
221 B11
= ?
HH (B10
, C11
, D11
, A11
, X6
, ?S34
, 16#
4881d05
),
223 A12
= ?
HH (A11
, B11
, C11
, D11
, X9
, ?S31
, 16#d9d4d039
),
224 D12
= ?
HH (D11
, A12
, B11
, C11
, X12
, ?S32
, 16#e6db99e5
),
225 C12
= ?
HH (C11
, D12
, A12
, B11
, X15
, ?S33
, 16#
1fa27cf8
),
226 B12
= ?
HH (B11
, C12
, D12
, A12
, X2
, ?S34
, 16#c4ac5665
),
229 A13
= ?
II (A12
, B12
, C12
, D12
, X0
, ?S41
, 16#f4292244
),
230 D13
= ?
II (D12
, A13
, B12
, C12
, X7
, ?S42
, 16#
432aff97
),
231 C13
= ?
II (C12
, D13
, A13
, B12
, X14
, ?S43
, 16#ab9423a7
),
232 B13
= ?
II (B12
, C13
, D13
, A13
, X5
, ?S44
, 16#fc93a039
),
234 A14
= ?
II (A13
, B13
, C13
, D13
, X12
, ?S41
, 16#
655b59c3
),
235 D14
= ?
II (D13
, A14
, B13
, C13
, X3
, ?S42
, 16#
8f0ccc92
),
236 C14
= ?
II (C13
, D14
, A14
, B13
, X10
, ?S43
, 16#ffeff47d
),
237 B14
= ?
II (B13
, C14
, D14
, A14
, X1
, ?S44
, 16#
85845dd1
),
239 A15
= ?
II (A14
, B14
, C14
, D14
, X8
, ?S41
, 16#
6fa87e4f
),
240 D15
= ?
II (D14
, A15
, B14
, C14
, X15
, ?S42
, 16#fe2ce6e0
),
241 C15
= ?
II (C14
, D15
, A15
, B14
, X6
, ?S43
, 16#a3014314
),
242 B15
= ?
II (B14
, C15
, D15
, A15
, X13
, ?S44
, 16#
4e0811a1
),
244 A16
= ?
II (A15
, B15
, C15
, D15
, X4
, ?S41
, 16#f7537e82
),
245 D16
= ?
II (D15
, A16
, B15
, C15
, X11
, ?S42
, 16#bd3af235
),
246 C16
= ?
II (C15
, D16
, A16
, B15
, X2
, ?S43
, 16#
2ad7d2bb
),
247 B16
= ?
II (B15
, C16
, D16
, A16
, X9
, ?S44
, 16#eb86d391
),
249 {?
U32(A0
+A16
), ?
U32(B0
+B16
), ?
U32(C0
+C16
), ?
U32(D0
+D16
)}.