Ćwiczenia 2
This commit is contained in:
parent
994c287af6
commit
b973310a9a
120
2/1.py
Normal file
120
2/1.py
Normal file
@ -0,0 +1,120 @@
|
||||
import gmpy2
|
||||
from gmpy2 import mpz, is_prime, powmod, invert, random_state, mpz_random
|
||||
import random
|
||||
|
||||
# Task 1: Generate a random elliptic curve over F_p
|
||||
def generate_random_curve(p):
|
||||
p = mpz(p)
|
||||
rs = random_state(random.randrange(2**32))
|
||||
while True:
|
||||
A = mpz_random(rs, p)
|
||||
B = mpz_random(rs, p)
|
||||
# Check that the discriminant is non-zero
|
||||
discriminant = (4 * powmod(A, 3, p) + 27 * powmod(B, 2, p)) % p
|
||||
if discriminant != 0:
|
||||
return A, B
|
||||
|
||||
# Task 2: Find a random point on the elliptic curve over F_p
|
||||
def find_random_point(A, B, p):
|
||||
p = mpz(p)
|
||||
rs = random_state(random.randrange(2**32))
|
||||
while True:
|
||||
x = mpz_random(rs, p)
|
||||
rhs = (powmod(x, 3, p) + A * x + B) % p
|
||||
legendre_symbol = gmpy2.legendre(rhs, p)
|
||||
if legendre_symbol == 1:
|
||||
# Compute y using the fact that p ≡ 3 mod 4
|
||||
y = powmod(rhs, (p + 1) // 4, p)
|
||||
return x, y
|
||||
elif legendre_symbol == 0:
|
||||
# y = 0 is a valid solution
|
||||
y = mpz(0)
|
||||
return x, y
|
||||
# If rhs is not a quadratic residue, try another x
|
||||
|
||||
# Task 3: Compute the inverse (negative) of a given point
|
||||
def point_negation(P, p):
|
||||
x, y = P
|
||||
return x, (-y) % p
|
||||
|
||||
# Task 4: Compute P ⊕ Q, the sum of two points on the elliptic curve
|
||||
def point_addition(P, Q, A, p):
|
||||
if P == 'O':
|
||||
return Q
|
||||
if Q == 'O':
|
||||
return P
|
||||
x1, y1 = P
|
||||
x2, y2 = Q
|
||||
if x1 == x2 and (y1 + y2) % p == 0:
|
||||
# P + (-P) = O
|
||||
return 'O'
|
||||
if x1 == x2 and y1 == y2:
|
||||
# Point doubling
|
||||
if y1 == 0:
|
||||
return 'O'
|
||||
numerator = (3 * powmod(x1, 2, p) + A) % p
|
||||
denominator = (2 * y1) % p
|
||||
else:
|
||||
# P ≠ Q
|
||||
numerator = (y2 - y1) % p
|
||||
denominator = (x2 - x1) % p
|
||||
inv_denominator = invert(denominator, p)
|
||||
if inv_denominator is None:
|
||||
return 'O' # Cannot invert denominator; result is point at infinity
|
||||
lam = (numerator * inv_denominator) % p
|
||||
x3 = (powmod(lam, 2, p) - x1 - x2) % p
|
||||
y3 = (lam * (x1 - x3) - y1) % p
|
||||
return x3, y3
|
||||
|
||||
# Task 5: Compute nP, the scalar multiplication of a point
|
||||
def scalar_multiplication(P, n, A, p):
|
||||
n = mpz(n)
|
||||
result = 'O' # Start with the point at infinity
|
||||
addend = P
|
||||
while n > 0:
|
||||
if n % 2 == 1:
|
||||
result = point_addition(result, addend, A, p)
|
||||
addend = point_addition(addend, addend, A, p)
|
||||
n = n // 2
|
||||
return result
|
||||
|
||||
# Helper function to generate a large prime p ≡ 3 mod 4
|
||||
def generate_large_prime(bits):
|
||||
rs = random_state(random.randrange(2**32))
|
||||
while True:
|
||||
candidate = mpz_random(rs, 2 ** bits)
|
||||
candidate |= 1 # Ensure it's odd
|
||||
candidate |= 3 # Ensure p ≡ 3 mod 4
|
||||
candidate = gmpy2.next_prime(candidate)
|
||||
if candidate % 4 == 3 and candidate.bit_length() == bits:
|
||||
return candidate
|
||||
|
||||
# Example usage of the functions
|
||||
if __name__ == "__main__":
|
||||
# Generate a large prime p ≡ 3 mod 4 (approximately 300 bits)
|
||||
bits = 300
|
||||
p = generate_large_prime(bits)
|
||||
print(f"Generated prime p = {p}")
|
||||
|
||||
# Task 1: Generate random curve coefficients A and B
|
||||
A, B = generate_random_curve(p)
|
||||
print(f"Random curve coefficients: A = {A}, B = {B}")
|
||||
|
||||
# Task 2: Find a random point on the curve
|
||||
P = find_random_point(A, B, p)
|
||||
print(f"Random point P = {P}")
|
||||
|
||||
# Task 3: Compute the inverse of point P
|
||||
negative_P = point_negation(P, p)
|
||||
print(f"Inverse of P: -P = {negative_P}")
|
||||
|
||||
# Task 4: Add two points P and Q on the curve
|
||||
Q = find_random_point(A, B, p)
|
||||
print(f"Another random point Q = {Q}")
|
||||
R = point_addition(P, Q, A, p)
|
||||
print(f"Sum of P and Q: R = P ⊕ Q = {R}")
|
||||
|
||||
# Task 5: Compute nP for a random scalar n
|
||||
n = mpz_random(random_state(random.randrange(2**32)), p)
|
||||
nP = scalar_multiplication(P, n, A, p)
|
||||
print(f"Scalar multiplication: {n} * P = {nP}")
|
BIN
miniprojekt_nr2.pdf
Normal file
BIN
miniprojekt_nr2.pdf
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user