class Analyzers::CbcMac::VariableLength::Analyzer

Public Class Methods

new(oracle_class = ::Analyzers::CbcMac::VariableLength::Oracles::Tcp,block_length=32) click to toggle source

This class implements an attack on CBC-MAC with variable length. This issue is known for a long time and thus should be avoided by any implementation. However this code shows how to forge a tag in this mode and can be seen das a PoC.

Thanks to Matthew Green for this great article about the potential implementation problems of CBC-MAC: blog.cryptographyengineering.com/2013/02/why-i-hate-cbc-mac.html

This class has the VL (variable length) suffix it its name to make100% clear that this attack works only on this condition

# File lib/crypto-toolbox/analyzers/cbc_mac/variable_length/analyzer.rb, line 18
def initialize(oracle_class = ::Analyzers::CbcMac::VariableLength::Oracles::Tcp,block_length=32)
  @oracle = oracle_class.new
end

Public Instance Methods

analyze(target_message) click to toggle source

NOTE: handle too short messages properly

# File lib/crypto-toolbox/analyzers/cbc_mac/variable_length/analyzer.rb, line 23
def analyze(target_message)
  @oracle.connect

  # split the target message into chunks of size N (e.g. 32)
  target_bufs = CryptBuffer(target_message).chunks_of(32)

  # receive the valid mac for the first chunk of the target message
  tag1 = CryptBuffer(@oracle.mac(target_bufs[0]))

  attack_message = assemble_malicious_message(target_bufs,tag1)
  forged_tag = @oracle.mac(attack_message)

  ret = @oracle.verify(target_message, forged_tag)

  report_result(ret,forged_tag)
  
  @oracle.disconnect          
end

Private Instance Methods

assemble_malicious_message(target_bufs,tag1) click to toggle source

Create a message that consists of 1) the first n byte of the second message xored with tag t from the first message 2) the remaining blocks of the second message short: t'' = (m'_0 xor t ) ||m'_1 ||…||m'_n]

# File lib/crypto-toolbox/analyzers/cbc_mac/variable_length/analyzer.rb, line 47
def assemble_malicious_message(target_bufs,tag1)

  # split the second chunk into blocks of the size of the tag
  m2_blocks = target_bufs[1].chunks_of(tag1.length)

  CryptBuffer((m2_blocks[0].xor(tag1)).bytes + m2_blocks[1].bytes)
end
forge_successfull?(retval) click to toggle source
# File lib/crypto-toolbox/analyzers/cbc_mac/variable_length/analyzer.rb, line 63
def forge_successfull?(retval)
  retval == 1
end
report_result(ret,tag) click to toggle source
# File lib/crypto-toolbox/analyzers/cbc_mac/variable_length/analyzer.rb, line 55
def report_result(ret,tag)
  if forge_successfull?(ret)
    puts "[Success] Resulting tag is: #{CryptBuffer(tag).pretty_hexstring}"
  else
    puts "[Failure] Message verification failed."
  end
end