Class: OpenSSL::CMAC

Inherits:
Object
  • Object
show all
Defined in:
lib/openssl_cmac.rb

Constant Summary collapse

CONST_ZERO =
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".force_encoding('ASCII-8BIT')
CONST_RB =
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x87]

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(key) ⇒ CMAC

key - base 128 bit AES key



15
16
17
18
# File 'lib/openssl_cmac.rb', line 15

def initialize(key)
  @key = key
  @k1, @k2 = CMAC.gen_subkeys(@key)
end

Class Method Details

.gen_subkeys(key) ⇒ Object



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/openssl_cmac.rb', line 46

def self.gen_subkeys(key)
  cipher = Cipher::AES.new(128, :ECB)
  cipher.encrypt
  cipher.key = key

  k1 = (cipher.update(CONST_ZERO)).unpack('C*')
  xor_flag = k1[0] >= 0x80

  k2 = Array.new(16)

  k1.each_with_index {|e, i| 
    lsb = i == 15 ? 0 : (k1[i+1] & 0x80) / 0x80
    k1[i] = (k1[i] << 1) % 256 | lsb
    k1[i] ^= CONST_RB[i] if xor_flag

    lsb = i == 15 ? 0 : (k1[i+1] << 1 & 0x80) / 0x80
    k2[i] = (k1[i] << 1) % 256 | lsb
    k2[i] ^= CONST_RB[i] if k1[0] >= 0x80
  }

  [k1, k2]
end

Instance Method Details

#generate(data) ⇒ Object



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/openssl_cmac.rb', line 20

def generate(data)
  data8 = data.dup.force_encoding('ASCII-8BIT')

  xor_key = @k1
  unless data8.size > 0 && 0 == data8.size % 16
    xor_key = @k2
    padding = "\x80"
    padding << "\x00" * (15 - data8.size % 16)
    data8 << padding
  end

  data8[-16, 16].unpack('C*').each_with_index do |e, i| 
    data8[data8.size - 16 + i] = (e ^ xor_key[i]).chr
  end

  cipher = Cipher::AES.new(128, :CBC)
  cipher.encrypt
  cipher.key = @key

  cipher.update(data8)[-16, 16]
end

#verify(data, cmac) ⇒ Object



42
43
44
# File 'lib/openssl_cmac.rb', line 42

def verify(data, cmac)
  generate(data) == cmac
end