def get_handler(arg): public = None uri = "" if arg.cap: cap = arg.cap.split(":") else: # TODO this should read the current dir to find out the URI for the file with open('private/files.txt', "r") as f: for line in f: ind = line.find(arg.name) # here assumes the files have different names # TODO check for the same names that are substring of the other if ind != -1: key_ind = line.find("|")+1 line = line[key_ind:] cap = line.split(":") file_name = arg.name abs_path = os.path.abspath(pjoin('private/keys/', file_name)) # check if this file was created by the user # TODO the public key should be in the file we get if os.path.exists(abs_path): with open('private/keys/'+arg.name+"public", "r") as f: public = f.read() break if cap[0] == FILE_WRITE_CAP or cap[0] == DIR_WRITE_CAP: h = crypto.my_hash(cap[1])[:16] h = crypto.my_hash(h) uri = capToString((cap[0], h, cap[2])) elif cap[0] == DIR_READ_CAP or cap[0] == FILE_WRITE_CAP: h = crypto.my_hash(cap[1]) uri = capToString((cap[0], h, cap[2])) else: uri = "" # access the file via the write-cap cipher = get_data(uri) data_ar = cipher.split(SPLIT_SYMBOL) sign = data_ar[1] data = data_ar[0] public = data_ar[2] try: assert(data_ar[3] == crypto.my_hash(public)) valid = crypto.verify_RSA(public, sign, data) print "Valid: ", valid assert(valid) except AssertionError as e: print "Data invalid" return # generate the AES decryption key and decrypt salt = "a"*16 s = str(cap[1] + salt) hashed_key = crypto.my_hash(s) ptext = crypto.decrypt(data, hashed_key[:16]) txt = ptext.find(SPLIT_SYMBOL) return ptext[:txt]
def do_POST(s): """Respond to a POST request.""" s.send_response(200) s.send_header("Content-type", "text/html") s.end_headers() # before doing post, first check integrity, then check permissions # if the file exists, the path must be the write capability length = s.headers['content-length'] data = s.rfile.read(int(length)) decoded = data[5:] decoded = urllib.unquote(decoded).decode("utf8") decoded = DecodeAES(decoded) data_ar = decoded.split(SPLIT_SYMBOL) sign = data_ar[1] data = data_ar[0] # obtain public key from the data and verify public = data_ar[2] cap = s.path[s.path.rfind("/") + 1:].split(":") h = crypto.my_hash(public) print cap print data_ar if h != data_ar[3] or h[:16] != cap[2]: send_error(s) return valid = crypto.verify_RSA(public, sign, data) print "Valid: ", valid if not valid: send_error(s) return # allow write if the file does not exist or # when you present write cap file_name = crypto.my_hash(crypto.my_hash(cap[1])) store_path = pjoin(curdir+DATALOCATION, file_name) print "STORE PATH: ", store_path # TODO with the directory structure, notify the server of the created files # so that it can check if this store_path is ever created if os.path.exists(store_path): print "PATH EXISTS" with open(store_path, 'w') as fh: fh.write(decoded) else: print "NO PATH" with open(store_path, 'w') as fh: fh.write(decoded)
def put_handler(arg): if arg.writecap: # putting with a cap requires # 1) Getting the encrypted private key # 2) Decrypting it, and using it to sign the updated data # 3) Signing the encryption of the updated data with the private key cap = arg.writecap.split(":") cipher = get_data(arg.writecap) (data, private, public) = crypto.unpackage_data(cap, cipher) else: with open("private/root_dir.cap", 'r') as f: line = f.read() if line and line != "\n": line = line[line.find("|")+1:].strip("\n") root_cap = line.split(":") cipher = get_data(line) (data, root_private, root_public)= crypto.unpackage_data(root_cap, cipher) data = json.loads(data) # here cap is (my_hash(private_key), my_hash(public_key)) (private, public, cap) = crypto.generate_RSA() cap = [FILE_WRITE_CAP, cap[0], cap[1]] # put name in dir data[arg.name] = capToString(cap) # update root dir data data = json.dumps(data) data = crypto.package_data(data, root_cap, root_private, root_public) print_capabilities(root_cap) post_data(data, capToString(root_cap)) # save the cap in a private file with open('private/files.txt', "a") as f: c = arg.name+ "|" + capToString(cap)+ "\n" f.write(c) # TODO get rid of key storage by making get to the server via URI after createion # save the private key in a file with open('private/keys/'+arg.name+"public", "w") as f: f.write(public) with open('private/keys/'+arg.name+"private", "w") as f: f.write(private) data = arg.data data = crypto.package_data(data, cap, private, public) print_capabilities(cap) h = crypto.my_hash(cap[1])[:16] cap[1] = crypto.my_hash(h) post_data(data, capToString(cap))
def do_GET(s): # TODO different responses to write, read, none """Respond to a GET request.""" s.send_response(200) s.send_header("Content-type", "text/html") s.end_headers() # determine the capability: write, read, or none name = s.path[s.path.rfind("/")+1:] cap = name.split(":") file_name = crypto.my_hash(cap[1]) print "kar server file name: ", file_name print "cap: ", cap abs_path = os.path.abspath(pjoin(curdir+DATALOCATION, file_name)) if os.path.exists(abs_path): # it is read cap print "READ" s.wfile.write("<html><head><title>READ CAP PRESENTED</title></head>") s.wfile.write("<body><p>You do not have write privileges.</p>") s.wfile.write("<p>You accessed path: %s</p>" % s.path) s.wfile.write("<p>File exists: %s</p>" % pjoin(curdir+DATALOCATION, s.path)) content = "" with open(abs_path, 'r') as fh: content = fh.read() s.wfile.write("<p>File content: data=%s</p>" % EncodeAES(content)) s.wfile.write("</body></html>") else: file_name = crypto.my_hash(file_name) abs_path = os.path.abspath(pjoin(curdir+DATALOCATION, file_name)) if os.path.exists(abs_path): # it is a write cap print "WRITE" s.wfile.write("<html><head><title>WRITE CAP PRESENTED</title></head>") s.wfile.write("<body><p>Thanks for updating the file</p>") s.wfile.write("<p>You accessed path: %s</p>" % s.path) s.wfile.write("<p>File exists: %s</p>" % pjoin(curdir+DATALOCATION, s.path)) content = "" with open(abs_path, 'r') as fh: content = fh.read() s.wfile.write("<p>File content: data=%s</p>" % EncodeAES(content)) s.wfile.write("</body></html>") else: # it is nothing print "NOTHING" s.wfile.write("<html><head><title> ERROR </title></head>") s.wfile.write("<body><p>Can't access</p>") s.wfile.write("</body></html>")
def print_capabilities(cap): if cap[0] == FILE_WRITE_CAP: t = "file" r = FILE_READ_CAP elif cap[0] == DIR_WRITE_CAP: t = "directory" r = DIR_READ_CAP else: t = "unknown" r = "unknown" # double hash the key to get the file name h = crypto.my_hash(cap[1])[:16] file_name = crypto.my_hash(h) write = capToString(cap) print "Write cap for the %s is: %s" % (t, write) read = capToString(cap) print "Read cap for the %s is: %s" % (t, capToString((r, h, cap[2])))
def get_handler(arg): public = None uri = "" if arg.cap: uri = arg.cap cap = uri.split(":") else: # TODO this should read the current dir to find out the URI for the file with open('private/files.txt', "r") as f: for line in f: ind = line.find(arg.name) # here assumes the files have different names # TODO check for the same names that are substring of the other if ind != -1: key_ind = line.find("|")+1 line = line[key_ind:] #splitting the file name from cap cap = line.split(":") uri = cap[0]+":"+cap[1]+":"+cap[2] file_name = arg.name abs_path = os.path.abspath(pjoin('private/keys/', file_name)) # check if this file was created by the user # the public key should be in the file we get if os.path.exists(abs_path): with open('private/keys/'+arg.name+"public", "r") as f: public = f.read() break #creating the public private keys # access the file via the write-cap cipher = get_data(uri) data_ar = cipher.split(SPLIT_SYMBOL) sign = data_ar[1] data = data_ar[0] public = data_ar[2] assert(data_ar[3] == crypto.my_hash(public)) valid = crypto.verify_RSA(public, sign, data) print "Valid: ", valid if valid: # generate the AES decryption key and decrypt salt = "a"*16 s = str(cap[1] + salt) hashed_key = crypto.my_hash(s) ptext = crypto.decrypt(data, hashed_key[:16]) txt = ptext.find(SPLIT_SYMBOL) return ptext[:txt] return None
def put_handler(arg): if arg.writecap: # putting with a cap requires # 1) Getting the encrypted private key # 2) Decrypting it, and using it to sign the updated data same signature fro authenticity # 3) Signing the encryption of the updated data with the private key cap = arg.writecap.split(":") cipher = get_data(arg.writecap) data_ar = cipher.split(SPLIT_SYMBOL) sign = data_ar[1] data = data_ar[0] public = data_ar[2] assert(data_ar[3] == crypto.my_hash(public)) valid = crypto.verify_RSA(public, sign, data) print "Valid: ", valid if valid: # generate the AES decryption key and decrypt salt = "a"*16 s = str(cap[1] + salt) hashed_key = crypto.my_hash(s) ptext = crypto.decrypt(data, hashed_key[:16]) splitted = ptext.split(SPLIT_SYMBOL) raw_data = splitted[0] enc_pk = splitted[1] private = crypto.decrypt(enc_pk, cap[1]) data = arg.data else: # here cap is (my_hash(private_key), my_hash(public_key)) (private, public, cap) = crypto.generate_RSA() cap = [FILE_WRITE_CAP, cap[0], cap[1]] # save the cap in a private file with open('private/files.txt', "a") as f: c = arg.name+ "|" + cap[0] + ":" + cap[1] + ":" + cap[2] + "\n" f.write(c) # save the private key in a file with open('private/keys/'+arg.name+"public", "w") as f: f.write(public) with open('private/keys/'+arg.name+"private", "w") as f: f.write(private) data = arg.data # store the encrypted private key in the data data = data + SPLIT_SYMBOL + crypto.encrypt(private, cap[1], False) # use the read key as an encryption key for the concatted data salt = "a"*16 s = str(cap[1] + salt) hashed_key = crypto.my_hash(s) # encrypt the data data = crypto.encrypt(data, hashed_key[:16], False) # sign it with private key signature = crypto.sign_data(private, data) # FINAL DATA IS # enc_data | signature | public_key | hash(public_key) data = data +SPLIT_SYMBOL+ signature + SPLIT_SYMBOL + public + SPLIT_SYMBOL + crypto.my_hash(public) # double hash the key to get the file name file_name = crypto.my_hash(crypto.my_hash(cap[1])) write = ":".join(map(str, cap)) print "Write cap for the file is: %s" % write cap[0] = FILE_READ_CAP cap[1] = crypto.my_hash(cap[1])[:16] read = ":".join(map(str, cap)) print "Read cap for the file is: %s" % read print "You can access the capability in private/files.txt" post_data(data, write)