def verify(self, m, r, s, y, dgst=hashlib.sha1):
   # signature verification
   # https://en.wikipedia.org/wiki/Digital_Signature_Algorithm#Verifying
   assert (r > 0 and r < self.q), "wrong r: 0 < r < q"
   assert (s > 0 and s < self.q), "wrong s: 0 < s < q"
   w = invmod(s, self.q)
   u1 = (s2i(dgst(m).digest())*w) % self.q
   u2 = (r*w) % self.q
   v = ((modexp(self.g, u1, self.p)*modexp(y, u2, self.p)) % self.p )% self.q
   assert (v == r), "verification failed, v != r"
   return True
  def signk(self, m, x, dgst=hashlib.sha1):
    # signing with a leak of the k value
    # m - message
    # x - private key
    # https://en.wikipedia.org/wiki/Digital_Signature_Algorithm#Signing
    r = 0
    k = 0
    while r == 0:
      k = randint(0, self.q)
      r = modexp(self.g, k, self.p) % self.q
    s = (invmod(k, self.q) * (s2i(dgst(m).digest())+(x*r))) % self.q

    return (r, s, k)
def b_step2a (pubkey, prvkey, c, oracle):
  """
  Bleichenbacher step 2a
  """
  e = pubkey[0]
  n = pubkey[1]

  c = s2i("".join(c))
  c0 = (c * modexp(1, e, n)) % n

  s1 = n // 0x3B
  count = 0
  while True:
    c1 = (c0 * modexp(s1, e, n)) % n
    if oracle(prvkey, list(i2s(c1))):
      break
    s1 += 1
    if count % 10 == 0:
      sys.stdout.write("%s   \r" % (count))
      sys.stdout.flush()
    count += 1

  return s1
 def y_gen(self, x):
   # y generator
   return modexp(self.g, x, self.p)
 def magic_sign(self, y, z = 20):
   # only if g == p+1
   assert (self.g == self.p+1), "only if g == p+1"
   r = modexp(y, z, self.p) % self.q
   s = r * invmod(z, self.q)
   return (r, s)