Module: Miscreant::Internals::Util

Defined in:
lib/miscreant/internals/util.rb

Overview

Internal utility functions

Constant Summary collapse

CTZ_TABLE =

:nodoc: Lookup table for the number of trailing zeroes in a byte

[
  8, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
].freeze

Class Method Summary collapse

Class Method Details

.ct_equal(a, b) ⇒ Object

Perform a constant time-ish comparison of two bytestrings



31
32
33
34
35
36
37
38
39
40
# File 'lib/miscreant/internals/util.rb', line 31

def ct_equal(a, b)
  return false unless a.bytesize == b.bytesize

  l = a.unpack("C*")
  r = 0
  i = -1

  b.each_byte { |v| r |= v ^ l[i += 1] }
  r.zero?
end

.ct_select(subject, result_if_one, result_if_zero) ⇒ Object

Perform a constant time(-ish) branch operation



43
44
45
# File 'lib/miscreant/internals/util.rb', line 43

def ct_select(subject, result_if_one, result_if_zero)
  (~(subject - 1) & result_if_one) | ((subject - 1) & result_if_zero)
end

.ctz(value) ⇒ Object

Count the number of zeros in a given 8-bit integer

Parameters:

  • value (Integer)

    an integer in the 8-bit unsigned range (0-255)



50
51
52
# File 'lib/miscreant/internals/util.rb', line 50

def ctz(value)
  CTZ_TABLE.fetch(value)
end

.pad(message, length) ⇒ Object

Pad value with a 0x80 value and zeroes up to the given length



55
56
57
58
59
# File 'lib/miscreant/internals/util.rb', line 55

def pad(message, length)
  padded_length = message.length + length - (message.length % length)
  message += "\x80"
  message.ljust(padded_length, "\0")
end

.validate_bytestring(name, string, length: nil) ⇒ Object

Ensure a string is a valid bytestring (potentially of a given length)

Raises:

  • (TypeError)


62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/miscreant/internals/util.rb', line 62

def validate_bytestring(name, string, length: nil)
  raise TypeError, "expected String for #{name}, got #{string.class}" unless string.is_a?(String)
  raise ArgumentError, "#{name} must be Encoding::BINARY" unless string.encoding == Encoding::BINARY

  case length
  when Array
    raise ArgumentError, "#{name} must be #{length.join(' or ')} bytes long" unless length.include?(string.bytesize)
  when Integer
    raise ArgumentError, "#{name} must be #{length}-bytes long" unless string.bytesize == length
  else
    raise TypeError, "bad length parameter: #{length.inspect} (#{length.class}" unless length.nil?
  end

  string
end