49 lines
1.4 KiB
Python
49 lines
1.4 KiB
Python
|
import random
|
||
|
from sympy import isprime
|
||
|
|
||
|
def generate_large_prime(bits=512):
|
||
|
"""Generate a large prime number of specified bit length."""
|
||
|
p = 1
|
||
|
while not isprime(p):
|
||
|
p = random.getrandbits(bits)
|
||
|
return p
|
||
|
|
||
|
def blum_blum_shub(p, q, seed, length):
|
||
|
"""Blum-Blum-Shub PRNG for generating nonces."""
|
||
|
n = p * q
|
||
|
x = seed ** 2 % n
|
||
|
output_bits = []
|
||
|
for _ in range(length):
|
||
|
x = x ** 2 % n
|
||
|
output_bits.append(x % 2)
|
||
|
return int(''.join(map(str, output_bits)), 2)
|
||
|
|
||
|
def generate_keys():
|
||
|
"""Generate public and private keys for the Schnorr signature scheme."""
|
||
|
p = generate_large_prime()
|
||
|
q = generate_large_prime()
|
||
|
n = p * q
|
||
|
g = 0o12341234 # Example
|
||
|
x = 0o12341234 # Example
|
||
|
y = pow(g, x, n)
|
||
|
return (p, q, g, n, x, y)
|
||
|
|
||
|
def schnorr_sign(message, p, q, g, n, x):
|
||
|
"""Generate a Schnorr signature for a message."""
|
||
|
k = blum_blum_shub(p, q, random.randint(2, 2), 256)
|
||
|
r = pow(g, k, n)
|
||
|
s = (k - x * hash(message)) % (n-1)
|
||
|
return (r, s)
|
||
|
|
||
|
def main():
|
||
|
p, q, g, n, x, y = generate_keys()
|
||
|
message = "Sign this message!"
|
||
|
signature1 = schnorr_sign(message, p, q, g, n, x)
|
||
|
signature2 = schnorr_sign(message, p, q, g, n, x)
|
||
|
print("Public Key:", y)
|
||
|
print("Signature 1:", signature1)
|
||
|
print("Signature 2:", signature2)
|
||
|
|
||
|
if __name__ == "__main__":
|
||
|
main()
|