usawa

Signed, immutable accounting.
Log | Files | Refs | Submodules | LICENSE

commit 539466ec5d68693475cad50967dc6f1197c0f4fb
parent f9ebd99a7bebae320546762c2a9f42616ea6c6fd
Author: Carlosokumu <carlosokumu254@gmail.com>
Date:   Fri, 13 Mar 2026 19:55:25 +0300

add wallet setup logic

Diffstat:
Adummy/usawa/core/setup_wallet.py | 116+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adummy/usawa/core/usawa_wallet.py | 19+++++++++++++++++++
2 files changed, 135 insertions(+), 0 deletions(-)

diff --git a/dummy/usawa/core/setup_wallet.py b/dummy/usawa/core/setup_wallet.py @@ -0,0 +1,116 @@ +import getpass +import logging +import os +import subprocess +from nacl.signing import SigningKey + + +logg = logging.getLogger("core.setup_wallet") + +GNUPG_DIR = "gnupg" +PRIVATEKEY_FILE = "privatekey.asc" +PUBLICKEY_FILE = "publickey.bin" + + +def _generate_gpg_key(gpg_dir, name, email, passphrase=None): + env = {**os.environ, "GNUPGHOME": gpg_dir} + + subprocess.run( + ["gpg-agent", "--homedir", gpg_dir, "--daemon"], + capture_output=True, + env=env, + ) + + batch_input = "\n".join( + [ + "Key-Type: EdDSA", + "Key-Curve: ed25519", + "Subkey-Type: ECDH", + "Subkey-Curve: cv25519", + f"Name-Real: {name}", + f"Name-Email: {email}", + f"Passphrase: {passphrase}" if passphrase else "%no-protection", + "%commit", + "", + ] + ) + + result = subprocess.run( + ["gpg", "--homedir", gpg_dir, "--batch", "--gen-key"], + input=batch_input.encode(), + capture_output=True, + env=env, + ) + if result.returncode != 0: + logg.error("key generation failed: %s", result.stderr.decode()) + return None + + list_result = subprocess.run( + ["gpg", "--homedir", gpg_dir, "--with-colons", "--fingerprint", email], + capture_output=True, + env=env, + ) + for line in list_result.stdout.decode().splitlines(): + if line.startswith("fpr"): + return line.split(":")[9] + return None + + +def setup_wallet(): + # Step 1 - Create gnupg dir + gpg_dir = os.path.abspath(GNUPG_DIR) + os.makedirs(gpg_dir, mode=0o700, exist_ok=True) + logg.debug("gpg directory: %s", gpg_dir) + + env = {**os.environ, "GNUPGHOME": gpg_dir} + + # Step 2 - Prompt user + name = input("Enter your name: ") + email = input("Enter your email: ") + passphrase = getpass.getpass("Enter wallet passphrase: ") + + # Step 3 - Generate keypair via subprocess + fingerprint = _generate_gpg_key(gpg_dir, name, email, passphrase) + if not fingerprint: + logg.error("key generation failed") + return 1 + logg.info("generated key fingerprint: %s", fingerprint) + + # Step 4 - Generate privatekey.asc (32 random bytes encrypted to GPG key) + random_bytes = os.urandom(32) + result = subprocess.run( + [ + "gpg", + "--homedir", + gpg_dir, + "--armor", + "--encrypt", + "--trust-model", + "always", + "-r", + fingerprint, + ], + input=random_bytes, + capture_output=True, + env=env, + ) + if result.returncode != 0: + logg.error("encryption failed: %s", result.stderr.decode()) + return 1 + with open(PRIVATEKEY_FILE, "wb") as f: + f.write(result.stdout) + logg.info("private key material saved to: %s", PRIVATEKEY_FILE) + + # Step 5 - Derive public key + sk = SigningKey(random_bytes) + pk = sk.verify_key + with open(PUBLICKEY_FILE, "wb") as f: + f.write(pk.encode()) + logg.info("public key saved to: %s", PUBLICKEY_FILE) + + # Step 6 - Config summary + logg.info("setup complete. add the following to your config:") + logg.info(" gpg_dir = %s", gpg_dir) + logg.info("public key (hex): %s", pk.encode().hex()) + + return 0 diff --git a/dummy/usawa/core/usawa_wallet.py b/dummy/usawa/core/usawa_wallet.py @@ -0,0 +1,19 @@ +import gnupg +import logging + +from usawa.crypto import DemoWallet + + +logg = logging.getLogger("usawawallet") + + +class UsawaWallet(DemoWallet): + + def __init__(self, keyfile, gpgdir="~/.gnupg", passphrase=None): + self.gpg = gnupg.GPG(gnupghome=gpgdir) + self.keyfile = keyfile + f = open(self.keyfile, "rb") + pk = self.gpg.decrypt_file(f, passphrase=passphrase) + f.close() + logg.debug("decrypted pk with key {}".format(pk.key_id)) + super(UsawaWallet, self).__init__(privatekey=pk.data)