Skip to content
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,6 @@ pip-log.txt

#Mr Developer
.mr.developer.cfg

# 2to3.py
/ecc/*.bak
24 changes: 12 additions & 12 deletions ecc/Key.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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 ---------------------------------------

Expand Down Expand Up @@ -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'''
Expand All @@ -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 --------------------------------------------
Expand All @@ -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__':
Expand All @@ -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)
Expand Down
59 changes: 35 additions & 24 deletions ecc/Rabbit.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -41,30 +44,36 @@ 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)]
else:
for i in range(14, -1, -2)]
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 is_integer(key):
# 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)]
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
(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
self.b = 0
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
Expand Down Expand Up @@ -109,12 +118,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
Expand All @@ -139,7 +148,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
Expand All @@ -152,6 +161,8 @@ def next(self):

self.b = b
return self

next = __next__

def derive(self):
'''Derive a 128 bit integer from the internal state'''
Expand All @@ -172,10 +183,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()
Expand All @@ -191,23 +202,23 @@ def keystream(self, n):
def encrypt(self, data):
'''Encrypt/Decrypt data of arbitrary length.'''

res = ""
res = []
b = self._buf
j = self._buf_bytes
next = self.next
next = self.__next__
derive = self.derive

for c in data:
if not j: # empty buffer => fetch next 128 bits
j = 16
next()
b = derive()
res += chr(ord(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

Expand Down Expand Up @@ -267,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
Expand Down
76 changes: 38 additions & 38 deletions ecc/curves.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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):
Expand Down
14 changes: 7 additions & 7 deletions ecc/eccrypt.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
# COPYRIGHT (c) 2010 by Toni Mattis <[email protected]>
#

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:
Expand All @@ -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
Expand All @@ -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)
Loading