joinmarket-clientserver icon indicating copy to clipboard operation
joinmarket-clientserver copied to clipboard

[Feature request] run the Yield Generator without a password

Open openoms opened this issue 3 years ago • 11 comments

Was thinking about a safe way for YieldGenerator to restart safely in: https://github.com/openoms/joininbox/issues/17

Question is if the Maker would not sign a transaction resulting to losing funds does it need to be password protected at all?

There could be a config option in the joinmarket.cfg to allow the Yield Generator to run (even this might be unnecessary.)

Starting the YG is an active process so no user would participate in transactions unwillingly, but could be easily automated with a systemd process as it happens in JoininBox for example: https://github.com/openoms/joininbox/blob/master/scripts/start.service.sh

openoms avatar Dec 16 '20 11:12 openoms

Password is used to encrypt .jmdat wallet files, so no way you can do anything without password in JM.

kristapsk avatar Dec 16 '20 11:12 kristapsk

I think: if a person has access to the executable script, then they have access to the code, so I'm not sure in what sense you ever have a guarantee that the code will do what you believe it will do (in this case, only sign transactions strictly increasing balance). So as @kristapsk says the only defence we have is for the secrecy of the privileged wallet information (keys) in the encrypted wallet file, not the code execution.

So our security model is that we ensure it's the valid/trusted user who accesses the keys AND starts execution. Of course if the environment in which the code is executing is not safe, running Joinmarket is not safe, but if you removed password protection from starting that execution it would be a lot worse/less secure, and would require leaving the keys (or the encryption key protecting the keys :) ) in plaintext somewhere at rest.

So I think this idea would only make sense if we were running the maker against a hardware wallet signer, as has been discussed before. In that scenario, I think it makes sense (and indeed, it is different from the two other main wallet use scenarios: read only, no unlock required, and spend, where unlocking is unconditionally required - it exists in a third scenario, perhaps shared with lightning and other smart contracts: open for spending, but spending constrained with limits).

AdamISZ avatar Dec 16 '20 13:12 AdamISZ

@AdamISZ Thank you for the detailed answer. It makes sense that the most viable option would be to remove the signing keys from the machine running the scripts so the topic is related to the hardware wallet support. As mentioned here: https://github.com/JoinMarket-Org/joinmarket-clientserver/issues/663#issuecomment-704546610 the ColdCard MK3 in HSM mode could already be configured to only sign transactions sending up to a given amount (0 in this case).

The challenge here is that only the unmixed change (and fees) are being returned to the same mixdepth and the coinjoined amount would move to the next account. This would require the hardware wallet to check for self-payments in multiple accounts. There are two candidates which might be able to develop this in the future:

  • https://github.com/Coldcard/ckbunker
  • https://github.com/cryptoadvance/specter-diy (there is no work done towards an HSM mode yet)

openoms avatar Dec 16 '20 15:12 openoms

The Yield Generator does not ask for a password at startup if your wallet file is not encrypted. :wink:

whitslack avatar Jan 02 '21 17:01 whitslack

I think LND solves this in a nice way that would be an easy add here I think: Add a flag --stdin that reads the passphrase from stdin instead of prompting for it. An alternative would be to take a path to a file containing the passphrase as an argument.

This makes it trivial to just pipe it into the command at the entrypoint.

That way, operators who have secrets management systems like Vault can do automatic unlocking without needing to store the keys in cleartext, or the passphrase on disk (to clarify, the file path could exist on a ramfs).

3nprob avatar Feb 13 '21 05:02 3nprob

@3nprob There already is --wallet-password-stdin option, see #427.

kristapsk avatar Feb 13 '21 09:02 kristapsk

Well what do you know, totally missed that one, thanks @kristapsk ! Doesn't that solve your use-case @openom? For a budget setup you could have the passphrase on an encrypted USB key that is piped in from the systemd unit file. Keeping the passphrase and encrypted wallet on separate volumes is at least better than storing it in cleartext.

3nprob avatar Feb 13 '21 10:02 3nprob

@3nprob

For a budget setup you could have the passphrase on an encrypted USB key that is piped in from the systemd unit file. Keeping the passphrase and encrypted wallet on separate volumes is at least better than storing it in cleartext.

Yes, as per what I said above :

but if you removed password protection from starting that execution it would be a lot worse/less secure, and would require leaving the keys (or the encryption key protecting the keys :) ) in plaintext somewhere at rest.

Your idea is to finesse that a bit, it may well be of interest in some contexts, but the general principle applies. Either it's available at rest or there's interaction.

@whitslack

The Yield Generator does not ask for a password at startup if your wallet file is not encrypted.

Joinmarket does not allow that; it does not even allow a password of "". Maybe you're thinking of an older version of the code?

I feel like this issue stays open; it's a valid thought and ultimately quite connected with the whole idea of a hardware wallet signer.

AdamISZ avatar Feb 15 '21 12:02 AdamISZ

The Yield Generator does not ask for a password at startup if your wallet file is not encrypted.

Joinmarket does not allow that; it does not even allow a password of "". Maybe you're thinking of an older version of the code?

JoinMarket doesn't allow creating a wallet with no encryption, but it'll still open and use one just fine. It's not hard (if one has any programming experience) to figure out how to create an unencrypted wallet by calling the right functions manually.

whitslack avatar Feb 15 '21 15:02 whitslack

Yes good point (and relevant, here).

AdamISZ avatar Feb 15 '21 16:02 AdamISZ

It won't get perfect, but what about something like this @openoms

  • The unlock password is stored in the pass password manager, which is set up to encrypt/decrypt its password store with a GPG key (instead of using pass, we could also just encrypt the plaintext password with gpg --encrypt [...])
  • The private GPG key for pass is stored on a YubiKey without PIN and the encrypted password store file is only readable by a privileged user (e.g., root)
  • When the system starts, just before the yield generator is launched, an init script running as the privileged user unlocks the password store with the YubiKey and writes the password into a named FIFO pipe (mkfifo -m600 /dev/shm/jm-pw && pass [...] > /dev/shm/jm-pw &; chown joinmarket /dev/shm/jm-pw)
  • Now the joinmarket user can read the password ONCE from the pipe (cat /dev/shm/jm-pw | ./ygprivacyenhanced [...])

If root gets compromised, then the attacker could just decrypt the password a second time. To protect from that, we would have to remove the YubiKey physically.

A poor man's version of this would be to have a plaintext password stored on an USB stick that is set up in /etc/fstab to only be readable by root. root could then cat that file into the named pipe. (For a little extra protection the data on the USB stick could be encrypted with a keyfile stored on the Pi.)

xanoni avatar Aug 04 '21 09:08 xanoni