Module: Mifare::UltralightC
- Defined in:
- lib/mifare/ultralight_c.rb
Constant Summary collapse
- CMD_3DES_AUTH =
Ultralight C 3DES Authentication.
0x1A
Instance Method Summary collapse
- #auth(auth_key) ⇒ Object
- #authed? ⇒ Boolean
- #counter_increment(value) ⇒ Object
- #enable_protection_from(block_addr) ⇒ Object
- #set_protection_type(type) ⇒ Object
- #write_des_key(key) ⇒ Object
Instance Method Details
#auth(auth_key) ⇒ Object
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
# File 'lib/mifare/ultralight_c.rb', line 5 def auth(auth_key) if auth_key.cipher_suite != 'des-ede-cbc' raise UnexpectedDataError, 'Incorrect Auth Key Type' end auth_key.clear_iv # Ask for authentication buffer = [CMD_3DES_AUTH, 0x00] received_data = @pcd.picc_transceive(buffer) card_status = received_data.shift raise UnexpectedDataError, 'Incorrect response' if card_status != 0xAF challenge = auth_key.decrypt(received_data) challenge_rot = challenge.rotate # Generate 8 bytes random number and encrypt it with rotated challenge random_number = SecureRandom.random_bytes(8).bytes response = auth_key.encrypt(random_number + challenge_rot) # Send challenge response buffer = [0xAF] + response received_data = @pcd.picc_transceive(buffer) card_status = received_data.shift raise UnexpectedDataError, 'Incorrect response' if card_status != 0x00 # Check if verification matches rotated random_number verification = auth_key.decrypt(received_data) if random_number.rotate != verification halt return @authed = false end @authed = true end |
#authed? ⇒ Boolean
42 43 44 |
# File 'lib/mifare/ultralight_c.rb', line 42 def authed? @authed end |
#counter_increment(value) ⇒ Object
61 62 63 64 65 66 67 68 |
# File 'lib/mifare/ultralight_c.rb', line 61 def counter_increment(value) if value < 0 raise UnexpectedDataError, 'Expect positive integer for counter' end # you can set any value between 0x0000 to 0xFFFF on the first write (initialize) # after initialized, counter can only be incremented by 0x01 ~ 0x0F write(0x29, [value & 0xFF, (value >> 8) & 0xFF, 0x00, 0x00]) end |
#enable_protection_from(block_addr) ⇒ Object
70 71 72 73 74 75 76 77 78 |
# File 'lib/mifare/ultralight_c.rb', line 70 def enable_protection_from(block_addr) if block_addr >= 0x03 && block_addr <= 0x30 raise UnexpectedDataError, 'Requested block beyond memory limit' end # authentication will be required from `block_addr` to 0x2F # valid value are from 0x03 to 0x30 # set to 0x30 to disable memory protection write(0x2A, [block_addr & 0x3F, 0x00, 0x00, 0x00]) end |
#set_protection_type(type) ⇒ Object
80 81 82 83 84 |
# File 'lib/mifare/ultralight_c.rb', line 80 def set_protection_type(type) # set to 0 for read-write access restriction (default) # set to 1 for write access restriction write(0x2B, [type & 0x01, 0x00, 0x00, 0x00]) end |
#write_des_key(key) ⇒ Object
46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
# File 'lib/mifare/ultralight_c.rb', line 46 def write_des_key(key) # key should be 16 bytes long bytes = [key].pack('H*').bytes if bytes.size != 16 raise UnexpectedDataError, "Expect 16 bytes 3DES key, got: #{bytes.size} byte" end # Key1 write(0x2C, bytes[4..7].reverse) write(0x2D, bytes[0..3].reverse) # Key2 write(0x2E, bytes[12..15].reverse) write(0x2F, bytes[8..11].reverse) end |