Created
April 30, 2012 01:51
-
-
Save arirusso/2554841 to your computer and use it in GitHub Desktop.
Ruby methods for protecting against timing attacks
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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) |
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
Sorry, I read the gist in a rush, timeout.rb is a limiter
Still why the thread?