mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-12-06 19:41:15 +01:00
slownacl's pure-python curve25519 lets us test ntor everywhere.
Improvement on f308adf838, where we made the ntor
unit tests run everywhere... so long as a python curve25519 module
was installed. Now the unit tests don't require that module.
This commit is contained in:
+10
-9
@@ -30,11 +30,12 @@ commands:
|
||||
import binascii
|
||||
try:
|
||||
import curve25519
|
||||
curve25519mod = curve25519.keys
|
||||
except ImportError:
|
||||
curve25519 = None
|
||||
print "SKIPPING: No Python curve25519 module installed"
|
||||
import sys
|
||||
sys.exit(0)
|
||||
import slownacl_curve25519
|
||||
curve25519mod = slownacl_curve25519
|
||||
|
||||
import hashlib
|
||||
import hmac
|
||||
import subprocess
|
||||
@@ -74,17 +75,17 @@ T_VERIFY = PROTOID + ":verify"
|
||||
def H_mac(msg): return H(msg, tweak=T_MAC)
|
||||
def H_verify(msg): return H(msg, tweak=T_VERIFY)
|
||||
|
||||
class PrivateKey(curve25519.keys.Private):
|
||||
"""As curve25519.keys.Private, but doesn't regenerate its public key
|
||||
class PrivateKey(curve25519mod.Private):
|
||||
"""As curve25519mod.Private, but doesn't regenerate its public key
|
||||
every time you ask for it.
|
||||
"""
|
||||
def __init__(self):
|
||||
curve25519.keys.Private.__init__(self)
|
||||
curve25519mod.Private.__init__(self)
|
||||
self._memo_public = None
|
||||
|
||||
def get_public(self):
|
||||
if self._memo_public is None:
|
||||
self._memo_public = curve25519.keys.Private.get_public(self)
|
||||
self._memo_public = curve25519mod.Private.get_public(self)
|
||||
|
||||
return self._memo_public
|
||||
|
||||
@@ -184,7 +185,7 @@ def server(seckey_b, my_node_id, message, keyBytes=72):
|
||||
badness = (keyid(seckey_b.get_public()) !=
|
||||
message[NODE_ID_LENGTH:NODE_ID_LENGTH+H_LENGTH])
|
||||
|
||||
pubkey_X = curve25519.keys.Public(message[NODE_ID_LENGTH+H_LENGTH:])
|
||||
pubkey_X = curve25519mod.Public(message[NODE_ID_LENGTH+H_LENGTH:])
|
||||
seckey_y = PrivateKey()
|
||||
pubkey_Y = seckey_y.get_public()
|
||||
pubkey_B = seckey_b.get_public()
|
||||
@@ -247,7 +248,7 @@ def client_part2(seckey_x, msg, node_id, pubkey_B, keyBytes=72):
|
||||
"""
|
||||
assert len(msg) == G_LENGTH + H_LENGTH
|
||||
|
||||
pubkey_Y = curve25519.keys.Public(msg[:G_LENGTH])
|
||||
pubkey_Y = curve25519mod.Public(msg[:G_LENGTH])
|
||||
their_auth = msg[G_LENGTH:]
|
||||
|
||||
pubkey_X = seckey_x.get_public()
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
# This is the curve25519 implementation from Matthew Dempsky's "Slownacl"
|
||||
# library. It is in the public domain.
|
||||
#
|
||||
# It isn't constant-time. Don't use it except for testing.
|
||||
#
|
||||
# Nick got the slownacl source from:
|
||||
# https://github.com/mdempsky/dnscurve/tree/master/slownacl
|
||||
|
||||
__all__ = ['smult_curve25519_base', 'smult_curve25519']
|
||||
|
||||
P = 2 ** 255 - 19
|
||||
A = 486662
|
||||
|
||||
def expmod(b, e, m):
|
||||
if e == 0: return 1
|
||||
t = expmod(b, e / 2, m) ** 2 % m
|
||||
if e & 1: t = (t * b) % m
|
||||
return t
|
||||
|
||||
def inv(x):
|
||||
return expmod(x, P - 2, P)
|
||||
|
||||
# Addition and doubling formulas taken from Appendix D of "Curve25519:
|
||||
# new Diffie-Hellman speed records".
|
||||
|
||||
def add((xn,zn), (xm,zm), (xd,zd)):
|
||||
x = 4 * (xm * xn - zm * zn) ** 2 * zd
|
||||
z = 4 * (xm * zn - zm * xn) ** 2 * xd
|
||||
return (x % P, z % P)
|
||||
|
||||
def double((xn,zn)):
|
||||
x = (xn ** 2 - zn ** 2) ** 2
|
||||
z = 4 * xn * zn * (xn ** 2 + A * xn * zn + zn ** 2)
|
||||
return (x % P, z % P)
|
||||
|
||||
def curve25519(n, base):
|
||||
one = (base,1)
|
||||
two = double(one)
|
||||
# f(m) evaluates to a tuple containing the mth multiple and the
|
||||
# (m+1)th multiple of base.
|
||||
def f(m):
|
||||
if m == 1: return (one, two)
|
||||
(pm, pm1) = f(m / 2)
|
||||
if (m & 1):
|
||||
return (add(pm, pm1, one), double(pm1))
|
||||
return (double(pm), add(pm, pm1, one))
|
||||
((x,z), _) = f(n)
|
||||
return (x * inv(z)) % P
|
||||
|
||||
def unpack(s):
|
||||
if len(s) != 32: raise ValueError('Invalid Curve25519 argument')
|
||||
return sum(ord(s[i]) << (8 * i) for i in range(32))
|
||||
|
||||
def pack(n):
|
||||
return ''.join([chr((n >> (8 * i)) & 255) for i in range(32)])
|
||||
|
||||
def clamp(n):
|
||||
n &= ~7
|
||||
n &= ~(128 << 8 * 31)
|
||||
n |= 64 << 8 * 31
|
||||
return n
|
||||
|
||||
def smult_curve25519(n, p):
|
||||
n = clamp(unpack(n))
|
||||
p = unpack(p)
|
||||
return pack(curve25519(n, p))
|
||||
|
||||
def smult_curve25519_base(n):
|
||||
n = clamp(unpack(n))
|
||||
return pack(curve25519(n, 9))
|
||||
|
||||
|
||||
#
|
||||
# This part I'm adding in for compatibility with the curve25519 python
|
||||
# module. -Nick
|
||||
#
|
||||
import os
|
||||
|
||||
class Private:
|
||||
def __init__(self, secret=None, seed=None):
|
||||
self.private = pack(clamp(unpack(os.urandom(32))))
|
||||
|
||||
def get_public(self):
|
||||
return Public(smult_curve25519_base(self.private))
|
||||
|
||||
def get_shared_key(self, public, hashfn):
|
||||
return hashfn(smult_curve25519(self.private, public.public))
|
||||
|
||||
def serialize(self):
|
||||
return self.private
|
||||
|
||||
class Public:
|
||||
def __init__(self, public):
|
||||
self.public = public
|
||||
|
||||
def serialize(self):
|
||||
return self.public
|
||||
|
||||
Reference in New Issue
Block a user