From e1a455f044d922cd0e0809586e4469787115b3f5 Mon Sep 17 00:00:00 2001 From: Nicco Kunzmann Date: Fri, 20 Nov 2015 15:26:49 +0100 Subject: [PATCH 01/13] ignored backupp files --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index f24cd99..2c95970 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,6 @@ pip-log.txt #Mr Developer .mr.developer.cfg + +# 2to3.py +/ecc/*.bak From 0a625b6860753b4a62d8fd21317b4cbf6c4c1372 Mon Sep 17 00:00:00 2001 From: Nicco Kunzmann Date: Fri, 20 Nov 2015 15:28:29 +0100 Subject: [PATCH 02/13] curves.py converted --- ecc/curves.py | 76 +++++++++++++++++++++++++-------------------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/ecc/curves.py b/ecc/curves.py index 5f6d7e9..edc40ab 100644 --- a/ecc/curves.py +++ b/ecc/curves.py @@ -15,52 +15,52 @@ # (see FIPS 186-3, Appendix D.1.2) DOMAINS = { # Bits : (p, order of E(GF(P)), parameter b, base point x, base point y) - 192: (0xfffffffffffffffffffffffffffffffeffffffffffffffffL, - 0xffffffffffffffffffffffff99def836146bc9b1b4d22831L, - 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1L, - 0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012L, - 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811L), - - 224: (0xffffffffffffffffffffffffffffffff000000000000000000000001L, - 0xffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3dL, - 0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4L, - 0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21L, - 0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34L), - - 256: (0xffffffff00000001000000000000000000000000ffffffffffffffffffffffffL, - 0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551L, - 0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604bL, - 0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296L, - 0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5L), - - 384: (0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffffL, - 0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973L, - 0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aefL, - 0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7L, - 0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5fL), - - 521: (0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffL, - 0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409L, - 0x051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00L, - 0x0c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66L, - 0x11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650L) + 192: (0xfffffffffffffffffffffffffffffffeffffffffffffffff, + 0xffffffffffffffffffffffff99def836146bc9b1b4d22831, + 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1, + 0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012, + 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811), + + 224: (0xffffffffffffffffffffffffffffffff000000000000000000000001, + 0xffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d, + 0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4, + 0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21, + 0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34), + + 256: (0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff, + 0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551, + 0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b, + 0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296, + 0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5), + + 384: (0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff, + 0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973, + 0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef, + 0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7, + 0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f), + + 521: (0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff, + 0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409, + 0x051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00, + 0x0c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66, + 0x11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650) } # Additional non-standard curves for low security but high performance # (not intended for use in signing, hence the missing group order) DOMAINS.update({ - 128: (0xffffffffffffffffffffffffffffff61L, + 128: (0xffffffffffffffffffffffffffffff61, None, - 0xd83d3eb8266a89927d73d5fe263d5f23L, - 0xa94d2d8531f7af8bde367def12b98eadL, - 0x9f44e1d671beb68fd2df7f877ab13fa6L), + 0xd83d3eb8266a89927d73d5fe263d5f23, + 0xa94d2d8531f7af8bde367def12b98ead, + 0x9f44e1d671beb68fd2df7f877ab13fa6), - 160: (0xffffffffffffffffffffffffffffffffffffffd1L, + 160: (0xffffffffffffffffffffffffffffffffffffffd1, None, - 0x94bfe70deef7b94742c089ca4db3ca27fbe1f754L, - 0xcc6562c2969ac57524b8d0f300d1f598c908c121L, - 0x952ddde80a252683dd7ba90fb5919899b5af69f5L) + 0x94bfe70deef7b94742c089ca4db3ca27fbe1f754, + 0xcc6562c2969ac57524b8d0f300d1f598c908c121, + 0x952ddde80a252683dd7ba90fb5919899b5af69f5) }) # global parameter of all curves (for efficiency reasons) @@ -74,7 +74,7 @@ def get_curve(bits): p, n, b, x, y = DOMAINS[bits] return bits, p, n, CURVE_P, p - b, (x, y) else: - raise KeyError, "Key size not implemented: %s" % bits + raise KeyError("Key size not implemented: {}".format(bits)) def implemented_keys(must_sign=False): From d074a323001008372a723b08b4cc35a162dc24f6 Mon Sep 17 00:00:00 2001 From: Nicco Kunzmann Date: Fri, 20 Nov 2015 15:31:24 +0100 Subject: [PATCH 03/13] eccrypt converted --- ecc/eccrypt.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ecc/eccrypt.py b/ecc/eccrypt.py index 237fad8..3d0e33b 100644 --- a/ecc/eccrypt.py +++ b/ecc/eccrypt.py @@ -5,11 +5,11 @@ # COPYRIGHT (c) 2010 by Toni Mattis # -from curves import get_curve -from elliptic import mulp -from encoding import enc_long +from .curves import get_curve +from .elliptic import mulp +from .encoding import enc_long from random import SystemRandom -from Rabbit import Rabbit +from .Rabbit import Rabbit # important for cryptographically secure random numbers: @@ -33,9 +33,9 @@ def encrypt(message, qk, encrypter=Rabbit): try: bits, cn, n, cp, cq, g = get_curve(bits) if not n: - raise ValueError, "Key size %s not suitable for encryption" % bits + raise ValueError("Key size %s not suitable for encryption" % bits) except KeyError: - raise ValueError, "Key size %s not implemented" % bits + raise ValueError("Key size %s not implemented" % bits) k = random.randint(1, n - 1) # temporary private key k kg = mulp(cp, cq, cn, g, k) # temporary public key k*G @@ -59,7 +59,7 @@ def decrypt(message, kg, dk, decrypter=Rabbit): try: bits, cn, n, cp, cq, g = get_curve(bits) except KeyError: - raise ValueError, "Key size %s not implemented" % bits + raise ValueError("Key size %s not implemented" % bits) sg = mulp(cp, cq, cn, kg, d) # shared secret d*(k*G) = k*d*G return decrypter(enc_long(sg[0])).decrypt(message) From e7f5ca94997daf8c29e2c113c387760602829980 Mon Sep 17 00:00:00 2001 From: Nicco Kunzmann Date: Fri, 20 Nov 2015 15:44:03 +0100 Subject: [PATCH 04/13] added python versions module to create compatibility --- ecc/ecdsa.py | 19 ++++++++++--------- ecc/python_version2.py | 2 ++ ecc/python_version3.py | 3 +++ ecc/python_versions.py | 12 ++++++++++++ 4 files changed, 27 insertions(+), 9 deletions(-) create mode 100644 ecc/python_version2.py create mode 100644 ecc/python_version3.py create mode 100644 ecc/python_versions.py diff --git a/ecc/ecdsa.py b/ecc/ecdsa.py index 0867394..e92e1a6 100644 --- a/ecc/ecdsa.py +++ b/ecc/ecdsa.py @@ -11,16 +11,17 @@ from os import urandom -from elliptic import inv, mulf, mulp, muladdp, element -from curves import get_curve, implemented_keys +from .elliptic import inv, mulf, mulp, muladdp, element +from .curves import get_curve, implemented_keys +from .python_versions import byte_to_integer def randkey(bits, n): '''Generate a random number (mod n) having the specified bit length''' - rb = urandom(bits / 8 + 8) # + 64 bits as recommended in FIPS 186-3 + rb = urandom(bits // 8 + 8) # + 64 bits as recommended in FIPS 186-3 c = 0 for r in rb: - c = (c << 8) | ord(r) + c = (c << 8) | byte_to_integer(r) return (c % (n - 1)) + 1 @@ -29,13 +30,13 @@ def keypair(bits): try: bits, cn, n, cp, cq, g = get_curve(bits) except KeyError: - raise ValueError, "Key size %s not implemented" % bits + raise ValueError("Key size %s not implemented" % bits) if n > 0: d = randkey(bits, n) q = mulp(cp, cq, cn, g, d) return (bits, q), (bits, d) else: - raise ValueError, "Key size %s not suitable for signing" % bits + raise ValueError("Key size %s not suitable for signing" % bits) def supported_keys(): @@ -148,17 +149,17 @@ def test_perf(bits, rounds=50): d = get_curve(bits) t = time.time() - for i in xrange(rounds): + for i in range(rounds): qk, dk = keypair(bits) tgen = time.time() - t t = time.time() - for i in xrange(rounds): + for i in range(rounds): s = sign(0, dk) tsign = time.time() - t t = time.time() - for i in xrange(rounds): + for i in range(rounds): verify(0, s, qk) tver = time.time() - t diff --git a/ecc/python_version2.py b/ecc/python_version2.py new file mode 100644 index 0000000..07cacec --- /dev/null +++ b/ecc/python_version2.py @@ -0,0 +1,2 @@ + +byte_to_integer = ord \ No newline at end of file diff --git a/ecc/python_version3.py b/ecc/python_version3.py new file mode 100644 index 0000000..4e93d16 --- /dev/null +++ b/ecc/python_version3.py @@ -0,0 +1,3 @@ + +def byte_to_integer(byte): + return byte \ No newline at end of file diff --git a/ecc/python_versions.py b/ecc/python_versions.py new file mode 100644 index 0000000..8d41ebd --- /dev/null +++ b/ecc/python_versions.py @@ -0,0 +1,12 @@ + +import sys + +PY2 = sys.version_info[0] == 2 +PY3 = sys.version_info[0] == 3 + +if PY2: + from .python_version2 import * +elif PY3: + from .python_version3 import * +else: + raise ValueError("This should be either Python version 2 or Python version 3.") From 35da0b40a3cce93c8c44979092f387490ea6b180 Mon Sep 17 00:00:00 2001 From: Nicco Kunzmann Date: Fri, 20 Nov 2015 16:03:20 +0100 Subject: [PATCH 05/13] added link to rsa module and fixed errors in elliptic.py --- ecc/elliptic.py | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/ecc/elliptic.py b/ecc/elliptic.py index 6bf0da5..4ec7243 100644 --- a/ecc/elliptic.py +++ b/ecc/elliptic.py @@ -348,17 +348,24 @@ def y_from_x(x, p, q, n, sign): if __name__ == "__main__": - import rsa + try: + import rsa + except ImportError: + print("""Install the rsa module to run these tests: + pip install rsa + The module can be found at https://pypi.python.org/pypi/rsa .""") + import time + import random t = time.time() - n = rsa.get_prime(256 / 8, 20) + n = rsa.prime.getprime(256) tp = time.time() - t - p = rsa.random.randint(1, n) - p1 = (rsa.random.randint(1, n), rsa.random.randint(1, n)) + p = random.randint(1, n) + p1 = (random.randint(1, n), random.randint(1, n)) q = curve_q(p1[0], p1[1], p, n) - r1 = rsa.random.randint(1, n) - r2 = rsa.random.randint(1, n) + r1 = random.randint(1, n) + r2 = random.randint(1, n) q1 = mulp(p, q, n, p1, r1) q2 = mulp(p, q, n, p1, r2) s1 = mulp(p, q, n, q1, r2) @@ -367,15 +374,15 @@ def y_from_x(x, p, q, n, sign): tt = time.time() - t def test(tcount, bits=256): - n = rsa.get_prime(bits / 8, 20) - p = rsa.random.randint(1, n) - p1 = (rsa.random.randint(1, n), rsa.random.randint(1, n)) + n = rsa.prime.getprime(bits) + p = random.randint(1, n) + p1 = (random.randint(1, n), random.randint(1, n)) q = curve_q(p1[0], p1[1], p, n) - p2 = mulp(p, q, n, p1, rsa.random.randint(1, n)) + p2 = mulp(p, q, n, p1, random.randint(1, n)) - c1 = [rsa.random.randint(1, n) for i in xrange(tcount)] - c2 = [rsa.random.randint(1, n) for i in xrange(tcount)] - c = zip(c1, c2) + c1 = [random.randint(1, n) for i in range(tcount)] + c2 = [random.randint(1, n) for i in range(tcount)] + c = list(zip(c1, c2)) t = time.time() for i, j in c: @@ -389,3 +396,5 @@ def test(tcount, bits=256): t2 = time.time() - t return tcount, t1, t2 + + test(10) \ No newline at end of file From ee13891dd24760ea0f357b669519d3f85933a631 Mon Sep 17 00:00:00 2001 From: Nicco Kunzmann Date: Fri, 20 Nov 2015 16:04:35 +0100 Subject: [PATCH 06/13] converted encoding.py --- ecc/encoding.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ecc/encoding.py b/ecc/encoding.py index 2cf3ff9..ee519a4 100644 --- a/ecc/encoding.py +++ b/ecc/encoding.py @@ -4,7 +4,7 @@ # Encodings and Formats for Elliptic Curve Cryptography # -import StringIO +import io # Big-Endian Encoding @@ -85,7 +85,7 @@ def dec_point(s): class Encoder: def __init__(self): - self._io = StringIO.StringIO() + self._io = io.StringIO() def int(self, n, size=4): self._io.write(enc_fixed_long(n, size)) @@ -117,7 +117,7 @@ def out(self): class Decoder: def __init__(self, data, offset=0): - self._io = StringIO.StringIO(data) + self._io = io.StringIO(data) self._io.seek(offset) self._res = [] self._limit = None @@ -168,7 +168,7 @@ def exit(self): self._parent._res.append(self._res) return self._parent else: - raise RuntimeError, "Cannont exit top level Decoder" + raise RuntimeError("Cannont exit top level Decoder") def continues(self): return (not self._limit) or (self._io.tell() < self._limit) From e320ddd6517e4e7e899b37c86b0250f9c0612ce9 Mon Sep 17 00:00:00 2001 From: Nicco Kunzmann Date: Fri, 20 Nov 2015 16:13:52 +0100 Subject: [PATCH 07/13] Rabbit.py converted --- ecc/Rabbit.py | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/ecc/Rabbit.py b/ecc/Rabbit.py index c8c868a..26880ac 100644 --- a/ecc/Rabbit.py +++ b/ecc/Rabbit.py @@ -41,17 +41,17 @@ def __init__(self, key, iv=None): key = '\x00' * (16 - len(key)) + key # if len(key) > 16 bytes only the first 16 will be considered k = [ord(key[i + 1]) | (ord(key[i]) << 8) - for i in xrange(14, -1, -2)] + for i in range(14, -1, -2)] else: # k[0] = least significant 16 bits # k[7] = most significant 16 bits - k = [(key >> i) & 0xFFFF for i in xrange(0, 128, 16)] + k = [(key >> i) & 0xFFFF for i in range(0, 128, 16)] # State and counter initialization x = [(k[(j + 5) % 8] << 16) | k[(j + 4) % 8] if j & 1 else - (k[(j + 1) % 8] << 16) | k[j] for j in xrange(8)] + (k[(j + 1) % 8] << 16) | k[j] for j in range(8)] c = [(k[j] << 16) | k[(j + 1) % 8] if j & 1 else - (k[(j + 4) % 8] << 16) | k[(j + 5) % 8] for j in xrange(8)] + (k[(j + 4) % 8] << 16) | k[(j + 5) % 8] for j in range(8)] self.x = x self.c = c @@ -59,12 +59,12 @@ def __init__(self, key, iv=None): self._buf = 0 # output buffer self._buf_bytes = 0 # fill level of buffer - self.next() - self.next() - self.next() - self.next() + next(self) + next(self) + next(self) + next(self) - for j in xrange(8): + for j in range(8): c[j] ^= x[(j + 4) % 8] self.start_x = self.x[:] # backup initial key for IV/reset @@ -109,12 +109,12 @@ def set_iv(self, iv): c[6] ^= i2 c[7] ^= i3 - self.next() - self.next() - self.next() - self.next() + next(self) + next(self) + next(self) + next(self) - def next(self): + def __next__(self): '''Proceed to the next internal state''' c = self.c @@ -139,7 +139,7 @@ def next(self): c[7] = t % WORDSIZE b = t // WORDSIZE - g = [_nsf(x[j], c[j]) for j in xrange(8)] + g = [_nsf(x[j], c[j]) for j in range(8)] x[0] = (g[0] + rot16(g[7]) + rot16(g[6])) % WORDSIZE x[1] = (g[1] + rot08(g[0]) + g[7]) % WORDSIZE @@ -152,6 +152,8 @@ def next(self): self.b = b return self + + next = __next__ def derive(self): '''Derive a 128 bit integer from the internal state''' @@ -172,10 +174,10 @@ def keystream(self, n): res = "" b = self._buf j = self._buf_bytes - next = self.next + next = self.__next__ derive = self.derive - for i in xrange(n): + for i in range(n): if not j: j = 16 next() @@ -194,7 +196,7 @@ def encrypt(self, data): res = "" b = self._buf j = self._buf_bytes - next = self.next + next = self.__next__ derive = self.derive for c in data: From cc68b29ef32013fd85757b1768f086911c603d6d Mon Sep 17 00:00:00 2001 From: Nicco Kunzmann Date: Fri, 20 Nov 2015 16:14:16 +0100 Subject: [PATCH 08/13] added notes --- ecc/elliptic.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ecc/elliptic.py b/ecc/elliptic.py index 4ec7243..a005952 100644 --- a/ecc/elliptic.py +++ b/ecc/elliptic.py @@ -359,6 +359,7 @@ def y_from_x(x, p, q, n, sign): import random t = time.time() + # note: we could also use .primes.get_prime(256/8, 20) n = rsa.prime.getprime(256) tp = time.time() - t p = random.randint(1, n) @@ -374,6 +375,7 @@ def y_from_x(x, p, q, n, sign): tt = time.time() - t def test(tcount, bits=256): + # note: we could also use .primes.get_prime(256/8, 20) n = rsa.prime.getprime(bits) p = random.randint(1, n) p1 = (random.randint(1, n), random.randint(1, n)) From 9022ae304e77b5f9477b773612cc3478f5cdcc0c Mon Sep 17 00:00:00 2001 From: Nicco Kunzmann Date: Fri, 20 Nov 2015 16:52:53 +0100 Subject: [PATCH 09/13] converted Key.py --- ecc/Key.py | 24 ++++++++++++------------ ecc/Rabbit.py | 17 +++++++++++++---- ecc/encoding.py | 37 ++++++++++++++++++++----------------- ecc/python_version2.py | 3 ++- ecc/python_version3.py | 4 +++- ecc/python_versions.py | 10 ++++++++-- 6 files changed, 58 insertions(+), 37 deletions(-) diff --git a/ecc/Key.py b/ecc/Key.py index f9c8cef..5a65736 100644 --- a/ecc/Key.py +++ b/ecc/Key.py @@ -170,12 +170,12 @@ over a constructed 512 bit field.) """ -import ecdsa +from . import ecdsa import hashlib -from encoding import * -from eccrypt import * -from SecurityViolationException import * +from .encoding import * +from .eccrypt import * +from .SecurityViolationException import * class Key: @@ -217,7 +217,7 @@ def decode(s): if kid == k.keyid(): return k else: - raise ValueError, "Invalid Key ID" + raise ValueError("Invalid Key ID") # --- IDENTIFICATION AND VALIDATION --------------------------------------- @@ -262,7 +262,7 @@ def sign(self, data, hashfunc='sha256'): s = ecdsa.sign(h, self._priv) return enc_point(s) else: - raise AttributeError, 'Private key needed for signing.' + raise AttributeError('Private key needed for signing.') def verify(self, data, sig, hashfunc='sha256'): '''Verify the signature of data using the specified hash function''' @@ -275,11 +275,11 @@ def verify(self, data, sig, hashfunc='sha256'): def encrypt(self, data): '''Encrypt a message using this public key''' ctext, mkey = encrypt(data, self._pub) - return Encoder().point(mkey).str(ctext, 4).out() + return Encoder().point(mkey).bytes(ctext, 4).out() def decrypt(self, data): '''Decrypt an encrypted message using this private key''' - mkey, ctext = Decoder(data).point().str(4).out() + mkey, ctext = Decoder(data).point().bytes(4).out() return decrypt(ctext, mkey, self._priv) # --- AUTHENTICATED ENCRYPTION -------------------------------------------- @@ -288,16 +288,16 @@ def auth_encrypt(self, data, receiver): '''Sign and encrypt a message''' sgn = self.sign(data) ctext, mkey = encrypt(data, receiver._pub) - return Encoder().point(mkey).str(ctext, 4).str(sgn, 2).out() + return Encoder().point(mkey).bytes(ctext, 4).bytes(sgn, 2).out() def auth_decrypt(self, data, source): '''Decrypt and verify a message''' - mkey, ctext, sgn = Decoder(data).point().str(4).str(2).out() + mkey, ctext, sgn = Decoder(data).point().bytes(4).bytes(2).out() text = decrypt(ctext, mkey, self._priv) if source.verify(text, sgn): return text else: - raise SecurityViolationException, 'Invalid Signature' + raise SecurityViolationException('Invalid Signature') if __name__ == '__main__': @@ -311,7 +311,7 @@ def test_overhead(): for r in [192, 224, 256, 384, 521]: receiver = Key.generate(r) t = time.time() - e = sender.auth_encrypt('', receiver) + e = sender.auth_encrypt(b'', receiver) t1 = time.time() - t t = time.time() receiver.auth_decrypt(e, sender) diff --git a/ecc/Rabbit.py b/ecc/Rabbit.py index 26880ac..13d0237 100644 --- a/ecc/Rabbit.py +++ b/ecc/Rabbit.py @@ -11,9 +11,12 @@ # # ------------------------------------------------------------------------------ - WORDSIZE = 0x100000000 +try: + from .python_versions import * +except ImportError: + from python_versions import * def rot08(x): return ((x << 8) & 0xFFFFFFFF) | (x >> 24) @@ -42,10 +45,16 @@ def __init__(self, key, iv=None): # if len(key) > 16 bytes only the first 16 will be considered k = [ord(key[i + 1]) | (ord(key[i]) << 8) for i in range(14, -1, -2)] - else: + elif isinstance(key, bytes): + # This is only the case in Python 3 since str == bytes in Python 2 + k = [(key[i + 1]) | ((key[i]) << 8) + for i in range(14, -1, -2)] + elif isinstance(key, int): # k[0] = least significant 16 bits # k[7] = most significant 16 bits k = [(key >> i) & 0xFFFF for i in range(0, 128, 16)] + else: + raise ValueError("key must be either int, bytes or str") # State and counter initialization x = [(k[(j + 5) % 8] << 16) | k[(j + 4) % 8] if j & 1 else @@ -193,7 +202,7 @@ def keystream(self, n): def encrypt(self, data): '''Encrypt/Decrypt data of arbitrary length.''' - res = "" + res = b"" b = self._buf j = self._buf_bytes next = self.__next__ @@ -204,7 +213,7 @@ def encrypt(self, data): j = 16 next() b = derive() - res += chr(ord(c) ^ (b & 0xFF)) + res += integer_to_bytes(byte_to_integer(c) ^ (b & 0xFF)) j -= 1 b >>= 1 self._buf = b diff --git a/ecc/encoding.py b/ecc/encoding.py index ee519a4..56203b7 100644 --- a/ecc/encoding.py +++ b/ecc/encoding.py @@ -5,16 +5,18 @@ # import io - +from .python_versions import byte_to_integer +import struct # Big-Endian Encoding def enc_long(n): '''Encodes arbitrarily large number n to a sequence of bytes. Big endian byte order is used.''' - s = "" + assert n >= 0 + s = struct.pack('') while n > 0: - s = chr(n & 0xFF) + s + s = struct.pack('B', n & 0xFF) + s n >>= 8 return s @@ -22,20 +24,21 @@ def enc_long(n): def enc_int(n): '''Encodes an integer n to a 4-byte string. Big endian byte order is used.''' - return (chr((n >> 24) & 0xFF) + chr((n >> 16) & 0xFF) + - chr((n >> 8) & 0xFF) + chr(n & 0xFF)) + assert n >= 0 + return struct.pack(">L", n) +ZERO_BYTE = struct.pack('B', 0) def enc_fixed_long(n, length): - return enc_long(n)[:length].rjust(length, '\x00') + return enc_long(n)[:length].rjust(length, ZERO_BYTE) -def dec_long(s): - '''Decodes s to its numeric representation. +def dec_long(b): + '''Decodes b to its numeric representation. Big endian byte order is used.''' n = 0 - for c in s: - n = (n << 8) | ord(c) + for c in b: + n = (n << 8) | byte_to_integer(c) return n # dec_int not necessary, @@ -70,22 +73,22 @@ def enc_point(p): sy = enc_long(y) diff = len(sx) - len(sy) if diff > 0: - sy = '\x00' * diff + sy + sy = ZERO_BYTE * diff + sy elif diff < 0: - sx = '\x00' * -diff + sx + sx = ZERO_BYTE * -diff + sx return sx + sy def dec_point(s): '''Decode an even length string s to a point(x, y)''' - d = len(s) / 2 + d = len(s) // 2 return (dec_long(s[:d]), dec_long(s[d:])) class Encoder: def __init__(self): - self._io = io.StringIO() + self._io = io.BytesIO() def int(self, n, size=4): self._io.write(enc_fixed_long(n, size)) @@ -96,7 +99,7 @@ def long(self, n, pre=2): self._io.write(enc_fixed_long(len(lstr), pre) + lstr) return self - def str(self, s, pre=2): + def bytes(self, s, pre=2): self._io.write(enc_fixed_long(len(s), pre) + s) return self @@ -117,7 +120,7 @@ def out(self): class Decoder: def __init__(self, data, offset=0): - self._io = io.StringIO(data) + self._io = io.BytesIO(data) self._io.seek(offset) self._res = [] self._limit = None @@ -139,7 +142,7 @@ def long(self, pre=2): self._res.append(dec_long(self._io.read(llen))) return self._ret() - def str(self, pre=2): + def bytes(self, pre=2): llen = dec_long(self._io.read(pre)) self._res.append(self._io.read(llen)) return self._ret() diff --git a/ecc/python_version2.py b/ecc/python_version2.py index 07cacec..be4c389 100644 --- a/ecc/python_version2.py +++ b/ecc/python_version2.py @@ -1,2 +1,3 @@ -byte_to_integer = ord \ No newline at end of file +byte_to_integer = ord +integer_to_bytes = chr \ No newline at end of file diff --git a/ecc/python_version3.py b/ecc/python_version3.py index 4e93d16..75655cb 100644 --- a/ecc/python_version3.py +++ b/ecc/python_version3.py @@ -1,3 +1,5 @@ def byte_to_integer(byte): - return byte \ No newline at end of file + return byte + +integer_to_bytes = lambda byte: bytes((byte,)) \ No newline at end of file diff --git a/ecc/python_versions.py b/ecc/python_versions.py index 8d41ebd..c44b7b2 100644 --- a/ecc/python_versions.py +++ b/ecc/python_versions.py @@ -5,8 +5,14 @@ PY3 = sys.version_info[0] == 3 if PY2: - from .python_version2 import * + try: + from .python_version2 import * + except ImportError: + from python_version2 import * elif PY3: - from .python_version3 import * + try: + from .python_version3 import * + except ImportError: + from python_version3 import * else: raise ValueError("This should be either Python version 2 or Python version 3.") From 0996fcf025cc03956092d5da98393fb7f719d3e3 Mon Sep 17 00:00:00 2001 From: Nicco Kunzmann Date: Fri, 20 Nov 2015 16:57:46 +0100 Subject: [PATCH 10/13] performance.py converted --- ecc/performance.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/ecc/performance.py b/ecc/performance.py index 23fa472..05ae821 100644 --- a/ecc/performance.py +++ b/ecc/performance.py @@ -5,14 +5,14 @@ from collections import OrderedDict -from Key import Key +from .Key import Key def test_generation_perf(n=100): results = OrderedDict() for bits in (192, 224, 256, 384, 521): t = time.time() - for i in xrange(n): + for i in range(n): k = Key.generate(bits) t = time.time() - t results[bits] = t @@ -24,8 +24,8 @@ def test_signing_perf(n=100): for bits in (192, 224, 256, 384, 521): k = Key.generate(bits) t = time.time() - for i in xrange(n): - k.sign('random string') + for i in range(n): + k.sign(b'random string') t = time.time() - t results[bits] = t return results @@ -35,10 +35,10 @@ def test_verification_perf(n=100): results = OrderedDict() for bits in (192, 224, 256, 384, 521): k = Key.generate(bits) - s = k.sign('random string') + s = k.sign(b'random string') t = time.time() - for i in xrange(n): - k.verify('random string', s) + for i in range(n): + k.verify(b'random string', s) t = time.time() - t results[bits] = t return results @@ -47,7 +47,7 @@ def test_verification_perf(n=100): def print_dict(title, d, n): print(title) print('-' * len(title)) - for k, v in d.items(): + for k, v in list(d.items()): print('{} bits {:10.5f} seconds {:10.5f}/sec'.format(k, v, n / v)) print('') From 6248144d398ac1f06ed8862c032225b841e760af Mon Sep 17 00:00:00 2001 From: Nicco Kunzmann Date: Fri, 20 Nov 2015 16:58:11 +0100 Subject: [PATCH 11/13] primes converted --- ecc/primes.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ecc/primes.py b/ecc/primes.py index d3cc9bd..8c6d982 100644 --- a/ecc/primes.py +++ b/ecc/primes.py @@ -38,14 +38,14 @@ def prime(n, k): s += 1 d /= 2 - for i in xrange(k): + for i in range(k): - a = long(2 + random.randint(0, n - 4)) + a = int(2 + random.randint(0, n - 4)) x = exp(a, d, n) if (x == 1) or (x == n - 1): continue - for r in xrange(1, s): + for r in range(1, s): x = (x * x) % n if x == 1: From d576bbe5108e73bba7bc6929725178aeff88f4a7 Mon Sep 17 00:00:00 2001 From: Nicco Kunzmann Date: Fri, 20 Nov 2015 16:58:35 +0100 Subject: [PATCH 12/13] shacrypt.py converted --- ecc/shacrypt.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ecc/shacrypt.py b/ecc/shacrypt.py index b4107ee..fe7d10c 100644 --- a/ecc/shacrypt.py +++ b/ecc/shacrypt.py @@ -21,7 +21,7 @@ def enc_block(block, key, rounds=16): x = block[:64] y = block[64:] - for i in xrange(rounds): + for i in range(rounds): h = sha512(x + key).digest() y = ''.join([chr(ord(y[k]) ^ ord(h[k])) for k in BPOS]) h = sha512(y + key).digest() @@ -32,7 +32,7 @@ def enc_block(block, key, rounds=16): def dec_block(block, key, rounds=16): x = block[:64] y = block[64:] - for i in xrange(rounds): + for i in range(rounds): h = sha512(y + key).digest() x = ''.join([chr(ord(x[k]) ^ ord(h[k])) for k in BPOS]) h = sha512(x + key).digest() From a9c8d2464874238f10b9dfedacf9729442711629 Mon Sep 17 00:00:00 2001 From: Nicco Kunzmann Date: Fri, 20 Nov 2015 17:12:18 +0100 Subject: [PATCH 13/13] fixed bug in rabbit cipher -> more performance inPython 3 --- ecc/Rabbit.py | 10 +++++----- ecc/python_version2.py | 6 +++++- ecc/python_version3.py | 4 +++- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/ecc/Rabbit.py b/ecc/Rabbit.py index 13d0237..872497f 100644 --- a/ecc/Rabbit.py +++ b/ecc/Rabbit.py @@ -49,7 +49,7 @@ def __init__(self, key, iv=None): # This is only the case in Python 3 since str == bytes in Python 2 k = [(key[i + 1]) | ((key[i]) << 8) for i in range(14, -1, -2)] - elif isinstance(key, int): + elif is_integer(key): # k[0] = least significant 16 bits # k[7] = most significant 16 bits k = [(key >> i) & 0xFFFF for i in range(0, 128, 16)] @@ -202,7 +202,7 @@ def keystream(self, n): def encrypt(self, data): '''Encrypt/Decrypt data of arbitrary length.''' - res = b"" + res = [] b = self._buf j = self._buf_bytes next = self.__next__ @@ -213,12 +213,12 @@ def encrypt(self, data): j = 16 next() b = derive() - res += integer_to_bytes(byte_to_integer(c) ^ (b & 0xFF)) + res.append(integer_to_bytes(byte_to_integer(c) ^ (b & 0xFF))) j -= 1 b >>= 1 self._buf = b self._buf_bytes = j - return res + return b''.join(res) decrypt = encrypt @@ -278,7 +278,7 @@ def test_enc(n=1048576): '''Measure time for encrypting n bytes => (total, bytes per second)''' r = Rabbit(0) - x = 'x' * n + x = b'x' * n t = time.time() r.encrypt(x) t = time.time() - t diff --git a/ecc/python_version2.py b/ecc/python_version2.py index be4c389..d1feb12 100644 --- a/ecc/python_version2.py +++ b/ecc/python_version2.py @@ -1,3 +1,7 @@ byte_to_integer = ord -integer_to_bytes = chr \ No newline at end of file + + +integer_to_bytes = chr + +is_integer = lambda i: isinstance(i, int) or isinstance(i, long) \ No newline at end of file diff --git a/ecc/python_version3.py b/ecc/python_version3.py index 75655cb..10dce4f 100644 --- a/ecc/python_version3.py +++ b/ecc/python_version3.py @@ -2,4 +2,6 @@ def byte_to_integer(byte): return byte -integer_to_bytes = lambda byte: bytes((byte,)) \ No newline at end of file +integer_to_bytes = lambda byte: bytes((byte,)) + +is_integer = lambda i: isinstance(i, int) \ No newline at end of file