xi-keyring

simple and extensible alternative for gnome-keyring
git clone https://git.ce9e.org/xi-keyring.git

commit
45f757d0a1fcd7ec699942bee88fd55c26c92df4
parent
45fd19d6e80fe1318a467c8a49d14e64a01c2ef1
Author
Tobias Bengfort <tobias.bengfort@posteo.de>
Date
2024-08-04 06:24
refactor crypt to be more flexible

Diffstat

M xikeyring/keyring.py 38 ++++++++++++++++----------------------

1 files changed, 16 insertions, 22 deletions


diff --git a/xikeyring/keyring.py b/xikeyring/keyring.py

@@ -35,7 +35,7 @@ class Crypt:
   35    35     def __init__(self, password: bytes):
   36    36         self.password = KernelKey(password)
   37    37 
   38    -1     def get_key(self, salt: bytes, iterations: int) -> bytes:
   -1    38     def get_pkbf2(self, salt: bytes, iterations: int) -> bytes:
   39    39         if iterations < 100_000:
   40    40             raise ValueError('Too few iterations')
   41    41         kdf = PBKDF2HMAC(
@@ -44,37 +44,31 @@ class Crypt:
   44    44             salt=salt,
   45    45             iterations=iterations,
   46    46         )
   47    -1         return base64.urlsafe_b64encode(kdf.derive(self.password.value))
   -1    47         key = kdf.derive(self.password.value)
   -1    48         return base64.urlsafe_b64encode(key)
   48    49 
   49    -1     def encode(self, salt: bytes, iterations: int, content: bytes) -> bytes:
   -1    50     def encrypt(self, data: bytes) -> bytes:
   -1    51         salt = os.urandom(16)
   -1    52         params = [100_000]
   -1    53         key = self.get_pkbf2(salt, *params)
   -1    54         content = Fernet(key).encrypt(data)
   50    55         return b'$'.join(
   51    56             [
   52    57                 b'fernet',
   53    58                 base64.urlsafe_b64encode(salt),
   54    -1                 str(iterations).encode(),
   -1    59                 *[str(p).encode() for p in params],
   55    60                 content,
   56    61             ]
   57    62         )
   58    63 
   59    -1     def decode(self, data: bytes) -> tuple[bytes, int, bytes]:
   60    -1         algo, salt, iterations, content = data.split(b'$')
   61    -1         if algo != b'fernet':
   62    -1             raise TypeError('Unknown encryption algorithm')
   63    -1         return (
   64    -1             base64.urlsafe_b64decode(salt),
   65    -1             int(iterations, 10),
   66    -1             content,
   67    -1         )
   68    -1 
   69    -1     def encrypt(self, data: bytes, iterations=100_000) -> bytes:
   70    -1         salt = os.urandom(16)
   71    -1         key = self.get_key(salt, iterations)
   72    -1         content = Fernet(key).encrypt(data)
   73    -1         return self.encode(salt, iterations, content)
   74    -1 
   75    64     def decrypt(self, data: bytes) -> bytes:
   76    -1         salt, iterations, content = self.decode(data)
   77    -1         key = self.get_key(salt, iterations)
   -1    65         algo, salt, *params, content = data.split(b'$')
   -1    66         salt = base64.urlsafe_b64decode(salt)
   -1    67         params = [int(p, 10) for p in params]
   -1    68         if algo == b'fernet' and len(params) == 1:
   -1    69             key = self.get_pkbf2(salt, *params)
   -1    70         else:
   -1    71             raise TypeError('Unknown encryption algorithm')
   78    72         return Fernet(key).decrypt(content)
   79    73 
   80    74