Module: RbNaCl::Util

Extended by:
Sodium
Defined in:
lib/rbnacl/util.rb

Overview

Various utility functions

Class Method Summary collapse

Methods included from Sodium

primitive, sodium_constant, sodium_function, sodium_primitive, sodium_type

Class Method Details

.bin2hex(bytes) ⇒ String

Hex encodes a message

Parameters:

  • bytes (String)

    The bytes to encode

Returns:

  • (String)

    Tasty, tasty hexadecimal



169
170
171
# File 'lib/rbnacl/util.rb', line 169

def bin2hex(bytes)
  bytes.to_s.unpack("H*").first
end

.check_length(string, length, description) ⇒ Object

Check the length of the passed in string

In several places through the codebase we have to be VERY strict with what length of string we accept. This method supports that.

Parameters:

  • string (String)

    The string to compare

  • length (Integer)

    The desired length

  • description (String)

    Description of the string (used in the error)

Raises:



58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/rbnacl/util.rb', line 58

def check_length(string, length, description)
  if string.nil?
    raise LengthError,
      "#{description} was nil (Expected #{length.to_int})",
      caller
  end

  if string.bytesize != length.to_int
    raise LengthError,
          "#{description} was #{string.bytesize} bytes (Expected #{length.to_int})",
          caller
  end
  true
end

.check_string(string, length, description) ⇒ Object

Check a passed in string, converting the argument if necessary

In several places through the codebase we have to be VERY strict with the strings we accept. This method supports that.

Parameters:

  • string (#to_str)

    The input string

  • length (Integer)

    The only acceptable length of the string

  • description (String)

    Description of the string (used in the error)

Raises:

  • (ArgumentError)

    If we cannot convert to a string with #to_str

  • (RbNaCl::LengthError)

    If the string is not the right length



84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/rbnacl/util.rb', line 84

def check_string(string, length, description)
  unless string.respond_to? :to_str
    raise TypeError, "can't convert #{string.class} into String with #to_str"
  end

  string = string.to_str
  unless string.encoding == Encoding::BINARY
    raise EncodingError, "strings must use BINARY encoding (got #{string.encoding})"
  end
  check_length(string, length, description)

  string
end

.hex2bin(hex) ⇒ String

Hex decodes a message

Parameters:

  • hex (String)

    hex to decode.

Returns:

  • (String)

    crisp and clean bytes



178
179
180
# File 'lib/rbnacl/util.rb', line 178

def hex2bin(hex)
  [hex.to_s].pack("H*")
end

.prepend_zeros(n, message) ⇒ String

Prepends a message with zeros

Many functions require a string with some zeros prepended.

Parameters:

  • n (Integer)

    The number of zeros to prepend

  • message (String)

    The string to be prepended

Returns:

  • (String)

    a bunch of zeros



32
33
34
# File 'lib/rbnacl/util.rb', line 32

def prepend_zeros(n, message)
  zeros(n) + message
end

.remove_zeros(n, message) ⇒ String

Remove zeros from the start of a message

Many functions require a string with some zeros prepended, then need them removing after. Note, this modifies the passed in string

Parameters:

  • n (Integer)

    The number of zeros to remove

  • message (String)

    The string to be slice

Returns:

  • (String)

    less a bunch of zeros



44
45
46
# File 'lib/rbnacl/util.rb', line 44

def remove_zeros(n, message)
  message.slice!(n, message.bytesize - n)
end

.verify16(one, two) ⇒ Boolean

Compare two 16 byte strings in constant time

This should help to avoid timing attacks for string comparisons in your application. Note that many of the functions (such as OneTime#verify) use this method under the hood already.

Parameters:

  • one (String)

    String #1

  • two (String)

    String #2

Returns:

  • (Boolean)

    Well, are they equal?



141
142
143
144
# File 'lib/rbnacl/util.rb', line 141

def verify16(one, two)
  return false unless two.bytesize == 16 && one.bytesize == 16
  c_verify16(one, two)
end

.verify16!(one, two) ⇒ Boolean

Compare two 16 byte strings in constant time

This should help to avoid timing attacks for string comparisons in your application. Note that many of the functions (such as OneTime#verify) use this method under the hood already.

Parameters:

  • one (String)

    String #1

  • two (String)

    String #2

Returns:

  • (Boolean)

    Well, are they equal?

Raises:

  • (ArgumentError)

    If the strings are not equal in length



158
159
160
161
162
# File 'lib/rbnacl/util.rb', line 158

def verify16!(one, two)
  check_length(one, 16, "First message")
  check_length(two, 16, "Second message")
  c_verify16(one, two)
end

.verify32(one, two) ⇒ Boolean

Compare two 32 byte strings in constant time

This should help to avoid timing attacks for string comparisons in your application. Note that many of the functions (such as HmacSha256#verify) use this method under the hood already.

Parameters:

  • one (String)

    String #1

  • two (String)

    String #2

Returns:

  • (Boolean)

    Well, are they equal?



108
109
110
111
# File 'lib/rbnacl/util.rb', line 108

def verify32(one, two)
  return false unless two.bytesize == 32 && one.bytesize == 32
  c_verify32(one, two)
end

.verify32!(one, two) ⇒ Boolean

Compare two 32 byte strings in constant time

This should help to avoid timing attacks for string comparisons in your application. Note that many of the functions (such as HmacSha256#verify) use this method under the hood already.

Parameters:

  • one (String)

    String #1

  • two (String)

    String #2

Returns:

  • (Boolean)

    Well, are they equal?

Raises:

  • (ArgumentError)

    If the strings are not equal in length



125
126
127
128
129
# File 'lib/rbnacl/util.rb', line 125

def verify32!(one, two)
  check_length(one, 32, "First message")
  check_length(two, 32, "Second message")
  c_verify32(one, two)
end

.zeros(n = 32) ⇒ String

Returns a string of n zeros

Lots of the functions require us to create strings to pass into functions of a specified size.

Parameters:

  • n (Integer) (defaults to: 32)

    the size of the string to make

Returns:

  • (String)

    A nice collection of zeros



17
18
19
20
21
22
# File 'lib/rbnacl/util.rb', line 17

def zeros(n=32)
  zeros = "\0" * n
  # make sure they're 8-bit zeros, not 7-bit zeros.  Otherwise we might get
  # encoding errors later
  zeros.respond_to?(:force_encoding) ? zeros.force_encoding('ASCII-8BIT') : zeros
end