fix one too small
[RRG-proxmark3.git] / client / lualibs / utils.lua
blob03862ac29bd3d8023d0ff49a69cfa8c160d4d38c
1 --[[
2 This may be moved to a separate library at some point (Holiman)
3 --]]
4 local Utils =
6 -- Asks the user for Yes or No
7 confirm = function(message, ...)
8 local answer
9 message = message .. " [y/n] ?"
10 repeat
11 io.write(message)
12 io.flush()
13 answer = io.read()
14 if answer == 'Y' or answer == "y" then
15 return true
16 elseif answer == 'N' or answer == 'n' then
17 return false
18 end
19 until false
20 end,
21 ---
22 -- Asks the user for input
23 input = function (message, default)
24 local answer = ''
25 if default ~= nil then
26 message = message .. " (default: ".. default.. " )"
27 end
28 io.write(message, "\n > ")
29 io.flush()
30 answer = io.read("*L")
31 answer = string.gsub(answer, "\r\n", "")
32 answer = string.gsub(answer, "\n", "")
33 if answer == '' or answer == nil then answer = default end
34 return answer
35 end,
37 ------------ FILE READING
38 ReadDumpFile = function (filename)
40 filename = filename or 'dumpdata.bin'
41 if #filename == 0 then
42 return nil, 'Filename length is zero'
43 end
45 infile = io.open(filename, "rb")
46 if infile == nil then
47 return nil, string.format("Could not read file %s",filename)
48 end
49 local t = infile:read("*all")
50 io.close(infile)
51 len = string.len(t)
52 local _,hex = bin.unpack(("H%d"):format(len),t)
53 return hex
54 end,
56 ------------ FILE WRITING (EML)
57 --- Writes an eml-file.
58 -- @param uid - the uid of the tag. Used in filename
59 -- @param blockData. Assumed to be on the format {'\0\1\2\3,'\b\e\e\f' ...,
60 -- that is, blockData[row] contains a string with the actual data, not ascii hex representation
61 -- return filename if all went well,
62 -- @reurn nil, error message if unsuccessful
63 WriteDumpFile = function(uid, blockData)
64 local destination = string.format("%s.eml", uid)
65 local file = io.open(destination, "w")
66 if file == nil then
67 return nil, string.format("Could not write to file %s", destination)
68 end
69 local rowlen = string.len(blockData[1])
71 for i,block in ipairs(blockData) do
72 if rowlen ~= string.len(block) then
73 prlog(string.format("WARNING: Dumpdata seems corrupted, line %d was not the same length as line 1",i))
74 end
76 local formatString = string.format("H%d", string.len(block))
77 local _,hex = bin.unpack(formatString,block)
78 file:write(hex.."\n")
79 end
80 file:close()
81 return destination
82 end,
84 ------------ string split function
85 Split = function( inSplitPattern, outResults )
86 if not outResults then
87 outResults = {}
88 end
89 local start = 1
90 local splitStart, splitEnd = string.find( self, inSplitPattern, start )
91 while splitStart do
92 table.insert( outResults, string.sub( self, start, splitStart-1 ) )
93 start = splitEnd + 1
94 splitStart, splitEnd = string.find( self, inSplitPattern, start )
95 end
96 table.insert( outResults, string.sub( self, start ) )
97 return outResults
98 end,
100 ----ISO14443-B CRC
101 Crc14b = function(s)
102 if s == nil then return nil end
103 if #s == 0 then return nil end
104 if type(s) == 'string' then
105 local utils = require('utils')
106 return utils.ConvertAsciiToHex(
107 core.iso14443b_crc(s)
110 return nil
111 end,
112 ----ISO15693 CRC
113 Crc15 = function(s)
114 if s == nil then return nil end
115 if #s == 0 then return nil end
116 if type(s) == 'string' then
117 local utils = require('utils')
118 return utils.ConvertAsciiToHex(
119 core.iso15693_crc(s)
122 return nil
123 end,
125 ------------ CRC-8 Legic checksum
126 -- Takes a hex string and calculates a crc8
127 Crc8Legic = function(s)
128 if s == nil then return nil end
129 if #s == 0 then return nil end
130 if type(s) == 'string' then
131 local utils = require('utils')
132 local asc = utils.ConvertHexToAscii(s)
133 return core.crc8legic(asc)
135 return nil
136 end,
137 ------------ CRC-16 Legic checksum
138 -- Takes data as hex string, uid hex and calculates a crc16 legic
139 Crc16Legic = function(s, uid)
140 if s == nil then return nil end
141 if #s == 0 then return nil end
142 if uid == nil then return nil end
143 if #uid == 0 then return nil end
145 if type(s) == 'string' then
146 local utils = require('utils')
147 local asc = utils.ConvertHexToAscii(s)
148 local uidstr = utils.ConvertHexToAscii(uid)
149 return core.crc16legic(asc, uidstr)
151 return nil
152 end,
155 ------------ CRC-16 ccitt checksum
156 -- Takes a hex string and calculates a crc16
157 Crc16 = function(s)
158 if s == nil then return nil end
159 if #s == 0 then return nil end
160 if type(s) == 'string' then
161 local utils = require('utils')
162 local asc = utils.ConvertHexToAscii(s)
163 local hash = core.crc16(asc)
164 return hash
166 return nil
167 end,
170 ------------ CRC-64 ecma checksum
171 -- Takes a hex string and calculates a crc64 ecma hash
172 Crc64 = function(s)
173 if s == nil then return nil end
174 if #s == 0 then return nil end
175 if type(s) == 'string' then
176 local utils = require('utils')
177 local asc = utils.ConvertHexToAscii(s)
178 local hash = core.crc64(asc)
179 return hash
181 return nil
182 end,
183 ------------ CRC-64 ecma 182 checksum
184 -- Takes a hex string and calculates a crc64 ecma182 hash
185 Crc64_ecma182 = function(s)
186 if s == nil then return nil end
187 if #s == 0 then return nil end
188 if type(s) == 'string' then
189 local utils = require('utils')
190 local asc = utils.ConvertHexToAscii(s)
191 local hash = core.crc64_ecma182(asc)
192 return hash
194 return nil
195 end,
197 ------------ SHA1 hash
198 -- Takes a string and calculates a SHA1 hash
199 Sha1 = function(s)
200 if s == nil then return nil end
201 if #s == 0 then return nil end
202 if type(s) == 'string' then
203 return core.sha1(s)
205 return nil
206 end,
207 -- Takes a hex string and calculates a SHA1 hash
208 Sha1Hex = function(s)
209 if s == nil then return nil end
210 if #s == 0 then return nil end
211 if type(s) == 'string' then
212 local utils = require('utils')
213 local asc = utils.ConvertHexToAscii(s)
214 local hash = core.sha1(asc)
215 return hash
217 return nil
218 end,
221 -- input parameter is a string
222 -- Swaps the endianness and returns a number,
223 -- IE: 'cd7a' -> '7acd' -> 0x7acd
224 SwapEndianness = function(s, len)
225 if s == nil then return nil end
226 if #s == 0 then return '' end
227 if type(s) ~= 'string' then return nil end
229 local retval = 0
230 if len == 16 then
231 local t = s:sub(3,4)..s:sub(1,2)
232 retval = tonumber(t,16)
233 elseif len == 24 then
234 local t = s:sub(5,6)..s:sub(3,4)..s:sub(1,2)
235 retval = tonumber(t,16)
236 elseif len == 32 then
237 local t = s:sub(7,8)..s:sub(5,6)..s:sub(3,4)..s:sub(1,2)
238 retval = tonumber(t,16)
240 return retval
241 end,
243 -- input parameter is a string
244 -- Swaps the endianness and returns a string,
245 -- IE: 'cd7a' -> '7acd' -> 0x7acd
246 SwapEndiannessStr = function(s, len)
247 if s == nil then return nil end
248 if #s == 0 then return '' end
249 if type(s) ~= 'string' then return nil end
251 local retval
252 if len == 16 then
253 retval = s:sub(3,4)..s:sub(1,2)
254 elseif len == 24 then
255 retval = s:sub(5,6)..s:sub(3,4)..s:sub(1,2)
256 elseif len == 32 then
257 retval = s:sub(7,8)..s:sub(5,6)..s:sub(3,4)..s:sub(1,2)
259 return retval
260 end,
261 ------------ CONVERSIONS
264 -- Converts DECIMAL to HEX
265 ConvertDecToHex = function(decimal)
266 if decimal == 0 then
267 return "0"
270 local B,DIGITS,hex = 16, "0123456789ABCDEF", ""
272 while decimal > 0 do
273 local remainder = math.fmod(decimal, B)
274 hex = string.sub(DIGITS, remainder + 1, remainder + 1) .. hex
275 decimal = math.floor(decimal / B)
277 return hex
278 end,
280 -- Convert Byte array to string of hex
281 ConvertBytesToHex = function(bytes, reverse)
282 if bytes == nil then return '' end
283 if #bytes == 0 then return '' end
284 local s={}
285 if reverse then
286 local j=1
287 for i = #bytes, 1, -1 do
288 s[i] = string.format("%02X", bytes[j])
289 j = j + 1
291 else
292 for i = 1, #bytes do
293 s[i] = string.format("%02X", bytes[i])
296 return table.concat(s)
297 end,
298 -- Convert byte array to string with ascii
299 ConvertBytesToAscii = function(bytes)
300 if bytes == nil then return '' end
301 if #bytes == 0 then return '' end
302 local s={}
303 for i = 1, #(bytes) do
304 s[i] = string.char(bytes[i])
306 return table.concat(s)
307 end,
308 ConvertHexToBytes = function(s)
309 local t={}
310 if s == nil then return t end
311 if #s == 0 then return t end
312 for k in s:gmatch"(%x%x)" do
313 table.insert(t,tonumber(k,16))
315 return t
316 end,
317 ConvertAsciiToBytes = function(s, reverse)
318 local t = {}
319 if s == nil then return t end
320 if #s == 0 then return t end
322 for k in s:gmatch"(.)" do
323 table.insert(t, string.byte(k))
326 if not reverse then
327 return t
330 local rev = {}
331 if reverse then
332 for i = #t, 1,-1 do
333 table.insert(rev, t[i] )
336 return rev
337 end,
339 ConvertHexToAscii = function(s, useSafechars)
340 if s == nil then return '' end
341 if #s == 0 then return '' end
342 local t={}
343 for k in s:gmatch"(%x%x)" do
345 local n = tonumber(k,16)
346 local c
347 if useSafechars and ( (n < 32) or (n == 127) ) then
348 c = '.';
349 else
350 c = string.char(n)
352 table.insert(t,c)
354 return table.concat(t)
355 end,
357 ConvertAsciiToHex = function(s)
358 if s == nil then return '' end
359 if #s == 0 then return '' end
360 local t={}
361 for k in s:gmatch"(.)" do
362 table.insert(t, string.format("%02X", string.byte(k)))
364 return table.concat(t)
365 end,
367 hexlify = function(s)
368 local u = require('utils')
369 return u.ConvertAsciiToHex(s)
370 end,
372 Chars2num = function(s)
373 return (s:byte(1)*16777216)+(s:byte(2)*65536)+(s:byte(3)*256)+(s:byte(4))
374 end,
376 -- use length of string to determine 8,16,32,64 bits
377 bytes_to_int = function(str,endian,signed)
378 local t = {str:byte(1, -1)}
379 if endian == "big" then --reverse bytes
380 local tt = {}
381 for k = 1, #t do
382 tt[#t-k+1] = t[k]
384 t = tt
386 local n = 0
387 for k = 1, #t do
388 n = n + t[k] * 2^((k-1) * 8)
390 if signed then
391 n = (n > 2^(#t*8-1) -1) and (n - 2^(#t*8)) or n -- if last bit set, negative.
393 return n
394 end,
396 -- a simple implementation of a sleep command. Thanks to Mosci
397 -- takes number of seconds to sleep
398 Sleep = function(n)
399 local clock = os.clock
400 local t0 = clock()
401 while clock() - t0 <= n do end
402 return nil
403 end,
405 -- function convertStringToBytes(str)
406 -- local bytes = {}
407 -- local strLength = string.len(str)
408 -- for i=1,strLength do
409 -- table.insert(bytes, string.byte(str, i))
410 -- end
412 -- return bytes
413 -- end
415 -- function convertBytesToString(bytes)
416 -- local bytesLength = table.getn(bytes)
417 -- local str = ""
418 -- for i=1,bytesLength do
419 -- str = str .. string.char(bytes[i])
420 -- end
422 -- return str
423 -- end
425 -- function convertHexStringToBytes(str)
426 -- local bytes = {}
427 -- local strLength = string.len(str)
428 -- for k=2,strLength,2 do
429 -- local hexString = "0x" .. string.sub(str, (k - 1), k)
430 -- table.insert(bytes, hex.to_dec(hexString))
431 -- end
433 -- return bytes
434 -- end
436 -- function convertBytesToHexString(bytes)
437 -- local str = ""
438 -- local bytesLength = table.getn(bytes)
439 -- for i=1,bytesLength do
440 -- local hexString = string.sub(hex.to_hex(bytes[i]), 3)
441 -- if string.len(hexString) == 1 then
442 -- hexString = "0" .. hexString
443 -- end
444 -- str = str .. hexString
445 -- end
447 -- return str
448 -- end
451 return Utils