def test_signature_verification(self): "Test that signing and verification works" logger.debug("test_signature_verification begins") key = self.generate_key("Andrew", "Able", "alpha.com") self.gpg.encoding = 'latin-1' if gnupg._py3k: data = 'Hello, André!' else: data = unicode('Hello, André', self.gpg.encoding) data = data.encode(self.gpg.encoding) sig = self.gpg.sign(data, keyid=key.fingerprint, passphrase='bbrown') self.assertFalse(sig, "Bad passphrase should fail") sig = self.gpg.sign(data, keyid=key.fingerprint, passphrase='aable') self.assertTrue(sig, "Good passphrase should succeed") verified = self.gpg.verify(sig.data) if key.fingerprint != verified.fingerprint: logger.debug("key: %r", key.fingerprint) logger.debug("ver: %r", verified.fingerprint) self.assertEqual(key.fingerprint, verified.fingerprint, "Fingerprints must match") self.assertEqual(verified.trust_level, verified.TRUST_ULTIMATE) self.assertEqual(verified.trust_text, 'TRUST_ULTIMATE') if not os.path.exists('random_binary_data'): data_file = open('random_binary_data', 'wb') data_file.write(os.urandom(5120 * 1024)) data_file.close() data_file = open('random_binary_data', 'rb') sig = self.gpg.sign_file(data_file, keyid=key.fingerprint, passphrase='aable') data_file.close() self.assertTrue(sig, "File signing should succeed") try: file = gnupg._make_binary_stream(sig.data, self.gpg.encoding) verified = self.gpg.verify_file(file) except UnicodeDecodeError: #happens in Python 2.6 from io import BytesIO verified = self.gpg.verify_file(BytesIO(sig.data)) if key.fingerprint != verified.fingerprint: logger.debug("key: %r", key.fingerprint) logger.debug("ver: %r", verified.fingerprint) self.assertEqual(key.fingerprint, verified.fingerprint, "Fingerprints must match") data_file = open('random_binary_data', 'rb') sig = self.gpg.sign_file(data_file, keyid=key.fingerprint, passphrase='aable', detach=True) data_file.close() self.assertTrue(sig, "File signing should succeed") try: file = gnupg._make_binary_stream(sig.data, self.gpg.encoding) verified = self.gpg.verify_file(file, 'random_binary_data') except UnicodeDecodeError: #happens in Python 2.6 from io import BytesIO verified = self.gpg.verify_file(BytesIO(sig.data)) if key.fingerprint != verified.fingerprint: logger.debug("key: %r", key.fingerprint) logger.debug("ver: %r", verified.fingerprint) self.assertEqual(key.fingerprint, verified.fingerprint, "Fingerprints must match") logger.debug("test_signature_verification ends")
def test_file_encryption_and_decryption(): "Test that encryption/decryption to/from file works" logger.debug("test_file_encryption_and_decryption begins") encfno, encfname = tempfile.mkstemp() decfno, decfname = tempfile.mkstemp() # On Windows, if the handles aren't closed, the files can't be deleted os.close(encfno) os.close(decfno) logger.debug('Encrypting to: %r', encfname) logger.debug('Decrypting to: %r', decfname) try: data = "Hello, world!" file = gnupg._make_binary_stream(data, gpg.encoding) edata = self.gpg.encrypt_file(file, fprint, armor=False, output=encfname) efile = open(encfname, 'rb') ddata = self.gpg.decrypt_file(efile, passphrase="bbrown", output=decfname) efile.seek(0, 0) # can't use os.SEEK_SET in 2.4 edata = efile.read() efile.close() dfile = open(decfname, 'rb') ddata = dfile.read() dfile.close() data = data.encode(self.gpg.encoding) if ddata != data: logger.debug("was: %r", data) logger.debug("new: %r", ddata) self.assertEqual(data, ddata, "Round-trip must work") finally: for fn in (encfname, decfname): if os.path.exists(fn): os.remove(fn) logger.debug("test_file_encryption_and_decryption ends")
def store(self, data, **kwargs): """ Process the message contained in the string 'data' """ data = _make_binary_stream(data, self.encoding) result = self.store_file(data, **kwargs) data.close() return result
def list_packets(self, raw_data): args = ["--list-packets"] result = self.result_map['list-packets'](self) self._handle_io( args, _make_binary_stream(raw_data, self.encoding), result, ) return result
def do_file_encryption_and_decryption(self, encfname, decfname): "Do the actual encryption/decryption test using given filenames" mode = None if os.name == 'posix': # pick a mode that won't be already in effect via umask if os.path.exists(encfname) and os.path.exists(decfname): mode = os.stat(encfname).st_mode | stat.S_IXUSR os.chmod(encfname, mode) # assume same for decfname os.chmod(decfname, mode) logger.debug('Encrypting to: %r', encfname) logger.debug('Decrypting to: %r', decfname) try: key = self.generate_key("Andrew", "Able", "alpha.com", passphrase="andy") andrew = key.fingerprint key = self.generate_key("Barbara", "Brown", "beta.com") barbara = key.fingerprint data = "Hello, world!" file = gnupg._make_binary_stream(data, self.gpg.encoding) edata = self.gpg.encrypt_file(file, barbara, armor=False, output=encfname) efile = open(encfname, 'rb') ddata = self.gpg.decrypt_file(efile, passphrase="bbrown", output=decfname) efile.seek(0, 0) # can't use os.SEEK_SET in 2.4 edata = efile.read() efile.close() self.assertTrue(os.path.exists(decfname)) dfile = open(decfname, 'rb') ddata = dfile.read() dfile.close() data = data.encode(self.gpg.encoding) if ddata != data: # pragma: no cover logger.debug("was: %r", data) logger.debug("new: %r", ddata) self.assertEqual(data, ddata, "Round-trip must work") # Try opening the encrypted file in text mode (Issue #39) # this doesn't fail in 2.x if gnupg._py3k: efile = open(encfname, 'r') ddata = self.gpg.decrypt_file(efile, passphrase="bbrown", output=decfname) self.assertFalse(ddata) self.assertEqual(ddata.status, "no data was provided") efile.close() finally: for fn in (encfname, decfname): if os.name == 'posix' and mode is not None: # Check that the file wasn't deleted, and that the # mode bits we set are still in effect self.assertEqual(os.stat(fn).st_mode, mode) if os.path.exists(fn): os.remove(fn)
def export_keys( self, keyids, secret=False, armor=True, minimal=False, passphrase=None, expect_passphrase=True, ): """ Export the indicated keys. A 'keyid' is anything gpg accepts. Since GnuPG 2.1, you can't export secret keys without providing a passphrase. However, if you're expecting the passphrase to go to gpg via pinentry, you should specify expect_passphrase=False. (It's only checked for GnuPG >= 2.1). """ which = "" if secret: which = "-secret-key" if ( self.version >= (2, 1) and passphrase is None and expect_passphrase ): raise ValueError( "For GnuPG >= 2.1, exporting secret keys " "needs a passphrase to be provided" ) if gnupg._is_sequence(keyids): keyids = [gnupg.no_quote(k) for k in keyids] else: keyids = [gnupg.no_quote(keyids)] args = ["--export%s" % which] if armor: args.append("--armor") if minimal: args.extend(["--export-options", "export-minimal"]) args.extend(keyids) result = self.result_map["export"](self) if not secret or self.version < (2, 1): p = self._open_subprocess(args) self._collect_output(p, result, stdin=p.stdin) else: f = gnupg._make_binary_stream("", self.encoding) try: self._handle_io( args, f, result, passphrase=passphrase, binary=True ) finally: f.close() gnupg.logger.debug("export_keys result: %r", result.data) if armor: result.data = result.data.decode(self.encoding, self.decode_errors) return result
def do_file_encryption_and_decryption(self, encfname, decfname): "Do the actual encryption.decryptin test using given filenames" mode = None if os.name == 'posix': # pick a mode that won't be already in effect via umask if os.path.exists(encfname) and os.path.exists(decfname): mode = os.stat(encfname).st_mode | stat.S_IXUSR os.chmod(encfname, mode) # assume same for decfname os.chmod(decfname, mode) logger.debug('Encrypting to: %r', encfname) logger.debug('Decrypting to: %r', decfname) try: key = self.generate_key("Andrew", "Able", "alpha.com", passphrase="andy") andrew = key.fingerprint key = self.generate_key("Barbara", "Brown", "beta.com") barbara = key.fingerprint data = "Hello, world!" file = gnupg._make_binary_stream(data, self.gpg.encoding) edata = self.gpg.encrypt_file(file, barbara, armor=False, output=encfname) efile = open(encfname, 'rb') ddata = self.gpg.decrypt_file(efile, passphrase="bbrown", output=decfname) efile.seek(0, 0) # can't use os.SEEK_SET in 2.4 edata = efile.read() efile.close() dfile = open(decfname, 'rb') ddata = dfile.read() dfile.close() data = data.encode(self.gpg.encoding) if ddata != data: # pragma: no cover logger.debug("was: %r", data) logger.debug("new: %r", ddata) self.assertEqual(data, ddata, "Round-trip must work") # Try opening the encrypted file in text mode (Issue #39) # this doesn't fail in 2.x if gnupg._py3k: efile = open(encfname, 'r') ddata = self.gpg.decrypt_file(efile, passphrase="bbrown", output=decfname) self.assertFalse(ddata) self.assertEqual(ddata.status, "no data was provided") efile.close() finally: for fn in (encfname, decfname): if os.name == 'posix' and mode is not None: # Check that the file wasn't deleted, and that the # mode bits we set are still in effect self.assertEqual(os.stat(fn).st_mode, mode) if os.path.exists(fn): os.remove(fn)
def send_keys(self, keyserver, *keyids): """ Send keys to a keyserver """ result = self.result_map['list'](self) gnupg.logger.debug('send_keys: %r', keyids) data = gnupg._make_binary_stream("", self.encoding) args = ['--keyserver', keyserver, '--send-keys'] args.extend(keyids) self._handle_io(args, data, result, binary=True) gnupg.logger.debug('send_keys result: %r', result.__dict__) data.close() return result
def delete_keys( self, fingerprints, secret=False, passphrase=None, expect_passphrase=True, ): """ Delete the indicated keys. Since GnuPG 2.1, you can't delete secret keys without providing a passphrase. However, if you're expecting the passphrase to go to gpg via pinentry, you should specify expect_passphrase=False. (It's only checked for GnuPG >= 2.1). """ which = "key" if secret: # pragma: no cover if ( self.version >= (2, 1) and passphrase is None and expect_passphrase ): raise ValueError( "For GnuPG >= 2.1, deleting secret keys " "needs a passphrase to be provided" ) which = "secret-key" if gnupg._is_sequence(fingerprints): # pragma: no cover fingerprints = [gnupg.no_quote(s) for s in fingerprints] else: fingerprints = [gnupg.no_quote(fingerprints)] args = [] if secret and passphrase and expect_passphrase: args = ["--yes"] args.append("--delete-%s" % which) args.extend(fingerprints) result = self.result_map["delete"](self) if not secret or self.version < (2, 1): p = self._open_subprocess(args) self._collect_output(p, result, stdin=p.stdin) else: # Need to send in a passphrase. f = gnupg._make_binary_stream("", self.encoding) try: self._handle_io( args, f, result, passphrase=passphrase, binary=True ) finally: f.close() return result
def import_trust(trust_text): ## Remember to submit to *gnupg* project. class NoResult(object): def handle_status(self, key, value): pass log.debug('--import-owner input: %r', trust_text[:256]) data = gnupg._make_binary_stream(trust_text, GPG.encoding) result = NoResult() GPG._handle_io(['--import-ownertrust'], data, result, binary=True) data.close() result = result.stderr return result if ' error' in result else 'ok'
def list_packets(self, data): """ List the sequence of packets. @param data: The data to extract packets from. @type data: str @return: An object with packet info. @rtype ListPackets """ args = ["--list-packets"] result = self.result_map['list-packets'](self) self._handle_io( args, _make_binary_stream(data, self.encoding), result, ) return result
def list_packets(self, data): """ List the sequence of packets. :param data: The data to extract packets from. :type data: str :return: An object with packet info. :rtype ListPackets """ args = ["--list-packets"] result = self.result_map['list-packets'](self) self._handle_io( args, _make_binary_stream(data, self.encoding), result, ) return result
def test_file_encryption_and_decryption(self): "Test that encryption/decryption to/from file works" logger.debug("test_file_encryption_and_decryption begins") encfno, encfname = tempfile.mkstemp() decfno, decfname = tempfile.mkstemp() # On Windows, if the handles aren't closed, the files can't be deleted os.close(encfno) os.close(decfno) logger.debug('Encrypting to: %r', encfname) logger.debug('Decrypting to: %r', decfname) try: key = self.generate_key("Andrew", "Able", "alpha.com", passphrase="andy") andrew = key.fingerprint key = self.generate_key("Barbara", "Brown", "beta.com") barbara = key.fingerprint data = "Hello, world!" file = gnupg._make_binary_stream(data, self.gpg.encoding) edata = self.gpg.encrypt_file(file, barbara, armor=False, output=encfname) efile = open(encfname, 'rb') ddata = self.gpg.decrypt_file(efile, passphrase="bbrown", output=decfname) efile.seek(0, 0) # can't use os.SEEK_SET in 2.4 edata = efile.read() efile.close() dfile = open(decfname, 'rb') ddata = dfile.read() dfile.close() data = data.encode(self.gpg.encoding) if ddata != data: logger.debug("was: %r", data) logger.debug("new: %r", ddata) self.assertEqual(data, ddata, "Round-trip must work") finally: for fn in (encfname, decfname): if os.path.exists(fn): os.remove(fn) logger.debug("test_file_encryption_and_decryption ends")
def test_invalid_outputs(self): "Test encrypting to invalid output files" encfno, encfname = tempfile.mkstemp() os.close(encfno) cases = ( ('/dev/null/foo', 'not a directory'), ('/etc/foo', 'permission denied'), ) key = self.generate_key("Barbara", "Brown", "beta.com") barbara = key.fingerprint data = "Hello, world!" for badout, message in cases: stream = gnupg._make_binary_stream(data, self.gpg.encoding) edata = self.gpg.encrypt_file(stream, barbara, armor=False, output=badout) # on GnuPG 1.4, you sometimes don't get any FAILURE messages, in # which case status will not be set if edata.status: self.assertEqual(edata.status, message)
def validate(self, value): super(GPGSignatureValidator, self).validate(value) data = '' ending = "_signature" _len = len(ending) signature = self.field.getName() signed_file = signature[:-_len] file = self.request.form.get('form.widgets.%s' % signed_file) if file: file.seek(0) data = file.read() file.seek(0) else: pdf_field = getattr(self.context, signed_file, None) if pdf_field: data = pdf_field.data # It would be nice to be able to do this from a stream, # but unfortunately, gnupg expects files fd, fn = tempfile.mkstemp(prefix='elections') os.write(fd, data) os.close(fd) sig = _make_binary_stream(value.data, gpg.encoding) verify = gpg.verify_file(sig, fn) if not verify.valid: if hasattr(verify, 'status'): # Error codes gnupg.py line 150 if verify.status == 'signature bad': raise Invalid( _(u"This signature is not valid for the uploaded file." )) else: raise Invalid(_(u"Error: %s." % verify.status)) else: raise Invalid(_(u"Invalid signature."))
def validate(self, value): super(GPGSignatureValidator, self).validate(value) data = '' ending = "_signature" _len = len(ending) signature = self.field.getName() signed_file = signature[:-_len] file = self.request.form.get('form.widgets.%s' % signed_file) if file: file.seek(0) data = file.read() file.seek(0) else: pdf_field = getattr(self.context, signed_file, None) if pdf_field: data = pdf_field.data # It would be nice to be able to do this from a stream, # but unfortunately, gnupg expects files fd, fn = tempfile.mkstemp(prefix='elections') os.write(fd, data) os.close(fd) sig = _make_binary_stream(value.data, gpg.encoding) verify = gpg.verify_file(sig, fn) if not verify.valid: if hasattr(verify, 'status'): # Error codes gnupg.py line 150 if verify.status == 'signature bad': raise Invalid(_(u"This signature is not valid for the uploaded file.")) else: raise Invalid(_(u"Error: %s." % verify.status)) else: raise Invalid(_(u"Invalid signature."))
def send_keys(self, keyserver, *keyids): """ Send keys to a keyserver @param keyserver: The keyserver to send the keys to. @type keyserver: str @param keyids: The key ids to send. @type keyids: list @return: A list of keys sent to server. @rtype: gnupg.ListKeys """ # TODO: write tests for this. # TODO: write a SendKeys class to handle status for this. result = self.result_map['list'](self) gnupg.logger.debug('send_keys: %r', keyids) data = gnupg._make_binary_stream("", self.encoding) args = ['--keyserver', keyserver, '--send-keys'] args.extend(keyids) self._handle_io(args, data, result, binary=True) gnupg.logger.debug('send_keys result: %r', result.__dict__) data.close() return result
def send_keys(self, keyserver, *keyids): """ Send keys to a keyserver :param keyserver: The keyserver to send the keys to. :type keyserver: str :param keyids: The key ids to send. :type keyids: list :return: A list of keys sent to server. :rtype: gnupg.ListKeys """ # TODO: write tests for this. # TODO: write a SendKeys class to handle status for this. result = self.result_map['list'](self) gnupg.logger.debug('send_keys: %r', keyids) data = gnupg._make_binary_stream("", self.encoding) args = ['--keyserver', keyserver, '--send-keys'] args.extend(keyids) self._handle_io(args, data, result, binary=True) gnupg.logger.debug('send_keys result: %r', result.__dict__) data.close() return result
def test_signature_verification(self): "Test that signing and verification works" logger.debug("test_signature_verification begins") key = self.generate_key("Andrew", "Able", "alpha.com") if gnupg._py3k: data = 'Hello, André!' else: data = unicode('Hello, André', self.gpg.encoding) data = data.encode(self.gpg.encoding) sig = self.gpg.sign(data, keyid=key.fingerprint, passphrase='bbrown') self.assertFalse(sig, "Bad passphrase should fail") sig = self.gpg.sign(data, keyid=key.fingerprint, passphrase='aable') self.assertTrue(sig, "Good passphrase should succeed") self.assertTrue(sig.username.startswith('Andrew Able')) self.assertTrue(key.fingerprint.endswith(sig.key_id)) self.assertTrue(sig.hash_algo) verified = self.gpg.verify(sig.data) if key.fingerprint != verified.fingerprint: # pragma: no cover logger.debug("key: %r", key.fingerprint) logger.debug("ver: %r", verified.fingerprint) self.assertEqual(key.fingerprint, verified.fingerprint, "Fingerprints must match") self.assertEqual(verified.trust_level, verified.TRUST_ULTIMATE) self.assertEqual(verified.trust_text, 'TRUST_ULTIMATE') data_file = open(self.test_fn, 'rb') sig = self.gpg.sign_file(data_file, keyid=key.fingerprint, passphrase='aable') data_file.close() self.assertTrue(sig, "File signing should succeed") self.assertTrue(sig.hash_algo) try: file = gnupg._make_binary_stream(sig.data, self.gpg.encoding) verified = self.gpg.verify_file(file) except UnicodeDecodeError: # pragma: no cover # sometimes happens in Python 2.6 from io import BytesIO verified = self.gpg.verify_file(BytesIO(sig.data)) if key.fingerprint != verified.fingerprint: # pragma: no cover logger.debug("key: %r", key.fingerprint) logger.debug("ver: %r", verified.fingerprint) self.assertEqual(key.fingerprint, verified.fingerprint, "Fingerprints must match") data_file = open(self.test_fn, 'rb') sig = self.gpg.sign_file(data_file, keyid=key.fingerprint, passphrase='aable', detach=True) data_file.close() self.assertTrue(sig, "File signing should succeed") self.assertTrue(sig.hash_algo) try: file = gnupg._make_binary_stream(sig.data, self.gpg.encoding) verified = self.gpg.verify_file(file, self.test_fn) except UnicodeDecodeError: # pragma: no cover # sometimes happens in Python 2.6 from io import BytesIO verified = self.gpg.verify_file(BytesIO(sig.data)) if key.fingerprint != verified.fingerprint: # pragma: no cover logger.debug("key: %r", key.fingerprint) logger.debug("ver: %r", verified.fingerprint) self.assertEqual(key.fingerprint, verified.fingerprint, "Fingerprints must match") # Test in-memory verification data_file = open(self.test_fn, 'rb') data = data_file.read() data_file.close() fd, fn = tempfile.mkstemp() os.write(fd, sig.data) os.close(fd) try: verified = self.gpg.verify_data(fn, data) finally: os.unlink(fn) if key.fingerprint != verified.fingerprint: # pragma: no cover logger.debug("key: %r", key.fingerprint) logger.debug("ver: %r", verified.fingerprint) self.assertEqual(key.fingerprint, verified.fingerprint, "Fingerprints must match") logger.debug("test_signature_verification ends")
def test_signature_verification(self): "Test that signing and verification works" logger.debug("test_signature_verification begins") key = self.generate_key("Andrew", "Able", "alpha.com") self.gpg.encoding = 'latin-1' if gnupg._py3k: data = 'Hello, André!' else: data = unicode('Hello, André', self.gpg.encoding) data = data.encode(self.gpg.encoding) sig = self.gpg.sign(data, keyid=key.fingerprint, passphrase='bbrown') self.assertFalse(sig, "Bad passphrase should fail") sig = self.gpg.sign(data, keyid=key.fingerprint, passphrase='aable') self.assertTrue(sig, "Good passphrase should succeed") self.assertTrue(sig.hash_algo) verified = self.gpg.verify(sig.data) if key.fingerprint != verified.fingerprint: # pragma: no cover logger.debug("key: %r", key.fingerprint) logger.debug("ver: %r", verified.fingerprint) self.assertEqual(key.fingerprint, verified.fingerprint, "Fingerprints must match") self.assertEqual(verified.trust_level, verified.TRUST_ULTIMATE) self.assertEqual(verified.trust_text, 'TRUST_ULTIMATE') data_file = open(self.test_fn, 'rb') sig = self.gpg.sign_file(data_file, keyid=key.fingerprint, passphrase='aable') data_file.close() self.assertTrue(sig, "File signing should succeed") self.assertTrue(sig.hash_algo) try: file = gnupg._make_binary_stream(sig.data, self.gpg.encoding) verified = self.gpg.verify_file(file) except UnicodeDecodeError: # pragma: no cover # sometimes happens in Python 2.6 from io import BytesIO verified = self.gpg.verify_file(BytesIO(sig.data)) if key.fingerprint != verified.fingerprint: # pragma: no cover logger.debug("key: %r", key.fingerprint) logger.debug("ver: %r", verified.fingerprint) self.assertEqual(key.fingerprint, verified.fingerprint, "Fingerprints must match") data_file = open(self.test_fn, 'rb') sig = self.gpg.sign_file(data_file, keyid=key.fingerprint, passphrase='aable', detach=True) data_file.close() self.assertTrue(sig, "File signing should succeed") self.assertTrue(sig.hash_algo) try: file = gnupg._make_binary_stream(sig.data, self.gpg.encoding) verified = self.gpg.verify_file(file, self.test_fn) except UnicodeDecodeError: # pragma: no cover # sometimes happens in Python 2.6 from io import BytesIO verified = self.gpg.verify_file(BytesIO(sig.data)) if key.fingerprint != verified.fingerprint: # pragma: no cover logger.debug("key: %r", key.fingerprint) logger.debug("ver: %r", verified.fingerprint) self.assertEqual(key.fingerprint, verified.fingerprint, "Fingerprints must match") # Test in-memory verification data_file = open(self.test_fn, 'rb') data = data_file.read() data_file.close() fd, fn = tempfile.mkstemp() os.write(fd, sig.data) os.close(fd) try: verified = self.gpg.verify_data(fn, data) finally: os.unlink(fn) if key.fingerprint != verified.fingerprint: # pragma: no cover logger.debug("key: %r", key.fingerprint) logger.debug("ver: %r", verified.fingerprint) self.assertEqual(key.fingerprint, verified.fingerprint, "Fingerprints must match") logger.debug("test_signature_verification ends")