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/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 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/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/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() diff --git a/misc/coding_helpers/python.supp b/misc/coding_helpers/python.supp index 102e2ec..6d219e3 100644 --- a/misc/coding_helpers/python.supp +++ b/misc/coding_helpers/python.supp @@ -44,29 +44,29 @@ 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 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.* } # 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 @@ -172,7 +172,7 @@ { ADDRESS_IN_RANGE/Invalid read of size 8 Memcheck:Value8 - fun:PyObject_Realloc + fun:PyObject_Realloc.* } { @@ -181,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 @@ -202,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 diff --git a/setup.py b/setup.py index 238f22a..dff6446 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 @@ -18,9 +18,6 @@ import versioneer -# ECDSA=False -ECDSA=True - DEBUG=False if "--debug" in sys.argv: DEBUG=True @@ -106,28 +103,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,34 +120,6 @@ 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 - trove_classifiers=[ "Environment :: Console", "License :: OSI Approved :: GNU General Public License (GPL)", # See README.rst for alternative licensing. @@ -192,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-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 } 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 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_ciphers.py b/src/pycryptopp/bench/bench_ciphers.py index c8ee6b9..fb86cf5 100644 --- a/src/pycryptopp/bench/bench_ciphers.py +++ b/src/pycryptopp/bench/bench_ciphers.py @@ -29,9 +29,7 @@ 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), + ("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 9ce1c86..a4e3c8d 100644 --- a/src/pycryptopp/bench/bench_hashes.py +++ b/src/pycryptopp/bench/bench_hashes.py @@ -35,9 +35,7 @@ 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**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 8fc70fc..9a929b5 100644 --- a/src/pycryptopp/bench/bench_sigs.py +++ b/src/pycryptopp/bench/bench_sigs.py @@ -1,20 +1,20 @@ -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): +class Ed25519(object): def __init__(self): self.seed = insecurerandstr(32) self.signer = None def gen(self, N): for i in xrange(N): - ecdsa.SigningKey(self.seed) + ed25519.SigningKey(self.seed) def sign_init(self, N): - self.signer = ecdsa.SigningKey(self.seed) + self.signer = ed25519.SigningKey(self.seed) def sign(self, N): signer = self.signer @@ -22,9 +22,9 @@ def sign(self, N): signer.sign(msg) def ver_init(self, N): - signer = ecdsa.SigningKey(self.seed) + signer = ed25519.SigningKey(self.seed) self.sig = signer.sign(msg) - self.verifier = signer.get_verifying_key() + self.verifier = ed25519.VerifyingKey(signer.get_verifying_key_bytes()) def ver(self, N): sig = self.sig @@ -119,15 +119,26 @@ def ver(self, N): verifier.verify(msg, sig) def bench_sigs(MAXTIME): - for klass in [ECDSA256, Ed25519, RSA2048, RSA3248]: + for klass in [Ed25519,]: + print klass + ob = klass() + print "generate key" + rep_bench(ob.gen, 1000, UNITS_PER_SECOND=1000, MAXTIME=MAXTIME, MAXREPS=100) + print "sign" + rep_bench(ob.sign, 1000, UNITS_PER_SECOND=1000, initfunc=ob.sign_init, MAXTIME=MAXTIME, MAXREPS=100) + print "verify" + rep_bench(ob.ver, 1000, 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, 4, UNITS_PER_SECOND=1000, MAXTIME=MAXTIME, MAXREPS=100) + rep_bench(ob.gen, 1, 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, 1000, 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, 10000, UNITS_PER_SECOND=1000, initfunc=ob.ver_init, MAXTIME=MAXTIME, MAXREPS=100) print print "milliseconds per operation" diff --git a/src/pycryptopp/bench/common.py b/src/pycryptopp/bench/common.py index d14cd25..7a90572 100644 --- a/src/pycryptopp/bench/common.py +++ b/src/pycryptopp/bench/common.py @@ -4,39 +4,49 @@ 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 if initfunc is not None: initfunc(N) - mean = 0 + meanc = 0 MAXREPS = 100 - timeout = time.time() + MAXTIME + timeout = tt() + MAXTIME for i in range(MAXREPS): - start = time.time() + startc = clock() func(N) - stop = time.time() + stopc = clock() - mean += (stop - start) + deltac = stopc - startc + 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 stop >= timeout: + if time.time() >= timeout: break num = i+1 - mean *= UNITS_PER_SECOND - mean /= num - mean /= N + meanc *= UNITS_PER_SECOND + meanc /= num + meanc /= N res = { - 'mean': mean/num, + 'meanc': meanc, 'num': num } - print "mean: %(mean)#8.03e (of %(num)6d)" % res + print "mean: %(meanc)#8.03e (of %(num)6d)" % res rep_bench = this_rep_bench try: 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_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 deleted file mode 100644 index 62fbfe1..0000000 --- a/src/pycryptopp/test/test_ecdsa.py +++ /dev/null @@ -1,260 +0,0 @@ -#!/usr/bin/env python - -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<