|
1 | 1 | #!/usr/bin/env lua |
2 | 2 |
|
3 | | ---- Read file hash |
4 | | ---- @param file file The file to read (to end) |
5 | | ---- @return string MD5 checksum |
| 3 | +---Get file hash |
| 4 | +---@param file file The file to read |
| 5 | +---@return string MD5 checksum |
6 | 6 | function md5_file(file) |
7 | | - local function Md5Transform(chunk, A, B, C, D) |
8 | | - local F = function(x, y, z) return (x & y) | (~x & z) end |
9 | | - local G = function(x, y, z) return (x & z) | (y & ~z) end |
10 | | - local H = function(x, y, z) return x ~ y ~ z end |
11 | | - local I = function(x, y, z) return y ~ (x | ~z) end |
12 | | - local function LS(x, n) return ((x << n) | (x >> (32 - n))) & 0xFFFFFFFF end |
13 | | - local wo, sh = {}, {{ 7, 12, 17, 22 }, { 5, 9, 14, 20 }, { 4, 11, 16, 23 }, { 6, 10, 15, 21 }} |
14 | | - for i = 0, 15 do |
15 | | - local o = i * 4 + 1 |
16 | | - wo[i + 1] = |
17 | | - string.byte(chunk, o) | |
18 | | - (string.byte(chunk, o + 1) << 8) | |
19 | | - (string.byte(chunk, o + 2) << 16) | |
20 | | - (string.byte(chunk, o + 3) << 24) |
21 | | - end |
22 | | - local a, b, c, d = A, B, C, D |
23 | | - for i = 1, 64 do |
24 | | - local f, g |
25 | | - local r = math.floor((i - 1) / 16) + 1 |
26 | | - local s = sh[r][(i - 1) % 4 + 1] |
27 | | - if r == 1 then |
28 | | - f = F(b, c, d) |
29 | | - g = (i - 1) % 16 |
30 | | - elseif r == 2 then |
31 | | - f = G(b, c, d) |
32 | | - g = (5 * (i - 1) + 1) % 16 |
33 | | - elseif r == 3 then |
34 | | - f = H(b, c, d) |
35 | | - g = (3 * (i - 1) + 5) % 16 |
36 | | - elseif r == 4 then |
37 | | - f = I(b, c, d) |
38 | | - g = (7 * (i - 1)) % 16 |
39 | | - end |
40 | | - local t = d |
41 | | - d = c |
42 | | - c = b |
43 | | - b = (b + LS((a + f + wo[g + 1] + SINE[i]) & 0xFFFFFFFF, s)) & 0xFFFFFFFF |
44 | | - a = t |
45 | | - end |
46 | | - A = (A + a) & 0xFFFFFFFF |
47 | | - B = (B + b) & 0xFFFFFFFF |
48 | | - C = (C + c) & 0xFFFFFFFF |
49 | | - D = (D + d) & 0xFFFFFFFF |
50 | | - return A, B, C, D |
51 | | - end |
52 | | - local function Md5Pad(messageLength) |
53 | | - local ml = messageLength * 8 |
54 | | - local p = "\128" |
55 | | - local pl = (56 - (messageLength % 64)) |
56 | | - if pl <= 0 then pl = pl + 64 end |
57 | | - p = p .. string.rep("\0", pl - 1) |
58 | | - for i = 0, 7 do p = p .. string.char((ml >> (8 * i)) & 0xFF) end |
59 | | - return p |
60 | | - end |
61 | | - local A, B, C, D, l = 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0 |
| 7 | + local MAX=0xFFFFFFFF |
| 8 | + local function T(ch,A,B,C,D) |
| 9 | + local F,G,H,I,LS=function(x,y,z)return(x&y)|(~x&z)end,function(x,y,z)return(x&z)|(y&~z)end,function(x,y,z)return x~y~z end,function(x,y,z)return y~(x|~z)end,function(x,n)return((x<<n)|(x>>(32-n)))&MAX end |
| 10 | + local wo,sh,a,b,c,d={},{{7,12,17,22},{5,9,14,20},{4,11,16,23},{6,10,15,21}},A,B,C,D |
| 11 | + for i=0,15 do local o=i*4+1 wo[i+1]=string.byte(ch,o)|(string.byte(ch,o+1)<<8)|(string.byte(ch,o+2)<<16)|(string.byte(ch,o+3)<<24)end |
| 12 | + for i=1,64 do local r,f,g,t=math.floor((i-1)/16)+1 local s=sh[r][(i-1)%4+1] |
| 13 | + if r==1 then f=F(b,c,d)g=(i-1)%16 elseif r==2 then f=G(b,c,d)g=(5*(i-1)+1)%16 elseif r==3 then f=H(b,c,d)g=(3*(i-1)+5)%16 elseif r==4 then f=I(b,c,d)g=(7*(i-1))%16 end |
| 14 | + t=d d=c c=b b=(b+LS((a+f+wo[g+1]+SINE[i])&MAX,s))&MAX a=t end |
62 | 15 |
|
63 | | - while 1 do |
64 | | - local c = file:read(64) |
65 | | - if not c then break end |
66 | | - l = l + #c |
67 | | - if #c < 64 then c = c .. Md5Pad(l) end |
68 | | - A, B, C, D = Md5Transform(c, A, B, C, D) |
69 | | - if #c > 64 then break end |
70 | | - end |
71 | | - local function to_hex(x) |
72 | | - return string.format("%02x%02x%02x%02x", |
73 | | - x & 0xFF, (x >> 8) & 0xFF, (x >> 16) & 0xFF, (x >> 24) & 0xFF) |
74 | | - end |
75 | | - return to_hex(A) .. to_hex(B) .. to_hex(C) .. to_hex(D) |
76 | | -end |
| 16 | + A=(A+a)&MAX B=(B+b)&MAX C=(C+c)&MAX D=(D+d)&MAX return A,B,C,D end |
77 | 17 |
|
78 | | -local function init() |
79 | | - SINE = {} |
80 | | - for i = 1, 64 do SINE[i] = math.floor(2 ^ 32 * math.abs(math.sin(i))) end |
81 | | -end |
| 18 | + local function P(msgLen) |
| 19 | + local ml,p,pl=msgLen*8,"\128",(56-(msgLen%64)) |
| 20 | + if pl<=0 then pl=pl+64 end p=p..string.rep("\0",pl-1) |
| 21 | + for i=0,7 do p=p..string.char((ml>>(8*i))&0xFF)end return p end |
82 | 22 |
|
83 | | -if LIB then init() return end |
84 | | -if #arg < 1 then |
85 | | - print((arg[-1] or "?") .. " " .. (arg[0] or "?") .. " [FILE]...") |
86 | | - os.exit(1) |
87 | | -else |
88 | | - init() |
89 | | - for i = 1, #arg do |
90 | | - local f, e = io.open(arg[i], "rb") |
91 | | - if f then |
92 | | - local sum = md5_file(f) f:close() |
93 | | - if sum then |
94 | | - print(sum .. " " .. arg[i]) |
95 | | - else |
96 | | - print(arg[i] .. ": " .. "Unknown error") os.exit(-1) |
97 | | - end |
98 | | - else |
99 | | - print(arg[i] .. ": " .. e) os.exit(1) |
100 | | - end |
101 | | - end |
| 23 | + local A,B,C,D,l=0x67452301,0xefcdab89,0x98badcfe,0x10325476,0 |
| 24 | + while 1 do local c=file:read(64) if not c then break end l=l+#c if #c<64 then c=c..P(l)end A,B,C,D=T(c,A,B,C,D) if #c>64 then break end end |
| 25 | + local function hex(x)return string.format("%02x%02x%02x%02x",x&0xFF,(x>>8)&0xFF,(x>>16)&0xFF,(x>>24)&0xFF)end |
| 26 | + return hex(A)..hex(B)..hex(C)..hex(D) |
102 | 27 | end |
| 28 | + |
| 29 | +local function init()SINE={}for i=1,64 do SINE[i]=math.floor(2^32*math.abs(math.sin(i)))end end |
| 30 | + |
| 31 | +if LIB then init()return end |
| 32 | +if #arg<1 then print((arg[-1] or "?").." "..(arg[0] or "?").." [FILE]...")os.exit(1) |
| 33 | +else init()for i=1,#arg do local f,e=io.open(arg[i],"rb") |
| 34 | + if f then local sum=md5_file(f)f:close()if sum then print(sum.." "..arg[i])else print(arg[i]..": ".."Unknown error")os.exit(-1)end |
| 35 | + else print(e)os.exit(1)end end end |
0 commit comments