Skip to content

Commit 96a4371

Browse files
authored
Tidy up before release
1 parent ee0196d commit 96a4371

File tree

4 files changed

+400
-0
lines changed

4 files changed

+400
-0
lines changed

config.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import getpass
2+
3+
# Using infura as to not require the user to run an IPFS node
4+
host = "https://ipfs.infura.io"
5+
port = 5001
6+
7+
# Temporary directory where all the processing happens
8+
tmpDir = "/tmp"
9+
10+
# History location
11+
dbLocation = "/home/{}/.local/skyhook.db".format(getpass.getuser())
12+
13+
usage = """
14+
skyhook clear history - Delete everything from history
15+
skyhook list history - List all entries in history
16+
skyhook list keys - List all files and their corresponding encryption keys
17+
18+
skyhook search [file name] - Search history for entries matching [file name]
19+
skyhook delete [hash] - Delete an entry specified by [hash] from history
20+
skyhook save [hash] - Save a single history entry specified by [hash] to the current directory (Importable)
21+
22+
skyhook import [path] - Import history from a location specified by [path]
23+
skyhook export [path] - Export history to a location specified by [path]
24+
25+
skyhook upload [file name] - Upload a file specified by [file name] from the current directory to the IPFS network
26+
skyhook download [hash] - Download a file specified by [hash] from the IPFS network to the current directory
27+
"""

crypto.py

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
import os, math, threading, multiprocessing
2+
from Crypto.Cipher import AES
3+
4+
separator = b" :><:><:><: "
5+
6+
chunkS = int(math.pow(AES.block_size, 4))
7+
threads = int(math.pow(multiprocessing.cpu_count(), 2))
8+
9+
def pad(content):
10+
return(content + b"!" * (AES.block_size - len(content) % AES.block_size))
11+
12+
def enCrypt(cipher, content, fileHandle, previous):
13+
14+
encrypted = cipher.encrypt(content)
15+
16+
if previous == None:
17+
fileHandle.write(encrypted)
18+
exit()
19+
else:
20+
while previous.is_alive() == True:
21+
pass
22+
else:
23+
fileHandle.write(encrypted)
24+
exit()
25+
26+
def encryptFile(originalName, newName, key):
27+
28+
global chunkS
29+
global threads
30+
31+
chunkSize = chunkS
32+
maxThreads = threads
33+
34+
iv = os.urandom(16)
35+
cipher = AES.new(key, AES.MODE_CBC, iv)
36+
37+
outFile = open(newName, "wb")
38+
outFile.write(iv + separator)
39+
40+
inFile = open(originalName, "rb")
41+
inFile.seek(0, os.SEEK_END)
42+
43+
contentLength = inFile.tell()
44+
45+
while contentLength % AES.block_size != 0:
46+
contentLength = contentLength + 1
47+
48+
if contentLength <= chunkSize:
49+
chunkSize = contentLength
50+
maxThreads = 1
51+
52+
parts = int(contentLength / chunkSize / maxThreads)
53+
54+
for i in range(0, parts):
55+
56+
seekDefault = i * chunkSize * maxThreads
57+
58+
threadPool = list()
59+
previous = None
60+
last = False
61+
62+
if i == parts - 1:
63+
last = True
64+
maxThreads = 1
65+
66+
for x in range(0, maxThreads):
67+
68+
inFile.seek(seekDefault + x * chunkSize)
69+
70+
if last == True:
71+
content = pad(inFile.read())
72+
else:
73+
content = inFile.read(chunkSize)
74+
75+
t = threading.Thread(target=enCrypt, args=(cipher, content, outFile, previous))
76+
threadPool.append(t)
77+
previous = t
78+
79+
for thread in threadPool:
80+
thread.start()
81+
thread.join()
82+
83+
while previous.is_alive() == True:
84+
pass
85+
86+
inFile.close()
87+
outFile.close()
88+
89+
def deCrypt(cipher, content, fileHandle, padded, previous):
90+
91+
decrypted = cipher.decrypt(content)
92+
93+
if padded == True:
94+
decrypted = decrypted.rstrip(b"!")
95+
96+
if previous == None:
97+
fileHandle.write(decrypted)
98+
exit()
99+
else:
100+
while previous.is_alive() == True:
101+
pass
102+
else:
103+
fileHandle.write(decrypted)
104+
exit()
105+
106+
def decryptFile(oldName, newName, key):
107+
108+
global chunkS
109+
global threads
110+
111+
chunkSize = chunkS
112+
maxThreads = threads
113+
114+
inFile = open(oldName, "rb")
115+
outFile = open(newName, "wb")
116+
117+
iv = inFile.read(16)
118+
119+
skip = len(iv + separator)
120+
cipher = AES.new(key, AES.MODE_CBC, iv)
121+
122+
inFile.seek(0, os.SEEK_END)
123+
124+
contentLength = inFile.tell() - skip
125+
126+
if contentLength <= chunkSize:
127+
chunkSize = contentLength
128+
maxThreads = 1
129+
130+
parts = int(contentLength / chunkSize / maxThreads)
131+
132+
for i in range(0, parts):
133+
134+
seekDefault = i * chunkSize * maxThreads + skip
135+
136+
threadPool = list()
137+
previous = None
138+
last = False
139+
140+
padded = False
141+
142+
if i == parts - 1:
143+
last = True
144+
maxThreads = 1
145+
padded = True
146+
147+
for x in range(0, maxThreads):
148+
149+
inFile.seek(seekDefault + x * chunkSize)
150+
151+
if last == True:
152+
content = inFile.read()
153+
else:
154+
content = inFile.read(chunkSize)
155+
156+
t = threading.Thread(target=deCrypt, args=(cipher, content, outFile, padded, previous))
157+
threadPool.append(t)
158+
previous = t
159+
160+
for thread in threadPool:
161+
thread.start()
162+
thread.join()
163+
164+
while previous.is_alive() == True:
165+
pass
166+
167+
inFile.close()
168+
outFile.close()

db.py

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
import os, sqlite3, shutil
2+
from config import *
3+
4+
try:
5+
connection = sqlite3.connect(dbLocation)
6+
cursor = connection.cursor()
7+
cursor.execute("CREATE TABLE IF NOT EXISTS history (name TEXT, hash TEXT, key TEXT, date TEXT)")
8+
except:
9+
print("[!] Could not connect to {}".format(dbLocation))
10+
exit()
11+
12+
if os.path.isdir(tmpDir):
13+
pass
14+
else:
15+
print("[!] Temporary path {} is not a valid directory".format(tmpDir))
16+
exit()
17+
18+
if os.path.isabs(tmpDir):
19+
pass
20+
else:
21+
print("[!] Temporary path {} is not absolute".format(tmpDir))
22+
exit()
23+
24+
if os.access(tmpDir, os.W_OK) and os.access(tmpDir, os.R_OK):
25+
pass
26+
else:
27+
print("[!] Cannot read or write to and from {}".format(tmpDir))
28+
exit()
29+
30+
def listDb():
31+
items = cursor.execute("SELECT DISTINCT name, hash, date FROM history").fetchall()
32+
if len(items) == 0:
33+
print("[!] History is empty")
34+
exit()
35+
else:
36+
print("\n[+] History (Name (Date) [Hash])")
37+
for name, hash, date in items:
38+
print("\n{} ({}) [{}]".format(name, date, hash))
39+
print()
40+
41+
def listKeys():
42+
items = cursor.execute("SELECT DISTINCT name, key FROM history").fetchall()
43+
if len(items) == 0:
44+
print("[!] History is empty")
45+
exit()
46+
else:
47+
print("\n[+] Keys (Name [Key])")
48+
for name, key in items:
49+
print("\n{} [{}]".format(name, key))
50+
print()
51+
52+
def clearDb():
53+
cursor.execute("DROP TABLE IF EXISTS history")
54+
connection.commit()
55+
print("[+] History cleared")
56+
57+
def searchDb(fileName):
58+
items = cursor.execute("SELECT DISTINCT name, hash, date FROM history WHERE name = ?", (fileName,)).fetchall()
59+
if len(items) == 0:
60+
print("[!] Could not find any entries for {}".format(fileName))
61+
exit()
62+
else:
63+
print("\n[+] Files (Name (Date) [Hash])")
64+
for name, hash, date in items:
65+
print("\n{} ({}) [{}]".format(name, date, hash))
66+
print()
67+
68+
def exportDb(newPath):
69+
try:
70+
shutil.copyfile(dbLocation, newPath)
71+
return(0)
72+
except:
73+
return(1)
74+
75+
def saveOne(fileHash):
76+
item = cursor.execute("SELECT DISTINCT name, hash, key, date FROM history WHERE hash = ?", (fileHash,)).fetchone()
77+
if item == None:
78+
return(1)
79+
try:
80+
auxcon = sqlite3.connect("{}.save".format(fileHash))
81+
auxcur = auxcon.cursor()
82+
auxcur.execute("CREATE TABLE IF NOT EXISTS history (name TEXT, hash TEXT, key TEXT, date TEXT)")
83+
auxcur.execute("INSERT INTO history VALUES (?, ?, ?, ?)", tuple(item))
84+
auxcon.commit()
85+
except:
86+
return(2)
87+
return(0)
88+
89+
def importDb(dbPath):
90+
try:
91+
with open(dbPath, "rb") as db:
92+
header = db.read(15)
93+
except:
94+
return(1)
95+
if header == b"SQLite format 3":
96+
try:
97+
auxcon = sqlite3.connect(dbPath)
98+
auxcur = auxcon.cursor()
99+
auxfetch = auxcur.execute("SELECT DISTINCT name, hash, key, date FROM history").fetchall()
100+
if len(auxfetch) == 0:
101+
return(3)
102+
else:
103+
for item in auxfetch:
104+
cursor.execute("INSERT INTO history VALUES (?, ?, ?, ?)", tuple(item))
105+
connection.commit()
106+
return(0)
107+
except:
108+
return(2)
109+
else:
110+
return(2)
111+
112+
def deleteItem(fileHash):
113+
item = cursor.execute("SELECT DISTINCT hash FROM history WHERE hash = ?", (fileHash,)).fetchone()
114+
if item == None:
115+
return(1)
116+
else:
117+
try:
118+
cursor.execute("DELETE FROM history WHERE hash = ?", (fileHash,))
119+
connection.commit()
120+
return(0)
121+
except:
122+
return(2)
123+
124+
def cleanUp(filePath):
125+
os.remove(filePath)

0 commit comments

Comments
 (0)