Makefile: display firmware size
[RRG-proxmark3.git] / client / luascripts / hf_mf_uidkeycalc.lua
blobdd2ca6c3a7cb2a603339b5fb799742b01dc6e61d
1 local bin = require('bin')
2 local getopt = require('getopt')
3 local lib14a = require('read14a')
4 local utils = require('utils')
5 local ansicolors = require('ansicolors')
7 copyright = ''
8 author = "Iceman"
9 version = 'v1.0.1'
10 desc = [[
11 This script calculates mifare keys based on uid diversification for DI.
12 Algo not found by me.
14 example = [[
15 -- if called without, it reads tag uid
16 script run hf_mf_uidkeycalc
19 script run hf_mf_uidkeycalc -u 11223344556677
21 usage = [[
22 script run hf_mf_uidkeycalc -h -u <uid>
24 arguments = [[
25 -h : this help
26 -u <UID> : UID
29 local DEBUG = true
30 local BAR = '286329204469736E65792032303133'
31 local MIS = '0A14FD0507FF4BCD026BA83F0A3B89A9'
32 local bxor = bit32.bxor
33 ---
34 -- A debug printout-function
35 local function dbg(args)
36 if not DEBUG then return end
37 if type(args) == 'table' then
38 local i = 1
39 while args[i] do
40 dbg(args[i])
41 i = i+1
42 end
43 else
44 print('###', args)
45 end
46 end
47 ---
48 -- This is only meant to be used when errors occur
49 local function oops(err)
50 print('ERROR: ', err)
51 core.clearCommandBuffer()
52 return nil, err
53 end
54 ---
55 -- Usage help
56 local function help()
57 print(copyright)
58 print(author)
59 print(version)
60 print(desc)
61 print(ansicolors.cyan..'Usage'..ansicolors.reset)
62 print(usage)
63 print(ansicolors.cyan..'Arguments'..ansicolors.reset)
64 print(arguments)
65 print(ansicolors.cyan..'Example usage'..ansicolors.reset)
66 print(example)
67 end
68 ---
69 -- Exit message
70 local function exitMsg(msg)
71 print( string.rep('--',20) )
72 print( string.rep('--',20) )
73 print(msg)
74 print()
75 end
76 ---
77 -- dumps all keys to file
78 local function dumptofile(uid, keys)
79 dbg('dumping keys to file')
81 if utils.confirm('Do you wish to save the keys to dumpfile?') then
83 local filename = ('hf-mf-%s-key.bin'):format(uid);
85 local destination = utils.input('Select a filename to store to', filename)
86 local file = io.open(destination, 'wb')
87 if file == nil then
88 print('Could not write to file ', destination)
89 return
90 end
92 -- Mifare Mini has 5 sectors,
93 local key_a = ''
94 local key_b = ''
96 for sector = 0, #keys do
97 local keyA, keyB = table.unpack(keys[sector])
98 key_a = key_a .. bin.pack('H', keyA);
99 key_b = key_b .. bin.pack('H', keyB);
101 file:write(key_a)
102 file:write(key_b)
103 file:close()
107 -- create key
108 local function keygen(uid)
109 local data = MIS..uid..BAR
110 local hash = utils.ConvertAsciiToBytes(utils.Sha1Hex(data))
111 return string.format("%02X%02X%02X%02X%02X%02X",
112 hash[3+1],
113 hash[2+1],
114 hash[1+1],
115 hash[0+1],
116 hash[7+1],
117 hash[6+1]
121 -- print keys
122 local function printKeys(keys)
123 print('|---|----------------|---|----------------|---|')
124 print('|sec|key A |res|key B |res|')
125 print('|---|----------------|---|----------------|---|')
126 for sector = 0, #keys do
127 local keyA, keyB = table.unpack(keys[sector])
128 print(('|%03d| %s | %s | %s | %s |'):format(sector, keyA, 1, keyB, 1))
130 print('|---|----------------|---|----------------|---|')
133 -- createfull set of keys
134 local function createKeys(uid)
135 local key = keygen(uid)
136 local k = {}
137 for i = 0,4 do
138 k[i] = { key, key }
140 return k
143 -- main
144 local function main(args)
146 print( string.rep('==', 30) )
147 print()
149 local uid
150 local useUID = false
152 -- Arguments for the script
153 for o, a in getopt.getopt(args, 'hu:') do
154 if o == 'h' then return help() end
155 if o == 'u' then uid = a; useUID = true end
158 if useUID then
159 -- uid string checks if supplied
160 if uid == nil then return oops('empty uid string') end
161 if #uid == 0 then return oops('empty uid string') end
162 if #uid ~= 14 then return oops('uid wrong length. Should be 7 hex bytes') end
163 else
164 -- GET TAG UID
165 local tag, err = lib14a.read(false, true)
166 if not tag then return oops(err) end
167 core.clearCommandBuffer()
169 -- simple tag check
170 if 0x09 ~= tag.sak then
171 if 0x4400 ~= tag.atqa then
172 return oops(('[!] found tag %s :: looking for Mifare Mini 0.3k'):format(tag.name))
175 uid = tag.uid
178 print('|UID|', uid)
180 local keys, err = createKeys( uid )
181 printKeys( keys )
182 dumptofile( uid, keys )
185 main(args)