diff --git a/gnupg/_meta.py b/gnupg/_meta.py index 53d7620..6e73467 100644 --- a/gnupg/_meta.py +++ b/gnupg/_meta.py @@ -772,6 +772,7 @@ class GPGBase(object): symmetric=False, always_trust=True, output=None, + hidden_recipients=None, cipher_algo='AES256', digest_algo='SHA512', compress_algo='ZLIB'): @@ -895,7 +896,7 @@ class GPGBase(object): ## is decryptable with a passphrase or secretkey. if symmetric: args.append('--symmetric') if encrypt: args.append('--encrypt') - + if len(recipients) >= 1: log.debug("GPG.encrypt() called for recipients '%s' with type '%s'" % (recipients, type(recipients))) @@ -910,21 +911,27 @@ class GPGBase(object): log.info("Can't accept recipient string: %s" % recp) else: - args.append('--recipient %s' % str(recp)) + self._add_recipient_string(args, hidden_recipients, recp) continue ## will give unicode in 2.x as '\uXXXX\uXXXX' - args.append('--recipient %r' % recp) + if isinstance(hidden_recipients, (list, tuple)): + if [s for s in hidden_recipients if recp in str(s)]: + args.append('--hidden-recipient %r' % recp) + else: + args.append('--recipient %r' % recp) + else: + args.append('--recipient %r' % recp) continue if isinstance(recp, str): - args.append('--recipient %s' % recp) + self._add_recipient_string(args, hidden_recipients, recp) elif (not _util._py3k) and isinstance(recp, basestring): for recp in recipients.split('\x20'): - args.append('--recipient %s' % recp) + self._add_recipient_string(args, hidden_recipients, recp) elif _util._py3k and isinstance(recp, str): for recp in recipients.split(' '): - args.append('--recipient %s' % recp) + self._add_recipient_string(args, hidden_recipients, recp) ## ...and now that we've proven py3k is better... else: @@ -946,3 +953,12 @@ class GPGBase(object): log.info("Encrypted output written successfully.") return result + + def _add_recipient_string(self, args, hidden_recipients, recipient): + if isinstance(hidden_recipients, (list, tuple)): + if [s for s in hidden_recipients if recipient in str(s)]: + args.append('--hidden-recipient %s' % recipient) + else: + args.append('--recipient %s' % recipient) + else: + args.append('--recipient %s' % recipient) \ No newline at end of file diff --git a/gnupg/test/test_gnupg.py b/gnupg/test/test_gnupg.py index 6a352a6..0382c8a 100755 --- a/gnupg/test/test_gnupg.py +++ b/gnupg/test/test_gnupg.py @@ -887,6 +887,31 @@ authentication.""" self.assertEqual(message, decrypted) +def test_encryption_hidden_recipient(self): + """Test to ensure hidden recipient isn't detailed in packet info""" + + alice = open(os.path.join(_files, 'test_key_1.pub')) + alice_pub = alice.read() + alice_public = self.gpg.import_keys(alice_pub) + res = alice_public.results[-1:][0] + alice_pfpr = str(res['fingerprint']) + alice.close() + + message = """ +In 2010 Riggio and Sicari presented a practical application of homomorphic +encryption to a hybrid wireless sensor/mesh network. The system enables +transparent multi-hop wireless backhauls that are able to perform statistical +analysis of different kinds of data (temperature, humidity, etc.) coming from +a WSN while ensuring both end-to-end encryption and hop-by-hop +authentication.""" + enc = self.gpg.encrypt(message, alice_pfpr, hidden_recipients=[alice_pfpr]) + encrypted = str(enc) + log.debug("keyid = %s" + % alice_pfpr) + + self.assertNotEquals(message, encrypted) + self.assertEquals("0000000000000000", self.gpg.list_packets(encrypted).key) + def test_encryption_decryption_multi_recipient(self): """Test decryption of an encrypted string for multiple users"""