compression, argparse
This commit is contained in:
265
pgpfs.py
265
pgpfs.py
@@ -1,127 +1,210 @@
|
||||
#!bin/python
|
||||
#!/usr/bin/env python2
|
||||
#
|
||||
# watch out, this is only possible with modified gpg version
|
||||
# download this version as well from aestetix repo
|
||||
|
||||
""" pgpfs is a tool to turn your friendly pgp keyserver into a redundant
|
||||
persistant filesystem."""
|
||||
|
||||
import re
|
||||
import os
|
||||
import sys
|
||||
import re
|
||||
import base64
|
||||
from hashlib import sha256
|
||||
import gnupg
|
||||
import base64
|
||||
import pylzma
|
||||
import argparse
|
||||
import threading
|
||||
|
||||
os.system('rm -rf gpg')
|
||||
GPG = gnupg.GPG(gnupghome='gpg')
|
||||
KEYSERVER = 'pgp.mit.edu'
|
||||
from hashlib import sha256
|
||||
|
||||
# TODO adjust with pgpfspath
|
||||
os.system('rm -fr .pgpfs')
|
||||
|
||||
# trial and error lead to this number
|
||||
SPLIT_LENGTH = 986
|
||||
|
||||
# store file
|
||||
# pack file
|
||||
def pack_file_to_disk(source_file):
|
||||
''' takes the file and packs it '''
|
||||
print 'Compressing file'
|
||||
# TODO gen random temp here
|
||||
target_file='tempfile.tmp'
|
||||
with open(source_file, 'r') as source, open(target_file,'wb') as target:
|
||||
lz = pylzma.compressfile(source, eos=1)
|
||||
while True:
|
||||
b =lz.read(1)
|
||||
if not b:
|
||||
break
|
||||
target.write(b)
|
||||
target.close()
|
||||
return target_file
|
||||
|
||||
def unpack_file_from_disk(packed_file, out_file):
|
||||
''' unpack file '''
|
||||
print 'Uncompressing file'
|
||||
with open(packed_file, 'rb') as packed, open(out_file,'wb') as out:
|
||||
obj = pylzma.decompressobj()
|
||||
decompress = ''
|
||||
while True:
|
||||
b = packed.read(1)
|
||||
if not b:
|
||||
break
|
||||
dec = obj.decompress(b)
|
||||
out.write(dec)
|
||||
return True
|
||||
|
||||
# store file
|
||||
def read_file_into_list(source_file):
|
||||
""" reads file into list"""
|
||||
with open(source_file, 'r') as source:
|
||||
data = base64.b64encode(source.read())
|
||||
return [data[i:i+SPLIT_LENGTH] for i in range(0, len(data), SPLIT_LENGTH)]
|
||||
""" reads file into list"""
|
||||
with open(source_file, 'r') as source:
|
||||
data = base64.b64encode(source.read())
|
||||
return [data[i:i+SPLIT_LENGTH] for i in range(0, len(data), SPLIT_LENGTH)]
|
||||
|
||||
def create_comment(data):
|
||||
""" takes data bit and turns it into a key comment"""
|
||||
checksum = sha256(data).hexdigest()
|
||||
comment = checksum + ' ' + data
|
||||
return comment
|
||||
""" takes data bit and turns it into a key comment"""
|
||||
checksum = sha256(data).hexdigest()
|
||||
comment = checksum + ' ' + data
|
||||
return comment
|
||||
|
||||
def create_key(name):
|
||||
""" creates gpg key out of given data"""
|
||||
input_data = GPG.gen_key_input(
|
||||
key_type='RSA',
|
||||
key_length='1024',
|
||||
name_real='PGP File System',
|
||||
name_comment=create_comment(name),
|
||||
name_email='placeholder@email.address'
|
||||
)
|
||||
return GPG.gen_key(input_data)
|
||||
""" creates gpg key out of given data"""
|
||||
input_data = GPG.gen_key_input(
|
||||
key_type='RSA',
|
||||
key_length='1024',
|
||||
name_real='PGP File System',
|
||||
name_comment=create_comment(name),
|
||||
name_email='placeholder@email.address'
|
||||
)
|
||||
return GPG.gen_key(input_data)
|
||||
|
||||
def send_key(key_id):
|
||||
""" uploads given key to keyserver"""
|
||||
key_id = str(key_id)
|
||||
GPG.send_keys(KEYSERVER, key_id)
|
||||
if key_id == GPG.search_keys(key_id, KEYSERVER)[0]['keyid']:
|
||||
return key_id
|
||||
else:
|
||||
error = 'Error uploading key ', key_id
|
||||
return error
|
||||
""" uploads given key to keyserver"""
|
||||
key_id = str(key_id)
|
||||
GPG.send_keys(KEYSERVER, key_id)
|
||||
if key_id == GPG.search_keys(key_id, KEYSERVER)[0]['keyid']:
|
||||
return key_id
|
||||
else:
|
||||
error = 'Error uploading key ', key_id
|
||||
return error
|
||||
|
||||
def store_file(filename1, filename2):
|
||||
""" overall function to upload file to keyserver"""
|
||||
print 'Splitting ', filename1, ' into encoded comments for keys'
|
||||
file_list = read_file_into_list(filename1)
|
||||
output_file = open(filename2, 'w')
|
||||
counter_length = len(file_list)
|
||||
counter = 0
|
||||
for chunk in file_list:
|
||||
print 'Creating key ', counter, ' of ', counter_length
|
||||
counter = counter + 1
|
||||
key_id = create_key(chunk)
|
||||
output_file.write(send_key(key_id)+'\n')
|
||||
print '--> key has been created and uploaded'
|
||||
print 'File has been successfully uploaded to ', KEYSERVER
|
||||
""" overall function to upload file to keyserver"""
|
||||
print 'Splitting ', filename1, ' into encoded comments for keys'
|
||||
|
||||
# watch out return value is the name of the newly packed file now
|
||||
filename1 = pack_file_to_disk(filename1)
|
||||
|
||||
file_list = read_file_into_list(filename1)
|
||||
output_file = open(filename2, 'w')
|
||||
counter_length = len(file_list)
|
||||
counter = 0
|
||||
for chunk in file_list:
|
||||
print 'Creating key ', counter, ' of ', counter_length
|
||||
counter = counter + 1
|
||||
key_id = create_key(chunk)
|
||||
output_file.write(send_key(key_id)+'\n')
|
||||
output_file.flush()
|
||||
print '--> key has been created and uploaded'
|
||||
print 'File has been successfully uploaded to ', KEYSERVER
|
||||
|
||||
# TODO adjust with args
|
||||
# tempfile is created at packing stage
|
||||
os.system('tempfile.tmp')
|
||||
|
||||
# fetch file
|
||||
|
||||
def get_key_comment(key_id):
|
||||
""" returns comment section of a given key"""
|
||||
return GPG.search_keys(key_id, KEYSERVER)[0]['uids']
|
||||
""" returns comment section of a given key"""
|
||||
return GPG.search_keys(key_id, KEYSERVER)[0]['uids']
|
||||
|
||||
def parse_key(key_id):
|
||||
"""" parses file bit out of key comment"""
|
||||
comment = get_key_comment(key_id)[0]
|
||||
regex = re.compile(".*?\\((.*?)\\)")
|
||||
comment_bits = re.findall(regex, comment)[0].split(' ')
|
||||
if comment_bits[0] == sha256(comment_bits[1]).hexdigest():
|
||||
return comment_bits[1]
|
||||
"""" parses file bit out of key comment"""
|
||||
comment = get_key_comment(key_id)[0]
|
||||
regex = re.compile(".*?\\((.*?)\\)")
|
||||
comment_bits = re.findall(regex, comment)[0].split(' ')
|
||||
if comment_bits[0] == sha256(comment_bits[1]).hexdigest():
|
||||
return comment_bits[1]
|
||||
|
||||
def fetch_file(index_file, filename):
|
||||
""" overall function to fetch component file parts from keyserver"""
|
||||
with open(index_file, 'r') as index, open(filename, 'w+') as download:
|
||||
print 'Fetching keys from ', KEYSERVER, ' to create ', filename
|
||||
fetched_file = ''
|
||||
index_length = len(index.readlines())
|
||||
index.seek(0) # because python is stupid
|
||||
counter = 0
|
||||
for key in index.readlines():
|
||||
print 'Fetching key ', counter, ' of ', index_length
|
||||
counter = counter + 1
|
||||
fetched_file = fetched_file + parse_key(key.rstrip('\n'))
|
||||
print 'All keys have been downloaded'
|
||||
download.write(base64.b64decode(fetched_file))
|
||||
print 'File has been decoded and saved as ', filename
|
||||
""" overall function to fetch component file parts from keyserver"""
|
||||
filelzma='%s.lzma' % filename
|
||||
with open(index_file, 'r') as index, open(filelzma, 'w+') as download:
|
||||
print 'Fetching keys from ', KEYSERVER, ' to create ', filelzma
|
||||
fetched_file = ''
|
||||
index_length = len(index.readlines())
|
||||
index.seek(0) # because python is stupid
|
||||
counter = 0
|
||||
for key in index.readlines():
|
||||
print 'Fetching key ', counter, ' of ', index_length
|
||||
counter = counter + 1
|
||||
fetched_file = fetched_file + parse_key(key.rstrip('\n'))
|
||||
print 'All keys have been downloaded'
|
||||
download.write(base64.b64decode(fetched_file))
|
||||
# hook in here and unpack the data
|
||||
# filename == original outname
|
||||
# filelzma == packed file here as download
|
||||
unpack_file_from_disk(filelzma,filename)
|
||||
print 'File has been decoded and saved as ', filename
|
||||
|
||||
# handle command line input
|
||||
# remove lzma
|
||||
os.unlink(filelzma)
|
||||
|
||||
if len(sys.argv) < 3:
|
||||
print """Usage: ./pgpfs.py [action] filename1 filename2'
|
||||
action can be either ''store'' or ''fetch'''
|
||||
def usage():
|
||||
print """Usage: ./pgpfs.py [action] filename1 filename2'
|
||||
action can be either ''store'' or ''fetch'''
|
||||
|
||||
When action is 'store':
|
||||
filename1 is the file to upload, filename2 is the name of the key allocation table
|
||||
When action is 'fetch':
|
||||
filename1 is the key allocation table, filename2 is the output file
|
||||
When action is 'store':
|
||||
filename1 is the file to upload, filename2 is the name of the key allocation table
|
||||
When action is 'fetch':
|
||||
filename1 is the key allocation table, filename2 is the output file
|
||||
|
||||
Example uses:
|
||||
- To store 'sample.mp3' on the keyserver
|
||||
./pgpfs.py store sample.mp3 sample.kat
|
||||
- To fetch the file contained in 'sample.kat' and store it as 'sample.mp3'
|
||||
./pgpfs.py fetch sample.kat sample.mp3
|
||||
"""
|
||||
sys.exit(0)
|
||||
Example uses:
|
||||
- To store 'sample.mp3' on the keyserver
|
||||
./pgpfs.py store sample.mp3 sample.kat
|
||||
- To fetch the file contained in 'sample.kat' and store it as 'sample.mp3'
|
||||
./pgpfs.py fetch sample.kat sample.mp3
|
||||
"""
|
||||
sys.exit(0)
|
||||
|
||||
ACTION = sys.argv[1]
|
||||
def run(args):
|
||||
''' run function, do all the magic '''
|
||||
|
||||
if ACTION not in ['store', 'fetch']:
|
||||
print 'Please specific either ''store'' or ''fetch'''
|
||||
sys.exit(0)
|
||||
global KEYSERVER
|
||||
global GPG
|
||||
|
||||
if ACTION == 'store':
|
||||
store_file(sys.argv[2], sys.argv[3])
|
||||
elif ACTION == 'fetch':
|
||||
fetch_file(sys.argv[2], sys.argv[3])
|
||||
|
||||
pgpfspath = args.pgpfspath
|
||||
pgpfsbin = args.pgpfsbin
|
||||
KEYSERVER = args.keyserver
|
||||
ACTION = args.action
|
||||
kat = args.kat
|
||||
store = args.store
|
||||
|
||||
GPG = gnupg.GPG(gnupghome=pgpfspath,gpgbinary=pgpfsbin)
|
||||
|
||||
if ACTION not in ['store', 'fetch']:
|
||||
print 'Please specific either ''store'' or ''fetch'''
|
||||
sys.exit(0)
|
||||
|
||||
if ACTION == 'store':
|
||||
store_file(store, kat)
|
||||
elif ACTION == 'fetch':
|
||||
fetch_file(kat, store)
|
||||
pass
|
||||
|
||||
def main():
|
||||
prog_name='pgpfs.py'
|
||||
prog_desc='https://github.com/aestetix/pgpfs'
|
||||
|
||||
parser = argparse.ArgumentParser(prog=prog_name, description=prog_desc)
|
||||
parser.add_argument('-a','--action',help='action to do: store or fetch',dest='action',required=True)
|
||||
parser.add_argument('-k','--katfile',help='if fetch specify KAT file',dest='kat',required=False)
|
||||
parser.add_argument('-s','--storefile',help='if store specify file for upload',dest='store',required=False)
|
||||
parser.add_argument('--keyserver',help='specify keyserver',dest='keyserver',required=False, default='pgp.mit.edu')
|
||||
parser.add_argument('--pgpfspath',help='specify path for pgpfs',dest='pgpfspath',required=False, default='.pgpfs')
|
||||
parser.add_argument('--gpgbinary',help='specify path for pgpfs binary(patched gpg bin)',dest='pgpfsbin',required=False, default='/root/fuzzygpg/bin/gpg2')
|
||||
args = parser.parse_args()
|
||||
run(args)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
Reference in New Issue
Block a user