2020-12-31 03:59:26 +00:00
|
|
|
"""Onionr - Private P2P Communication
|
|
|
|
|
|
|
|
Wrap RinseOff, a c# CLI tool for secure data erasure via a keyfile.
|
2020-12-31 03:25:05 +00:00
|
|
|
|
|
|
|
Intended for encrypting database entries.
|
|
|
|
|
|
|
|
It is quite slow since it spawns an external process,
|
|
|
|
but an ext process is necessary to keep the key out
|
|
|
|
of memory as much as possible
|
|
|
|
"""
|
2020-12-30 06:48:59 +00:00
|
|
|
import os
|
|
|
|
from typing import Union
|
|
|
|
|
|
|
|
import subprocess
|
|
|
|
|
|
|
|
from filepaths import secure_erase_key_file, app_root
|
|
|
|
import logger
|
2020-12-31 03:59:26 +00:00
|
|
|
"""
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
"""
|
|
|
|
|
2020-12-30 06:48:59 +00:00
|
|
|
|
|
|
|
_rinseoff = f"{app_root}/src/rinseoff/rinseoffcli"
|
|
|
|
|
|
|
|
|
2020-12-30 07:48:19 +00:00
|
|
|
def generate_key_file():
|
2020-12-30 06:48:59 +00:00
|
|
|
if os.path.exists(secure_erase_key_file):
|
2020-12-31 03:25:05 +00:00
|
|
|
raise FileExistsError(
|
|
|
|
"Key file for rinseoff secure erase already exists")
|
2020-12-30 06:48:59 +00:00
|
|
|
|
2020-12-31 03:25:05 +00:00
|
|
|
with open(secure_erase_key_file, 'wb') as f:
|
|
|
|
f.write(os.urandom(32))
|
2020-12-30 06:48:59 +00:00
|
|
|
|
|
|
|
|
2020-12-30 07:48:19 +00:00
|
|
|
def protect_string(plaintext: Union[bytes, bytearray, str]) -> bytes:
|
2020-12-30 06:48:59 +00:00
|
|
|
"""Create a "secure" string. Dont really rely on this, and dont use for comms
|
|
|
|
|
|
|
|
This is just to make forensics a little harder"""
|
|
|
|
try:
|
|
|
|
plaintext = plaintext.encode('utf-8')
|
|
|
|
except AttributeError:
|
|
|
|
pass
|
|
|
|
|
|
|
|
process = subprocess.Popen(
|
|
|
|
["dotnet", "run",
|
|
|
|
"--project", _rinseoff,
|
|
|
|
"store", "stdout", f"{secure_erase_key_file}"],
|
|
|
|
stdout=subprocess.PIPE,
|
|
|
|
stderr=subprocess.PIPE,
|
|
|
|
stdin=subprocess.PIPE)
|
|
|
|
res = process.communicate(plaintext)
|
|
|
|
|
|
|
|
if res[0] and not res[1]:
|
|
|
|
return res[0]
|
|
|
|
else:
|
2020-12-30 07:48:19 +00:00
|
|
|
logger.warn("Error when protecting string for database", terminal=True)
|
2020-12-30 06:48:59 +00:00
|
|
|
for line in res[1].decode('utf-8').split('\n'):
|
|
|
|
logger.error(line, terminal=True)
|
2020-12-31 03:25:05 +00:00
|
|
|
raise subprocess.CalledProcessError(
|
|
|
|
"Error protecting string")
|
2020-12-30 07:48:19 +00:00
|
|
|
|
|
|
|
|
|
|
|
def unprotect_string(ciphertext: Union[bytes, bytearray]) -> bytes:
|
|
|
|
process = subprocess.Popen(
|
|
|
|
["dotnet", "run",
|
|
|
|
"--project", _rinseoff,
|
|
|
|
"load", "stdin", f"{secure_erase_key_file}"],
|
|
|
|
stdout=subprocess.PIPE,
|
|
|
|
stderr=subprocess.PIPE,
|
|
|
|
stdin=subprocess.PIPE)
|
|
|
|
res = process.communicate(ciphertext)
|
|
|
|
|
|
|
|
if res[0] and not res[1]:
|
|
|
|
return res[0]
|
|
|
|
else:
|
|
|
|
logger.warn(
|
|
|
|
"Error when decrypting ciphertext from database", terminal=True)
|
|
|
|
for line in res[1].decode('utf-8').split('\n'):
|
|
|
|
logger.error(line, terminal=True)
|
2020-12-31 03:25:05 +00:00
|
|
|
raise subprocess.CalledProcessError(
|
|
|
|
"Error unprotecting string")
|