Skip to content

Commit

Permalink
rename package to 'spake2'. code changes only.
Browse files Browse the repository at this point in the history
  • Loading branch information
warner committed Jan 23, 2015
1 parent 45ba058 commit e2fef9c
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 48 deletions.
28 changes: 14 additions & 14 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ def initialize_options(self):
def finalize_options(self):
pass
def run(self):
for t in ["pake2/test_pake2.py",
for t in ["spake2/test_spake2.py",
]:
rc = self.do_test(t)
if rc != 0:
Expand Down Expand Up @@ -43,23 +43,23 @@ def update_version_py():
p = subprocess.Popen(["git", "describe", "--tags", "--dirty", "--always"],
stdout=subprocess.PIPE)
except EnvironmentError:
print "unable to run git, leaving pake2/_version.py alone"
print "unable to run git, leaving spake2/_version.py alone"
return
stdout = p.communicate()[0]
if p.returncode != 0:
print "unable to run git, leaving pake2/_version.py alone"
print "unable to run git, leaving spake2/_version.py alone"
return
# we use tags like "python-pake2-0.5", so strip the prefix
assert stdout.startswith("python-pake2-"), stdout
ver = stdout[len("python-pake2-"):].strip()
f = open("pake2/_version.py", "w")
# we use tags like "python-spake2-0.5", so strip the prefix
assert stdout.startswith("python-spake2-"), stdout
ver = stdout[len("python-spake2-"):].strip()
f = open("spake2/_version.py", "w")
f.write(VERSION_PY % ver)
f.close()
print "set pake2/_version.py to '%s'" % ver
print "set spake2/_version.py to '%s'" % ver

def get_version():
try:
f = open("pake2/_version.py")
f = open("spake2/_version.py")
except EnvironmentError:
return None
for line in f.readlines():
Expand Down Expand Up @@ -89,13 +89,13 @@ def run(self):
self.distribution.metadata.version = get_version()
return _sdist.run(self)

setup(name="pake2",
setup(name="spake2",
version=get_version(),
description="PAKE2/PAKE2+ password-authenticated key exchange (pure python)",
description="SPAKE2 password-authenticated key exchange (pure python)",
author="Brian Warner",
author_email="warner-pypake2@lothar.com",
url="http://github.com/warner/python-pake2",
packages=["pake2"],
author_email="warner-pyspake2@lothar.com",
url="http://github.com/warner/python-spake2",
packages=["spake2"],
license="MIT",
cmdclass={ "test": Test, "version": Version, "sdist": sdist },
)
4 changes: 2 additions & 2 deletions spake2/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

from pake2 import PAKE2, PAKE2_P, PAKE2_Q, PAKEError, \
from spake2 import SPAKE2, SPAKE2_P, SPAKE2_Q, PAKEError, \
params_80, params_112, params_128
_hush_pyflakes = [PAKE2, PAKE2_P, PAKE2_Q, PAKEError,
_hush_pyflakes = [SPAKE2, SPAKE2_P, SPAKE2_Q, PAKEError,
params_80, params_112, params_128]
del _hush_pyflakes

Expand Down
16 changes: 8 additions & 8 deletions spake2/bench_spake2.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@

import timeit, sys
from pake2 import PAKE2_P, PAKE2_Q, params_80, params_112, params_128
from spake2 import SPAKE2_P, SPAKE2_Q, params_80, params_112, params_128
hush_pyflakes = [params_80, params_112, params_128]

class Harness:
def setup(self, params=params_80):
self.params = params
self.pw = pw = "password"
self.jA = PAKE2_P(pw, params=params)
self.jB = PAKE2_Q(pw, params=params)
self.jA = SPAKE2_P(pw, params=params)
self.jB = SPAKE2_Q(pw, params=params)
self.m1A,self.m1B = self.jA.one(), self.jB.one()
#kA,kB = self.jA.two(m1B), self.jB.two(m1A)
def construct(self):
PAKE2_P(self.pw, params=self.params)
SPAKE2_P(self.pw, params=self.params)
def one(self):
self.jA.one()
def two(self):
Expand All @@ -32,12 +32,12 @@ def two(self):
for name in all_names:
print "%s %s:" % (params, name),
timeit.main(["--setup",
("import bench_pake2; "
"bench_pake2.h.setup(bench_pake2.%s)" % params),
"bench_pake2.h.%s()" % name,
("import bench_spake2; "
"bench_spake2.h.setup(bench_spake2.%s)" % params),
"bench_spake2.h.%s()" % name,
])

# 78:warner@Cookies% python pake2/bench_pake2.py
# 78:warner@Cookies% python spake2/bench_spake2.py
# params_80 construct: 100000 loops, best of 3: 13.6 usec per loop
# params_80 one: 100 loops, best of 3: 19.3 msec per loop
# params_80 two: 100 loops, best of 3: 19.2 msec per loop
Expand Down
24 changes: 12 additions & 12 deletions spake2/spake2.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,14 +138,14 @@ def randrange(order, entropy):
" is very wrong or you got realllly unlucky. Order was"
" %x" % order)

class PAKE2:
"""This class manages one half of a PAKE2 key negotiation.
class SPAKE2:
"""This class manages one half of a SPAKE2 key negotiation.
The protocol has four public system parameters: a group, a generator, and
two group elements (one each for sides P and Q). The participants must
agree ahead of time which role each will play (either P or Q).
Create an instance with PAKE2(password=pw, side='P') (or side='Q'), where
Create an instance with SPAKE2(password=pw, side='P') (or side='Q'), where
'password' is either a number (0 < number < params.q-1) or a bytestring.
You can also pass an optional params= value (one of [params_80,
params_112, params_128], for increasing levels of security and CPU
Expand Down Expand Up @@ -178,9 +178,9 @@ class PAKE2:
A: hkey = receive()
A: assert sha256(Akey).digest() == hkey
If you can't keep the PAKE2 instance alive for the whole negotiation, you
If you can't keep the SPAKE2 instance alive for the whole negotiation, you
can persist the important data from an instance with data=p.to_json(),
and then reconstruct the instance with p=PAKE2.from_json(data). The
and then reconstruct the instance with p=SPAKE2.from_json(data). The
instance data is sensitive: protect it better than you would the original
password. An attacker who learns the instance state from both sides will
be able to reconstruct the shared key. These functions return a
Expand All @@ -189,17 +189,17 @@ class PAKE2:
the serialized JSON is typically about 1236 bytes after construction and
1528 bytes after one().
p = PAKE2(password)
p = SPAKE2(password)
send(p.one())
open('save.json','w').write(simplejson.dumps(p.to_json()))
...
p = PAKE2.from_json(simplejson.loads(open('save.json').read()))
p = SPAKE2.from_json(simplejson.loads(open('save.json').read()))
key = p.two(receive())
The message returned by one() is a small dictionary, safe to serialize as
a JSON object, and will survive being deserialized in a javascript
environment (i.e. the large numbers are encoded as hex strings, since JS
does not have bigints). If you wish for smaller messages, the PAKE2
does not have bigints). If you wish for smaller messages, the SPAKE2
instance has pack_msg() and unpack_msg() methods to encode/decode these
strings into smaller bytestrings. The encoding scheme is slightly
different for each params= value. For params_80, a JSON encoding of
Expand Down Expand Up @@ -316,13 +316,13 @@ def from_json(klass, data, entropy=None):
setattr(self, name, int(data[name], 16))
return self

class PAKE2_P(PAKE2):
class SPAKE2_P(SPAKE2):
def __init__(self, password, params=params_80, entropy=None):
PAKE2.__init__(self, password, "P", params, entropy)
SPAKE2.__init__(self, password, "P", params, entropy)

class PAKE2_Q(PAKE2):
class SPAKE2_Q(SPAKE2):
def __init__(self, password, params=params_80, entropy=None):
PAKE2.__init__(self, password, "Q", params, entropy)
SPAKE2.__init__(self, password, "Q", params, entropy)


# add ECC version for smaller messages/storage
Expand Down
24 changes: 12 additions & 12 deletions spake2/test_spake2.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@

import unittest
from pake2 import PAKE2, PAKE2_P, PAKE2_Q, PAKEError, \
from spake2 import SPAKE2, SPAKE2_P, SPAKE2_Q, PAKEError, \
params_80, params_112, params_128
from binascii import hexlify
from hashlib import sha256
Expand All @@ -9,15 +9,15 @@
class Basic(unittest.TestCase):
def test_success(self):
pw = "password"
pA,pB = PAKE2_P(pw), PAKE2_Q(pw)
pA,pB = SPAKE2_P(pw), SPAKE2_Q(pw)
m1A,m1B = pA.one(), pB.one()
kA,kB = pA.two(m1B), pB.two(m1A)
self.failUnlessEqual(hexlify(kA), hexlify(kB))
self.failUnlessEqual(len(kA), len(sha256().digest()))

def test_failure(self):
pw = "password"
pA,pB = PAKE2_P(pw), PAKE2_Q("passwerd")
pA,pB = SPAKE2_P(pw), SPAKE2_Q("passwerd")
m1A,m1B = pA.one(), pB.one()
kA,kB = pA.two(m1B), pB.two(m1A)
self.failIfEqual(hexlify(kA), hexlify(kB))
Expand All @@ -27,14 +27,14 @@ def test_failure(self):
class Parameters(unittest.TestCase):
def do_tests(self, params):
pw = "password"
pA,pB = PAKE2_P(pw, params=params), PAKE2_Q(pw, params=params)
pA,pB = SPAKE2_P(pw, params=params), SPAKE2_Q(pw, params=params)
m1A,m1B = pA.one(), pB.one()
#print len(json.dumps(m1A))
kA,kB = pA.two(m1B), pB.two(m1A)
self.failUnlessEqual(hexlify(kA), hexlify(kB))
self.failUnlessEqual(len(kA), len(sha256().digest()))

pA,pB = PAKE2_P(pw, params=params), PAKE2_Q("passwerd", params=params)
pA,pB = SPAKE2_P(pw, params=params), SPAKE2_Q("passwerd", params=params)
m1A,m1B = pA.one(), pB.one()
kA,kB = pA.two(m1B), pB.two(m1A)
self.failIfEqual(hexlify(kA), hexlify(kB))
Expand All @@ -47,7 +47,7 @@ def test_params(self):

def test_default_is_80(self):
pw = "password"
pA,pB = PAKE2_P(pw, params=params_80), PAKE2_Q(pw)
pA,pB = SPAKE2_P(pw, params=params_80), SPAKE2_Q(pw)
m1A,m1B = pA.one(), pB.one()
kA,kB = pA.two(m1B), pB.two(m1A)
self.failUnlessEqual(hexlify(kA), hexlify(kB))
Expand All @@ -74,15 +74,15 @@ class OtherEntropy(unittest.TestCase):
def test_entropy(self):
entropy = PRNG("seed")
pw = "password"
pA,pB = PAKE2_P(pw, entropy=entropy), PAKE2_Q(pw, entropy=entropy)
pA,pB = SPAKE2_P(pw, entropy=entropy), SPAKE2_Q(pw, entropy=entropy)
m1A1,m1B1 = pA.one(), pB.one()
kA1,kB1 = pA.two(m1B1), pB.two(m1A1)
self.failUnlessEqual(hexlify(kA1), hexlify(kB1))

# run it again with the same entropy stream: all messages should be
# identical
entropy = PRNG("seed")
pA,pB = PAKE2_P(pw, entropy=entropy), PAKE2_Q(pw, entropy=entropy)
pA,pB = SPAKE2_P(pw, entropy=entropy), SPAKE2_Q(pw, entropy=entropy)
m1A2,m1B2 = pA.one(), pB.one()
kA2,kB2 = pA.two(m1B2), pB.two(m1A2)
self.failUnlessEqual(hexlify(kA2), hexlify(kB2))
Expand All @@ -96,11 +96,11 @@ class Serialize(unittest.TestCase):
def replace(self, orig):
data = json.dumps(orig.to_json())
#print len(data)
return PAKE2.from_json(json.loads(data))
return SPAKE2.from_json(json.loads(data))

def test_serialize(self):
pw = "password"
pA,pB = PAKE2_P(pw), PAKE2_Q(pw)
pA,pB = SPAKE2_P(pw), SPAKE2_Q(pw)
pA = self.replace(pA)
m1A,m1B = pA.one(), pB.one()
pA = self.replace(pA)
Expand All @@ -111,7 +111,7 @@ def test_serialize(self):
class Packed(unittest.TestCase):
def test_pack(self):
pw = "password"
pA,pB = PAKE2_P(pw), PAKE2_Q(pw)
pA,pB = SPAKE2_P(pw), SPAKE2_Q(pw)
m1A,m1B = pA.one(), pB.one()
m1Ap = pA.pack_msg(m1A)
#print "m1:", len(json.dumps(m1A)), len(m1Ap)
Expand All @@ -122,7 +122,7 @@ def test_pack(self):
class Errors(unittest.TestCase):
def test_bad_side(self):
self.failUnlessRaises(PAKEError,
PAKE2, "password", "R", params_80)
SPAKE2, "password", "R", params_80)

if __name__ == '__main__':
unittest.main()
Expand Down

0 comments on commit e2fef9c

Please sign in to comment.