def recover_private_key(m: bytes, signature: DSASignature, k: int, q: int) -> int: """Recover private key from signature and subkey k""" r, s = signature h_m = m39.to_int(m28.SHA1(m).digest()) r_inv = m39.invmod(r, q) return r_inv * (s * k - h_m) % q
def sign(m: bytes, x: int, p: int, q: int, g: int) -> DSASignature: """Sign message with DSA private key""" h_m = m39.to_int(m28.SHA1(m).digest()) r, s = 0, 0 while r == 0 or s == 0: k = randint(1, q - 1) r = pow(g, k, p) % q k_inv = m39.invmod(k, q) s = (k_inv * (h_m + x * r)) % q return DSASignature(r, s)
def verify_relaxed(m: bytes, signature: m43.DSASignature, y: int, p: int, q: int, g: int) -> bool: """Verify DSA signature without checking constraints on r, s""" r, s = signature w = m39.invmod(s, q) h_m = m39.to_int(m28.SHA1(m).digest()) u_1 = h_m * w % q u_2 = r * w % q v = pow(g, u_1, p) * pow(y, u_2, p) % p % q return v == r
def sign_relaxed(m: bytes, x: int, p: int, q: int, g: int) -> m43.DSASignature: """Sign message without checking constraints on r, s""" # The original implementation checks this and falls into # an infinite loop. h_m = m39.to_int(m28.SHA1(m).digest()) k = randint(1, q - 1) k_inv = m39.invmod(k, q) r = pow(g, k, p) % q s = (k_inv * (h_m + x * r)) % q return m43.DSASignature(r, s)
def verify(m: bytes, signature: DSASignature, y: int, p: int, q: int, g: int) -> bool: """Verify DSA signature""" r, s = signature if not 0 < r < q or not 0 < s < q: return False w = m39.invmod(s, q) h_m = m39.to_int(m28.SHA1(m).digest()) u_1 = h_m * w % q u_2 = r * w % q v = pow(g, u_1, p) * pow(y, u_2, p) % p % q return v == r