rmlibre / tiny_gnupg

tiny_gnupg - A small-as-possible solution for handling GnuPG ed25519 ECC keys.
https://pypi.org/project/tiny-gnupg/
Other
2 stars 1 forks source link

_raw_packets Doesnt work - gpg: decryption failed: No secret key #6

Open T35R6braPwgDJKq opened 3 years ago

T35R6braPwgDJKq commented 3 years ago
    def _raw_packets(self, target: str):
        """
        Returns OpenPGP metadata from ``target`` in raw string format.
        """
        command = self.encode_command(
            "--pinentry-mode",
            "cancel",
            "-vv",
            "--list-packets",
            "--show-session-key",
        )
        command.remove("--batch")
        inputs = self.encode_inputs(target)
        with Terminal(if_exception=Error.secret_packets) as terminal:
            return terminal.enter(command, inputs, stderr=STDOUT)

Wouldnt --show-session-key imply the need for a password? So with_passphrase=True in encode_command and self.user.passphrase in encode_inputs? But I tried that and it still fails :/

T35R6braPwgDJKq commented 3 years ago
from tiny_gnupg import GnuPG

PATH_TO_GPG_BINARY = "/usr/bin/gpg2"
gpg = GnuPG(
    email_address="bob@user.net",
    passphrase="bobs's passphrase",
    executable=PATH_TO_GPG_BINARY,
)
gpg.generate_key()
options = ["--armor", "--encrypt", "-r", gpg.fingerprint]
command = gpg.encode_command(*options)
inputs = gpg.encode_inputs("Message to myself")
encrypted_message=gpg.encrypt("Message to myself",uid=gpg.fingerprint)
decrypted_msg = gpg.decrypt(encrypted_message)

This is basically the example code - it does not work for me:

source venv/bin/activate
venv/bin/python tinygpgexample.py 2>&1
Traceback (most recent call last):
  File "/tmp/venv/lib/python3.9/site-packages/tiny_gnupg/tiny_gnupg.py", line 1452, in _packet_fingerprint
    bus.packets = self._raw_packets(target)
  File "/tmp/venv/lib/python3.9/site-packages/tiny_gnupg/tiny_gnupg.py", line 1430, in _raw_packets
    return terminal.enter(command, inputs, stderr=STDOUT)
  File "/tmp/venv/lib/python3.9/site-packages/tiny_gnupg/tiny_gnupg.py", line 680, in __exit__
    return self.if_exception(self, error)
  File "/tmp/venv/lib/python3.9/site-packages/tiny_gnupg/tiny_gnupg.py", line 787, in secret_packets
    raise warning if "No secret key" in warning.packets else error
  File "/tmp/venv/lib/python3.9/site-packages/tiny_gnupg/tiny_gnupg.py", line 1430, in _raw_packets
    return terminal.enter(command, inputs, stderr=STDOUT)
  File "/tmp/venv/lib/python3.9/site-packages/tiny_gnupg/tiny_gnupg.py", line 641, in enter
    result = check_output(
  File "/usr/lib/python3.9/subprocess.py", line 424, in check_output
    return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
  File "/usr/lib/python3.9/subprocess.py", line 528, in run
    raise CalledProcessError(retcode, process.args,
subprocess.CalledProcessError: Command '['/usr/bin/gpg2', '--yes', '--quiet', '--no-tty', '--options', '/tmp/venv/lib/python3.9/site-packages/tiny_gnupg/gpghome/gpg2.conf', '--homedir', '/tmp/venv/lib/python3.9/site-packages/tiny_gnupg/gpghome', '--pinentry-mode', 'cancel', '-vv', '--list-packets', '--show-session-key']' returned non-zero exit status 2.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/tmp/tinygpgexample.py", line 18, in <module>
    decrypted_msg = gpg.decrypt(encrypted_message)
  File "/tmp/venv/lib/python3.9/site-packages/tiny_gnupg/tiny_gnupg.py", line 1648, in decrypt
    uid = self._packet_fingerprint(message)
  File "/tmp/venv/lib/python3.9/site-packages/tiny_gnupg/tiny_gnupg.py", line 1452, in _packet_fingerprint
    bus.packets = self._raw_packets(target)
  File "/tmp/venv/lib/python3.9/site-packages/tiny_gnupg/tiny_gnupg.py", line 680, in __exit__
    return self.if_exception(self, error)
  File "/tmp/venv/lib/python3.9/site-packages/tiny_gnupg/tiny_gnupg.py", line 805, in invalid_pgp_packets
    raise warning
TypeError: The ``target`` doesn't seem to be valid OpenPGP data.
rmlibre commented 3 years ago

Curious... I'm not getting this error. Here's some thoughts:

  1. Try wrapping the offending code in a try block and looking at the target & packets attributes of the error. What do those look like? Like this:
try:
    decrypted_msg = gpg.decrypt(encrypted_message)
except Exception as error:
    print(f"target:\n{error.target}")
    print(f"packets:\n{error.packets}")

1.a. Also, what does the encrypted_message look like? And, what does gpg.fingerprint look like? It should be 40 hex characters and exist in the gpg.list_keys(secret=True) dictionary.

  1. The options, command, and inputs variables aren't necessary. They are used to manually construct commands that are sent into the read_output method. Stick with the encrypt and decrypt methods unless you are manually calling read_output with custom commands.

  2. I'm not sure how the package plays with venv. For instance, does your environment have gpg2 correctly installed? Is your environment able to access the executable? Does gpg2 successfully create files where generated keys are saved in the "/tmp/venv/lib/python3.9/site-packages/tiny_gnupg/gpghome/" directory?

  3. Yes, _raw_packets will throw an error if the data is encrypted, which is handled in Error.secret_packets. The relevant data is given to the terminal bus which is then available where the method was called. Its job isn't to decrypt the data, though, just to determine what kind of data it is.

T35R6braPwgDJKq commented 3 years ago

Thanks for your quick response. The problem was the LANGUAGE - if it is not US (probably due to unicode characters?), it breaks

edit: WTF? LANGUAGE=zh_CN.utf8 works fine, but LANGUAGE=da_DK.utf8 does not?! is that a local problem?

Maybe you could try that:

from tiny_gnupg import GnuPG

PATH_TO_GPG_BINARY = "/usr/bin/gpg2"
gpg = GnuPG(
    email_address="bob@user.net",
    passphrase="bobs's passphrase",
    executable=PATH_TO_GPG_BINARY,
)
try:
    gpg.generate_key()
except Exception as e:
    print(e)
gpg: Underskrift lavet Fr 20 Aug 2021 09:46:23 CEST
gpg:                bruger EDDSA nøgle C7CCA99267EB3D5B101C195B40D2BFEC3E7E723B
gpg: God underskrift fra »bob@user.net« [ultimativ]
e.output.decode('utf8')
gpg (GnuPG) 2.2.29; Copyright (C) 2021 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

[GNUPG:] GET_LINE keygen.algo
[GNUPG:] GOT_IT
[GNUPG:] GET_LINE keygen.flags
[GNUPG:] GOT_IT
[GNUPG:] GET_LINE keygen.flags
[GNUPG:] GOT_IT
[GNUPG:] GET_LINE keygen.flags
[GNUPG:] GOT_IT
[GNUPG:] GET_LINE keygen.flags
[GNUPG:] GOT_IT
[GNUPG:] GET_LINE keygen.flags
[GNUPG:] GOT_IT
[GNUPG:] GET_LINE keygen.flags
[GNUPG:] GOT_IT
[GNUPG:] GET_LINE keygen.curve
[GNUPG:] GOT_IT
[GNUPG:] GET_LINE keygen.curve
[GNUPG:] GOT_IT
[GNUPG:] GET_LINE keygen.valid
[GNUPG:] GOT_IT
[GNUPG:] GET_LINE keygen.valid
[GNUPG:] GOT_IT
[GNUPG:] GET_LINE keygen.valid
[GNUPG:] GOT_IT
[GNUPG:] GET_LINE keygen.valid
[GNUPG:] GOT_IT
[GNUPG:] GET_LINE keygen.valid

gpg: signal 1 caught ... exiting
rmlibre commented 3 years ago

That is quite strange... I don't have the capacity to work on creating localization support atm. But if you diagnose the exact issue, or write up a patch that is simple and has tests, I'd be willing to merge it.