scepticulous/crypto-toolbox

View on GitHub
lib/crypto-toolbox/analyzers/cbc_mac/variable_length/analyzer.rb

Summary

Maintainability
A
0 mins
Test Coverage
require 'crypto-toolbox/analyzers/cbc_mac/variable_length/oracles/tcp.rb'

module Analyzers
  module CbcMac
    module VariableLength
      
      class Analyzer
        # 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: http://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
        def initialize(oracle_class = ::Analyzers::CbcMac::VariableLength::Oracles::Tcp,block_length=32)
          @oracle = oracle_class.new
        end
        # NOTE: handle too short messages properly
        
        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
          # 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]          
        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
        
        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
        
        def forge_successfull?(retval)
          retval == 1
        end
        
      end
      

      
    end
  end
end