Skip to content

Commit dcfa19f

Browse files
committed
update speed.py
make it a bit more modular and make the output look more like OpenSSL's
1 parent 4076c2d commit dcfa19f

File tree

2 files changed

+49
-21
lines changed

2 files changed

+49
-21
lines changed

README.md

Lines changed: 33 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -35,27 +35,44 @@ and 1.0.0a .
3535
## Speed
3636

3737
The following table shows how long this library takes to generate keypairs
38-
(keygen=), to sign data (sign=), and to verify those signatures (verify=), on
39-
my 2008 Mac laptop. All times are in seconds. It also shows the length of a
40-
signature (in bytes): the verifying ("public") key is typically the same
41-
length as the signature, and the signing ("private") key is half that length.
38+
(`keygen`), to sign data (`sign`), and to verify those signatures (`verify`).
39+
All those values are in seconds.
40+
For convenience, the inverses of those values are also provided:
41+
how many keys per second can be generated (`keygen/s`), how many signatures
42+
can be made per second (`sign/s`) and how many signatures can be verified
43+
per second (`verify/s`). The size of raw signature (generally the smallest
44+
way a signature can be encoded) is also provided in the `siglen` column.
4245
Use `tox -e speed` to generate this table on your own computer.
46+
On an Intel Core i7 4790K @ 4.0GHz I'm getting the following performance:
4347

44-
* NIST192p: siglen= 48, keygen=0.160s, sign=0.058s, verify=0.116s
45-
* NIST224p: siglen= 56, keygen=0.230s, sign=0.086s, verify=0.165s
46-
* NIST256p: siglen= 64, keygen=0.305s, sign=0.112s, verify=0.220s
47-
* NIST384p: siglen= 96, keygen=0.801s, sign=0.289s, verify=0.558s
48-
* NIST521p: siglen=132, keygen=1.582s, sign=0.584s, verify=1.152s
48+
```
49+
siglen keygen keygen/s sign sign/s verify verify/s
50+
NIST192p: 48 0.03183s 31.42 0.01127s 88.70 0.02253s 44.39
51+
NIST224p: 56 0.04304s 23.24 0.01548s 64.59 0.03122s 32.03
52+
NIST256p: 64 0.05720s 17.48 0.02055s 48.67 0.04075s 24.54
53+
NIST384p: 96 0.13216s 7.57 0.04696s 21.29 0.09400s 10.64
54+
NIST521p: 132 0.25805s 3.88 0.09329s 10.72 0.18841s 5.31
55+
SECP256k1: 64 0.05677s 17.61 0.02073s 48.23 0.04067s 24.59
56+
```
4957

50-
For comparison, a quality C++ implementation of ECDSA (Crypto++) typically
51-
computes a NIST256p signature in 2.88ms and a verification in 8.53ms, about
52-
30-40x faster.
58+
For comparison, a highly optimised implementation (including curve-specific
59+
assemply) like OpenSSL provides following performance numbers on the same
60+
machine. Run `openssl speed`:
61+
```
62+
sign verify sign/s verify/s
63+
192 bits ecdsa (nistp192) 0.0002s 0.0002s 4785.6 5380.7
64+
224 bits ecdsa (nistp224) 0.0000s 0.0001s 22475.6 9822.0
65+
256 bits ecdsa (nistp256) 0.0000s 0.0001s 45069.6 14166.6
66+
384 bits ecdsa (nistp384) 0.0008s 0.0006s 1265.6 1648.1
67+
521 bits ecdsa (nistp521) 0.0003s 0.0005s 3753.1 1819.5
68+
```
5369

5470
Keys and signature can be serialized in different ways (see Usage, below).
5571
For a NIST192p key, the three basic representations require strings of the
5672
following lengths (in bytes):
5773

5874
to_string: signkey= 24, verifykey= 48, signature=48
75+
compressed: signkey=n/a, verifykey= 25, signature=n/a
5976
DER: signkey=106, verifykey= 80, signature=55
6077
PEM: signkey=278, verifykey=162, (no support for PEM signatures)
6178

@@ -76,13 +93,12 @@ more for the wrapper. To run them all, do this:
7693

7794
tox -e coverage
7895

79-
On my 2014 Mac Mini, the combined tests take about 20 seconds to run. On a
80-
2.4GHz P4 Linux box, they take 81 seconds.
96+
On an Intel Core i7 4790K @ 4.0GHz, the combined tests take about 8 minutes to
97+
run.
8198

8299
One component of `test_pyecdsa.py` checks compatibility with OpenSSL, by
83-
running the "openssl" CLI tool. If this tool is not on your $PATH, you may
84-
want to comment out this test (the easiest way is to add a line that says
85-
"del OpenSSL" to the end of test_pyecdsa.py).
100+
running the "openssl" CLI tool, make sure it's in your `PATH` if you want
101+
to test it.
86102

87103
## Security
88104

speed.py

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import six
22
import timeit
3+
from ecdsa.curves import curves
34

45
def do(setup_statements, statement):
56
# extracted from timeit.py
@@ -13,8 +14,17 @@ def do(setup_statements, statement):
1314
break
1415
return x / number
1516

16-
for curve in ["NIST192p", "NIST224p", "NIST256p", "SECP256k1",
17-
"NIST384p", "NIST521p"]:
17+
prnt_form = ("{name:>10}{sep:1} {siglen:>6} {keygen:>9{form}}{unit:1} "
18+
"{keygen_inv:>9{form_inv}} {sign:>9{form}}{unit:1} "
19+
"{sign_inv:>9{form_inv}} {verify:>9{form}}{unit:1} "
20+
"{verify_inv:>9{form_inv}}")
21+
22+
print(prnt_form.format(siglen="siglen", keygen="keygen", keygen_inv="keygen/s",
23+
sign="sign", sign_inv="sign/s", verify="verify",
24+
verify_inv="verify/s", name="", sep="", unit="",
25+
form="", form_inv=""))
26+
27+
for curve in [i.name for i in curves]:
1828
S1 = "import six; from ecdsa import SigningKey, %s" % curve
1929
S2 = "sk = SigningKey.generate(%s)" % curve
2030
S3 = "msg = six.b('msg')"
@@ -31,5 +41,7 @@ def do(setup_statements, statement):
3141
import ecdsa
3242
c = getattr(ecdsa, curve)
3343
sig = ecdsa.SigningKey.generate(c).sign(six.b("msg"))
34-
print("%9s: siglen=%3d, keygen=%.3fs, sign=%.3fs, verify=%.3fs" \
35-
% (curve, len(sig), keygen, sign, verf))
44+
print(prnt_form.format(
45+
name=curve, sep=":", siglen=len(sig), unit="s", keygen=keygen,
46+
keygen_inv=1.0/keygen, sign=sign, sign_inv=1.0/sign, verify=verf,
47+
verify_inv=1.0/verf, form=".5f", form_inv=".2f"))

0 commit comments

Comments
 (0)