Skip to content

Commit

Permalink
Modified: User model to include certificate data (#71)
Browse files Browse the repository at this point in the history
  • Loading branch information
signebedi committed Mar 26, 2024
1 parent 007239b commit 6354bd1
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 14 deletions.
32 changes: 18 additions & 14 deletions libreforms_fastapi/utils/certificates.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""
# Example usage:
user_id = 'user123'
ds_manager = DigitalSignatureManager(user_id)
username = 'user123'
ds_manager = DigitalSignatureManager(username)
ds_manager.generate_rsa_key_pair()
data_to_sign = b"Important document content."
Expand All @@ -26,8 +26,8 @@
from cryptography.exceptions import InvalidSignature

class DigitalSignatureManager:
def __init__(self, user_id, env="development", key_storage_path=os.path.join('instance', 'keys')):
self.user_id = user_id
def __init__(self, username, env="development", key_storage_path=os.path.join('instance', 'keys')):
self.username = username
self.env = env
self.key_storage_path = key_storage_path
self.ensure_key_storage()
Expand All @@ -37,10 +37,10 @@ def ensure_key_storage(self):
os.makedirs(self.key_storage_path)

def get_private_key_file(self):
return os.path.join(self.key_storage_path, f"{self.env}_{self.user_id}_private.key")
return os.path.join(self.key_storage_path, f"{self.env}_{self.username}_private.key")

def get_public_key_file(self):
return os.path.join(self.key_storage_path, f"{self.env}_{self.user_id}_public.key")
return os.path.join(self.key_storage_path, f"{self.env}_{self.username}_public.key")

def generate_rsa_key_pair(self):
"""
Expand All @@ -53,6 +53,12 @@ def generate_rsa_key_pair(self):
)
public_key = private_key.public_key()

self.public_key_bytes = public_key.public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo
)


# Save the private key
with open(self.get_private_key_file(), "wb") as private_file:
private_file.write(
Expand All @@ -65,12 +71,7 @@ def generate_rsa_key_pair(self):

# Save the public key
with open(self.get_public_key_file(), "wb") as public_file:
public_file.write(
public_key.public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo
)
)
public_file.write(self.public_key_bytes)

def sign_data(self, data):
"""
Expand Down Expand Up @@ -131,23 +132,26 @@ def serialize_record_for_signing(record):
print(select_data_fields)
return json.dumps(select_data_fields, sort_keys=True)

def sign_record(record, ds_manager):
def sign_record(record, username, env="development"):
"""
Generates a signature for the given record and inserts it into the '_signature' field.
"""
ds_manager = DigitalSignatureManager(username=username, env=env)
serialized = serialize_record_for_signing(record)
signature = ds_manager.sign_data(serialized.encode())
record['metadata']['_signature'] = signature.hex() # Store the signature as a hex string
return record

def verify_record_signature(record, ds_manager):
def verify_record_signature(record, username, env="development"):
"""
Verifies the signature of the given record.
Returns True if the signature is valid, False otherwise.
"""
if '_signature' not in record['metadata'] or record['metadata']['_signature'] is None:
return False # No signature to verify

ds_manager = DigitalSignatureManager(username=username, env=env)

record_copy = copy.deepcopy(record)
signature_bytes = bytes.fromhex(record['metadata']['_signature'])
serialized = serialize_record_for_signing(record_copy)
Expand Down
3 changes: 3 additions & 0 deletions libreforms_fastapi/utils/sqlalchemy_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
String,
DateTime,
JSON,
LargeBinary,
)
from sqlalchemy.orm import relationship, declarative_base

Expand Down Expand Up @@ -49,6 +50,8 @@ class User(Base):
created_date = Column(DateTime, nullable=False, default=tz_aware_datetime)
last_login = Column(DateTime, nullable=True, default=tz_aware_datetime)
locked_until = Column(DateTime, nullable=True, default=tz_aware_datetime)
public_key = Column(LargeBinary(), nullable=True)
private_key_ref = Column(String, nullable=True)
last_password_change = Column(DateTime, nullable=True, default=tz_aware_datetime)
failed_login_attempts = Column(Integer, default=0)
api_key = Column(String(1000), ForeignKey('signing.signature'), nullable=True, unique=True)
Expand Down

0 comments on commit 6354bd1

Please sign in to comment.