Class: Digest::CMAC

Inherits:
Object
  • Object
show all
Defined in:
lib/digest/cmac.rb,
lib/digest/cmac/version.rb

Constant Summary collapse

BLOCK_SIZE =
16.freeze
RB =

Constant defined in the RFC for 16-byte block sizes

"\0" * (BLOCK_SIZE - 1) + "\x87"
VERSION =
'1.0.0'.freeze

Instance Method Summary collapse

Constructor Details

#initialize(cipher, key) ⇒ CMAC

Constructs an object to calculate CMACs for data



12
13
14
15
16
17
18
19
20
21
# File 'lib/digest/cmac.rb', line 12

def initialize(cipher, key)
  raise "Cipher block size must be #{BLOCK_SIZE}" unless cipher.block_size == BLOCK_SIZE

  @cipher = cipher
  @cipher.encrypt
  @cipher.key = @key = key

  generate_subkeys
  reset
end

Instance Method Details

#digestObject



44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/digest/cmac.rb', line 44

def digest
  raise 'Bad data length' if @data.length > BLOCK_SIZE

  if @data.length == BLOCK_SIZE
    @data = xor(@data, @lu)
  else
    @data << "\200".force_encoding('ASCII-8BIT') + ("\000".force_encoding('ASCII-8BIT') * (BLOCK_SIZE - @data.length - 1))
    @data = xor(@data, @lu2)
  end

  @tag = xor(@tag, @data)
  @tag = encrypt_block(@tag)
end

#resetObject



23
24
25
26
# File 'lib/digest/cmac.rb', line 23

def reset
  @data = ''
  @tag = "\0" * BLOCK_SIZE
end

#update(data) ⇒ Object



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/digest/cmac.rb', line 28

def update(data)
  @data += data
  complete_block_count = (@data.length / BLOCK_SIZE).floor

  if @data.length > BLOCK_SIZE
    0.upto(complete_block_count - 1) do |_i|
      break if @data.length == BLOCK_SIZE
      block = @data[0..(BLOCK_SIZE - 1)]
      @data = @data[BLOCK_SIZE..@data.length]
      raise 'Bad block length' if block.length != BLOCK_SIZE
      @tag = xor(@tag, block)
      @tag = encrypt_block(@tag)
    end
  end
end