diff --git a/speed.py b/speed.py index 7e5eb02b..c44dcba6 100644 --- a/speed.py +++ b/speed.py @@ -1,8 +1,10 @@ -import six import timeit from ecdsa.curves import curves +UNIQUE_KEYS = 100 + + def do(setup_statements, statement): # extracted from timeit.py t = timeit.Timer(stmt=statement, setup="\n".join(setup_statements)) @@ -12,7 +14,7 @@ def do(setup_statements, statement): x = t.timeit(number) if x >= 0.2: break - return x / number + return x / number / UNIQUE_KEYS prnt_form = ( @@ -43,13 +45,21 @@ def do(setup_statements, statement): ) for curve in [i.name for i in curves]: - S1 = "import six; from ecdsa import SigningKey, %s" % curve - S2 = "sk = SigningKey.generate(%s)" % curve - S3 = "msg = six.b('msg')" - S4 = "sig = sk.sign(msg)" - S5 = "vk = sk.get_verifying_key()" - S6 = "vk.precompute()" - S7 = "vk.verify(sig, msg)" + S1 = "from ecdsa import SigningKey, %s" % curve + S1 += "; from ecdsa.util import PRNG" + # as the code is very much data dependant, use the same 100 keys + # to sign the same 100 messages over and over to make the + # benchmarking stable + S2 = ( + "sk = [" + "SigningKey.generate({0}, entropy=PRNG(i)) " + "for i in range({1})]" + ).format(curve, UNIQUE_KEYS) + S3 = "msg = b'msg'" + S4 = "sig = [k.sign(msg, entropy=PRNG(b'A')) for k in sk]" + S5 = "vk = [k.get_verifying_key() for k in sk]" + S6 = "[k.precompute() for k in vk]" + S7 = "[k.verify(s, msg) for k, s in zip(vk, sig)]" # We happen to know that .generate() also calculates the # verifying key, which is the time-consuming part. If the code # were changed to lazily calculate vk, we'd need to change this @@ -61,7 +71,7 @@ def do(setup_statements, statement): import ecdsa c = getattr(ecdsa, curve) - sig = ecdsa.SigningKey.generate(c).sign(six.b("msg")) + sig = ecdsa.SigningKey.generate(c).sign(b"msg") print( prnt_form.format( name=curve, @@ -101,10 +111,25 @@ def do(setup_statements, statement): if curve == "Ed25519" or curve == "Ed448": continue S1 = "from ecdsa import SigningKey, ECDH, {0}".format(curve) - S2 = "our = SigningKey.generate({0})".format(curve) - S3 = "remote = SigningKey.generate({0}).verifying_key".format(curve) - S4 = "ecdh = ECDH(private_key=our, public_key=remote)" - S5 = "ecdh.generate_sharedsecret_bytes()" + S1 += "; from ecdsa.util import PRNG" + # as with signatures, calculate shared secrets for the same + # set of keys over and over + S2 = ( + "our = [" + "SigningKey.generate({0}, entropy=PRNG(i)) " + "for i in range({1})]" + ).format(curve, UNIQUE_KEYS) + S3 = ( + "remote = [" + "SigningKey.generate({0}, entropy=PRNG(i+10)).verifying_key " + "for i in range({1})]" + ).format(curve, UNIQUE_KEYS) + S4 = ( + "ecdh = [" + "ECDH(private_key=o, public_key=r) " + "for o, r in zip(our, remote)]" + ) + S5 = "[e.generate_sharedsecret_bytes() for e in ecdh]" ecdh = do([S1, S2, S3, S4], S5) print( ecdh_form.format(