xi-keyring

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

commit
25cfb6114c00dbe07be55fc144d6513d6470f5b6
parent
6d9bc9fe0a96469ee864c6755c125991a8e73115
Author
Tobias Bengfort <tobias.bengfort@posteo.de>
Date
2024-05-10 10:36
store primary password in kernel keyring

Diffstat

A xikeyring/kernel_keyring.py 39 +++++++++++++++++++++++++++++++++++++++
M xikeyring/keyring.py 5 +++--

2 files changed, 42 insertions, 2 deletions


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

@@ -0,0 +1,39 @@
   -1     1 import ctypes
   -1     2 import os
   -1     3 
   -1     4 keyutils = ctypes.CDLL('libkeyutils.so.1')
   -1     5 
   -1     6 THREAD_KEYRING = -1
   -1     7 PROCESS_KEYRING = -2
   -1     8 SESSION_KEYRING = -3
   -1     9 USER_KEYRING = -4
   -1    10 USER_SESSION_KEYRING = -5
   -1    11 GROUP_KEYRING = -6
   -1    12 
   -1    13 
   -1    14 def add_key(name: bytes, value: bytes, keyring: int) -> tuple[int, int]:
   -1    15     size = len(value)
   -1    16     id = keyutils.add_key(b'user', name, value, size, keyring)
   -1    17     if id == -1:
   -1    18         errno = ctypes.get_errno()
   -1    19         raise OSError(errno, os.strerror(errno))
   -1    20     return id, size
   -1    21 
   -1    22 
   -1    23 def get_key(id: int, size: int) -> bytes:
   -1    24     buf = ctypes.create_string_buffer(size)
   -1    25     result = keyutils.keyctl_read(id, buf, size)
   -1    26     if result == -1:
   -1    27         errno = ctypes.get_errno()
   -1    28         raise OSError(errno, os.strerror(errno))
   -1    29     return buf.value
   -1    30 
   -1    31 
   -1    32 class KernelKey:
   -1    33     def __init__(self, value: bytes, keyring: int = PROCESS_KEYRING):
   -1    34         name = f'kernel-key-{id(self)}'.encode()
   -1    35         self.id, self.size = add_key(name, value, keyring)
   -1    36 
   -1    37     @property
   -1    38     def value(self):
   -1    39         return get_key(self.id, self.size)

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

@@ -8,6 +8,7 @@ from cryptography.fernet import InvalidToken
    8     8 from cryptography.hazmat.primitives import hashes
    9     9 from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
   10    10 
   -1    11 from .kernel_keyring import KernelKey
   11    12 from .prompt import PinentryPrompt as Prompt
   12    13 
   13    14 TRUSTED_MANAGERS = [
@@ -32,7 +33,7 @@ class Item:
   32    33 
   33    34 class Crypt:
   34    35     def __init__(self, password: bytes):
   35    -1         self.password = password
   -1    36         self.password = KernelKey(password)
   36    37 
   37    38     def get_key(self, salt: bytes, iterations: int) -> bytes:
   38    39         if iterations < 100_000:
@@ -43,7 +44,7 @@ class Crypt:
   43    44             salt=salt,
   44    45             iterations=iterations,
   45    46         )
   46    -1         return base64.urlsafe_b64encode(kdf.derive(self.password))
   -1    47         return base64.urlsafe_b64encode(kdf.derive(self.password.value))
   47    48 
   48    49     def encode(self, salt: bytes, iterations: int, content: bytes) -> bytes:
   49    50         return b'$'.join(