def verify(self, msg, signature, y): r, s = signature # assert 0 < r < self.q assert 0 < s < self.q w = modinv(s, self.q) u1 = (sha1num(msg) * w) % self.q u2 = (r * w) % self.q v = (pow(self.g, u1, self.p) * pow(y, u2, self.p)) % self.p % self.q return v == r
def sign_hash(self, hash, x): s = 0 while s == 0: r = 0 # while r == 0: if True: k = randrange(1, self.q) r = pow(self.g, k, self.p) % self.q s = (modinv(k, self.q) * (hash + x * r)) % self.q return (r, s)
def reused_k(m1, s1, m2, s2, q): sm = (s1 - s2) % q mm = (m1 - m2) % q k = modinv(sm, q) * mm return k % q
y = 0x2d026f4bf30195ede3a088da85e398ef869611d0f68f0713d51c9c1a3a26c95105d915e2d8cdf26d056b86b8a7b85519b1c23cc3ecdc6062650462e3063bd179c2a6581519f674a61f1d89a1fff27171ebc1b93d4dc57bceb7ae2430f98a6a4d83d8279ee65d71c1203d2c96d65ebbf7cce9d32971c3de5084cce04a2e147821 def reused_k(m1, s1, m2, s2, q): sm = (s1 - s2) % q mm = (m1 - m2) % q k = modinv(sm, q) * mm return k % q assert reused_k(1, 1, 0, 0, 7) == 1 assert reused_k(8, 1, 0, 0, 7) == 1 assert reused_k(0, 1, 6, 0, 7) == 1 for m1 in messages: for m2 in messages: if m1 is m2: continue k = reused_k(m1['m'], m1['s'], m2['m'], m2['s'], q) if k == 0: continue x = (((m1['s'] * k) - m1['m']) * modinv(m1['r'], q)) % q r, s = sign_hash(m1['m'], x, k, q) if r == m1['r'] and s == m1['s']: print(x) break assert hashlib.sha1(hex(x)[2:].encode('ascii')).hexdigest() == 'ca8f6f7c66fa362d40760d135b763eb8527d3d52'