Skip to content

Instantly share code, notes, and snippets.

@arirusso
Created April 30, 2012 01:51
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save arirusso/2554841 to your computer and use it in GitHub Desktop.
Ruby methods for protecting against timing attacks
#!/usr/bin/env ruby
#
# Ruby methods for protecting against timing attacks
#
module ExpressionTimer
# a shortcut to ExpressionTimer.send that passes in the object for which this module
# was included
#
# @param [Numeric] seconds the minimum number of seconds to wait before returning
# @param [Array] send_args a splat of args to pass into self.send
# @return [Object] the result of calling send on this object
def timed_send(seconds, *send_args, &block)
ExpressionTimer.send(seconds, self, *send_args, &block)
end
# a wrapper for Object#send that protects against timing attacks by
# ensuring that it does not return from evaluation before a specified
# minimum time
#
# @param [Numeric] seconds the minimum number of seconds to wait before returning
# @param [Object] object the object to call send on
# @param [Array] send_args a splat of args to pass into Object#send
# @return [Object] the result of calling send on object
def self.send(seconds, object, *send_args, &b)
block(seconds) { object.send(*send_args, &b) }
end
# wrap a block with a method that protects against timing attacks by
# ensuring that it does not return from evaluation before a specified
# minimum time
#
# @param [Numeric] seconds the minimum number of seconds to wait before returning
# @param [Array] block_args splatted arguments to pass in to the block
# @yield [Array] the wrapped block to evaluate with block_args passed in splatted
# @return [Object] the result of yielding to the block
def self.block(seconds, *block_args, &block)
start = Time.now.to_f
result = yield(*block_args)
finish = Time.now.to_f
sleep (seconds - (finish - start))
result
end
end
#
#
# examples:
#
#
# send:
puts ExpressionTimer.send(0.25, "password attempt!", :==, "my password!")
# or a block
puts ExpressionTimer.block(0.75) { "password attempt!" == "my password!" }
# or with arguments passed into a block
puts ExpressionTimer.block(1.25, "password attempt!", "my password!") { |s1, s2| s1 == s2 }
# or with an included module (don't actually include it in String, this is just a demo)
class String
include ExpressionTimer
end
password_attempt, real_password = "password attempt!", "my password!"
p password_attempt.timed_send(0.75, :==, real_password)
@arirusso
Copy link
Author

Isn't timeout.rb a time limiter? How do you see that working here?

I normally use Thread#abort_on_exception but I don't see much opportunity for an exception in this thread, unless someone passes in a negative value for seconds ? lemme think about that one

@RobertLowe
Copy link

Sorry, I read the gist in a rush, timeout.rb is a limiter

Still why the thread?

@arirusso
Copy link
Author

Yeah, it may not be necessary -- most of the timers I've written before were actually multithreaded so I wrote that out of habit.

I'll give it a shot in the main thread and change it if it seems reliable.

Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment