Пример #1
0
def main():

    q = LockboxOrderedDict()
    observer = Observer()
    observer.schedule(CleartextEventHandler(q, cleartext_dir, ciphertext_dir), path=cleartext_dir, recursive=True)
    observer.schedule(CiphertextEventHandler(q, cleartext_dir, ciphertext_dir), path=ciphertext_dir, recursive=True)
    observer.start()

    try:
        while True:
            time.sleep(1)
            try:
                while True:
                    (stem, deets) = q.first()  #just read, don't pop here because we need it to stay in the OrderedDict in case another event comes in on this file before we're done
                    logger.debug('%s %s', stem, deets)
                    if not deets['collided']:
                        check_for_collided_after_operation = False
                        if deets['action'] == 'encrypt':
                            logger.debug('encrypting from %s to %s', deets['cleartext_full_path'], deets['ciphertext_full_path'])
                            check_for_collided_after_operation = True
                            target_path = deets['ciphertext_full_path']
                            (tmp_fd, tmp_path) = tempfile.mkstemp()
                            os.close(tmp_fd)


                            rio = BIO.openfile(deets['cleartext_full_path'], 'rb')
                            rio.write_close()
                            wrio = BIO.openfile(tmp_path, 'wb')

                            cf = BIO.CipherStream(wrio)

                            salt = Rand.rand_pseudo_bytes(8)[0]
                            logger.debug("salt=%s",ByteToHex(salt))

                            passphrase_f = open(os.path.join(deets['config_dir_path'], 'key.txt'), 'r')  ## TODO cache this
                            passphrase = passphrase_f.readline().rstrip()
                            passphrase_f.close()

                            (key, iv) = m2.bytes_to_key(m2.aes_256_cbc(), m2.md5(), passphrase, salt, 1)
                            logger.debug("key=%s", ByteToHex(key))
                            logger.debug("iv=%s", ByteToHex(iv))

                            cf.set_cipher('aes_256_cbc', key, iv, 1)
                            wrio.write('Salted__')  # magic - see openssl's enc.c
                            wrio.write(salt)

                            while True:
                                out = rio.read(4096)
                                if not out:
                                    break
                                cf.write(out)

                            cf.flush()
                            cf.write_close()
                            cf.close()
                            wrio.flush()
                            wrio.write_close()
                            wrio.close()

                        elif deets['action'] == 'decrypt':
                            logger.debug('decrypting from %s to %s', deets['ciphertext_full_path'], deets['cleartext_full_path'])
                            check_for_collided_after_operation = True
                            target_path = deets['cleartext_full_path']
                            (tmp_fd, tmp_path) = tempfile.mkstemp()
                            os.close(tmp_fd)
                            ## TODO: handle failure of decryption

                            rio = BIO.openfile(deets['ciphertext_full_path'], 'rb')
                            rio.write_close()
                            wrio = BIO.openfile(deets['cleartext_full_path'], 'wb')

                            cf = BIO.CipherStream(wrio)

                            header = rio.read(size=len('Salted__'))
                            if header != 'Salted__':
                                print "uh, this doesn't look like an encrypted file"
                                exit()
                            salt = rio.read(size=8)
                            logger.debug("salt=%s",ByteToHex(salt))

                            passphrase_f = open(os.path.join(deets['config_dir_path'], 'key.txt'), 'r')  ## TODO cache this
                            passphrase = passphrase_f.readline().rstrip()
                            passphrase_f.close()

                            (key, iv) = m2.bytes_to_key(m2.aes_256_cbc(), m2.md5(), passphrase, salt, 1)
                            logger.debug("key=%s", ByteToHex(key))
                            logger.debug("iv=%s", ByteToHex(iv))

                            cf.set_cipher('aes_256_cbc', key, iv, 0)

                            while True:
                                out = rio.read(4096)
                                if not out:
                                    break
                                cf.write(out)

                            cf.flush()
                            cf.write_close()
                            cf.close()
                            wrio.flush()
                            wrio.write_close()
                            wrio.close()


                        elif deets['action'] == 'delete-cipher':
                            logger.debug('deleting %s', deets['ciphertext_full_path'])
                            if os.path.exists(deets['ciphertext_full_path']):
                                os.unlink(deets['ciphertext_full_path'])

                        elif deets['action'] == 'delete-clear':
                            logger.debug('deleting %s', deets['cleartext_full_path'])
                            if os.path.exists(deets['cleartext_full_path']):
                                os.unlink(deets['cleartext_full_path'])

                        else:
                            logger.error('Unknown action %s on %s', deets['action'], deets)

                        time.sleep(0)  ## http://stackoverflow.com/questions/787803/how-does-a-threading-thread-yield-the-rest-of-its-quantum-in-python
                        (stem, deets) = q.popitem(False)

                        if check_for_collided_after_operation:
                            ## now, if it got marked as collided in the interim while we were encrypting/decrypting then we don't want to overwrite 
                            if not deets['collided']:
                                ## move from temp location to real location
                                if platform.system() == 'Windows':
                                    ## TODO: this can throw an exception on windows if the target_place is locked.  need to think about how to deal with this
                                    if os.path.exists(target_path):
                                        logger.debug('windows only: unlink %s', target_path)
                                        os.unlink(target_path)
                                logger.debug('rename %s to %s', tmp_path, target_path)
                                mkdir_p(os.path.dirname(target_path))
                                os.rename(tmp_path, target_path)
                            else:
                                ## TODO: if it was a decrypt, move the newly decrypted file to stem-from-dropbox-collision
                                ##       if it was an encrypt, immediately decrypt ciphertext version to stem-from-dropbox-collision
                                ## TODO: delete tmp_path in the case that we're no longer using it (it was an encrypt that we no longer can copy to the ciphertext location)
                                pass
                    else:
                        (stem, deets) = q.popitem(False)
                        if deets['action'] in ('delete-clear','delete-cipher'):
                            logger.error('should not get a collided delete because they should be removed from the queue in our OrderedDict subclass')
                        else:
                            ## TODO: immediately decrypt and put it into stem-from-dropbox-collision
                            pass

            except StopIteration:
                #print "nada"
                pass
    except KeyboardInterrupt:
        pass
    observer.stop()
    observer.join()
Пример #2
0
    return ''.join( bytes )


rio = BIO.openfile(os.path.expanduser('~/Lockbox/foobar/firsttest.txt'), 'rb')
rio.write_close()
wrio = BIO.openfile(os.path.expanduser('~/Dropbox/LOCKBOX-foobar/firsttest.txt'), 'wb')

cf = BIO.CipherStream(wrio)

salt = Rand.rand_pseudo_bytes(8)[0]
#salt = '\x00\x00\x00\x00\x00\x00\x00\x00'
print "salt=%s" % ByteToHex(salt)

passphrase = 'foo bar'

(key, iv) = m2.bytes_to_key(m2.aes_256_cbc(), m2.md5(), passphrase, salt, 1)
print "key=%s" % ByteToHex(key)
print "iv=%s" % ByteToHex(iv)

cf.set_cipher('aes_256_cbc', key, iv, 1)


wrio.write('Salted__')  # magic - see openssl's enc.c
wrio.write(salt)

while True:
    out = rio.read(4096)
    if not out:
        break
    cf.write(out)