class MIFARE::Classic
Constants
- CMD_AUTH_KEY_A
- CMD_AUTH_KEY_B
- CMD_DECREMENT
- CMD_INCREMENT
- CMD_READ
- CMD_RESTORE
- CMD_TRANSFER
- CMD_WRITE
- MF_ACK
Public Class Methods
new(pcd, uid, sak)
click to toggle source
Calls superclass method
PICC::new
# File lib/mifare/classic.rb, line 13 def initialize(pcd, uid, sak) super # Set transceive timeout to 15ms @pcd.internal_timer(50) end
Public Instance Methods
auth(block_addr, key = {})
click to toggle source
# File lib/mifare/classic.rb, line 29 def auth(block_addr, key = {}) if key[:a].nil? && key[:b].nil? raise UsageError, 'Missing key data' end if key[:a] cmd = CMD_AUTH_KEY_A key = key[:a] else cmd = CMD_AUTH_KEY_B key = key[:b] end key = [key].pack('H*').bytes if key.size != 6 raise UsageError, "Expect 6 bytes auth key, got: #{key.size} byte" end @pcd.mifare_crypto1_authenticate(cmd, block_addr, key, @uid) end
deauth()
click to toggle source
# File lib/mifare/classic.rb, line 50 def deauth @pcd.mifare_crypto1_deauthenticate end
decrement(block_addr, delta)
click to toggle source
Decrement: Decrements the contents of a block and stores the result in the internal Transfer Buffer
# File lib/mifare/classic.rb, line 123 def decrement(block_addr, delta) two_step(CMD_DECREMENT, block_addr, delta) end
increment(block_addr, delta)
click to toggle source
Increment: Increments the contents of a block and stores the result in the internal Transfer Buffer
# File lib/mifare/classic.rb, line 118 def increment(block_addr, delta) two_step(CMD_INCREMENT, block_addr, delta) end
read(block_addr)
click to toggle source
# File lib/mifare/classic.rb, line 54 def read(block_addr) transceive([CMD_READ, block_addr]) end
read_value(block_addr)
click to toggle source
# File lib/mifare/classic.rb, line 70 def read_value(block_addr) received_data = read(block_addr) value = received_data[0..3].to_sint value1 = ~(received_data[4..7].to_sint) value2 = received_data[8..11].to_sint if value != value1 || value != value2 raise UnexpectedDataError, 'Invalid value block' end value end
restore(block_addr)
click to toggle source
Restore: Moves the contents of a block into the internal Transfer Buffer
# File lib/mifare/classic.rb, line 128 def restore(block_addr) two_step(CMD_RESTORE, block_addr, 0) end
transceive(send_data, accept_timeout = false)
click to toggle source
# File lib/mifare/classic.rb, line 19 def transceive(send_data, accept_timeout = false) received_data, valid_bits = picc_transceive(send_data, accept_timeout, true) return if received_data.nil? && valid_bits.nil? && accept_timeout unless valid_bits == 0 raise UnexpectedDataError, 'Incorrect Mifare ACK format' if received_data.size != 1 || valid_bits != 4 # ACK is 4 bits long raise MifareNakError, "Mifare NAK detected: 0x#{received_data[0].to_bytehex}" if received_data[0] != MF_ACK end received_data end
transfer(block_addr)
click to toggle source
Transfer: Writes the contents of the internal Transfer Buffer to a value block
# File lib/mifare/classic.rb, line 133 def transfer(block_addr) transceive([CMD_TRANSFER, block_addr]) end
write(block_addr, send_data)
click to toggle source
# File lib/mifare/classic.rb, line 58 def write(block_addr, send_data) if send_data.size != 16 raise UsageError, "Expect 16 bytes data, got: #{send_data.size} byte" end # Ask PICC if we can write to block_addr transceive([CMD_WRITE, block_addr]) # Then start transfer our data transceive(send_data) end
write_value(block_addr, value)
click to toggle source
# File lib/mifare/classic.rb, line 84 def write_value(block_addr, value) # Value block format # # byte 0..3: 32 bit value in little endian # byte 4..7: copy of byte 0..3, with inverted bits (aka. XOR 255) # byte 8..11: copy of byte 0..3 # byte 12: index of backup block (can be any value) # byte 13: copy of byte 12 with inverted bits (aka. XOR 255) # byte 14: copy of byte 12 # byte 15: copy of byte 13 value = [].append_sint(value, 4) buffer = [] buffer[0] = value[0] buffer[1] = value[1] buffer[2] = value[2] buffer[3] = value[3] buffer[4] = ~buffer[0] buffer[5] = ~buffer[1] buffer[6] = ~buffer[2] buffer[7] = ~buffer[3] buffer[8] = buffer[0] buffer[9] = buffer[1] buffer[10] = buffer[2] buffer[11] = buffer[3] buffer[12] = block_addr buffer[13] = ~buffer[12] buffer[14] = buffer[12] buffer[15] = ~buffer[12] write(block_addr, buffer) end
Private Instance Methods
two_step(command, block_addr, value)
click to toggle source
Helper for increment, decrement, and restore command
# File lib/mifare/classic.rb, line 140 def two_step(command, block_addr, value) buffer = [command, block_addr] send_data = [].append_uint(value, 4) # Ask PICC if we can write to block_addr transceive(buffer) # Then start transfer our data transceive(send_data, true) # Accept timeout end