Class: MIFARE::Classic
Constant Summary collapse
- CMD_AUTH_KEY_A =
Perform authentication with Key A
0x60
- CMD_AUTH_KEY_B =
Perform authentication with Key B
0x61
- CMD_READ =
Reads one 16 byte block from the authenticated sector of the PICC.
0x30
- CMD_WRITE =
Writes one 16 byte block to the authenticated sector of the PICC.
0xA0
- CMD_DECREMENT =
Decrements the contents of a block and stores the result in the internal data register.
0xC0
- CMD_INCREMENT =
Increments the contents of a block and stores the result in the internal data register.
0xC1
- CMD_RESTORE =
Reads the contents of a block into the internal data register.
0xC2
- CMD_TRANSFER =
Writes the contents of the internal data register to a block.
0xB0
- MF_ACK =
Mifare Acknowledge
0x0A
Constants inherited from PICC
PICC::CMD_ADDITIONAL_FRAME, PICC::CMD_DESELECT, PICC::CMD_PPS, PICC::CMD_RATS, PICC::FSCI_to_FSC
Instance Attribute Summary
Attributes inherited from PICC
Instance Method Summary collapse
- #auth(block_addr, key = {}) ⇒ Object
- #deauth ⇒ Object
-
#decrement(block_addr, delta) ⇒ Object
Decrement: Decrements the contents of a block and stores the result in the internal Transfer Buffer.
-
#increment(block_addr, delta) ⇒ Object
Increment: Increments the contents of a block and stores the result in the internal Transfer Buffer.
-
#initialize(pcd, uid, sak) ⇒ Classic
constructor
A new instance of Classic.
- #read(block_addr) ⇒ Object
- #read_value(block_addr) ⇒ Object
-
#restore(block_addr) ⇒ Object
Restore: Moves the contents of a block into the internal Transfer Buffer.
- #transceive(send_data, accept_timeout = false) ⇒ Object
-
#transfer(block_addr) ⇒ Object
Transfer: Writes the contents of the internal Transfer Buffer to a value block.
- #write(block_addr, send_data) ⇒ Object
- #write_value(block_addr, value) ⇒ Object
Methods inherited from PICC
#halt, identify_model, #iso_deselect, #iso_select, #iso_transceive, #picc_transceive, #restart_communication
Constructor Details
#initialize(pcd, uid, sak) ⇒ Classic
Returns a new instance of Classic.
13 14 15 16 17 |
# File 'lib/mifare/classic.rb', line 13 def initialize(pcd, uid, sak) super # Set transceive timeout to 15ms @pcd.internal_timer(50) end |
Instance Method Details
#auth(block_addr, key = {}) ⇒ Object
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
# 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 ⇒ Object
50 51 52 |
# File 'lib/mifare/classic.rb', line 50 def deauth @pcd.mifare_crypto1_deauthenticate end |
#decrement(block_addr, delta) ⇒ Object
Decrement: Decrements the contents of a block and stores the result in the internal Transfer Buffer
123 124 125 |
# File 'lib/mifare/classic.rb', line 123 def decrement(block_addr, delta) two_step(CMD_DECREMENT, block_addr, delta) end |
#increment(block_addr, delta) ⇒ Object
Increment: Increments the contents of a block and stores the result in the internal Transfer Buffer
118 119 120 |
# File 'lib/mifare/classic.rb', line 118 def increment(block_addr, delta) two_step(CMD_INCREMENT, block_addr, delta) end |
#read(block_addr) ⇒ Object
54 55 56 |
# File 'lib/mifare/classic.rb', line 54 def read(block_addr) transceive([CMD_READ, block_addr]) end |
#read_value(block_addr) ⇒ Object
70 71 72 73 74 75 76 77 78 79 80 81 82 |
# 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) ⇒ Object
Restore: Moves the contents of a block into the internal Transfer Buffer
128 129 130 |
# 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) ⇒ Object
19 20 21 22 23 24 25 26 27 |
# 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) ⇒ Object
Transfer: Writes the contents of the internal Transfer Buffer to a value block
133 134 135 |
# File 'lib/mifare/classic.rb', line 133 def transfer(block_addr) transceive([CMD_TRANSFER, block_addr]) end |
#write(block_addr, send_data) ⇒ Object
58 59 60 61 62 63 64 65 66 67 68 |
# 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) ⇒ Object
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
# 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 |