forked from rossem/RedditStorage
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathreddit.py
More file actions
114 lines (102 loc) · 5.01 KB
/
Copy pathreddit.py
File metadata and controls
114 lines (102 loc) · 5.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
import gc
import os.path
from base64 import b64encode, b64decode
import praw
from typing import Tuple, List
from time import sleep
from secrets import SystemRandom
from redditglobals import *
from argon2 import Parameters # For typehints
# Tuple containing [ciphertext, MAC, salt, time_cost, memory_cost, parallelism, hash_len, argon2type, argon2version]
def post_encryption(post_title, ciphertext: bytes, MAC: bytes, salt: str, nonce: bytes, argon2_params: Parameters):
"""
Posts encrypted ciphertext to a subreddit defined in redditglobals.py
:param post_title: The title of the post to make
:param ciphertext: Encrypted text to post, encoded in base64
:param MAC: Associated MAC for the ciphertext, encoded in base64
:param salt: Salt used to hash the password, encoded in base64 utf-8
:param nonce: Nonce used by the AES algorithm
:param argon2_params: Argon2 parameters used to hash the password
"""
subreddit = REDDIT.subreddit(SUBREDDIT)
does_not_exist = True
post_title = os.path.basename(post_title)
file_submissions = subreddit.search(post_title, SUBREDDIT)
# getting the submission of the file if it exists already
count = 0
filename_lower = post_title.lower()
for submission in file_submissions:
if filename_lower in submission.title.lower(): # Looks for submissions with filename inside it
count += 1
does_not_exist = False
# create submission. Post text will be params necessary to recreate the hash in argon2
# Format is MAC$salt$time cost$memory cost$parallelism$hash length$salt length$argon2 type$argon2 version$nonce
# Ex: examplemac$examplesalt$20$45$4$32$16$Type.ID$19
post_text = f'{MAC.decode("utf-8")}${salt}==${argon2_params.time_cost}${argon2_params.memory_cost}$' \
f'{argon2_params.parallelism}${argon2_params.hash_len}${argon2_params.salt_len}${argon2_params.type}${argon2_params.version}${nonce.decode("utf-8")}'
if does_not_exist:
file_post = subreddit.submit(post_title, selftext=post_text)
else: # if file exists, then add a number to the end of the filename
file_post = subreddit.submit(post_title + " (" + str(count) + ")", selftext=post_text)
del post_text
gc.collect()
# going to be splitting the encryption since the comment limit is 10000 characters
# this is the first-level comment
print(f'\nNumber of comments to post: {len(ciphertext) / 10000 + 1}\n')
rand_num = SystemRandom()
current_comment = file_post.reply(ciphertext[:10000])
cur_index = 10000
ciphertext_len = len(ciphertext)
num_comments = 1
next_sleep = rand_num.randrange(10, 22)
print(f'\nPosted {num_comments} comment\n')
# Tries to reply with max chars for comments (10,000) until there isn't enough in the buffer
while ciphertext_len - cur_index >= 10000: # Keep replying with max chars until we can't
current_comment = current_comment.reply(ciphertext[cur_index:cur_index + 10000])
num_comments += 1
print(f'Posted {num_comments} comment\n')
if num_comments == next_sleep:
print('Sleeping')
next_sleep += rand_num.randrange(1, 10) # Stop commenting after 1-10 comments
sleep(float(rand_num.randrange(200, 450)) / 10.0) # 20.0-45.0 second sleep
cur_index += 10000
if ciphertext_len > cur_index:
current_comment.reply(ciphertext[cur_index:])
del ciphertext
gc.collect()
def get_ciphertext(post_title) -> Tuple[bytes, List[str]]:
"""
Returns the ciphertext and MAC from given post title
:param post_title: Name of the post to find
:return: A tuple containing [ciphertext, argon2 parameters]. Only ciphertext is decoded from base64
"""
ciphertext = ''
subreddit = REDDIT.subreddit(SUBREDDIT)
file_submissions = subreddit.search(post_title)
subm = []
submissions_found = 0
# find the corresponding post for the file
filename_lower = post_title.lower()
for submission in file_submissions:
if filename_lower in submission.title.lower():
subm.append(submission)
submissions_found += 1
if not submissions_found:
# todo: get an actual exception type
raise Exception("Couldn't find file")
if submissions_found == 1: # Found only 1 file
# level the comments
subm[0].comments.replace_more(limit=None, threshold=0)
comments = subm[0].comments.list()
params: List[str] = subm[0].selftext.split('$')
for comment in comments:
ciphertext: str = ciphertext + comment.body
return b64decode(ciphertext), params
else: # More than 1 similar file found;
# todo: Need to show a dialog window so they can select which version to dl (or all)
subm[0].comments.replace_more(limit=None, threshold=0)
comments = subm[0].comments.list()
params: List[str] = subm[0].selftext.split('$')
for comment in comments:
ciphertext: str = ciphertext + comment.body
return b64decode(ciphertext), params