import base64 from ecdsa import SigningKey, VerifyingKey, BadSignatureError from django.db import models TYPE_ECDSA = 'ecdsa' APP_LABEL_BOARDS = 'boards' class KeyPairManager(models.Manager): def generate_key(self, key_type=TYPE_ECDSA, primary=False): if primary and self.filter(primary=True).exists(): raise Exception('There can be only one primary key') if key_type == TYPE_ECDSA: private = SigningKey.generate() public = private.get_verifying_key() private_key_str = base64.b64encode(private.to_string()).decode() public_key_str = base64.b64encode(public.to_string()).decode() return self.create(public_key=public_key_str, private_key=private_key_str, key_type=TYPE_ECDSA, primary=primary) else: raise Exception('Key type not supported') def verify(self, public_key_str, string, signature, key_type=TYPE_ECDSA): if key_type == TYPE_ECDSA: public = VerifyingKey.from_string(base64.b64decode(public_key_str)) signature_byte = base64.b64decode(signature) try: return public.verify(signature_byte, string.encode()) except BadSignatureError: return False else: raise Exception('Key type not supported') def has_primary(self): return self.filter(primary=True).exists() class KeyPair(models.Model): class Meta: app_label = APP_LABEL_BOARDS objects = KeyPairManager() public_key = models.TextField() private_key = models.TextField() key_type = models.TextField() primary = models.BooleanField(default=False) def __str__(self): return '%s::%s' % (self.key_type, self.public_key) def sign(self, string): private = SigningKey.from_string(base64.b64decode( self.private_key.encode())) signature_byte = private.sign_deterministic(string.encode()) return base64.b64encode(signature_byte).decode()