isislovecruft / python-gnupg

A modified version of python-gnupg, including security patches, extensive documentation, and extra features.
Other
424 stars 172 forks source link

confusing api for symmetric encrypt #110

Open chrishinds opened 9 years ago

chrishinds commented 9 years ago

Am bringing forward some software which used an older version of gnupg. This newer version with the vulnerability fix is really great. However, one of the differences that confused me was as follows:

the old api allowed:

encrypt('foo', (), symmetric=True, passphrase='bar')

but on 2.0.2 this yields: ValueError: Unknown status message: u'NO_RECP'

the new version needs an extra encrypt=False, eg:

gpg.encrypt("foo", symmetric=True, passphrase='bar', encrypt=False)

Maybe others are smarter, but I wasn't able to figure this out from the docs. This is clearly a pretty minor issue, but perhaps in writing it up I'll save someone else an hour of faff. In sum, I get that the encrypt=False refers to the recipients that I'm not supplying, but fwiw, the older api seems more intuitive to me!

zarniwoop123 commented 8 years ago

Thanks. I had the same issue.

zanjibar commented 7 years ago

How decrypt ?

gpg = gnupg.GPG()
x = gpg.encrypt("foo", symmetric=True, passphrase='bar', encrypt=False)
gpg.decrypt(x.data, symmetric=True, passphrase='bar')

TypeError Traceback (most recent call last)

in () 1 gpg = gnupg.GPG() 2 x = gpg.encrypt("foo", symmetric=True, passphrase='bar', encrypt=False) ----> 3 gpg.decrypt(x.data, symmetric=True, passphrase='bar') /home/tadashi/anaconda3/lib/python3.5/site-packages/gnupg/gnupg.py in decrypt(self, message, **kwargs) 985 """ 986 stream = _make_binary_stream(message, self._encoding) --> 987 result = self.decrypt_file(stream, **kwargs) 988 stream.close() 989 return result TypeError: decrypt_file() got an unexpected keyword argument 'symmetric'
isislovecruft commented 7 years ago

Hi @chrishinds! Thanks for the suggestion! I agree that the API needs some work there. I'm happy to take a patch for this change, but since it would break backwards compatibility, I'd have to start a branch for python-gnupg 3.x.x and possibly maintain two sets of bug patches. It's be nice to group this together with any other API fixes which are non-backwards-compatible.

bradleyhurley commented 7 years ago

@zanjibar gpg.decrypt(x.data, passphrase='bar', output='/path/to/write/file')

zanjibar commented 7 years ago

thank you @bradleyhurley

import gnupg
gpg = gnupg.GPG()
x = gpg.encrypt("foo", symmetric=True, passphrase='bar', encrypt=False)
y = gpg.decrypt(x.data, passphrase='bar')
y.data.decode('utf-8')
Necklaces commented 7 years ago

I get a ValueError when I run the code @zanjibar posted above with Python 3.6.2

import gnupg
gpg = gnupg.GPG()
x = gpg.encrypt("foo", symmetric=True, passphrase='bar', encrypt=False)
y = gpg.decrypt(x.data, passphrase='bar')
y.data.decode('utf-8')

Exception in thread Thread-5: Traceback (most recent call last): File "/usr/lib/python3.6/threading.py", line 916, in _bootstrap_inner self.run() File "/usr/lib/python3.6/threading.py", line 864, in run self._target(*self._args, **self._kwargs) File "/usr/lib/python3.6/site-packages/gnupg/_meta.py", line 650, in _read_response result._handle_status(keyword, value) File "/usr/lib/python3.6/site-packages/gnupg/_parsers.py", line 1715, in _handle_status super(Crypt, self)._handle_status(key, value) File "/usr/lib/python3.6/site-packages/gnupg/_parsers.py", line 1628, in _handle_status raise ValueError("Unknown status message: %r" % key) ValueError: Unknown status message: 'DECRYPTION_COMPLIANCE_MODE'

I get the same with Python 2.7.13, but at least (in both versions) the returned object contains the decrypted data.

It also seems gpg.decrypt_file() has no way of decrypting symmetrically encrypted files:

$ echo "foo" | gpg --symmetric > bar.gpg # password; 12345
$ gpg --decrypt bar.gpg

gpg: AES encrypted data gpg: encrypted with 1 passphrase foo

import gnupg
gpg = gnupg.GPG()
with open('bar.gpg', 'rb') as f:
  y = gpg.decrypt_file(f, passphrase='12345')
y.data

b''

Or maybe I'm doing something wrong? Is there another/temporary solution for this?

Ah also just for records sake, I installed gnupg with pip on both Python 2 and 3; gnupg==2.3.0

x1o commented 6 years ago

Vinjay's python-gpg worked for me (version 0.4.3, GnuPG 2.2.4):

>>> import gnupg
>>> gpg = gnupg.GPG()                                                        
>>> x = gpg.encrypt("message", [], symmetric=True, passphrase='1234')      
>>> y = gpg.decrypt(x.data, passphrase='1234')                                
>>> y.data                                                                  
b'message'                                                                 
>>> 
JackDinn commented 2 years ago

Many many thx. I have a ancient encryption/decryption GUI app i built years ago, and it suddenly stopped working. It looked complicated and i was ready to say goodbye to it and all my encrypted texts because i have not used python for many years and have forgotten even where to start. Turns out after finding this post it was just one added argument.