class TimingAttack::Grouper
Constants
- ALLOWED_TEST_SYMBOLS
Attributes
attacks[R]
long_tests[R]
short_tests[R]
spike_delta[R]
test_args[R]
test_hash[R]
test_method[R]
Public Class Methods
new(attacks: , group_by: {})
click to toggle source
# File lib/timing_attack/grouper.rb, line 4 def initialize(attacks: , group_by: {}) @attacks = attacks setup_grouping_opts!(group_by) @short_tests = [] @long_tests = [] group_attacks serialize freeze end
Public Instance Methods
serialize()
click to toggle source
# File lib/timing_attack/grouper.rb, line 14 def serialize @serialize ||= {}.tap do |h| h[:attack_method] = test_method h[:attack_args] = test_args h[:short] = serialize_tests(short_tests) h[:long] = serialize_tests(long_tests) h[:spike_delta] = spike_delta end end
Private Instance Methods
decorated_attacks()
click to toggle source
# File lib/timing_attack/grouper.rb, line 86 def decorated_attacks return @decorated_attacks unless @decorated_attacks.nil? sorted = attacks.sort { |a,b| value_from_test(a) <=> value_from_test(b) } @decorated_attacks = sorted.each_with_object([]).with_index do |(attack, memo), index| delta = if index == 0 0.0 else value_from_test(attack) - value_from_test(sorted[index-1]) end memo << { attack: attack, delta: delta } end end
group_attacks()
click to toggle source
# File lib/timing_attack/grouper.rb, line 77 def group_attacks spike = decorated_attacks.max { |a,b| a[:delta] <=> b[:delta] } index = decorated_attacks.index(spike) stripped = decorated_attacks.map {|a| a[:attack] } @short_tests = stripped[0..(index-1)] @long_tests = stripped[index..-1] @spike_delta = spike[:delta] end
serialize_tests(test_arr)
click to toggle source
# File lib/timing_attack/grouper.rb, line 71 def serialize_tests(test_arr) test_arr.each_with_object({}) do |test, ret| ret[test.input] = value_from_test(test) end end
setup_grouping_opts!(group_by)
click to toggle source
# File lib/timing_attack/grouper.rb, line 30 def setup_grouping_opts!(group_by) case group_by when Symbol setup_symbol_opts!(group_by) when Hash setup_hash_opts!(group_by) else raise ArgumentError.new("Don't know what to do with #{group_by.class} #{group_by}") end end
setup_hash_opts!(hash)
click to toggle source
# File lib/timing_attack/grouper.rb, line 57 def setup_hash_opts!(hash) raise ArgumentError.new("Must provide configuration to Grouper") if hash.empty? key, value = hash.first unless ALLOWED_TEST_SYMBOLS.include? key raise ArgumentError.new("Allowed keys are #{ALLOWED_TEST_SYMBOLS.join(', ')}") end @test_method = key @test_args = value.is_a?(Array) ? value : [value] end
setup_symbol_opts!(symbol)
click to toggle source
# File lib/timing_attack/grouper.rb, line 41 def setup_symbol_opts!(symbol) case symbol when :mean @test_method = :mean @test_args = [] when :median @test_method = :percentile @test_args = [50] when :percentile @test_method = :percentile @test_args = [10] else raise ArgumentError.new("Allowed symbols are #{ALLOWED_TEST_SYMBOLS.join(', ')}") end end
value_from_test(test)
click to toggle source
# File lib/timing_attack/grouper.rb, line 67 def value_from_test(test) test.public_send(test_method, *test_args) end