diff --git a/pytor/ed25519.py b/pytor/ed25519.py index 1bc8b0d..e457fec 100644 --- a/pytor/ed25519.py +++ b/pytor/ed25519.py @@ -6,16 +6,14 @@ code released under the terms of the GNU Public License v3, copyleft 2015 yoochan """ import collections -import hashlib -import os Point = collections.namedtuple('Point', ['x', 'y']) -key_mask = int.from_bytes(b'\x3F' + b'\xFF' * 30 + - b'\xF8', 'big', signed=False) - class Ed25519(): + ''' + Generate public key from private key secret hash + ''' length = 256 @@ -28,9 +26,6 @@ class Ed25519(): self.B = self.point(4 * self.inverse(5)) - def to_hash(self, m): - return hashlib.sha512(m).digest() - def from_bytes(self, h): """ pick 32 bytes, return a 256 bit int """ return int.from_bytes(h[0:self.length // 8], 'little', signed=False) @@ -38,64 +33,13 @@ class Ed25519(): def to_bytes(self, k): return k.to_bytes(self.length // 8, 'little', signed=False) - def as_key(self, h): - return 2**(self.length - 2) + (self.from_bytes(h) & key_mask) - - def secret_key(self): - """ pick a random secret key """ - m = os.urandom(1024) - h = self.to_hash(m) - k = self.as_key(h) - return self.to_bytes(k) - - def public_key(self, sk): - """ compute the public key from the secret one """ - return self.public_key_from_hash(self.as_key(self.to_hash(sk))) - def public_key_from_hash(self, hash): - c = self.outer(self.B, hash) - return self.point_to_bytes(c) - - def public_key_from_byte_key(self, hash): c = self.outer(self.B, int.from_bytes(hash[:32], 'little')) return self.point_to_bytes(c) def inverse(self, x): return pow(x, self.q - 2, self.q) - def sign(self, message, secret_key, public_key): - s_h = self.to_hash(secret_key) - return self.sign_from_hash(message, s_h, public_key) - - def sign_from_hash(self, message, hash, public_key): - s_h = hash - s_d = self.as_key(s_h) - - m_h = self.to_hash(s_h[self.length // 8:self.length // 4] + message) - m_d = self.from_bytes(m_h) - - R = self.outer(self.B, m_d) - - r_h = self.to_hash(self.point_to_bytes(R) + public_key + message) - r_d = m_d + self.from_bytes(r_h) * s_d - - return self.point_to_bytes(R) + self.to_bytes(r_d % self.l) - - def verify(self, message, signature, public_key): - r_b = signature[0:self.length // 8] - r_h = self.to_hash(r_b + public_key + message) - r_d = self.from_bytes(r_h) - - s_d = self.from_bytes(signature[self.length // 8:self.length // 4]) - b_j = self.outer(self.B, s_d) - - P = self.bytes_to_point(public_key) - p_j = self.outer(P, r_d) - - R = self.bytes_to_point(r_b) - - return b_j == self.inner(R, p_j) - def recover(self, y): """ given a value y, recover the preimage x """ p = (y * y - 1) * self.inverse(self.d * y * y + 1) @@ -110,10 +54,6 @@ class Ed25519(): """ given a value y, recover x and return the corresponding P(x, y) """ return Point(self.recover(y) % self.q, y % self.q) - def is_on_curve(self, P): - return ( - P.y * P.y - P.x * P.x - 1 - self.d * P.x * P.x * P.y * P.y) % self.q == 0 - def inner(self, P, Q): """ inner product on the curve, between two points """ x = (P.x * Q.y + Q.x * P.y) * \ @@ -134,11 +74,3 @@ class Ed25519(): def point_to_bytes(self, P): return (P.y + ((P.x & 1) << 255)).to_bytes(self.length // 8, 'little') - - def bytes_to_point(self, b): - i = self.from_bytes(b) - y = i % 2**(self.length - 1) - x = self.recover(y) - if (x & 1) != ((i >> (self.length - 1)) & 1): - x = self.q - x - return Point(x, y) diff --git a/pytor/onion.py b/pytor/onion.py index 96f70eb..2902202 100644 --- a/pytor/onion.py +++ b/pytor/onion.py @@ -204,7 +204,7 @@ class OnionV3(Onion): def _save_keypair(self, key: bytes) -> None: self._priv = key - self._pub = Ed25519().public_key_from_byte_key(key) + self._pub = Ed25519().public_key_from_hash(key) def gen_new_private_key(self) -> None: 'Generate new tor ed25519 512 bits key'