Files
pgpfs/pgpfs.py
2017-05-19 19:45:50 +02:00

128 lines
4.1 KiB
Python
Executable File

#!bin/python
""" pgpfs is a tool to turn your friendly pgp keyserver into a redundant
persistant filesystem."""
import os
import sys
import re
import base64
from hashlib import sha256
import gnupg
os.system('rm -rf gpg')
GPG = gnupg.GPG(gnupghome='gpg')
KEYSERVER = 'pgp.mit.edu'
# trial and error lead to this number
SPLIT_LENGTH = 986
# 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)]
def create_comment(data):
""" 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)
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
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
# fetch file
def get_key_comment(key_id):
""" 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]
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
# handle command line input
if len(sys.argv) < 3:
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
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]
if ACTION not in ['store', 'fetch']:
print 'Please specific either ''store'' or ''fetch'''
sys.exit(0)
if ACTION == 'store':
store_file(sys.argv[2], sys.argv[3])
elif ACTION == 'fetch':
fetch_file(sys.argv[2], sys.argv[3])