summaryrefslogtreecommitdiff
path: root/src/xpit_/identity.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/xpit_/identity.py')
-rw-r--r--src/xpit_/identity.py59
1 files changed, 59 insertions, 0 deletions
diff --git a/src/xpit_/identity.py b/src/xpit_/identity.py
new file mode 100644
index 0000000..2786b2d
--- /dev/null
+++ b/src/xpit_/identity.py
@@ -0,0 +1,59 @@
+import os
+import base64
+from sys import stdout
+from cryptography.hazmat.primitives import serialization
+from cryptography.hazmat.primitives.asymmetric import ed25519
+from cryptography.hazmat.primitives.asymmetric.types import PrivateKeyTypes, PublicKeyTypes
+
+# TODO guard against bad file access
+def create(path: str) -> None:
+ private_key = ed25519.Ed25519PrivateKey.generate()
+ public_key = private_key.public_key()
+ enc = serialization.NoEncryption()
+
+ os.mkdir(path)
+
+ data = private_key.private_bytes(
+ encoding=serialization.Encoding.PEM,
+ format=serialization.PrivateFormat.PKCS8,
+ encryption_algorithm=enc,
+ )
+ with open(os.path.join(path, "private.pem"), "wb") as f:
+ f.write(data)
+
+ data = public_key.public_bytes(
+ encoding=serialization.Encoding.PEM,
+ format=serialization.PublicFormat.SubjectPublicKeyInfo,
+ )
+ with open(os.path.join(path, "public.pub"), "wb") as f:
+ f.write(data)
+
+def load(identities_dir: str, identity: str) -> tuple[PrivateKeyTypes, PublicKeyTypes]:
+ if not os.path.isdir(identities_dir):
+ os.makedirs(identities_dir)
+
+ path = os.path.join(identities_dir, identity)
+
+ if not os.path.isdir(path):
+ stdout.write(f"Generating new identity '{identity}'...\n")
+ create(path)
+ stdout.write(f"Created new identity '{identity}' at: {path}\n")
+
+ with open(os.path.join(path, "private.pem"), "rb") as f:
+ private_key_data = f.read()
+ with open(os.path.join(path, "public.pub"), "rb") as f:
+ public_key_data = f.read()
+
+ return (
+ serialization.load_pem_private_key(private_key_data, password=None),
+ serialization.load_pem_public_key(public_key_data)
+ )
+
+def id_from_pubkey(pubkey: PublicKeyTypes) -> bytes:
+ der = pubkey.public_bytes(
+ encoding=serialization.Encoding.DER,
+ format=serialization.PublicFormat.SubjectPublicKeyInfo,
+ )
+ b64 = base64.b64encode(der)
+ return b64[16:24]
+