+ File structure re-design
+ Moved ECC functions to a dedicated Crypto class
This commit is contained in:
42
pyplayready/crypto/elgamal.py
Normal file
42
pyplayready/crypto/elgamal.py
Normal file
@@ -0,0 +1,42 @@
|
||||
from typing import Tuple
|
||||
|
||||
from ecpy.curves import Curve, Point
|
||||
import secrets
|
||||
|
||||
|
||||
class ElGamal:
|
||||
"""ElGamal ECC utility using ecpy"""
|
||||
|
||||
def __init__(self, curve: Curve):
|
||||
"""Initialize the utility with a given curve type ('secp256r1' for PlayReady)"""
|
||||
self.curve = curve
|
||||
|
||||
@staticmethod
|
||||
def to_bytes(n: int) -> bytes:
|
||||
byte_len = (n.bit_length() + 7) // 8
|
||||
if byte_len % 2 != 0:
|
||||
byte_len += 1
|
||||
return n.to_bytes(byte_len, 'big')
|
||||
|
||||
def encrypt(self, message_point: Point, public_key: Point) -> Tuple[Point, Point]:
|
||||
"""
|
||||
Encrypt a single point with a given public key
|
||||
|
||||
Returns an encrypted point pair
|
||||
"""
|
||||
ephemeral_key = secrets.randbelow(self.curve.order)
|
||||
point1 = ephemeral_key * self.curve.generator
|
||||
point2 = message_point + (ephemeral_key * public_key)
|
||||
return point1, point2
|
||||
|
||||
@staticmethod
|
||||
def decrypt(encrypted: Tuple[Point, Point], private_key: int) -> Point:
|
||||
"""
|
||||
Decrypt and encrypted point pair with a given private key
|
||||
|
||||
Returns a single decrypted point
|
||||
"""
|
||||
point1, point2 = encrypted
|
||||
shared_secret = private_key * point1
|
||||
decrypted_message = point2 - shared_secret
|
||||
return decrypted_message
|
||||
Reference in New Issue
Block a user