From 370b1270f94fcbc3ee7fc391ee38460fc6fab6a1 Mon Sep 17 00:00:00 2001 From: Zooko O'Whielacronx Date: Thu, 22 Mar 2012 13:19:33 -0600 Subject: [PATCH 01/24] small packaging tweaks move ChangeLog to NEWS.rst remove the shebang lines from the beginnings of test files --- ChangeLog | 28 -------------------- NEWS.rst | 38 +++++++++++++++++----------- src/pycryptopp/test/test_aes.py | 2 -- src/pycryptopp/test/test_ecdsa.py | 2 -- src/pycryptopp/test/test_rsa.py | 2 -- src/pycryptopp/test/test_sha256.py | 2 -- src/pycryptopp/test/test_xsalsa20.py | 2 -- 7 files changed, 23 insertions(+), 53 deletions(-) delete mode 100644 ChangeLog diff --git a/ChangeLog b/ChangeLog deleted file mode 100644 index f4b99ac..0000000 --- a/ChangeLog +++ /dev/null @@ -1,28 +0,0 @@ -2012-03-13 Zooko Wilcox-O'Hearn - - • src/pycryptopp/_version.py: release pycryptopp-0.6.0 - • add Ed25519 signatures (#75) - • add XSalsa20 cipher (#40) - • switch from darcs to git for revision control - • pycryptopp version numbers now include a decimal encoding of the - git revid - • reorganize the source tree and the version number generation - • aesmodule.cpp: validate size of IV and throw exception if it is not 16 (#70) - • fixed compile errors with gcc-4.7.0 (#78) - • fixed compile errors concerning "CryptoPP::g_nullNameValuePairs" (#77) - • suppress warnings from valgrind with new OpenSSL 1.0.1 on Fedora (#82) - • raise Python exception instead of uncaught C++ exception - (resulting in abort) when deserializing malformed RSA keys (#83) - -2009-09-15 Zooko Wilcox-O'Hearn - - • release pycryptopp-0.5.17 - • publickey/rsamodule.cpp, publickey/ecdsamodule.cpp, - hash/sha256module.cpp, cipher/aesmodule.cpp: fix a segfault bug - when sizeof(size_t) > sizeof(int) (not exploitable); thanks Nathan - Wilcox and Brian Warner. (#19) - -2009-07-27 Zooko Wilcox-O'Hearn - - • release pycryptopp-0.5.16 - • setup.py, misc/: a few improvements to the build/packaging diff --git a/NEWS.rst b/NEWS.rst index f797344..f4b99ac 100644 --- a/NEWS.rst +++ b/NEWS.rst @@ -1,20 +1,28 @@ -2011-01-16 -- pycryptopp v0.5.28 +2012-03-13 Zooko Wilcox-O'Hearn - * re-enable the ECDSA module, but please do not rely on it as it is expected to change in backwards-incompatible ways in future releases - * several changes to the build system to make it tidier and less error-prone -- see revision control history for details + • src/pycryptopp/_version.py: release pycryptopp-0.6.0 + • add Ed25519 signatures (#75) + • add XSalsa20 cipher (#40) + • switch from darcs to git for revision control + • pycryptopp version numbers now include a decimal encoding of the + git revid + • reorganize the source tree and the version number generation + • aesmodule.cpp: validate size of IV and throw exception if it is not 16 (#70) + • fixed compile errors with gcc-4.7.0 (#78) + • fixed compile errors concerning "CryptoPP::g_nullNameValuePairs" (#77) + • suppress warnings from valgrind with new OpenSSL 1.0.1 on Fedora (#82) + • raise Python exception instead of uncaught C++ exception + (resulting in abort) when deserializing malformed RSA keys (#83) -2010-09-20 -- pycryptopp v0.5.25 +2009-09-15 Zooko Wilcox-O'Hearn - * make setup backwards-compatible to Python 2.4 - * fix incompatibilities between setup script and older versions of darcsver - * don't attempt to compile Mac OS X extended attribute files (this fixes the build breaking) - * include a version number of the specific version of Crypto++ in extraversion.h - * small changes to docs + • release pycryptopp-0.5.17 + • publickey/rsamodule.cpp, publickey/ecdsamodule.cpp, + hash/sha256module.cpp, cipher/aesmodule.cpp: fix a segfault bug + when sizeof(size_t) > sizeof(int) (not exploitable); thanks Nathan + Wilcox and Brian Warner. (#19) -2010-09-18 -- pycryptopp v0.5.20 +2009-07-27 Zooko Wilcox-O'Hearn - * fix bugs in assembly implementation of SHA-256 from Crypto++ - * fix it to compile on \*BSD (#39) - * improve doc strings - * add a quick start-up-self-test of SHA256 (#43) - * execute the quick start-up-self-tests of AES and SHA256 on module import + • release pycryptopp-0.5.16 + • setup.py, misc/: a few improvements to the build/packaging diff --git a/src/pycryptopp/test/test_aes.py b/src/pycryptopp/test/test_aes.py index 16c3e20..591b171 100644 --- a/src/pycryptopp/test/test_aes.py +++ b/src/pycryptopp/test/test_aes.py @@ -1,5 +1,3 @@ -#!/usr/bin/env python - import random, re import unittest diff --git a/src/pycryptopp/test/test_ecdsa.py b/src/pycryptopp/test/test_ecdsa.py index 62fbfe1..85f809d 100644 --- a/src/pycryptopp/test/test_ecdsa.py +++ b/src/pycryptopp/test/test_ecdsa.py @@ -1,5 +1,3 @@ -#!/usr/bin/env python - import random import base64 diff --git a/src/pycryptopp/test/test_rsa.py b/src/pycryptopp/test/test_rsa.py index 15294bc..7311a4f 100644 --- a/src/pycryptopp/test/test_rsa.py +++ b/src/pycryptopp/test/test_rsa.py @@ -1,5 +1,3 @@ -#!/usr/bin/env python - import random import unittest diff --git a/src/pycryptopp/test/test_sha256.py b/src/pycryptopp/test/test_sha256.py index 5e982dc..5705b91 100644 --- a/src/pycryptopp/test/test_sha256.py +++ b/src/pycryptopp/test/test_sha256.py @@ -1,5 +1,3 @@ -#!/usr/bin/env python - import random, re import unittest diff --git a/src/pycryptopp/test/test_xsalsa20.py b/src/pycryptopp/test/test_xsalsa20.py index f3ee02a..0f949e7 100644 --- a/src/pycryptopp/test/test_xsalsa20.py +++ b/src/pycryptopp/test/test_xsalsa20.py @@ -1,5 +1,3 @@ -#!/usr/bin/env python - import random, re import unittest From ebdf5f4a8a9d7cfe4e135ffcb1fb2aec26db9f1e Mon Sep 17 00:00:00 2001 From: Zooko O'Whielacronx Date: Sat, 31 Mar 2012 22:29:38 -0600 Subject: [PATCH 02/24] benchmarks: benchmark a higher number of reps of key-generation, because with fewer reps it finishes so fast the benchutil correctly detects that it can't accurately measure things that fast and raises an exception (on Johannes Nix's Pandaboard) --- src/pycryptopp/bench/bench_sigs.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pycryptopp/bench/bench_sigs.py b/src/pycryptopp/bench/bench_sigs.py index 8fc70fc..d42aabc 100644 --- a/src/pycryptopp/bench/bench_sigs.py +++ b/src/pycryptopp/bench/bench_sigs.py @@ -123,11 +123,11 @@ def bench_sigs(MAXTIME): print klass ob = klass() print "generate key" - rep_bench(ob.gen, 4, UNITS_PER_SECOND=1000, MAXTIME=MAXTIME, MAXREPS=100) + rep_bench(ob.gen, 800, UNITS_PER_SECOND=1000, MAXTIME=MAXTIME, MAXREPS=100) print "sign" - rep_bench(ob.sign, 20, UNITS_PER_SECOND=1000, initfunc=ob.sign_init, MAXTIME=MAXTIME, MAXREPS=100) + rep_bench(ob.sign, 8, UNITS_PER_SECOND=1000, initfunc=ob.sign_init, MAXTIME=MAXTIME, MAXREPS=100) print "verify" - rep_bench(ob.ver, 100, UNITS_PER_SECOND=1000, initfunc=ob.ver_init, MAXTIME=MAXTIME, MAXREPS=100) + rep_bench(ob.ver, 4, UNITS_PER_SECOND=1000, initfunc=ob.ver_init, MAXTIME=MAXTIME, MAXREPS=100) print print "milliseconds per operation" From b29b94b00b8e2b84721d707bd6ce2c77f57281ac Mon Sep 17 00:00:00 2001 From: Zooko O'Whielacronx Date: Sat, 31 Mar 2012 22:47:23 -0600 Subject: [PATCH 03/24] bench: RSA key generation takes way too long to use high reps, so separate elliptic curve from RSA benchmarks and use low reps for RSA --- src/pycryptopp/bench/bench_sigs.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/pycryptopp/bench/bench_sigs.py b/src/pycryptopp/bench/bench_sigs.py index d42aabc..2c9f637 100644 --- a/src/pycryptopp/bench/bench_sigs.py +++ b/src/pycryptopp/bench/bench_sigs.py @@ -119,7 +119,7 @@ def ver(self, N): verifier.verify(msg, sig) def bench_sigs(MAXTIME): - for klass in [ECDSA256, Ed25519, RSA2048, RSA3248]: + for klass in [ECDSA256, Ed25519,]: print klass ob = klass() print "generate key" @@ -130,6 +130,17 @@ def bench_sigs(MAXTIME): rep_bench(ob.ver, 4, UNITS_PER_SECOND=1000, initfunc=ob.ver_init, MAXTIME=MAXTIME, MAXREPS=100) print + for klass in [RSA2048, RSA3248]: + print klass + ob = klass() + print "generate key" + rep_bench(ob.gen, 1, UNITS_PER_SECOND=1000, MAXTIME=MAXTIME, MAXREPS=100) + print "sign" + rep_bench(ob.sign, 8, UNITS_PER_SECOND=1000, initfunc=ob.sign_init, MAXTIME=MAXTIME, MAXREPS=100) + print "verify" + rep_bench(ob.ver, 4, UNITS_PER_SECOND=1000, initfunc=ob.ver_init, MAXTIME=MAXTIME, MAXREPS=100) + print + print "milliseconds per operation" print_bench_footer(UNITS_PER_SECOND=1000) print From 7f15ab099049adbe2a413fc26df4bdb3f239797c Mon Sep 17 00:00:00 2001 From: Zooko O'Whielacronx Date: Sat, 31 Mar 2012 23:01:24 -0600 Subject: [PATCH 04/24] remove ChangeLog from MANIFEST.in --- MANIFEST.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MANIFEST.in b/MANIFEST.in index 37ed49f..2cb12e1 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,4 +1,4 @@ -include copyright COPYING.GPL COPYING.TGPPL.html ChangeLog NEWS.rst README.rst +include copyright COPYING.GPL COPYING.TGPPL.html NEWS.rst README.rst include COPYING.ed25519 README.ed25519.rst include MANIFEST.in include versioneer.py From 00b03ef513236acdf487f76173a6285445ca26bb Mon Sep 17 00:00:00 2001 From: Zooko O'Whielacronx Date: Sun, 1 Apr 2012 00:11:14 -0600 Subject: [PATCH 05/24] bench: benchmark larger strings because we're not capable of measuring the time taken for smaller strings on slow computers --- src/pycryptopp/bench/bench_ciphers.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/pycryptopp/bench/bench_ciphers.py b/src/pycryptopp/bench/bench_ciphers.py index c8ee6b9..8f09593 100644 --- a/src/pycryptopp/bench/bench_ciphers.py +++ b/src/pycryptopp/bench/bench_ciphers.py @@ -29,9 +29,8 @@ def bench_ciphers(MAXTIME): ob = BenchCrypt(klass, keysize) print ob for (legend, size) in [ - ("small (%d B)", 1000), - ("medium (%d B)", 10000), - ("large (%d B)", 100000), + ("medium (%d B)", 150000), + ("large (%d B)", 1500000), ]: print legend % size rep_bench(ob.crypt, size, UNITS_PER_SECOND=UNITS_PER_SECOND, MAXTIME=MAXTIME, MAXREPS=100, initfunc=ob.crypt_init) From 0e4720d7e7250bfa6533a7e1b60ab7fe0909f749 Mon Sep 17 00:00:00 2001 From: Zooko O'Whielacronx Date: Sun, 1 Apr 2012 05:21:49 -0600 Subject: [PATCH 06/24] add suppressions for a slightly newer version of gcc and CPython on sid which results in slightly different names for functions --- misc/coding_helpers/python.supp | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/misc/coding_helpers/python.supp b/misc/coding_helpers/python.supp index 102e2ec..e890edf 100644 --- a/misc/coding_helpers/python.supp +++ b/misc/coding_helpers/python.supp @@ -44,7 +44,7 @@ fun:_dl_catch_error } -# generated on luther sid +# generated on luther sid with "python: 2.7.2+ (default, Jan 20 2012, 23:05:38) [GCC 4.6.2]" # e.g. https://tahoe-lafs.org/buildbot-pycryptopp/builders/luther%20sid/builds/38/steps/double%20load%20valgrind/logs/valgrind { luther sid addr4 realloc @@ -64,6 +64,27 @@ fun:PyObject_Realloc.part.0.20700 } +# generated on luther sid with "python: 2.7.3rc2 (default, Mar 21 2012, 16:14:45) [GCC 4.6.3]" +https://tahoe-lafs.org/buildbot-pycryptopp/builders/luther%20sid/builds/106/steps/test%20valgrind/logs/valgrind +{ + luther sid addr4 realloc + Memcheck:Addr4 + fun:PyObject_Realloc.part.0.20707 +} + +{ + luther sid cond realloc + Memcheck:Cond + fun:PyObject_Realloc.part.0.20707 +} + +{ + luther sid value4 realloc + Memcheck:Value4 + fun:PyObject_Realloc.part.0.20707 +} + + # glibc was apparently changed to avoid this: http://sources.redhat.com/bugzilla/show_bug.cgi?id=4306 { use (not really, according to Ulrich Drepper) of uninitailised bytes by glibc in utimes() From 67748598a99840a5d1b970fe97e8f3cc04825d5a Mon Sep 17 00:00:00 2001 From: Zooko O'Whielacronx Date: Sun, 1 Apr 2012 05:45:19 -0600 Subject: [PATCH 07/24] force local rep_bench instead of pyutil rep_bench, and use both time.time and time.clock to compare them to each other --- src/pycryptopp/bench/common.py | 35 +++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/src/pycryptopp/bench/common.py b/src/pycryptopp/bench/common.py index d14cd25..3b2c18a 100644 --- a/src/pycryptopp/bench/common.py +++ b/src/pycryptopp/bench/common.py @@ -1,42 +1,55 @@ msg = "crypto libraries should come with benchmarks" try: + raise ImportError import pyutil.benchutil rep_bench = pyutil.benchutil.rep_bench except (ImportError, AttributeError): def this_rep_bench(func, N, UNITS_PER_SECOND, MAXTIME, MAXREPS, initfunc=None): import time + tt = time.time + tc = time.clock if initfunc is not None: initfunc(N) - mean = 0 + meant = 0 + meanc = 0 MAXREPS = 100 - timeout = time.time() + MAXTIME + timeout = tt() + MAXTIME for i in range(MAXREPS): - start = time.time() + startt = tt() + startc = tc() func(N) - stop = time.time() + stopt = time.time() + stopc = time.clock() - mean += (stop - start) + deltat = stopt - startt + deltac = stopc - startc + if (deltat <= 0) or (deltac <= 0): + print "startt: %s, startc: %s, stopt: %s, stopc: %s" % (startt, startc, stopt, stopc,) - if stop >= timeout: + meant += deltat + meanc += deltac + + if stopt >= timeout: break num = i+1 - mean *= UNITS_PER_SECOND - mean /= num - mean /= N + meant *= UNITS_PER_SECOND + meant /= num + meant /= N res = { - 'mean': mean/num, + 'meant': meant, + 'meanc': meanc, 'num': num } - print "mean: %(mean)#8.03e (of %(num)6d)" % res + print "mean: %(meant)#8.03e or %(meanc)#8.03e (of %(num)6d)" % res rep_bench = this_rep_bench try: From aa9a5ae681b96e99fc7836c5abe3017b110b103e Mon Sep 17 00:00:00 2001 From: Zooko O'Whielacronx Date: Sun, 1 Apr 2012 05:48:24 -0600 Subject: [PATCH 08/24] =?UTF-8?q?print=20out=20deltat=20and=20deltac=20whe?= =?UTF-8?q?never=20either=20is=20=E2=89=A4=200?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pycryptopp/bench/common.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pycryptopp/bench/common.py b/src/pycryptopp/bench/common.py index 3b2c18a..7e30232 100644 --- a/src/pycryptopp/bench/common.py +++ b/src/pycryptopp/bench/common.py @@ -31,7 +31,7 @@ def this_rep_bench(func, N, UNITS_PER_SECOND, MAXTIME, MAXREPS, initfunc=None): deltat = stopt - startt deltac = stopc - startc if (deltat <= 0) or (deltac <= 0): - print "startt: %s, startc: %s, stopt: %s, stopc: %s" % (startt, startc, stopt, stopc,) + print "startt: %s, stopt: %s, deltat: %s, startc: %s, stopc: %s, deltac: %s" % (startt, stopt, deltat, startc, stopc, deltac) meant += deltat meanc += deltac From 43fd4a0943ce5db41833724f3a62d8087054ad48 Mon Sep 17 00:00:00 2001 From: Zooko O'Whielacronx Date: Sun, 1 Apr 2012 05:50:40 -0600 Subject: [PATCH 09/24] print out deltac and deltat whenever they are more than 1 ms apart --- src/pycryptopp/bench/common.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pycryptopp/bench/common.py b/src/pycryptopp/bench/common.py index 7e30232..2e215ac 100644 --- a/src/pycryptopp/bench/common.py +++ b/src/pycryptopp/bench/common.py @@ -30,7 +30,7 @@ def this_rep_bench(func, N, UNITS_PER_SECOND, MAXTIME, MAXREPS, initfunc=None): deltat = stopt - startt deltac = stopc - startc - if (deltat <= 0) or (deltac <= 0): + if (deltat <= 0) or (deltac <= 0) or (abs(deltat - deltac) > 0.001): print "startt: %s, stopt: %s, deltat: %s, startc: %s, stopc: %s, deltac: %s" % (startt, stopt, deltat, startc, stopc, deltac) meant += deltat From 2fb327228c6fcab88fff75915bdf86ccf17b80d4 Mon Sep 17 00:00:00 2001 From: Zooko O'Whielacronx Date: Sun, 1 Apr 2012 06:11:02 -0600 Subject: [PATCH 10/24] fix typo in new suppressions --- misc/coding_helpers/python.supp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/misc/coding_helpers/python.supp b/misc/coding_helpers/python.supp index e890edf..712785c 100644 --- a/misc/coding_helpers/python.supp +++ b/misc/coding_helpers/python.supp @@ -65,7 +65,7 @@ } # generated on luther sid with "python: 2.7.3rc2 (default, Mar 21 2012, 16:14:45) [GCC 4.6.3]" -https://tahoe-lafs.org/buildbot-pycryptopp/builders/luther%20sid/builds/106/steps/test%20valgrind/logs/valgrind +# e.g. https://tahoe-lafs.org/buildbot-pycryptopp/builders/luther%20sid/builds/106/steps/test%20valgrind/logs/valgrind { luther sid addr4 realloc Memcheck:Addr4 From e159c034f977431f61cbf6cb74b64de3c6393070 Mon Sep 17 00:00:00 2001 From: Zooko O'Whielacronx Date: Sun, 1 Apr 2012 06:21:15 -0600 Subject: [PATCH 11/24] print out deltadelta --- src/pycryptopp/bench/common.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pycryptopp/bench/common.py b/src/pycryptopp/bench/common.py index 2e215ac..0b48621 100644 --- a/src/pycryptopp/bench/common.py +++ b/src/pycryptopp/bench/common.py @@ -31,7 +31,7 @@ def this_rep_bench(func, N, UNITS_PER_SECOND, MAXTIME, MAXREPS, initfunc=None): deltat = stopt - startt deltac = stopc - startc if (deltat <= 0) or (deltac <= 0) or (abs(deltat - deltac) > 0.001): - print "startt: %s, stopt: %s, deltat: %s, startc: %s, stopc: %s, deltac: %s" % (startt, stopt, deltat, startc, stopc, deltac) + print "startt: %s, stopt: %s, deltat: %s, startc: %s, stopc: %s, deltac: %s, ddelta: %s" % (startt, stopt, deltat, startc, stopc, deltac, deltac-deltat) meant += deltat meanc += deltac From 9e70642c779ad6f528e1faf3aa080ce97f63b795 Mon Sep 17 00:00:00 2001 From: Zooko O'Whielacronx Date: Sun, 1 Apr 2012 06:27:56 -0600 Subject: [PATCH 12/24] add dummy functions in order to test the accuracy of the clocks --- src/pycryptopp/bench/bench_sigs.py | 78 +++++++++++++++++++++++++++++- 1 file changed, 77 insertions(+), 1 deletion(-) diff --git a/src/pycryptopp/bench/bench_sigs.py b/src/pycryptopp/bench/bench_sigs.py index 2c9f637..fbb2e2c 100644 --- a/src/pycryptopp/bench/bench_sigs.py +++ b/src/pycryptopp/bench/bench_sigs.py @@ -60,6 +60,82 @@ def ver(self, N): for i in xrange(N): verifier.verify(sig, msg) +import time +class SleepSign(object): + def __init__(self): + pass + + def gen(self, N): + time.sleep(N*self.SLEEPINESS) + + def sign_init(self, N): + pass + + def sign(self, N): + time.sleep(N*self.SLEEPINESS) + + def ver_init(self, N): + pass + + def ver(self, N): + time.sleep(N*self.SLEEPINESS) + +class Sleep10msSign(SleepSign): + SLEEPINESS = 0.01 + +class Sleep10usSign(SleepSign): + SLEEPINESS = 0.00001 + +class NullSign(object): + def __init__(self): + pass + + def gen(self, N): + for i in xrange(N): + pass + + def sign_init(self, N): + pass + + def sign(self, N): + for i in xrange(N): + pass + + def ver_init(self, N): + pass + + def ver(self, N): + for i in xrange(N): + pass + +class Ed25519(object): + def __init__(self): + self.seed = insecurerandstr(32) + self.signer = None + + def gen(self, N): + for i in xrange(N): + ed25519.SigningKey(self.seed) + + def sign_init(self, N): + self.signer = ed25519.SigningKey(self.seed) + + def sign(self, N): + signer = self.signer + for i in xrange(N): + signer.sign(msg) + + def ver_init(self, N): + signer = ed25519.SigningKey(self.seed) + self.sig = signer.sign(msg) + self.verifier = ed25519.VerifyingKey(signer.get_verifying_key_bytes()) + + def ver(self, N): + sig = self.sig + verifier = self.verifier + for i in xrange(N): + verifier.verify(sig, msg) + class RSA2048(object): SIZEINBITS=2048 @@ -119,7 +195,7 @@ def ver(self, N): verifier.verify(msg, sig) def bench_sigs(MAXTIME): - for klass in [ECDSA256, Ed25519,]: + for klass in [ECDSA256, Ed25519, NullSign, Sleep10msSign, Sleep10usSign]: print klass ob = klass() print "generate key" From 7f134caee637b77e14b0d16dc23f8d7577060a3a Mon Sep 17 00:00:00 2001 From: Zooko O'Whielacronx Date: Sun, 1 Apr 2012 06:44:13 -0600 Subject: [PATCH 13/24] fix bug in calculation of meanc --- src/pycryptopp/bench/common.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/pycryptopp/bench/common.py b/src/pycryptopp/bench/common.py index 0b48621..c3da8b1 100644 --- a/src/pycryptopp/bench/common.py +++ b/src/pycryptopp/bench/common.py @@ -43,6 +43,9 @@ def this_rep_bench(func, N, UNITS_PER_SECOND, MAXTIME, MAXREPS, initfunc=None): meant *= UNITS_PER_SECOND meant /= num meant /= N + meanc *= UNITS_PER_SECOND + meanc /= num + meanc /= N res = { 'meant': meant, From f782ab37f18fd8c8003c0854e0b68df8c9560d08 Mon Sep 17 00:00:00 2001 From: Zooko O'Whielacronx Date: Sun, 1 Apr 2012 06:59:37 -0600 Subject: [PATCH 14/24] tune the size of the job to be benchmarked so it falls into the range of things long enough to measure but otherwise short --- src/pycryptopp/bench/bench_ciphers.py | 4 ++-- src/pycryptopp/bench/bench_hashes.py | 5 ++--- src/pycryptopp/bench/bench_sigs.py | 10 +++++----- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/pycryptopp/bench/bench_ciphers.py b/src/pycryptopp/bench/bench_ciphers.py index 8f09593..cc12338 100644 --- a/src/pycryptopp/bench/bench_ciphers.py +++ b/src/pycryptopp/bench/bench_ciphers.py @@ -29,8 +29,8 @@ def bench_ciphers(MAXTIME): ob = BenchCrypt(klass, keysize) print ob for (legend, size) in [ - ("medium (%d B)", 150000), - ("large (%d B)", 1500000), + ("large (%d B)", 10**6), + ("huge (%d B)", 10**7), ]: print legend % size rep_bench(ob.crypt, size, UNITS_PER_SECOND=UNITS_PER_SECOND, MAXTIME=MAXTIME, MAXREPS=100, initfunc=ob.crypt_init) diff --git a/src/pycryptopp/bench/bench_hashes.py b/src/pycryptopp/bench/bench_hashes.py index 9ce1c86..ba261e5 100644 --- a/src/pycryptopp/bench/bench_hashes.py +++ b/src/pycryptopp/bench/bench_hashes.py @@ -35,9 +35,8 @@ def bench_hashes(MAXTIME): print klass ob = klass() for (legend, size) in [ - ("small (%d B)", 1000), - ("medium (%d B)", 10000), - ("large (%d B)", 100000), + ("large (%d B)", 10**6), + ("huge (%d B)", 10**7), ]: print legend % size rep_bench(ob.proc, size, UNITS_PER_SECOND=UNITS_PER_SECOND, MAXTIME=MAXTIME, MAXREPS=100, initfunc=ob.proc_init) diff --git a/src/pycryptopp/bench/bench_sigs.py b/src/pycryptopp/bench/bench_sigs.py index fbb2e2c..35e9c7a 100644 --- a/src/pycryptopp/bench/bench_sigs.py +++ b/src/pycryptopp/bench/bench_sigs.py @@ -199,11 +199,11 @@ def bench_sigs(MAXTIME): print klass ob = klass() print "generate key" - rep_bench(ob.gen, 800, UNITS_PER_SECOND=1000, MAXTIME=MAXTIME, MAXREPS=100) + rep_bench(ob.gen, 1000, UNITS_PER_SECOND=1000, MAXTIME=MAXTIME, MAXREPS=100) print "sign" - rep_bench(ob.sign, 8, UNITS_PER_SECOND=1000, initfunc=ob.sign_init, MAXTIME=MAXTIME, MAXREPS=100) + rep_bench(ob.sign, 1000, UNITS_PER_SECOND=1000, initfunc=ob.sign_init, MAXTIME=MAXTIME, MAXREPS=100) print "verify" - rep_bench(ob.ver, 4, UNITS_PER_SECOND=1000, initfunc=ob.ver_init, MAXTIME=MAXTIME, MAXREPS=100) + rep_bench(ob.ver, 1000, UNITS_PER_SECOND=1000, initfunc=ob.ver_init, MAXTIME=MAXTIME, MAXREPS=100) print for klass in [RSA2048, RSA3248]: @@ -212,9 +212,9 @@ def bench_sigs(MAXTIME): print "generate key" rep_bench(ob.gen, 1, UNITS_PER_SECOND=1000, MAXTIME=MAXTIME, MAXREPS=100) print "sign" - rep_bench(ob.sign, 8, UNITS_PER_SECOND=1000, initfunc=ob.sign_init, MAXTIME=MAXTIME, MAXREPS=100) + rep_bench(ob.sign, 1000, UNITS_PER_SECOND=1000, initfunc=ob.sign_init, MAXTIME=MAXTIME, MAXREPS=100) print "verify" - rep_bench(ob.ver, 4, UNITS_PER_SECOND=1000, initfunc=ob.ver_init, MAXTIME=MAXTIME, MAXREPS=100) + rep_bench(ob.ver, 10000, UNITS_PER_SECOND=1000, initfunc=ob.ver_init, MAXTIME=MAXTIME, MAXREPS=100) print print "milliseconds per operation" From 3eb69a5c090da0f462d4b5200b38b9d488a7eb05 Mon Sep 17 00:00:00 2001 From: Zooko O'Whielacronx Date: Sun, 1 Apr 2012 07:25:11 -0600 Subject: [PATCH 15/24] bench: it turns out that hashing or ciphering even 1 MB of data is too fast to measure; use 10 MB instead --- src/pycryptopp/bench/bench_ciphers.py | 3 +-- src/pycryptopp/bench/bench_hashes.py | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/pycryptopp/bench/bench_ciphers.py b/src/pycryptopp/bench/bench_ciphers.py index cc12338..fb86cf5 100644 --- a/src/pycryptopp/bench/bench_ciphers.py +++ b/src/pycryptopp/bench/bench_ciphers.py @@ -29,8 +29,7 @@ def bench_ciphers(MAXTIME): ob = BenchCrypt(klass, keysize) print ob for (legend, size) in [ - ("large (%d B)", 10**6), - ("huge (%d B)", 10**7), + ("large (%d B)", 10**7), ]: print legend % size rep_bench(ob.crypt, size, UNITS_PER_SECOND=UNITS_PER_SECOND, MAXTIME=MAXTIME, MAXREPS=100, initfunc=ob.crypt_init) diff --git a/src/pycryptopp/bench/bench_hashes.py b/src/pycryptopp/bench/bench_hashes.py index ba261e5..a4e3c8d 100644 --- a/src/pycryptopp/bench/bench_hashes.py +++ b/src/pycryptopp/bench/bench_hashes.py @@ -35,8 +35,7 @@ def bench_hashes(MAXTIME): print klass ob = klass() for (legend, size) in [ - ("large (%d B)", 10**6), - ("huge (%d B)", 10**7), + ("large (%d B)", 10**7), ]: print legend % size rep_bench(ob.proc, size, UNITS_PER_SECOND=UNITS_PER_SECOND, MAXTIME=MAXTIME, MAXREPS=100, initfunc=ob.proc_init) From c0b4b3059bd1e4a0463f9f635e3d7971c93fa04b Mon Sep 17 00:00:00 2001 From: Zooko O'Whielacronx Date: Sun, 1 Apr 2012 07:25:51 -0600 Subject: [PATCH 16/24] bench: remove comparison of time.time() vs. time.clock(); use time.clock() on Windows but not on Cygwin --- src/pycryptopp/bench/common.py | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/src/pycryptopp/bench/common.py b/src/pycryptopp/bench/common.py index c3da8b1..7a90572 100644 --- a/src/pycryptopp/bench/common.py +++ b/src/pycryptopp/bench/common.py @@ -1,58 +1,52 @@ msg = "crypto libraries should come with benchmarks" try: - raise ImportError import pyutil.benchutil rep_bench = pyutil.benchutil.rep_bench except (ImportError, AttributeError): + import platform, time + if 'windows' in platform.system().lower(): + clock = time.clock + else: + clock = time.time + def this_rep_bench(func, N, UNITS_PER_SECOND, MAXTIME, MAXREPS, initfunc=None): - import time tt = time.time - tc = time.clock if initfunc is not None: initfunc(N) - meant = 0 meanc = 0 MAXREPS = 100 timeout = tt() + MAXTIME for i in range(MAXREPS): - startt = tt() - startc = tc() + startc = clock() func(N) - stopt = time.time() - stopc = time.clock() + stopc = clock() - deltat = stopt - startt deltac = stopc - startc - if (deltat <= 0) or (deltac <= 0) or (abs(deltat - deltac) > 0.001): - print "startt: %s, stopt: %s, deltat: %s, startc: %s, stopc: %s, deltac: %s, ddelta: %s" % (startt, stopt, deltat, startc, stopc, deltac, deltac-deltat) - - meant += deltat - meanc += deltac + if deltac <= 0: + print "clock jump backward or wrapped -- ignoring this sample. startc: %s, stopc: %s, deltac: %s" % (startc, stopc, deltac,) + else: + meanc += deltac - if stopt >= timeout: + if time.time() >= timeout: break num = i+1 - meant *= UNITS_PER_SECOND - meant /= num - meant /= N meanc *= UNITS_PER_SECOND meanc /= num meanc /= N res = { - 'meant': meant, 'meanc': meanc, 'num': num } - print "mean: %(meant)#8.03e or %(meanc)#8.03e (of %(num)6d)" % res + print "mean: %(meanc)#8.03e (of %(num)6d)" % res rep_bench = this_rep_bench try: From 10138f47740d23c765ac9d7c56c4973813049e08 Mon Sep 17 00:00:00 2001 From: Zooko O'Whielacronx Date: Sun, 1 Apr 2012 07:40:02 -0600 Subject: [PATCH 17/24] remove Null and Sleep signers which were for calibrating clocks --- src/pycryptopp/bench/bench_sigs.py | 50 +----------------------------- 1 file changed, 1 insertion(+), 49 deletions(-) diff --git a/src/pycryptopp/bench/bench_sigs.py b/src/pycryptopp/bench/bench_sigs.py index 35e9c7a..40746d2 100644 --- a/src/pycryptopp/bench/bench_sigs.py +++ b/src/pycryptopp/bench/bench_sigs.py @@ -60,54 +60,6 @@ def ver(self, N): for i in xrange(N): verifier.verify(sig, msg) -import time -class SleepSign(object): - def __init__(self): - pass - - def gen(self, N): - time.sleep(N*self.SLEEPINESS) - - def sign_init(self, N): - pass - - def sign(self, N): - time.sleep(N*self.SLEEPINESS) - - def ver_init(self, N): - pass - - def ver(self, N): - time.sleep(N*self.SLEEPINESS) - -class Sleep10msSign(SleepSign): - SLEEPINESS = 0.01 - -class Sleep10usSign(SleepSign): - SLEEPINESS = 0.00001 - -class NullSign(object): - def __init__(self): - pass - - def gen(self, N): - for i in xrange(N): - pass - - def sign_init(self, N): - pass - - def sign(self, N): - for i in xrange(N): - pass - - def ver_init(self, N): - pass - - def ver(self, N): - for i in xrange(N): - pass - class Ed25519(object): def __init__(self): self.seed = insecurerandstr(32) @@ -195,7 +147,7 @@ def ver(self, N): verifier.verify(msg, sig) def bench_sigs(MAXTIME): - for klass in [ECDSA256, Ed25519, NullSign, Sleep10msSign, Sleep10usSign]: + for klass in [ECDSA256, Ed25519,]: print klass ob = klass() print "generate key" From 8bb096bf7ebe1a995d90534d7e988014cd12b792 Mon Sep 17 00:00:00 2001 From: Zooko O'Whielacronx Date: Wed, 28 Nov 2012 15:03:06 -0700 Subject: [PATCH 18/24] show-tool-versions.py: print out L1 cache line size (on Linux, at least) --- misc/build_helpers/show-tool-versions.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/misc/build_helpers/show-tool-versions.py b/misc/build_helpers/show-tool-versions.py index 5011a7b..4a0e62d 100644 --- a/misc/build_helpers/show-tool-versions.py +++ b/misc/build_helpers/show-tool-versions.py @@ -127,6 +127,21 @@ def print_py_pkg_ver(pkgname, modulename=None): except AttributeError: pass +def print_cache_line_size(): + label = "cache line size" + try: + result = open('/sys/devices/system/cpu/cpu0/cache/index0/coherency_line_size', 'rU').read().strip() + except EnvironmentError, e: + if isinstance(e, OSError) and e.errno == 2: + print label + ': no such file or directory' + return + sys.stderr.write("\nGot exception trying to read cache line sizes out of /sys/. Exception follows.\n") + traceback.print_exc(file=sys.stderr) + sys.stderr.flush() + pass + else: + print label + ': ' + result + print_platform() print print_python_ver() @@ -157,3 +172,5 @@ def print_py_pkg_ver(pkgname, modulename=None): print_py_pkg_ver('pyOpenSSL', 'OpenSSL') print_py_pkg_ver('pycryptopp') print_py_pkg_ver('crpyto') + +print_cache_line_size() From 3866382329aeabc43798aba51f6f354c37a81c79 Mon Sep 17 00:00:00 2001 From: Zooko O'Whielacronx Date: Mon, 11 Mar 2013 04:48:14 +0000 Subject: [PATCH 19/24] improved suppressions file for valgrind+python I've learned how to glob function names and leave ellipses in call stacks, so now this file suppresses all bogus warnings on my Ubuntu x86_64 laptop. --- misc/coding_helpers/python.supp | 130 ++++++++++++++++++++++---------- 1 file changed, 91 insertions(+), 39 deletions(-) diff --git a/misc/coding_helpers/python.supp b/misc/coding_helpers/python.supp index 712785c..6d219e3 100644 --- a/misc/coding_helpers/python.supp +++ b/misc/coding_helpers/python.supp @@ -49,45 +49,24 @@ { luther sid addr4 realloc Memcheck:Addr4 - fun:PyObject_Realloc.part.0.20700 + fun:PyObject_Realloc.* } { luther sid cond realloc Memcheck:Cond - fun:PyObject_Realloc.part.0.20700 + fun:PyObject_Realloc.* } { luther sid value4 realloc Memcheck:Value4 - fun:PyObject_Realloc.part.0.20700 + fun:PyObject_Realloc.* } -# generated on luther sid with "python: 2.7.3rc2 (default, Mar 21 2012, 16:14:45) [GCC 4.6.3]" -# e.g. https://tahoe-lafs.org/buildbot-pycryptopp/builders/luther%20sid/builds/106/steps/test%20valgrind/logs/valgrind -{ - luther sid addr4 realloc - Memcheck:Addr4 - fun:PyObject_Realloc.part.0.20707 -} - -{ - luther sid cond realloc - Memcheck:Cond - fun:PyObject_Realloc.part.0.20707 -} - -{ - luther sid value4 realloc - Memcheck:Value4 - fun:PyObject_Realloc.part.0.20707 -} - - # glibc was apparently changed to avoid this: http://sources.redhat.com/bugzilla/show_bug.cgi?id=4306 { - use (not really, according to Ulrich Drepper) of uninitailised bytes by glibc in utimes() + use (not really, according to Ulrich Drepper) of uninitialised bytes by glibc in utimes() Memcheck:Param utimes(tvp[1]) fun:utimes @@ -193,7 +172,7 @@ { ADDRESS_IN_RANGE/Invalid read of size 8 Memcheck:Value8 - fun:PyObject_Realloc + fun:PyObject_Realloc.* } { @@ -202,15 +181,95 @@ fun:PyObject_Realloc } +{ + python mem management stuff I assume + Memcheck:Addr4 + obj:/usr/bin/python2.7 + fun:_PyObject_GC_Resize + fun:PyFrame_New +} + +{ + more python mem management stuff I assume + Memcheck:Cond + obj:/usr/bin/python2.7 + fun:_PyObject_GC_Resize + fun:PyFrame_New +} + +{ + more python mem management stuff I assume + Memcheck:Value8 + obj:/usr/bin/python2.7 + fun:_PyObject_GC_Resize + fun:PyFrame_New +} + +{ + more python mem management stuff I assume + Memcheck:Addr4 + obj:/usr/bin/python2.7 + fun:_PyString_Resize +} + +{ + more python mem management stuff I assume + Memcheck:Cond + obj:/usr/bin/python2.7 + fun:_PyString_Resize +} + +{ + more python mem management stuff I assume + Memcheck:Value8 + obj:/usr/bin/python2.7 + fun:_PyString_Resize +} + +{ + more python mem management stuff I assume + Memcheck:Cond + obj:/usr/bin/python2.7 + fun:PyNode_AddChild +} + +{ + more python mem management stuff I assume + Memcheck:Value8 + obj:/usr/bin/python2.7 + fun:PyNode_AddChild +} + +{ + more python mem management stuff I assume + Memcheck:Addr4 + obj:/usr/bin/python2.7 + fun:PyNode_AddChild +} + +{ + more python mem management stuff I assume + Memcheck:Addr4 + obj:/usr/bin/python2.7 + ... + obj:/usr/bin/python2.7 + fun:PyAST_Compile +} + +{ + more python mem management stuff I assume + Memcheck:Addr4 + obj:/usr/bin/python2.7 + ... + obj:/usr/bin/python2.7 + fun:PyAST_Compile +} + { some unknown problem in python getdynloadfunc Memcheck:Addr8 obj:/lib/ld-2.7.so - obj:/lib/ld-2.7.so - obj:/lib/ld-2.7.so - obj:/lib/ld-2.7.so - obj:/lib/ld-2.7.so - obj:/lib/ld-2.7.so + ... obj:/lib/ld-2.7.so obj:/lib/libdl-2.7.so obj:/lib/ld-2.7.so @@ -223,14 +282,7 @@ some other unknown problem in python libdl stuff Memcheck:Addr8 obj:/lib/ld-2.7.so - obj:/lib/ld-2.7.so - obj:/lib/ld-2.7.so - obj:/lib/ld-2.7.so - obj:/lib/ld-2.7.so - obj:/lib/ld-2.7.so - obj:/lib/ld-2.7.so - obj:/lib/ld-2.7.so - obj:/lib/ld-2.7.so + ... obj:/lib/ld-2.7.so obj:/lib/libdl-2.7.so obj:/lib/ld-2.7.so From a7f5955a576734396a54f5c10497c84018022691 Mon Sep 17 00:00:00 2001 From: Zooko O'Whielacronx Date: Mon, 11 Mar 2013 04:51:28 +0000 Subject: [PATCH 20/24] several extra self-checks in rsa.cpp This is for https://tahoe-lafs.org/trac/tahoe-lafs/ticket/1924#comment:7 . --- src-cryptopp/rsa.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src-cryptopp/rsa.cpp b/src-cryptopp/rsa.cpp index 59449c4..fa7eef9 100644 --- a/src-cryptopp/rsa.cpp +++ b/src-cryptopp/rsa.cpp @@ -1,5 +1,6 @@ // rsa.cpp - written and placed in the public domain by Wei Dai +#include #include "pch.h" #include "rsa.h" #include "asn.h" @@ -223,13 +224,27 @@ void InvertibleRSAFunction::DEREncodePrivateKey(BufferedTransformation &bt) cons Integer InvertibleRSAFunction::CalculateInverse(RandomNumberGenerator &rng, const Integer &x) const { DoQuickSanityCheck(); + Validate(rng, 2); ModularArithmetic modn(m_n); - Integer r, rInv; + Integer r, rInv, rDoubleCheck, rTripleCheck; do { // do this in a loop for people using small numbers for testing r.Randomize(rng, Integer::One(), m_n - Integer::One()); + rDoubleCheck = r + Integer::One(); // The +1 is just to make sure nobody's doing tricksy aliasing instead of making rDoubleCheck be a true bitwise copy of r, which is what we need. + //std::cout << "Hi I just generated a random r and it is " << r << std::endl; + if (r.IsZero()) + throw Exception(Exception::OTHER_ERROR, "InvertibleRSAFunction: internal error in Randomize() -- it returned 0 when asked for something from [1, n)."); + if (r == m_p) + throw Exception(Exception::OTHER_ERROR, "InvertibleRSAFunction: internal error in Randomize() -- it returned p when asked for something from [1, n)."); + if (r == m_q) + throw Exception(Exception::OTHER_ERROR, "InvertibleRSAFunction: internal error in Randomize() -- it returned q when asked for something from [1, n)."); rInv = modn.MultiplicativeInverse(r); + rTripleCheck = modn.MultiplicativeInverse(rInv) + Integer::One(); + if (rDoubleCheck != rTripleCheck) + throw Exception(Exception::OTHER_ERROR, "InvertibleRSAFunction: internal error in Randomize() -- inv(inv(r)) != r (because r changed after Randomize() had returned?)."); } while (rInv.IsZero()); Integer re = modn.Exponentiate(r, m_e); + if (rDoubleCheck != (r + Integer::One())) + throw Exception(Exception::OTHER_ERROR, "InvertibleRSAFunction: internal error in Randomize() -- r changed after Randomize() had returned?."); re = modn.Multiply(re, x); // blind // here we follow the notation of PKCS #1 and let u=q inverse mod p // but in ModRoot, u=p inverse mod q, so we reverse the order of p and q From 0a2474fca518f7380801d4fc599ee0c859e7ff44 Mon Sep 17 00:00:00 2001 From: Zooko O'Whielacronx Date: Thu, 11 Apr 2013 00:50:20 -0600 Subject: [PATCH 21/24] test for overrun of the output buffer when reading from /dev/urandom --- src-cryptopp/osrng.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src-cryptopp/osrng.cpp b/src-cryptopp/osrng.cpp index fa6dd36..f86762f 100644 --- a/src-cryptopp/osrng.cpp +++ b/src-cryptopp/osrng.cpp @@ -83,8 +83,16 @@ void NonblockingRng::GenerateBlock(byte *output, size_t size) if (!CryptGenRandom(m_Provider.GetProviderHandle(), (DWORD)size, output)) throw OS_RNG_Err("CryptGenRandom"); #else - if (read(m_fd, output, size) != size) + byte tmpbuf[size * 2]; + size_t i; + for (i = size ; i < size * 2; i++) + tmpbuf[i] = i; + if (read(m_fd, tmpbuf, size) != size) throw OS_RNG_Err("read /dev/urandom"); + for (i = size ; i < size * 2; i++) + if (tmpbuf[i] != i) + throw OS_RNG_Err("read /dev/urandom overran buffer"); + memcpy(output, tmpbuf, size); #endif } From 2a38bfd4b4ab714d5f624a4e505993b6aec4418b Mon Sep 17 00:00:00 2001 From: Zooko O'Whielacronx Date: Thu, 11 Apr 2013 01:23:17 -0600 Subject: [PATCH 22/24] always define CRYPTOPP_DISABLE_ASM=1 (see https://tahoe-lafs.org/trac/pycryptopp/ticket/85 ) --- setup.py | 28 +--------------------------- 1 file changed, 1 insertion(+), 27 deletions(-) diff --git a/setup.py b/setup.py index 238f22a..3e5f20c 100644 --- a/setup.py +++ b/setup.py @@ -137,33 +137,7 @@ extra_srcs.extend(cryptopp_src) -# In either case, we must provide a value for CRYPTOPP_DISABLE_ASM that -# matches the one used when Crypto++ was originally compiled. The Crypto++ -# GNUmakefile tests the assembler version and only enables assembly for -# recent versions of the GNU assembler (2.10 or later). The /usr/bin/as on -# Mac OS-X 10.6 is too old. - -try: - sp = subprocess.Popen(['as', '-v'], stdin=subprocess.PIPE, - stdout=subprocess.PIPE, stderr=subprocess.PIPE, - universal_newlines=True) - sp.stdin.close() - sp.wait() - if re.search("GNU assembler version (0|1|2.0)", sp.stderr.read()): - define_macros.append(('CRYPTOPP_DISABLE_ASM', 1)) -except EnvironmentError: - # Okay, nevermind. Maybe there isn't even an 'as' executable on this - # platform. - pass -else: - try: - # that "as -v" step creates an empty a.out, so clean it up. Modern GNU - # "as" has --version, which emits the version number without actually - # assembling anything, but older versions only have -v, which emits a - # version number and *then* assembles from stdin. - os.unlink("a.out") - except EnvironmentError: - pass +define_macros.append(('CRYPTOPP_DISABLE_ASM', 1)) trove_classifiers=[ "Environment :: Console", From 5c2e0f729a25eee8f374ff79a9299a818c378bc2 Mon Sep 17 00:00:00 2001 From: Zooko O'Whielacronx Date: Fri, 12 Apr 2013 02:31:38 -0600 Subject: [PATCH 23/24] disable asm only when we're building the embedded libcryptopp --- setup.py | 26 +++++--------------------- 1 file changed, 5 insertions(+), 21 deletions(-) diff --git a/setup.py b/setup.py index 3e5f20c..0760491 100644 --- a/setup.py +++ b/setup.py @@ -1,11 +1,11 @@ # -*- coding: utf-8 -*- -# Copyright © 2009-2012 Zooko Wilcox-O'Hearn +# Copyright © 2009-2013 Zooko Wilcox-O'Hearn # Author: Zooko Wilcox-O'Hearn # # See README.rst for licensing information. -import os, platform, re, subprocess, sys +import os, platform, re, sys from setuptools import Extension, setup from setuptools import Command @@ -106,28 +106,14 @@ else: # Build the bundled Crypto++ library which is included by source # code in the pycryptopp tree and link against it. + define_macros.append(('CRYPTOPP_DISABLE_ASM', 1)) + include_dirs.append(".") if 'sunos' in platform.system().lower(): extra_compile_args.append('-Wa,--divide') # allow use of "/" operator - if 'win32' in sys.platform.lower(): - try: - res = subprocess.Popen(['cl'], stdin=open(os.devnull), stdout=subprocess.PIPE).communicate() - except EnvironmentError, le: - # Okay I guess we're not using the "cl.exe" compiler. - using_msvc = False - else: - using_msvc = True - else: - using_msvc = False - - if using_msvc: - # We can handle out-of-line assembly. - cryptopp_src = [ os.path.join(EMBEDDED_CRYPTOPP_DIR, x) for x in os.listdir(EMBEDDED_CRYPTOPP_DIR) if x.endswith(('.cpp', '.asm')) ] - else: - # We can't handle out-of-line assembly. - cryptopp_src = [ os.path.join(EMBEDDED_CRYPTOPP_DIR, x) for x in os.listdir(EMBEDDED_CRYPTOPP_DIR) if x.endswith('.cpp') ] + cryptopp_src = [ os.path.join(EMBEDDED_CRYPTOPP_DIR, x) for x in os.listdir(EMBEDDED_CRYPTOPP_DIR) if x.endswith('.cpp') ] # Mac OS X extended attribute files when written to a non-Mac-OS-X # filesystem come out as "._$FNAME", for example "._rdtables.cpp", @@ -137,8 +123,6 @@ extra_srcs.extend(cryptopp_src) -define_macros.append(('CRYPTOPP_DISABLE_ASM', 1)) - trove_classifiers=[ "Environment :: Console", "License :: OSI Approved :: GNU General Public License (GPL)", # See README.rst for alternative licensing. From 417e746799795d8dca810ef2313ce7294516798c Mon Sep 17 00:00:00 2001 From: Zooko O'Whielacronx Date: Sat, 13 Apr 2013 13:30:31 -0600 Subject: [PATCH 24/24] remove ecdsa -- it has been replaced by ed25519 --- README.rst | 2 - setup.py | 5 - src/pycryptopp/_pycryptoppmodule.cpp | 4 +- src/pycryptopp/bench/bench_sigs.py | 32 +- src/pycryptopp/publickey/__init__.py | 4 +- src/pycryptopp/publickey/ecdsa.py | 5 - src/pycryptopp/publickey/ecdsamodule.cpp | 521 ----------------------- src/pycryptopp/publickey/ecdsamodule.hpp | 7 - src/pycryptopp/test/test_ecdsa.py | 258 ----------- 9 files changed, 5 insertions(+), 833 deletions(-) delete mode 100644 src/pycryptopp/publickey/ecdsa.py delete mode 100644 src/pycryptopp/publickey/ecdsamodule.cpp delete mode 100644 src/pycryptopp/publickey/ecdsamodule.hpp delete mode 100644 src/pycryptopp/test/test_ecdsa.py diff --git a/README.rst b/README.rst index a113b9e..047651c 100644 --- a/README.rst +++ b/README.rst @@ -25,8 +25,6 @@ supporting them. • RSA from the Crypto++ library ; see pycryptopp.publickey.rsa ; deprecated in favor of Ed25519 -• Ecdsa from the Crypto++ library ; see pycryptopp.publickey.ecdsa ; - deprecated in favor of Ed25519 • SHA-256 from the Crypto++ library ; see pycryptopp.hash.sha256 ; deprecated in favor of the Python Standard Library's hashlib module diff --git a/setup.py b/setup.py index 0760491..dff6446 100644 --- a/setup.py +++ b/setup.py @@ -18,9 +18,6 @@ import versioneer -# ECDSA=False -ECDSA=True - DEBUG=False if "--debug" in sys.argv: DEBUG=True @@ -150,8 +147,6 @@ 'src/pycryptopp/cipher/aesmodule.cpp', 'src/pycryptopp/cipher/xsalsa20module.cpp', ] -if ECDSA: - srcs.append('src/pycryptopp/publickey/ecdsamodule.cpp') if BUILD_DOUBLE_LOAD_TESTER: srcs.append('_doubleloadtester.cpp', ) diff --git a/src/pycryptopp/_pycryptoppmodule.cpp b/src/pycryptopp/_pycryptoppmodule.cpp index 1c99817..b299a27 100644 --- a/src/pycryptopp/_pycryptoppmodule.cpp +++ b/src/pycryptopp/_pycryptoppmodule.cpp @@ -1,6 +1,5 @@ #include -#include "publickey/ecdsamodule.hpp" #include "publickey/rsamodule.hpp" #include "hash/sha256module.hpp" #include "cipher/aesmodule.hpp" @@ -17,7 +16,7 @@ PyDoc_STRVAR(_pycryptopp__doc__, "_pycryptopp -- Python wrappers for a few algorithms from Crypto++\n\ \n\ from pycryptopp import publickey\n\ -from pycryptopp.publickey import ecdsa\n\ +from pycryptopp.publickey import ed25519\n\ from pycryptopp.publickey import rsa\n\ from pycryptopp import cipher\n\ from pycryptopp.cipher import aes\n\ @@ -64,7 +63,6 @@ init_pycryptopp(void) { return; - init_ecdsa(module); init_rsa(module); init_sha256(module); init_aes(module); diff --git a/src/pycryptopp/bench/bench_sigs.py b/src/pycryptopp/bench/bench_sigs.py index 40746d2..9a929b5 100644 --- a/src/pycryptopp/bench/bench_sigs.py +++ b/src/pycryptopp/bench/bench_sigs.py @@ -1,37 +1,9 @@ -from pycryptopp.publickey import ecdsa, ed25519, rsa +from pycryptopp.publickey import ed25519, rsa from common import insecurerandstr, rep_bench, print_bench_footer msg = 'crypto libraries should come with benchmarks' -class ECDSA256(object): - def __init__(self): - self.seed = insecurerandstr(32) - self.signer = None - - def gen(self, N): - for i in xrange(N): - ecdsa.SigningKey(self.seed) - - def sign_init(self, N): - self.signer = ecdsa.SigningKey(self.seed) - - def sign(self, N): - signer = self.signer - for i in xrange(N): - signer.sign(msg) - - def ver_init(self, N): - signer = ecdsa.SigningKey(self.seed) - self.sig = signer.sign(msg) - self.verifier = signer.get_verifying_key() - - def ver(self, N): - sig = self.sig - verifier = self.verifier - for i in xrange(N): - verifier.verify(sig, msg) - class Ed25519(object): def __init__(self): self.seed = insecurerandstr(32) @@ -147,7 +119,7 @@ def ver(self, N): verifier.verify(msg, sig) def bench_sigs(MAXTIME): - for klass in [ECDSA256, Ed25519,]: + for klass in [Ed25519,]: print klass ob = klass() print "generate key" diff --git a/src/pycryptopp/publickey/__init__.py b/src/pycryptopp/publickey/__init__.py index be9d7ad..178f3c0 100644 --- a/src/pycryptopp/publickey/__init__.py +++ b/src/pycryptopp/publickey/__init__.py @@ -1,3 +1,3 @@ -import ecdsa, rsa, ed25519 +import rsa, ed25519 -quiet_pyflakes=[ecdsa, rsa, ed25519] +quiet_pyflakes=[rsa, ed25519] diff --git a/src/pycryptopp/publickey/ecdsa.py b/src/pycryptopp/publickey/ecdsa.py deleted file mode 100644 index c25ba33..0000000 --- a/src/pycryptopp/publickey/ecdsa.py +++ /dev/null @@ -1,5 +0,0 @@ -from pycryptopp import _import_my_names - -_import_my_names(globals(), "ecdsa_") - -del _import_my_names diff --git a/src/pycryptopp/publickey/ecdsamodule.cpp b/src/pycryptopp/publickey/ecdsamodule.cpp deleted file mode 100644 index ab18a50..0000000 --- a/src/pycryptopp/publickey/ecdsamodule.cpp +++ /dev/null @@ -1,521 +0,0 @@ -/** -* Things to do: -* Make it work and pass tests. -* compressed pub keys -- check out Wei Dai's example code on mailinglist as linked to from pycryptopp trac by Brian -* Make new KDF (standard, Crypto++-compatible). -* in C++ -* in Python -* use Crypto++ Randomize()'s -* provide RNG class which is P1363-SHA-256 - -* Profit! -* Migrate pair-programming to Bespin. -* Put a Tahoe backend under Bespin. -*/ - -/** - * ecdsamodule.cpp -- Python wrappers around Crypto++'s - * ECDSA(1363)/EMSA1(SHA-256) -- ECDSA. - * - * The keys (256-bit) use the curve ASN1::secp256r1() and SHA-256 as the - * hash function. The Key Derivation Protocol is P1363_KDF2 - * http://www.users.zetnet.co.uk/hopwood/crypto/scan/prf.html#KDF2 - * to generate private (signing) keys from unguessable seeds -- see - * source code for details and doc string for usage. - */ - -#define PY_SSIZE_T_CLEAN -#include -#if (PY_VERSION_HEX < 0x02050000) -typedef int Py_ssize_t; -#endif - -#include - -#include "ecdsamodule.hpp" - -/* from Crypto++ */ -#ifdef DISABLE_EMBEDDED_CRYPTOPP -#include -#include -#include -#include -#include -#include -// only needed for debugging -- the _dump() function -#include -#include -#include -#else -#include -#include -#include -#include -#include -#include -// only needed for debugging -- the _dump() function -#include -#include -#include -#endif - -static const int KEY_SIZE_BITS=256; - -USING_NAMESPACE(CryptoPP) - -static const char*const ecdsa___doc__ = "ecdsa -- ECDSA(1363)/EMSA1(SHA-256) signatures\n\ -\n\ -To create a new ECDSA signing key (deterministically from a 32-byte seed), construct an instance of the class, passing the seed as argument, i.e. SigningKey(seed).\n\ -\n\ -To get a verifying key from a signing key, call get_verifying_key() on the signing key instance.\n\ -\n\ -To deserialize an ECDSA verifying key from a string, call VerifyingKey(serialized_verifying_key)."; - -static PyObject *ecdsa_error; - -typedef struct { - PyObject_HEAD - - /* internal */ - ECDSA::Verifier *k; -} VerifyingKey; - -PyDoc_STRVAR(VerifyingKey__doc__, -"an ECDSA verifying key"); - -static int -VerifyingKey___init__(PyObject* self, PyObject* args, PyObject* kwdict) { - static const char *kwlist[] = { "serializedverifyingkey", NULL }; - const char *serializedverifyingkey; - Py_ssize_t serializedverifyingkeysize = 0; - - if (!PyArg_ParseTupleAndKeywords(args, kwdict, "t#:VerifyingKey__init__", const_cast(kwlist), &serializedverifyingkey, &serializedverifyingkeysize)) - return NULL; - assert (serializedverifyingkeysize >= 0); - - if (serializedverifyingkeysize != 33) { - PyErr_Format(ecdsa_error, "Precondition violation: size in bits is required to be %d (for %d-bit key), but it was %d", 33, KEY_SIZE_BITS, serializedverifyingkeysize); - return -1; - } - - VerifyingKey *mself = reinterpret_cast(self); - - StringSource ss(reinterpret_cast(serializedverifyingkey), serializedverifyingkeysize, true); - - ECP::Element element; - DL_GroupParameters_EC params(ASN1::secp256r1()); - params.SetPointCompression(true); - try { - element = params.DecodeElement(reinterpret_cast(serializedverifyingkey), true); - mself->k = new ECDSA::Verifier(params, element); - if (!mself->k) { - PyErr_NoMemory(); - return -1; - } - } catch (InvalidDataFormat le) { - PyErr_Format(ecdsa_error, "Serialized verifying key was corrupted. Crypto++ gave this exception: %s", le.what()); - return -1; - } - - return 0; -} - -static void -VerifyingKey_dealloc(VerifyingKey* self) { - if (self->k) - delete self->k; - self->ob_type->tp_free((PyObject*)self); -} - -static PyObject * -VerifyingKey_verify(VerifyingKey *self, PyObject *args, PyObject *kwdict) { - static const char *kwlist[] = { "msg", "signature", NULL }; - const char *msg; - Py_ssize_t msgsize; - const char *signature; - Py_ssize_t signaturesize = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwdict, "t#t#:verify", const_cast(kwlist), &msg, &msgsize, &signature, &signaturesize)) - return NULL; - assert (msgsize >= 0); - assert (signaturesize >= 0); - - if (self->k->VerifyMessage(reinterpret_cast(msg), msgsize, reinterpret_cast(signature), signaturesize)) - Py_RETURN_TRUE; - else - Py_RETURN_FALSE; -} - -PyDoc_STRVAR(VerifyingKey_verify__doc__, -"Return whether the signature is a valid signature on the msg."); - -static PyObject * -VerifyingKey_serialize(VerifyingKey *self, PyObject *dummy) { - ECDSA::Verifier *pubkey; - pubkey = new ECDSA::Verifier(*(self->k)); - const DL_GroupParameters_EC& params = pubkey->GetKey().GetGroupParameters(); - - Py_ssize_t len = params.GetEncodedElementSize(true); - PyObject* result = PyString_FromStringAndSize(NULL, len); - if (!result) - return NULL; - - params.EncodeElement(true, pubkey->GetKey().GetPublicElement(), - reinterpret_cast(PyString_AS_STRING(result))); - - return result; -} - -PyDoc_STRVAR(VerifyingKey_serialize__doc__, -"Return a string containing the key material. The string can be passed to \n\ -the constructor of VerifyingKey to instantiate a new copy of this key."); - -static PyMethodDef VerifyingKey_methods[] = { - {"verify", reinterpret_cast(VerifyingKey_verify), METH_KEYWORDS, VerifyingKey_verify__doc__}, - {"serialize", reinterpret_cast(VerifyingKey_serialize), METH_NOARGS, VerifyingKey_serialize__doc__}, - {NULL}, -}; - -static PyTypeObject VerifyingKey_type = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "ecdsa.VerifyingKey", /*tp_name*/ - sizeof(VerifyingKey), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)VerifyingKey_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - VerifyingKey__doc__, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - VerifyingKey_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - VerifyingKey___init__, /* tp_init */ -}; - -typedef struct { - PyObject_HEAD - - /* internal */ - ECDSA::Signer *k; -} SigningKey; - -static void -SigningKey_dealloc(SigningKey* self) { - if (self->k) - delete self->k; - self->ob_type->tp_free((PyObject*)self); -} - -static const char* TAG_AND_SALT = "102:pycryptopp v0.5.3 key derivation algorithm using SHA-256 hash to generate ECDSA 256-bit secret exponents," \ - "16:H1yGNvUONoc0FD1d,"; -static const size_t TAG_AND_SALT_len = 127; - -/** copied from Crypto++'s integer.cpp */ -/** The following is in Crypto++'s integer.cpp and we use them: -* void Integer::Randomize(RandomNumberGenerator &rng, size_t nbits) -* { -* const size_t nbytes = nbits/8 + 1; -* SecByteBlock buf(nbytes); -* rng.GenerateBlock(buf, nbytes); -* if (nbytes) -* buf[0] = (byte)Crop(buf[0], nbits % 8); -* Decode(buf, nbytes, UNSIGNED); -* } -* void Integer::Randomize(RandomNumberGenerator &rng, const Integer &min, const Integer &max) -* { -* if (min > max) -* throw InvalidArgument("Integer: Min must be no greater than Max"); -* -* Integer range = max - min; -* const unsigned int nbits = range.BitCount(); -* -* do -* { -* Randomize(rng, nbits); -* } -* while (*this > range); -* -* *this += min; -* } -* -*/ - -static int -SigningKey___init__(PyObject* self, PyObject* args, PyObject* kwdict) { - static const char *kwlist[] = { "seed", NULL }; - const char* seed; - Py_ssize_t seedlen; - if (!PyArg_ParseTupleAndKeywords(args, kwdict, "t#:SigningKey___init__", const_cast(kwlist), &seed, &seedlen)) { - return -1; - } - - if (seedlen != 32) { - PyErr_Format(ecdsa_error, "Precondition violation: seed is required to be of length 32, but it was %zd", seedlen); - return -1; - } - - OID curve; - Integer grouporderm1; - byte privexpbytes[32] = {0}; - Integer privexponentm1; - privexponentm1.Decode(privexpbytes, sizeof(privexpbytes)); assert (privexponentm1 == 0); // just checking.. - - DL_GroupParameters_EC params(ASN1::secp256r1()); - params.SetPointCompression(true); - grouporderm1 = params.GetGroupOrder() - 1; - SHA256 t; - - t.Update(reinterpret_cast(TAG_AND_SALT), TAG_AND_SALT_len); - t.Update(reinterpret_cast(seed), seedlen); - t.TruncatedFinal(privexpbytes, SHA256::DIGESTSIZE); - privexponentm1.Decode(privexpbytes, sizeof(privexpbytes)); - - while (privexponentm1 >= grouporderm1) { - SHA256 t2; - t2.Update(reinterpret_cast(TAG_AND_SALT), TAG_AND_SALT_len); - std::cerr << "WHEE " << sizeof(privexpbytes) << "\n";std::cerr.flush(); - t2.Update(privexpbytes, sizeof(privexpbytes)); - t2.TruncatedFinal(privexpbytes, SHA256::DIGESTSIZE); - privexponentm1.Decode(privexpbytes, sizeof(privexpbytes)); - } - - SigningKey* mself = reinterpret_cast(self); - - mself->k = new ECDSA::Signer(params, privexponentm1+1); - - if (!mself->k) { - PyErr_NoMemory(); - return -1; - } - - return 0; -} - -PyDoc_STRVAR(SigningKey__init____doc__, -"Create a signing key (256 bits) deterministically from the given seed.\n\ -\n\ -This implies that if someone can guess the seed then they can learn the signing key. A good way to get an unguessable seed is os.urandom(32).\n\ -\n\ -@param seed seed\n\ -\n\ -@precondition len(seed) >= ceil(sizeinbits/16.0)"); - -static PyObject * -SigningKey__dump(SigningKey *self, PyObject *dummy) { - const DL_GroupParameters_EC& gp = self->k->GetKey().GetGroupParameters(); - std::cout << "whee " << gp.GetEncodedElementSize(true) << "\a"; - std::cout << "booo " << gp.GetEncodedElementSize(false) << "\n"; - - ECPPoint p = gp.GetSubgroupGenerator(); - std::cout << "generator " << p.x << ", " << p.y << "\n"; - - std::cout << "GroupOrder: "; - std::cout << gp.GetGroupOrder(); - std::cout << "\n"; - - std::string s; - StringSink* ss = new StringSink(s); - HexEncoder he(ss); - std::cout << "AlgorithmID: "; - gp.GetAlgorithmID().DEREncode(he); - std::cout << s << "\n"; - - const ECP& ec = gp.GetCurve(); - Integer fieldsize = ec.FieldSize(); - std::cout << "field size " << fieldsize.BitCount() << " " << fieldsize.ByteCount() << " " << ec.FieldSize() << "\n"; - std::cout << "Curve: "; - std::cout << "curve field max element bit length: " << ec.GetField().MaxElementBitLength() << "\n"; - std::cout << "curve field modulus: " << ec.GetField().GetModulus() << "\n"; - std::cout << "curve A: " << ec.GetA() << ", curve B: " << ec.GetB(); - - const ECP::Field& f = ec.GetField(); - std::cout << "curve field modulus: " << f.GetModulus() << "\n"; - std::cout << "curve field identity: " << f.Identity() << "\n"; - - std::string cfs; - StringSink* cfss = new StringSink(cfs); - HexEncoder cfhe(cfss); - f.DEREncode(cfhe); - std::cout << "curve field derencoding: " << cfs << "\n"; - - const CryptoMaterial& cm = self->k->GetMaterial(); - Integer i; - cm.GetValue("SubgroupOrder", i); - std::cout << "\n"; - std::cout << "SubgroupOrder: "; - std::cout << i; - std::cout << "\n"; - ECP::Element e; - cm.GetValue("SubgroupGenerator", e); - std::cout << "SubgroupGenerator: "; - std::cout << e.x << ", " << e.y; - std::cout << "\n"; - - std::cout << "private key: "; - - const PrivateKey& privkey = self->k->GetPrivateKey(); - - std::cout << privkey.GetValueNames() << "\n"; - - Integer privi; - privkey.GetValue("PrivateExponent", privi); - std::cout << privi << "\n"; - std::cout << "numbits: " << privi.BitCount() << "\n"; - std::cout << "numbytes: " << privi.ByteCount() << "\n"; - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(SigningKey__dump__doc__, -"Print to stdout some descriptions of the math pieces."); - -static PyObject * -SigningKey_sign(SigningKey *self, PyObject *msgobj) { - const char *msg; - Py_ssize_t msgsize; - PyString_AsStringAndSize(msgobj, const_cast(&msg), reinterpret_cast(&msgsize)); - assert (msgsize >= 0); - - Py_ssize_t sigsize; - sigsize = self->k->SignatureLength(); - - PyStringObject* result = reinterpret_cast(PyString_FromStringAndSize(NULL, sigsize)); - if (!result) - return NULL; - assert (sigsize >= 0); - - AutoSeededRandomPool randpool(false); //XXX - - Py_ssize_t siglengthwritten; - try { - siglengthwritten = self->k->SignMessage( - randpool, - reinterpret_cast(msg), - msgsize, - reinterpret_cast(PyString_AS_STRING(result))); - } catch (InvalidDataFormat le) { - Py_DECREF(result); - return PyErr_Format(ecdsa_error, "Signing key was corrupted. Crypto++ gave this exception: %s", le.what()); - } - - if (siglengthwritten < sigsize) - fprintf(stderr, "%s: %d: %s: %s", __FILE__, __LINE__, "SigningKey_sign", "INTERNAL ERROR: signature was shorter than expected."); - else if (siglengthwritten > sigsize) { - fprintf(stderr, "%s: %d: %s: %s", __FILE__, __LINE__, "SigningKey_sign", "INTERNAL ERROR: signature was longer than expected, so memory was invalidly overwritten."); - abort(); - } - assert (siglengthwritten >= 0); - - return reinterpret_cast(result); -} - -PyDoc_STRVAR(SigningKey_sign__doc__, - "Return a signature on the argument."); //XXX If randseed is not None then it is required to be an "); // XXX randseed! - -static PyObject * -SigningKey_get_verifying_key(SigningKey *self, PyObject *dummy) { - VerifyingKey *verifier = PyObject_New(VerifyingKey, &VerifyingKey_type); - if (!verifier) - return NULL; - - verifier->k = new ECDSA::Verifier(*(self->k)); - if (!verifier->k) - return PyErr_NoMemory(); - verifier->k->AccessKey().AccessGroupParameters().SetPointCompression(true); - - return reinterpret_cast(verifier); -} - -PyDoc_STRVAR(SigningKey_get_verifying_key__doc__, -"Return the corresponding verifying key."); - -static PyMethodDef SigningKey_methods[] = { - {"sign", reinterpret_cast(SigningKey_sign), METH_O, SigningKey_sign__doc__}, - {"_dump", reinterpret_cast(SigningKey__dump), METH_NOARGS, SigningKey__dump__doc__}, - {"get_verifying_key", reinterpret_cast(SigningKey_get_verifying_key), METH_NOARGS, SigningKey_get_verifying_key__doc__}, - {NULL}, -}; - -static PyTypeObject SigningKey_type = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "ecdsa.SigningKey", /*tp_name*/ - sizeof(SigningKey), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)SigningKey_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT, /*tp_flags*/ - SigningKey__init____doc__, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - SigningKey_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - SigningKey___init__, /* tp_init */ -}; - -void -init_ecdsa(PyObject*const module) { - VerifyingKey_type.tp_new = PyType_GenericNew; - if (PyType_Ready(&VerifyingKey_type) < 0) - return; - Py_INCREF(&VerifyingKey_type); - PyModule_AddObject(module, "ecdsa_VerifyingKey", (PyObject *)&VerifyingKey_type); - - SigningKey_type.tp_new = PyType_GenericNew; - if (PyType_Ready(&SigningKey_type) < 0) - return; - Py_INCREF(&SigningKey_type); - PyModule_AddObject(module, "ecdsa_SigningKey", (PyObject *)&SigningKey_type); - - ecdsa_error = PyErr_NewException(const_cast("_ecdsa.Error"), NULL, NULL); - PyModule_AddObject(module, "ecdsa_Error", ecdsa_error); - - PyModule_AddStringConstant(module, "ecdsa___doc__", const_cast(ecdsa___doc__)); -} diff --git a/src/pycryptopp/publickey/ecdsamodule.hpp b/src/pycryptopp/publickey/ecdsamodule.hpp deleted file mode 100644 index ad3c4fc..0000000 --- a/src/pycryptopp/publickey/ecdsamodule.hpp +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef __INCL_ECDSAMODULE_HPP -#define __INCL_ECDSAMODULE_HPP - -void -init_ecdsa(PyObject* module); - -#endif /* #ifndef __INCL_ECDSAMODULE_HPP */ diff --git a/src/pycryptopp/test/test_ecdsa.py b/src/pycryptopp/test/test_ecdsa.py deleted file mode 100644 index 85f809d..0000000 --- a/src/pycryptopp/test/test_ecdsa.py +++ /dev/null @@ -1,258 +0,0 @@ -import random -import base64 - -import os -SEED = os.environ.get('REPEATABLE_RANDOMNESS_SEED', None) - -if SEED is None: - # Generate a seed which is fairly short (to ease cut-and-paste, writing it - # down, etc.). Note that Python's random module's seed() function is going - # to take the hash() of this seed, which is a 32-bit value (currently) so - # there is no point in making this seed larger than 32 bits. Make it 30 - # bits, which conveniently fits into six base-32 chars. Include a separator - # because chunking facilitates memory (including working and short-term - # memory) in humans. - chars = "ybndrfg8ejkmcpqxot1uwisza345h769" # Zooko's choice, rationale in "DESIGN" doc in z-base-32 project - SEED = ''.join([random.choice(chars) for x in range(3)] + ['-'] + [random.choice(chars) for x in range(3)]) - -import logging -logging.info("REPEATABLE_RANDOMNESS_SEED: %s\n" % SEED) -logging.info("In order to reproduce this run of the code, set the environment variable \"REPEATABLE_RANDOMNESS_SEED\" to %s before executing.\n" % SEED) -random.seed(SEED) - -def seed_which_refuses(a): - logging.warn("I refuse to reseed to %s -- I already seeded with %s.\n" % (a, SEED,)) - return -random.seed = seed_which_refuses - -from random import randrange - -import unittest - -from pycryptopp.publickey import ecdsa - -def randstr(n, rr=randrange): - return ''.join([chr(rr(0, 256)) for x in xrange(n)]) - -from base64 import b32encode -def ab(x): # debuggery - if len(x) >= 3: - return "%s:%s" % (len(x), b32encode(x[-3:]),) - elif len(x) == 2: - return "%s:%s" % (len(x), b32encode(x[-2:]),) - elif len(x) == 1: - return "%s:%s" % (len(x), b32encode(x[-1:]),) - elif len(x) == 0: - return "%s:%s" % (len(x), "--empty--",) - -def div_ceil(n, d): - """ - The smallest integer k such that k*d >= n. - """ - return (n/d) + (n%d != 0) - -KEYBITS =256 - -SEEDBITS=256 -SEEDBYTES=div_ceil(SEEDBITS, 8) - -# The number of bytes required to encode a public key in this elliptic curve. -PUBKEYBYTES=div_ceil(KEYBITS, 8)+1 # 1 byte for the sign of the y component - -# The number of bytes requires to encode a signature in this elliptic curve. -SIGBITS=KEYBITS*2 -SIGBYTES=div_ceil(SIGBITS, 8) - -class Signer(unittest.TestCase): - def test_construct(self): - seed = randstr(SEEDBYTES) - ecdsa.SigningKey(seed) - - def test_sign(self): - seed = randstr(SEEDBYTES) - signer = ecdsa.SigningKey(seed) - sig = signer.sign("message") - self.failUnlessEqual(len(sig), SIGBYTES) - - def test_sign_and_verify(self): - seed = randstr(SEEDBYTES) - signer = ecdsa.SigningKey(seed) - sig = signer.sign("message") - v = signer.get_verifying_key() - self.failUnless(v.verify("message", sig)) - - def test_sign_and_verify_emptymsg(self): - seed = randstr(SEEDBYTES) - signer = ecdsa.SigningKey(seed) - sig = signer.sign("") - v = signer.get_verifying_key() - self.failUnless(v.verify("", sig)) - - def test_construct_from_same_seed_is_reproducible(self): - seed = randstr(SEEDBYTES) - signer1 = ecdsa.SigningKey(seed) - signer2 = ecdsa.SigningKey(seed) - self.failUnlessEqual(signer1.get_verifying_key().serialize(), signer2.get_verifying_key().serialize()) - - # ... and using different seeds constructs a different private key. - seed3 = randstr(SEEDBYTES) - assert seed3 != seed, "Internal error in Python random module's PRNG (or in pycryptopp's hacks to it to facilitate testing) -- got two identical strings from randstr(%s)" % SEEDBYTES - signer3 = ecdsa.SigningKey(seed3) - self.failIfEqual(signer1.get_verifying_key().serialize(), signer3.get_verifying_key().serialize()) - - # Also try the all-zeroes string just because bugs sometimes are - # data-dependent on zero or cause bogus zeroes. - seed4 = '\x00'*SEEDBYTES - assert seed4 != seed, "Internal error in Python random module's PRNG (or in pycryptopp's hacks to it to facilitate testing) -- got the all-zeroes string from randstr(%s)" % SEEDBYTES - signer4 = ecdsa.SigningKey(seed4) - self.failIfEqual(signer4.get_verifying_key().serialize(), signer1.get_verifying_key().serialize()) - - signer5 = ecdsa.SigningKey(seed4) - self.failUnlessEqual(signer5.get_verifying_key().serialize(), signer4.get_verifying_key().serialize()) - - def test_construct_short_seed(self): - try: - ecdsa.SigningKey("\x00\x00\x00") - except ecdsa.Error, le: - self.failUnless("seed is required to be of length " in str(le), le) - else: - self.fail("Should have raised error from seed being too short.") - - def test_construct_bad_arg_type(self): - try: - ecdsa.SigningKey(1) - except TypeError, le: - self.failUnless("must be string" in str(le), le) - else: - self.fail("Should have raised error from seed being of the wrong type.") - -class Verifier(unittest.TestCase): - def test_from_signer_and_serialize_and_deserialize(self): - seed = randstr(SEEDBYTES) - signer = ecdsa.SigningKey(seed) - - verifier = signer.get_verifying_key() - s1 = verifier.serialize() - self.failUnlessEqual(len(s1), PUBKEYBYTES) - ecdsa.VerifyingKey(s1) - s2 = verifier.serialize() - self.failUnlessEqual(s1, s2) - -def flip_one_bit(s): - assert s - i = randrange(0, len(s)) - result = s[:i] + chr(ord(s[i])^(0x01<