Class: Mifare::Classic

Inherits:
PICC
  • Object
show all
Defined in:
lib/mifare/classic.rb

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

Instance Attribute Summary

Attributes inherited from PICC

#sak, #uid

Instance Method Summary collapse

Methods inherited from PICC

#halt, #initialize, #resume_communication

Constructor Details

This class inherits a constructor from PICC

Instance Method Details

#auth(block_addr, key = {}) ⇒ Object



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/mifare/classic.rb', line 12

def auth(block_addr, key = {})
  if key[:a].nil? && key[:b].nil?
    raise UnexpectedDataError, '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 UnexpectedDataError, "Expect 6 bytes auth key, got: #{key.size} byte"
  end

  @pcd.mifare_crypto1_authenticate(cmd, block_addr, key, @uid)
end

#deauthObject



33
34
35
# File 'lib/mifare/classic.rb', line 33

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



102
103
104
# File 'lib/mifare/classic.rb', line 102

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



97
98
99
# File 'lib/mifare/classic.rb', line 97

def increment(block_addr, delta)
  two_step(CMD_INCREMENT, block_addr, delta)
end

#read(block_addr) ⇒ Object



37
38
39
40
41
# File 'lib/mifare/classic.rb', line 37

def read(block_addr)
  buffer = [CMD_READ, block_addr]

  @pcd.picc_transceive(buffer)
end

#read_value(block_addr) ⇒ Object



57
58
59
60
61
# File 'lib/mifare/classic.rb', line 57

def read_value(block_addr)
  received_data = read(block_addr)

  received_data[0..3].to_sint
end

#restore(block_addr) ⇒ Object

Restore: Moves the contents of a block into the internal Transfer Buffer



107
108
109
# File 'lib/mifare/classic.rb', line 107

def restore(block_addr)
  two_step(CMD_RESTORE, block_addr, 0)
end

#transfer(block_addr) ⇒ Object

Transfer: Writes the contents of the internal Transfer Buffer to a value block



112
113
114
115
116
# File 'lib/mifare/classic.rb', line 112

def transfer(block_addr)
  buffer = [CMD_TRANSFER, block_addr]

  @pcd.picc_transceive(buffer)
end

#write(block_addr, send_data) ⇒ Object



43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/mifare/classic.rb', line 43

def write(block_addr, send_data)
  if send_data.size != 16
    raise UnexpectedDataError, "Expect 16 bytes data, got: #{send_data.size} byte"
  end

  buffer = [CMD_WRITE, block_addr]

  # Ask PICC if we can write to block_addr
  @pcd.picc_transceive(buffer)

  # Then start transfer our data
  @pcd.picc_transceive(send_data)
end

#write_value(block_addr, value) ⇒ Object



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/mifare/classic.rb', line 63

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] = ~block_addr
  buffer[14] = buffer[12]
  buffer[15] = buffer[13]

  write(block_addr, buffer)
end