Class: MIFARE::Key
- Inherits:
-
Object
- Object
- MIFARE::Key
- Defined in:
- lib/mifare/key.rb
Instance Attribute Summary collapse
-
#cipher_suite ⇒ Object
readonly
Returns the value of attribute cipher_suite.
-
#key_size ⇒ Object
readonly
Returns the value of attribute key_size.
-
#type ⇒ Object
readonly
Returns the value of attribute type.
-
#version ⇒ Object
readonly
Returns the value of attribute version.
Instance Method Summary collapse
- #calculate_cmac(data) ⇒ Object
- #clear_iv ⇒ Object
- #decrypt(data, cbc_mode: :receive, data_length: nil) ⇒ Object
- #encrypt(data, cbc_mode: :send, data_length: nil) ⇒ Object
- #generate_cmac_subkeys ⇒ Object
-
#initialize(type, key, version = 0x00) ⇒ Key
constructor
A new instance of Key.
- #key ⇒ Object
-
#padding_mode(mode) ⇒ Object
Padding Method according to ISO-9797.
- #set_iv(iv) ⇒ Object
Constructor Details
#initialize(type, key, version = 0x00) ⇒ Key
Returns a new instance of Key.
8 9 10 11 12 13 |
# File 'lib/mifare/key.rb', line 8 def initialize(type, key, version = 0x00) @type = type set_key_data(type, key, version) clear_iv init_cipher end |
Instance Attribute Details
#cipher_suite ⇒ Object (readonly)
Returns the value of attribute cipher_suite.
4 5 6 |
# File 'lib/mifare/key.rb', line 4 def cipher_suite @cipher_suite end |
#key_size ⇒ Object (readonly)
Returns the value of attribute key_size.
5 6 7 |
# File 'lib/mifare/key.rb', line 5 def key_size @key_size end |
#type ⇒ Object (readonly)
Returns the value of attribute type.
3 4 5 |
# File 'lib/mifare/key.rb', line 3 def type @type end |
#version ⇒ Object (readonly)
Returns the value of attribute version.
6 7 8 |
# File 'lib/mifare/key.rb', line 6 def version @version end |
Instance Method Details
#calculate_cmac(data) ⇒ Object
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'lib/mifare/key.rb', line 81 def calculate_cmac(data) if @cmac_subkey1.nil? || @cmac_subkey2.nil? raise UsageError, 'Generate subkeys before calculating CMAC' end # Separate from input object data = data.dup if data.size == 0 || data.size % @block_size != 0 # padding with byte: 0x80, 0x00, 0x00..... data << 0x80 until data.size % @block_size == 0 data << 0x00 end key = @cmac_subkey2 else key = @cmac_subkey1 end # XOR last data block with selected CMAC subkey data = data[0...-@block_size] + data[-@block_size..-1].zip(key).map{|x, y| x ^ y } encrypt(data) @cipher_iv.bytes end |
#clear_iv ⇒ Object
63 64 65 |
# File 'lib/mifare/key.rb', line 63 def clear_iv @cipher_iv = "\x00" * @block_size end |
#decrypt(data, cbc_mode: :receive, data_length: nil) ⇒ Object
42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/mifare/key.rb', line 42 def decrypt(data, cbc_mode: :receive, data_length: nil) @cipher.decrypt data = cbc_crypt(data, cbc_mode) if @padding_mode == 1 data[0...data_length] elsif @padding_mode == 2 str = data.pack('C*') str.sub! /#{0x80.chr}#{0x00.chr}*\z/, '' str.bytes else raise UsageError, 'Padding mode not set' end end |
#encrypt(data, cbc_mode: :send, data_length: nil) ⇒ Object
27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
# File 'lib/mifare/key.rb', line 27 def encrypt(data, cbc_mode: :send, data_length: nil) @cipher.encrypt # Add padding if not a complete block if data.size % @block_size != 0 raise UsageError, 'Padding mode not set' unless @padding_mode data << 0x80 if @padding_mode == 2 until data.size % @block_size == 0 data << 0x00 end end cbc_crypt(data, cbc_mode) end |
#generate_cmac_subkeys ⇒ Object
67 68 69 70 71 72 73 74 75 76 77 78 79 |
# File 'lib/mifare/key.rb', line 67 def generate_cmac_subkeys r = (@block_size == 8) ? 0x1B : 0x87 data = Array.new(@block_size, 0) clear_iv data = encrypt(data, cbc_mode: :receive) @cmac_subkey1 = bit_shift_left(data) @cmac_subkey1[-1] ^= r if data[0] & 0x80 != 0 @cmac_subkey2 = bit_shift_left(@cmac_subkey1) @cmac_subkey2[-1] ^= r if @cmac_subkey1[0] & 0x80 != 0 end |
#key ⇒ Object
23 24 25 |
# File 'lib/mifare/key.rb', line 23 def key @key.bytes end |
#padding_mode(mode) ⇒ Object
Padding Method according to ISO-9797
16 17 18 19 20 21 |
# File 'lib/mifare/key.rb', line 16 def padding_mode(mode) if mode != 1 && mode != 2 raise UsageError, 'Unknown padding mode' end @padding_mode = mode end |
#set_iv(iv) ⇒ Object
57 58 59 60 61 |
# File 'lib/mifare/key.rb', line 57 def set_iv(iv) iv = iv.pack('C*') raise UsageError, 'Incorrect IV length' if iv.size != @block_size @cipher_iv = iv end |