Skip to content

Instantly share code, notes, and snippets.

@NSkelsey
Created January 10, 2017 12:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save NSkelsey/3a9cd2d68d2ec18b531a34823b5c32d9 to your computer and use it in GitHub Desktop.
Save NSkelsey/3a9cd2d68d2ec18b531a34823b5c32d9 to your computer and use it in GitHub Desktop.
Demonstrates lack of resolution in timing side channels
#!/usr/bin/env python
import string
import random
import timeit
#from globaleaks.handlers import authentication
from globaleaks.security import check_password, hash_password
guesses = 1000000
def rand_pw():
return ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(8))
def default_pws():
return
class TestFrame(object):
def __init__(self, pw_try=None):
self.correct_pass = ''.join(string.ascii_lowercase)
self.pw_try = pw_try
self.correct_pass_hash = hash_password(self.correct_pass, 'a-bit-of-salt')
def simple_cmp(self):
return self.correct_pass == self.pw_try
def zip_cmp(self):
result = 0
for x, y in zip(self.correct_pass, self.pw_try):
result |= ord(x) ^ ord(y)
return result == 0
def check_pw(self):
check_password(self.pw_try, 'a-bit-of-salt', self.correct_pass_hash)
def o(seconds):
return "%0.3f usec per eval" % ((seconds / guesses)*1e6)
def g(seconds):
return "%0.3f usec per eval" % ((seconds / 10)*1e6)
if __name__ == '__main__':
print("\ncheck_password: 100 runs\n")
res = timeit.timeit('tf.check_pw()', 'from __main__ import TestFrame; tf = TestFrame(pw_try="bbbbbbbbbbbbbbbbbbbbbbbbbb")', number=100)
print('first byte incorrect:\t%s'% g(res))
res = timeit.timeit('tf.check_pw()', 'from __main__ import TestFrame; tf = TestFrame(pw_try="abbbbbbbbbbbbbbbbbbbbbbbbb")', number=100)
print('first byte correct:\t%s'% g(res))
res = timeit.timeit('tf.check_pw()', 'from __main__ import TestFrame; tf = TestFrame(pw_try="abcdefghijklmnopqrstuvwxyg")', number=100)
print('very close pw time:\t%s'% g(res))
res = timeit.timeit('tf.check_pw()', 'from __main__ import TestFrame; tf = TestFrame(pw_try="abcdefghijklmnopqrstuvwxyz")', number=100)
print('correct pw time:\t%s' % g(res))
print("simple_cmp: 1 million runs\n")
res = timeit.timeit('tf.simple_cmp()', 'from __main__ import TestFrame; tf = TestFrame(pw_try="bbbbbbbbbbbbbbbbbbbbbbbbbb")', number=guesses)
print('first byte incorrect:\t%s'% o(res))
res = timeit.timeit('tf.simple_cmp()', 'from __main__ import TestFrame; tf = TestFrame(pw_try="abbbbbbbbbbbbbbbbbbbbbbbbb")', number=guesses)
print('first byte correct:\t%s'% o(res))
res = timeit.timeit('tf.simple_cmp()', 'from __main__ import TestFrame; tf = TestFrame(pw_try="abcdefghijklmnopqrstuvwxyg")', number=guesses)
print('very close pw time:\t%s'% o(res))
res = timeit.timeit('tf.simple_cmp()', 'from __main__ import TestFrame; tf = TestFrame(pw_try="abcdefghijklmnopqrstuvwxyz")', number=guesses)
print('correct pw time:\t%s' % o(res))
print("\nzip_cmp: 1 million runs\n")
res = timeit.timeit('tf.zip_cmp()', 'from __main__ import TestFrame; tf = TestFrame(pw_try="bbbbbbbbbbbbbbbbbbbbbbbbbb")', number=guesses)
print('first byte incorrect:\t%s'% o(res))
res = timeit.timeit('tf.zip_cmp()', 'from __main__ import TestFrame; tf = TestFrame(pw_try="abbbbbbbbbbbbbbbbbbbbbbbbb")', number=guesses)
print('first byte correct:\t%s'% o(res))
res = timeit.timeit('tf.zip_cmp()', 'from __main__ import TestFrame; tf = TestFrame(pw_try="abcdefghijklmnopqrstuvwxyg")', number=guesses)
print('very close pw time:\t%s'% o(res))
res = timeit.timeit('tf.zip_cmp()', 'from __main__ import TestFrame; tf = TestFrame(pw_try="abcdefghijklmnopqrstuvwxyz")', number=guesses)
print('correct pw time:\t%s' % o(res))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment