"""passbook crypto models""" from binascii import hexlify from typing import Optional from uuid import uuid4 from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.asymmetric.rsa import RSAPrivateKey from cryptography.hazmat.primitives.serialization import load_pem_private_key from cryptography.x509 import Certificate, load_pem_x509_certificate from django.db import models from django.utils.translation import gettext_lazy as _ from passbook.lib.models import CreatedUpdatedModel class CertificateKeyPair(CreatedUpdatedModel): """CertificateKeyPair that can be used for signing or encrypting if `key_data` is set, otherwise it can be used to verify remote data.""" kp_uuid = models.UUIDField(primary_key=True, editable=False, default=uuid4) name = models.TextField() certificate_data = models.TextField(help_text=_("PEM-encoded Certificate data")) key_data = models.TextField( help_text=_( "Optional Private Key. If this is set, you can use this keypair for encryption." ), blank=True, default="", ) _cert: Optional[Certificate] = None _key: Optional[RSAPrivateKey] = None @property def certificate(self) -> Certificate: """Get python cryptography Certificate instance""" if not self._cert: self._cert = load_pem_x509_certificate( self.certificate_data.encode("utf-8"), default_backend() ) return self._cert @property def private_key(self) -> Optional[RSAPrivateKey]: """Get python cryptography PrivateKey instance""" if not self._key: self._key = load_pem_private_key( str.encode("\n".join([x.strip() for x in self.key_data.split("\n")])), password=None, backend=default_backend(), ) return self._key @property def fingerprint(self) -> str: """Get SHA256 Fingerprint of certificate_data""" return hexlify(self.certificate.fingerprint(hashes.SHA256())).decode("utf-8") def __str__(self) -> str: return f"Certificate-Key Pair {self.name} {self.fingerprint}" class Meta: verbose_name = _("Certificate-Key Pair") verbose_name_plural = _("Certificate-Key Pairs")