def lookup(): msgs = [] flagged = False for fn in os.listdir(g.loc): if fn == '_FLAG': flagged = True continue if fn.startswith('reply-'): msgs.append(dict( id=fn, date=str( datetime.fromtimestamp( os.stat(store.path(g.sid, fn)).st_mtime)), msg=crypto_util.decrypt( g.sid, g.codename, file(store.path(g.sid, fn)).read()) )) if flagged: session['flagged'] = True def async_genkey(sid, codename): with app.app_context(): background.execute(lambda: crypto_util.genkeypair(sid, codename)) # Generate a keypair to encrypt replies from the journalist # Only do this if the journalist has flagged the source as one # that they would like to reply to. (Issue #140.) if not crypto_util.getkey(g.sid) and flagged: async_genkey(g.sid, g.codename) return render_template( 'lookup.html', codename=g.codename, msgs=msgs, flagged=flagged, haskey=crypto_util.getkey(g.sid))
def lookup(): replies = [] for reply in g.source.replies: reply_path = store.path(g.filesystem_id, reply.filename) try: reply.decrypted = crypto_util.decrypt( g.codename, open(reply_path).read()).decode('utf-8') except UnicodeDecodeError: app.logger.error("Could not decode reply %s" % reply.filename) else: reply.date = datetime.utcfromtimestamp( os.stat(reply_path).st_mtime) replies.append(reply) # Sort the replies by date replies.sort(key=operator.attrgetter('date'), reverse=True) # Generate a keypair to encrypt replies from the journalist # Only do this if the journalist has flagged the source as one # that they would like to reply to. (Issue #140.) if not crypto_util.getkey(g.filesystem_id) and g.source.flagged: async_genkey(g.filesystem_id, g.codename) return render_template('lookup.html', codename=g.codename, replies=replies, flagged=g.source.flagged, haskey=crypto_util.getkey(g.filesystem_id))
def lookup(): replies = [] for fn in os.listdir(g.loc): if fn.startswith('reply-'): try: msg = crypto_util.decrypt(g.sid, g.codename, file(store.path(g.sid, fn)).read()).decode("utf-8") except UnicodeDecodeError: app.logger.error("Could not decode reply %s" % fn) else: date = str(datetime.fromtimestamp( os.stat(store.path(g.sid, fn)).st_mtime)) replies.append(dict(id=fn, date=date, msg=msg)) def async_genkey(sid, codename): with app.app_context(): background.execute(lambda: crypto_util.genkeypair(sid, codename)) # Generate a keypair to encrypt replies from the journalist # Only do this if the journalist has flagged the source as one # that they would like to reply to. (Issue #140.) if not crypto_util.getkey(g.sid) and g.source.flagged: async_genkey(g.sid, g.codename) return render_template('lookup.html', codename=g.codename, msgs=replies, flagged=g.source.flagged, haskey=crypto_util.getkey(g.sid))
def test_encrypt_fingerprints_not_a_list_or_tuple(self): """If passed a single fingerprint as a string, encrypt should correctly place that string in a list, and encryption/ decryption should work as intended.""" source, codename = utils.db_helper.init_source() message = str(os.urandom(1)) ciphertext = crypto_util.encrypt( message, crypto_util.getkey(source.filesystem_id), store.path(source.filesystem_id, 'somefile.gpg')) plaintext = crypto_util.decrypt(codename, ciphertext) self.assertEqual(message, plaintext)
def test_encrypt_without_output(self): """We simply do not specify the option output keyword argument to crypto_util.encrypt() here in order to confirm encryption works when it defaults to `None`. """ source, codename = utils.db_helper.init_source() message = str(os.urandom(1)) ciphertext = crypto_util.encrypt( message, [crypto_util.getkey(source.filesystem_id), config.JOURNALIST_KEY]) plaintext = crypto_util.decrypt(codename, ciphertext) self.assertEqual(message, plaintext)
def test_basic_encrypt_then_decrypt_multiple_recipients(self): source, codename = utils.db_helper.init_source() message = str(os.urandom(1)) ciphertext = crypto_util.encrypt( message, [crypto_util.getkey(source.filesystem_id), config.JOURNALIST_KEY], store.path(source.filesystem_id, 'somefile.gpg')) plaintext = crypto_util.decrypt(codename, ciphertext) self.assertEqual(message, plaintext) # Since there's no way to specify which key to use for # decryption to python-gnupg, we delete the `source`'s key and # ensure we can decrypt with the `config.JOURNALIST_KEY`. crypto_util.delete_reply_keypair(source.filesystem_id) plaintext_ = crypto_util.gpg.decrypt(ciphertext).data self.assertEqual(message, plaintext_)
def lookup(): msgs = [] flagged = False for fn in os.listdir(g.loc): # TODO: make 'flag' a db column, so we can replace this with a db # lookup in the future if fn == '_FLAG': flagged = True continue if fn.startswith('reply-'): msg_candidate = crypto_util.decrypt( g.sid, g.codename, file(store.path(g.sid, fn)).read()) try: msgs.append( dict(id=fn, date=str( datetime.fromtimestamp( os.stat(store.path(g.sid, fn)).st_mtime)), msg=msg_candidate.decode())) except UnicodeDecodeError: # todo: we should have logging here! pass if flagged: session['flagged'] = True def async_genkey(sid, codename): with app.app_context(): background.execute(lambda: crypto_util.genkeypair(sid, codename)) # Generate a keypair to encrypt replies from the journalist # Only do this if the journalist has flagged the source as one # that they would like to reply to. (Issue #140.) if not crypto_util.getkey(g.sid) and flagged: async_genkey(g.sid, g.codename) return render_template('lookup.html', codename=g.codename, msgs=msgs, flagged=flagged, haskey=crypto_util.getkey(g.sid))
def lookup(): msgs = [] flagged = False for fn in os.listdir(g.loc): # TODO: make 'flag' a db column, so we can replace this with a db # lookup in the future if fn == '_FLAG': flagged = True continue if fn.startswith('reply-'): msg_candidate = crypto_util.decrypt( g.sid, g.codename, file(store.path(g.sid, fn)).read()) try: msgs.append(dict( id=fn, date=str( datetime.fromtimestamp( os.stat(store.path(g.sid, fn)).st_mtime)), msg=msg_candidate.decode())) except UnicodeDecodeError: # todo: we should have logging here! pass if flagged: session['flagged'] = True def async_genkey(sid, codename): with app.app_context(): background.execute(lambda: crypto_util.genkeypair(sid, codename)) # Generate a keypair to encrypt replies from the journalist # Only do this if the journalist has flagged the source as one # that they would like to reply to. (Issue #140.) if not crypto_util.getkey(g.sid) and flagged: async_genkey(g.sid, g.codename) return render_template( 'lookup.html', codename=g.codename, msgs=msgs, flagged=flagged, haskey=crypto_util.getkey(g.sid))
def test_encrypt_binary_stream(self): """Generally, we pass unicode strings (the type form data is returned as) as plaintext to crypto_util.encrypt(). These have to be converted to "binary stream" types (such as `file`) before we can actually call gnupg.GPG.encrypt() on them. This is done in crypto_util.encrypt() with an `if` branch that uses `gnupg._util._is_stream(plaintext)` as the predicate, and calls `gnupg._util._make_binary_stream(plaintext)` if necessary. This test ensures our encrypt function works even if we provide inputs such that this `if` branch is skipped (i.e., the object passed for `plaintext` is one such that `gnupg._util._is_stream(plaintext)` returns `True`). """ source, codename = utils.db_helper.init_source() with open(os.path.realpath(__file__)) as fh: ciphertext = crypto_util.encrypt( fh, [crypto_util.getkey(source.filesystem_id), config.JOURNALIST_KEY], store.path(source.filesystem_id, 'somefile.gpg')) plaintext = crypto_util.decrypt(codename, ciphertext) with open(os.path.realpath(__file__)) as fh: self.assertEqual(fh.read(), plaintext)