diff --git a/cashu/core/crypto/keys.py b/cashu/core/crypto/keys.py index 65869cba..36fb7974 100644 --- a/cashu/core/crypto/keys.py +++ b/cashu/core/crypto/keys.py @@ -16,8 +16,7 @@ def derive_keys(mnemonic: str, derivation_path: str): bip32 = BIP32.from_seed(mnemonic.encode()) orders_str = [f"/{i}'" for i in range(settings.max_order)] return { - 2 - ** i: PrivateKey( + 2**i: PrivateKey( bip32.get_privkey_from_path(derivation_path + orders_str[i]), raw=True, ) @@ -25,26 +24,25 @@ def derive_keys(mnemonic: str, derivation_path: str): } -def derive_keys_sha256(master_key: str, derivation_path: str = ""): +def derive_keys_sha256(seed: str, derivation_path: str = ""): """ Deterministic derivation of keys for 2^n values. TODO: Implement BIP32. """ return { - 2 - ** i: PrivateKey( - hashlib.sha256( - (master_key + derivation_path + str(i)).encode("utf-8") - ).digest()[:32], + 2**i: PrivateKey( + hashlib.sha256((seed + derivation_path + str(i)).encode("utf-8")).digest()[ + :32 + ], raw=True, ) for i in range(settings.max_order) } -def derive_pubkey(master_key: str): +def derive_pubkey(seed: str): return PrivateKey( - hashlib.sha256((master_key).encode("utf-8")).digest()[:32], + hashlib.sha256((seed).encode("utf-8")).digest()[:32], raw=True, ).pubkey diff --git a/cashu/core/legacy.py b/cashu/core/legacy.py index 87c64e96..7123476e 100644 --- a/cashu/core/legacy.py +++ b/cashu/core/legacy.py @@ -6,15 +6,14 @@ def derive_keys_backwards_compatible_insecure_pre_0_12( - master_key: str, derivation_path: str = "" + seed: str, derivation_path: str = "" ): """ WARNING: Broken key derivation for backwards compatibility with 0.11. """ return { - 2 - ** i: PrivateKey( - hashlib.sha256((master_key + derivation_path + str(i)).encode("utf-8")) + 2**i: PrivateKey( + hashlib.sha256((seed + derivation_path + str(i)).encode("utf-8")) .hexdigest() .encode("utf-8")[:32], raw=True, diff --git a/cashu/mint/decrypt.py b/cashu/mint/encrypt.py similarity index 91% rename from cashu/mint/decrypt.py rename to cashu/mint/encrypt.py index 53c4b63f..adf0113a 100644 --- a/cashu/mint/decrypt.py +++ b/cashu/mint/encrypt.py @@ -146,6 +146,17 @@ async def migrate(no_dry_run): keyset_dict["id"], ), ) + + click.echo("Initializing mint with encrypted seeds.") + encrypted_mint_private_key = aes.encrypt(settings.mint_private_key.encode()) + ledger = Ledger( + db=Database("mint", settings.mint_database), + seed=encrypted_mint_private_key, + seed_decryption_key=settings.mint_seed_decryption_key, + derivation_path=settings.mint_derivation_path, + backends={}, + crud=LedgerCrudSqlite(), + ) click.echo("✅ Migration complete.") diff --git a/cashu/mint/ledger.py b/cashu/mint/ledger.py index 1849d3cb..0035f24a 100644 --- a/cashu/mint/ledger.py +++ b/cashu/mint/ledger.py @@ -76,17 +76,22 @@ def __init__( assert seed, "seed not set" # decrypt seed if seed_decryption_key is set - self.master_key = ( - AESCipher(seed_decryption_key).decrypt(seed) - if seed_decryption_key - else seed - ) + try: + self.seed = ( + AESCipher(seed_decryption_key).decrypt(seed) + if seed_decryption_key + else seed + ) + except Exception as e: + raise Exception( + f"Could not decrypt seed. Make sure that the seed is correct and the decryption key is set. {e}" + ) self.derivation_path = derivation_path self.db = db self.crud = crud self.backends = backends - self.pubkey = derive_pubkey(self.master_key) + self.pubkey = derive_pubkey(self.seed) self.spent_proofs: Dict[str, Proof] = {} # ------- KEYS ------- @@ -109,7 +114,7 @@ async def activate_keyset( MintKeyset: Keyset """ assert derivation_path, "derivation path not set" - seed = seed or self.master_key + seed = seed or self.seed tmp_keyset_local = MintKeyset( seed=seed, derivation_path=derivation_path, @@ -132,7 +137,7 @@ async def activate_keyset( # no keyset for this derivation path yet # we create a new keyset (keys will be generated at instantiation) keyset = MintKeyset( - seed=seed or self.master_key, + seed=seed or self.seed, derivation_path=derivation_path, version=version or settings.version, ) @@ -503,7 +508,7 @@ async def melt_quote( melt_quote.request ) assert payment_quote.checking_id, "quote has no checking id" - + expiry = None if invoice_obj.expiry is not None: expiry = invoice_obj.date + invoice_obj.expiry