plattfot / pinentry-rofi

Rofi frontend to pinentry
44 stars 5 forks source link

pinentry-rofi is incompatible with other official backends if passphrase contains % character #27

Closed rcasta74 closed 2 months ago

rcasta74 commented 2 months ago

I'm trying to export a key to another host over ssh, but the passphrase containing % created with pinentry-rofi does not work with other backends.

Step to reproduce: 1) create 2 temporary folders:

❯ mkdir -m 700 /tmp/gpg1
❯ mkdir -m 700 /tmp/gpg2

2) configure pinentry-rofi for the 1st folder:

❯ echo pinentry-program /usr/bin/pinentry-rofi > /tmp/gpg1/gpg-agent.conf

3) create a test key with password Pass%word1

❯ gpg --homedir /tmp/gpg1 --yes --quick-generate-key test

Now we have a test key into folder gpg1:

❯ gpg --homedir /tmp/gpg1 --list-secret-keys --keyid-format LONG
/tmp/gpg1/pubring.kbx
---------------------
sec   ed25519/25EB84EFA5251C49 2024-09-13 [SC] [expires: 2027-09-13]
      21379FAF651C4B5C8D68082225EB84EFA5251C49
uid                 [ultimate] test
ssb   cv25519/0B26C2D0379EDE14 2024-09-13 [E]

4) export the key to file (the password works):

❯ gpg --homedir /tmp/gpg1/ --export-secret-keys 25EB84EFA5251C49 > /tmp/secret

5) try to import the key into gpg2 (where not using pinentry-rofi):

❯ gpg --homedir /tmp/gpg2/ --import /tmp/secret
gpg: keybox '/tmp/gpg2/pubring.kbx' created
gpg: /tmp/gpg2/trustdb.gpg: trustdb created
gpg: key 25EB84EFA5251C49: public key "test" imported
gpg: key 25EB84EFA5251C49/25EB84EFA5251C49: error sending to agent: Bad passphrase
gpg: key 25EB84EFA5251C49/0B26C2D0379EDE14: error sending to agent: Bad passphrase
gpg: error reading '/tmp/secret': Bad passphrase
gpg: import from '/tmp/secret' failed: Bad passphrase
gpg: Total number processed: 0
gpg:               imported: 1
gpg:       secret keys read: 1

It looks like that there is some changes on the password involving the % character: if I try to set the passphrase Pass%w0rd with pinentry-rofi I get the warning A passphrase should be at least 8 charaters long. (while it should be 9 characters long); this does not happen with others backends.

I'm using lbonn/rofi version, but the issue should not depend on it: if I try

❯ rofi -dmenu -password

I get the full password printed without changes.

rcasta74 commented 2 months ago

It looks like that the password is changed somewhere following url encoding: if I set the passphrase Pass%25w0rd with pinentry-rofi (where %25 is the character % as per url encodnig), then I can import the key with other backends using passphrase Pass%w0rd

plattfot commented 2 months ago

Yeah, sounds like a bug in how it handles the password. I.e. it is not escaping it properly as % in guile is use for format strings. I'll look into it this weekend.

plattfot commented 2 months ago

I tracked down the issue. As it turns out gpg is the one that did the decoding and was expected the password to be uri encoded. Which I had completely missed. #28 should fix this.

I tested your repro and it worked importing the secret key with pinentry-tty.

Can you test and make sure it works on your end?

Also heads up that this is a breaking change, see my note in the README for details.

rcasta74 commented 2 months ago

I confirme it works, thanks.