def sign_hash(self, hash): e = hex_to_int(hash) if isinstance(hash, str) else bytes_to_int(hash) r, s = 0, 0 while r == 0 or s == 0: k = secrets.randbelow(N) point = CURVE.G * k r = point.x % N inv_k = mulinv(k, N) s = (inv_k * (e + r * self.int())) % N return Signature(r=r, s=s)
def verify_hash(self, hash, pubkey): if not (1 <= self.r < CURVE.N and 1 <= self.s < CURVE.N): return False e = bytes_to_int(hash) w = mulinv(self.s, CURVE.N) u1 = (e * w) % CURVE.N u2 = (self.r * w) % CURVE.N point = CURVE.G * u1 + pubkey.point * u2 return self.r % CURVE.N == point.x % CURVE.N
def _verify_ecdsa(self, signature: Signature, public: PublicKey) -> bool: r, s = signature.r, signature.s if not (1 <= r < N and 1 <= s < N): return False e = hex_to_int(self.hash()) w = mulinv(s, N) u1 = (e * w) % N u2 = (r * w) % N point = CURVE.G * u1 + public.point * u2 return r % N == point.x % N
def sign(self, private: PrivateKey) -> Signature: e = hex_to_int(self.hash()) r, s = 0, 0 while r == 0 or s == 0: k = secrets.randbelow(N) point = CURVE.G * k r = point.x % N inv_k = mulinv(k, N) s = (inv_k * (e + r * private.int())) % N return Signature(r=r, s=s)
def generate_keypair(bits): p = random_prime(bits // 2) q = random_prime(bits // 2) n = p * q phi = (p - 1) * (q - 1) e = random_coprime(phi) # alternative e = 65537 d = mulinv(e, phi) private = (d, n) public = (e, n) return private, public