-
Notifications
You must be signed in to change notification settings - Fork 0
/
md5sum
363 lines (343 loc) · 14.6 KB
/
md5sum
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
# String message to MD5 Hash
# Creates a MD5 hash from a message string
# Version 1.00, 6/17/2012, Created by TealFrog
# Version 1.1 2/11/2016, Modified by FAMS
# Script tested and developed under MikroTik ROS 6.3 to 6.33
#
#
# This software is identified as using and is based on the, "RSA Data Security,
# Inc. MD5 Message-Digest Algorithm". This program is a derived work from the RSA Data
# Security, Inc. MD5 Message-Digest Algorithm.
# See http://www.ietf.org/rfc/rfc1321.txt for further information.
#
# The author of this program makes no representations concerning either
# the merchantability of this software or the suitability of this
# software for any particular purpose or non-infringement.
# This program is provided "as is" without express or implied warranty of any kind.
# The author makes no representations or warranties of any kind as to the
# completeness, accuracy, timeliness, availability, functionality and compliance
# with applicable laws. By using this software you accept the risk that the
# information may be incomplete or inaccurate or may not meet your needs
# and requirements. The author shall not be liable for any damages or
# injury arising out of the use of this program. Use this program at your own risk.
#
# MD5 has been shown to not be collision resistant, as such MD5 is not suitable
# for certain applications involving security and/or cryptography,
# see http://en.wikipedia.org/wiki/Md5 for additional information.
#
# $progName, Name of script, set appropriately
:global StrToMd5 do={
:local progName "StrToMd5"
:local strMessage $1
# $strPrefix, Set to a prefix to add before MD5 hash, set "" for empty
:local strPrefix ""
# $strSuffix, Set to a suffix to add after MD5 hash, set "" for empty
:local strSuffix ""
# Set $Debug to 1 for additional output, set to zero to turn off debug
:local Debug $2
# $strHexValues, Used to create hexadecimal output
:local strHexValues "0123456789abcdef"
# To have uppercase hexadecimal A-F use the next line instead of the above
# :local strHexValues "0123456789ABCDEF"
# No futher modification required beyond this point unless customizing script
# Start by defining constant values
# ASCII Table $CharSet[0..127]
:local arrCharSet ( "\00", "\01", "\02", "\03", "\04", "\05", "\06", "\07", \
"\08", "\09", "\0A", "\0B", "\0C", "\0D", "\0E", "\0F", \
"\10", "\11", "\12", "\13", "\14", "\15", "\16", "\17", \
"\18", "\19", "\1A", "\1B", "\1C", "\1D", "\1E", "\1F", \
"\20", "\21", "\22", "\23", "\24", "\25", "\26", "\27", \
"\28", "\29", "\2A", "\2B", "\2C", "\2D", "\2E", "\2F", \
"\30", "\31", "\32", "\33", "\34", "\35", "\36", "\37", \
"\38", "\39", "\3A", "\3B", "\3C", "\3D", "\3E", "\3F", \
"\40", "\41", "\42", "\43", "\44", "\45", "\46", "\47", \
"\48", "\49", "\4A", "\4B", "\4C", "\4D", "\4E", "\4F", \
"\50", "\51", "\52", "\53", "\54", "\55", "\56", "\57", \
"\58", "\59", "\5A", "\5B", "\5C", "\5D", "\5E", "\5F", \
"\60", "\61", "\62", "\63", "\64", "\65", "\66", "\67", \
"\68", "\69", "\6A", "\6B", "\6C", "\6D", "\6E", "\6F", \
"\70", "\71", "\72", "\73", "\74", "\75", "\76", "\77", \
"\78", "\79", "\7A", "\7B", "\7C", "\7D", "\7E", "\7F" )
# k[i] = floor(abs(sin(i + 1)) 4294967296)
# Or just use the following table $k[0..63]:
:local k ( 0xD76AA478, 0xE8C7B756, 0x242070DB, 0xC1BDCEEE, \
0xF57C0FAF, 0x4787C62A, 0xA8304613, 0xFD469501, \
0x698098D8, 0x8B44F7AF, 0xFFFF5BB1, 0x895CD7BE, \
0x6B901122, 0xFD987193, 0xA679438E, 0x49B40821, \
0xF61E2562, 0xC040B340, 0x265E5A51, 0xE9B6C7AA, \
0xD62F105D, 0x02441453, 0xD8A1E681, 0xE7D3FBC8, \
0x21E1CDE6, 0xC33707D6, 0xF4D50D87, 0x455A14ED, \
0xA9E3E905, 0xFCEFA3F8, 0x676F02D9, 0x8D2A4C8A, \
0xFFFA3942, 0x8771F681, 0x6D9D6122, 0xFDE5380C, \
0xA4BEEA44, 0x4BDECFA9, 0xF6BB4B60, 0xBEBFBC70, \
0x289B7EC6, 0xEAA127FA, 0xD4EF3085, 0x04881D05, \
0xD9D4D039, 0xE6DB99E5, 0x1FA27CF8, 0xC4AC5665, \
0xF4292244, 0x432AFF97, 0xAB9423A7, 0xFC93A039, \
0x655B59C3, 0x8F0CCC92, 0xFFEFF47D, 0x85845DD1, \
0x6FA87E4F, 0xFE2CE6E0, 0xA3014314, 0x4E0811A1, \
0xF7537E82, 0xBD3AF235, 0x2AD7D2BB, 0xEB86D391 )
:local a 0x67452301
:local b 0xEFCDAB89
:local c 0x98BADCFE
:local d 0x10325476
:local AA 0x67452301
:local BB 0xEFCDAB89
:local CC 0x98BADCFE
:local DD 0x10325476
:local s1 ( 7, 12, 17, 22 )
:local s2 ( 5, 9, 14, 20 )
:local s3 ( 4, 11, 16, 23 )
:local s4 ( 6, 10, 15, 21 )
:local i 0
:local j 0
:local x 0
:local S 0
:local T 0
:local lcv 0
:local tmp1 0
:local arrMd5State []
:local arrWordArray []
:local ch ""
:local iByteCount 0
:local iCharVal 3
:local iDec 0
:local iHexDigit 8
:local iMd5State 0
:local lBytePosition 0
:local lMessageLength 0
:local lNumberOfWords 0
:local lShiftedVal 0
:local lWordArray []
:local lWordArrLen 0
:local lWordCount 0
:local sHex ""
:local sMd5Hash ""
:local sMd5Output ""
:local strWordArray ""
# Start of main program and message loop
if ( $Debug > 0 ) do={
:put "$progName: Running..."
:put "$progName: Message: $strMessage"
}
:set ch ""
:set lShiftedVal 0
:set lWordCount 0
:set iByteCount 0
:set iCharVal 3
:set lBytePosition 0
:set lMessageLength [ :len $strMessage ]
:set lNumberOfWords ( ( ( ( $lMessageLength + 8 ) / 64 ) + 1 ) * 16 )
:set strWordArray ""
:set arrWordArray []
# Convert to word array
:for i from=1 to=($lNumberOfWords) do={
:set strWordArray ("0," . $strWordArray)
}
:set strWordArray [ :pick $strWordArray 0 ( [ :len $strWordArray ] - 1 ) ]
:set arrWordArray [ :toarray $strWordArray ]
:if ( $Debug > 0 ) do={
:put ("$progName: Message Length: " . $lMessageLength)
:put ("$progName: Number of Words: " . $lNumberOfWords)
:put ("$progName: strWordArray $strWordArray")
}
:while ($iByteCount < $lMessageLength) do={
:set lWordCount ($iByteCount / 4)
:set lBytePosition (($iByteCount % 4) * 8)
:if (($lBytePosition < 0) or ($lBytePosition > 31)) do={
:error ( "$progName: Error -- Calculating byte position " . \
"# $lBytePosition, must be 0 thru 31." )
}
:set ch [ :pick $strMessage $iByteCount ]
:if ( [ :len [ :find $arrCharSet $ch ] ] > 0 ) do={
:set iCharVal ([ :tonum [ :find $arrCharSet $ch ] ])
} else={
:error "$progName: Error -- Input contains undefined ASCII value."
}
:if ( $Debug > 0 ) do={
:put ( "$progName: parsed character \$ch: '$ch' " . \
"ASCII value \$iCharVal: $iCharVal" )
}
:set lShiftedVal ((($iCharVal) << ($lBytePosition)) | \
(($iCharVal) >> (32-($lBytePosition))))
:if ($iByteCount = 0) do={
:set lShiftedVal (([ :tonum $lShiftedVal ] + 0) & 0xFFFFFFFF)
:set arrWordArray (([ :tonum $lShiftedVal ]), \
[ :pick $arrWordArray 1 [ :len $arrWordArray] ])
} else={
:set lShiftedVal (([ :tonum [ :pick $arrWordArray $lWordCount] ] + 0) | \
([ :tonum $lShiftedVal ] + 0))
:set lShiftedVal (([ :tonum $lShiftedVal ] + 0) & 0xFFFFFFFF)
:set arrWordArray ([ :pick $arrWordArray 0 $lWordCount ], $lShiftedVal, \
[ :pick $arrWordArray ([ :tonum $lWordCount ] + 1) [ :len $arrWordArray] ])
}
:set iByteCount ( $iByteCount + 1 )
}
:set lWordCount ( $iByteCount / 4 )
:set lBytePosition ( ( $iByteCount % 4 ) * 8 )
:set lShiftedVal [ :pick $arrWordArray $lWordCount ]
:set lShiftedVal ( ( [ :tonum [ :pick $arrWordArray $lWordCount ] ] + 0 ) | \
( ( 0x80 << $lBytePosition ) | \
( 0x80 >> ( 32 - $lBytePosition ) ) ) )
:set arrWordArray ( ( [ :pick $arrWordArray 0 $lWordCount ] ), \
[ :tonum $lShiftedVal ], \
( [ :pick $arrWordArray ( [ :tonum $lWordCount ] + 1 ) \
[ :len $arrWordArray ] ] ) )
:set arrWordArray [ :toarray ( ( [ :pick $arrWordArray 0 ($lNumberOfWords - 2) ] ), \
( ( ( [ :tonum $lMessageLength ] + 0 ) << 3 ) | \
( ( [ :tonum $lMessageLength ] + 0 ) >> 29 ) ), \
( ( [ :tonum $lMessageLength ] + 0 ) >> 29 ) ) ]
:set lWordArray [ :toarray $arrWordArray ]
:set lWordArrLen ( ( [ :len $lWordArray ] ) - 1 )
:if ($Debug >0 ) do={
:put "lWordArrLen $lWordArrLen"
}
### Main Loop ###
:set tmp1 0
:set x 0
:set T 0
:set S 0
:set i 0
:set j 0
:local iteration 0
#:set a 0x67452301
#:set b 0xEFCDAB89
#:set c 0x98BADCFE
#:set d 0x10325476
#Loop Principal
:if ( $Debug >0 ) do={
:put $lWordArray
}
:for lcv from=0 to=( $lWordArrLen ) step=16 do={
:set AA [ :tonum $a ]
:set BB [ :tonum $b ]
:set CC [ :tonum $c ]
:set DD [ :tonum $d ]
:if ( $Debug > 0 ) do={
:put $iteration
}
:local chuckoffset ($iteration * 16)
### Round 1 ###
:for i from=0 to=15 do={
:set x ( [ :tonum [ :pick $lWordArray (( $i & 15 ) + $chuckoffset) ] ] + 0 )
:set T ( [ :tonum [ :pick $k $i ] ] + 0 )
:set S ( [ :tonum [ :pick $s1 ( $i & 3 ) ] ] + 0 )
# Next line is an alternate mmethod, instead of the line after it
# :set tmp1 ( ( (($b & $c) | (((($b + 1) * -1)) & $d)) + $a + $T + $x ) & 0xFFFFFFFF )
:set tmp1 ( ( ( $d ^ ( $b & ( $c ^ $d ) ) ) + $a + $T + $x ) & 0xFFFFFFFF )
:set tmp1 (((tmp1 << $S ) | (($tmp1 >> (32 - $S)))) & 0xFFFFFFFF)
:set tmp1 ( ( $tmp1 + $b ) & 0xFFFFFFFF )
:if ( $Debug > 0 ) do={
:put ("$progName: Round 1, Answer \$tmp1: $tmp1")
}
# Rotate a,b,c,d params positions, e.g. d, a, b, c ... c, d, a, b ... b, c, d, a
# and a gets new value from tmp1
:set a ( ( [ :tonum $d ] + 0 ) & 0xFFFFFFFF )
:set d ( ( [ :tonum $c ] + 0 ) & 0xFFFFFFFF )
:set c ( ( [ :tonum $b ] + 0 ) & 0xFFFFFFFF )
:set b ( ( [ :tonum $tmp1 ] + 0 ) & 0xFFFFFFFF )
}
### Round 2 ###
:set j 1
:for i from=0 to=15 do={
:set x ( [ :tonum [ :pick $lWordArray (( ( [ :tonum $j ] + 0 ) & 15 ) + $chuckoffset ) ] ] + 0 )
:set T ( [ :tonum [ :pick $k ( $i + 16 ) ] ] + 0 )
:set S ( [ :tonum [ :pick $s2 ( $i & 3 ) ] ] + 0 )
:set tmp1 ( ( ( $c ^ ( $d & ( $b ^ $c ) ) ) + $a + $T + $x ) & 0xFFFFFFFF )
:set tmp1 (((tmp1 << $S ) | (($tmp1 >> (32 - $S)))) & 0xFFFFFFFF)
:set tmp1 ( ( $tmp1 + $b ) & 0xFFFFFFFF )
:if ( $Debug > 0 ) do={
:put ("$progName: Round 2, Answer \$tmp1: $tmp1")
}
# Rotate a,b,c,d param positions, e.g. d, a, b, c ... c, d, a, b ... b, c, d, a
:set a ( ( [ :tonum $d ] + 0 ) & 0xFFFFFFFF )
:set d ( ( [ :tonum $c ] + 0 ) & 0xFFFFFFFF )
:set c ( ( [ :tonum $b ] + 0 ) & 0xFFFFFFFF )
:set b ( ( [ :tonum $tmp1 ] + 0 ) & 0xFFFFFFFF )
:set j ( $j + 5 )
}
### Round 3 ###
:set j 5
:for i from=0 to=15 do={
:set x ( [ :tonum [ :pick $lWordArray ( ( ( [ :tonum $j ] + 0 ) & 15 ) + $chuckoffset) ] ] + 0 )
:set T ( [ :tonum [ :pick $k ( $i + 32 ) ] ] + 0 )
:set S ( [ :tonum [ :pick $s3 ( $i & 3 ) ] ] + 0 )
:set tmp1 ( ( ( $b ^ $c ^ $d ) + $a + $T + $x ) & 0xFFFFFFFF )
:set tmp1 (((tmp1 << $S ) | (($tmp1 >> (32 - $S)))) & 0xFFFFFFFF)
:set tmp1 ( ( $tmp1 + $b ) & 0xFFFFFFFF )
:if ( $Debug > 0 ) do={
:put ("$progName: Round 3, Answer \$tmp1: $tmp1")
}
# Rotate a,b,c,d param positions, e.g. d, a, b, c ... c, d, a, b ... b, c, d, a
:set a ( ( [ :tonum $d ] + 0) & 0xFFFFFFFF )
:set d ( ( [ :tonum $c ] + 0) & 0xFFFFFFFF )
:set c ( ( [ :tonum $b ] + 0) & 0xFFFFFFFF )
:set b ( ( [ :tonum $tmp1 ] + 0) & 0xFFFFFFFF )
:set j ( $j + 3 )
}
### Round 4 ###
:set j 0
:for i from=0 to=15 do={
:set x ( [ :tonum [ :pick $lWordArray ( ( ( [ :tonum $j ] + 0 ) & 15 ) + $chuckoffset ) ] ] + 0 )
:set T ( [ :tonum [ :pick $k ( $i + 48 ) ] ] + 0 )
:set S ( [ :tonum [ :pick $s4 ( $i & 3 ) ] ] + 0 )
# Next line is alternate method to the line following
# :set tmp1 ( $c ^ ( $b | ( ( $d & 0xFFFFFFFF ) ^ 0xFFFFFFFF ) ) )
:set tmp1 ( ( $c ^ ( $b | ( -1 * ( $d + 1 ) ) ) ) & 0xFFFFFFFF )
:set tmp1 ( ( $tmp1 + $a + $T + $x ) & 0xFFFFFFFF )
:set tmp1 ( ((tmp1 << $S ) | (($tmp1 >> (32 - $S)))) & 0xFFFFFFFF )
:set tmp1 ( ( $tmp1 + $b ) & 0xFFFFFFFF )
:if ( $Debug > 0 ) do={
:put ("$progName: Round 4, Answer \$tmp1: $tmp1")
}
# Rotate a,b,c,d param positions, e.g. d, a, b, c ... c, d, a, b ... b, c, d, a
:set a ( ( [ :tonum $d ] + 0) & 0xFFFFFFFF )
:set d ( ( [ :tonum $c ] + 0) & 0xFFFFFFFF )
:set c ( ( [ :tonum $b ] + 0) & 0xFFFFFFFF )
:set b ( ( [ :tonum $tmp1 ] + 0) & 0xFFFFFFFF )
:set j ( $j + 7 )
}
:if ( $Debug > 0 ) do={
:put "Iteration $iteration = $a | $b | $c | $d"
}
:set a ( ( $a + $AA ) & 0xFFFFFFFF )
:set b ( ( $b + $BB ) & 0xFFFFFFFF )
:set c ( ( $c + $CC ) & 0xFFFFFFFF )
:set d ( ( $d + $DD ) & 0xFFFFFFFF )
:set iteration ( $iteration +1 )
}
:set arrMd5State [ :toarray "$a, $b, $c, $d" ]
:set sMd5Hash ""
:set sMd5Output ""
:set iDec 0
:set iMd5State 0
:set sHex ""
:for i from=0 to=3 do={
:set iMd5State [ :pick $arrMd5State $i ]
:for j from=0 to=3 do={
:set iMd5State ( [ :tonum $iMd5State ] & 0xFFFFFFFF )
:if ( $j < 1 ) do={
:set iDec ( [ :tonum $iMd5State ] & 255 )
} else={
:set iDec ( ( $iMd5State & 0x7FFFFFFE ) / ( 2 << ( ( $j * 8 ) - 1 ) ) )
:if ( ( $iMd5State & 0x80000000 ) > 0 ) do={
:set iDec ( $iDec | ( 0x40000000 / ( 2 << ( ( $j * 8 ) - 2 ) ) ) )
}
:set iDec ( $iDec & 0xFF )
}
:set sHex ""
:for k from=0 to=( 4 * ( $iHexDigit - 1 ) ) step=4 do={
:set sHex ( [ :pick [ :tostr $strHexValues ] \
( ( $iDec >> $k ) & 0xF ) \
( ( ( $iDec >> $k ) & 0xF ) + 1 ) ] . $sHex )
}
:set sHex [ :tostr $sHex ]
:set sHex [ :pick $sHex ( [ :len $sHex ] - 2 ) [ :len $sHex ] ]
:set sMd5Output ( $sMd5Output . $sHex )
}
}
# Modify next line to customize MD5 output string
:return [( [ :tostr $strPrefix ] . [ :tostr $sMd5Output ] . [ :tostr $strSuffix ] )]
if ( $Debug > 0 ) do={
:put "$progName: Done."
}
}