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')
11 This script calculates mifare keys based on uid diversification for DI.
15 -- if called without, it reads tag uid
16 script run hf_mf_uidkeycalc
19 script run hf_mf_uidkeycalc -u 11223344556677
22 script run hf_mf_uidkeycalc -h -u <uid>
30 local BAR
= '286329204469736E65792032303133'
31 local MIS
= '0A14FD0507FF4BCD026BA83F0A3B89A9'
32 local bxor
= bit32
.bxor
34 -- A debug printout-function
35 local function dbg(args
)
36 if not DEBUG
then return end
37 if type(args
) == 'table' then
48 -- This is only meant to be used when errors occur
49 local function oops(err
)
51 core
.clearCommandBuffer()
61 print(ansicolors
.cyan
..'Usage'..ansicolors
.reset
)
63 print(ansicolors
.cyan
..'Arguments'..ansicolors
.reset
)
65 print(ansicolors
.cyan
..'Example usage'..ansicolors
.reset
)
70 local function exitMsg(msg
)
71 print( string.rep('--',20) )
72 print( string.rep('--',20) )
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')
88 print('Could not write to file ', destination
)
92 -- Mifare Mini has 5 sectors,
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
);
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",
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
)
144 local function main(args
)
146 print( string.rep('==', 30) )
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
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
165 local tag, err
= lib14a
.read(false, true)
166 if not tag then return oops(err
) end
167 core
.clearCommandBuffer()
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
))
180 local keys
, err
= createKeys( uid
)
182 dumptofile( uid
, keys
)