|
|
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, signature, string):
|
|
|
if signature.key_type == TYPE_ECDSA:
|
|
|
public = VerifyingKey.from_string(base64.b64decode(signature.key))
|
|
|
signature_byte = base64.b64decode(signature.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()
|
|
|
|