Skip to content

Instantly share code, notes, and snippets.

@Apocryphon-X
Last active January 1, 2024 15:50
Show Gist options
  • Select an option

  • Save Apocryphon-X/6b628d4f5b69df01395165281291986e to your computer and use it in GitHub Desktop.

Select an option

Save Apocryphon-X/6b628d4f5b69df01395165281291986e to your computer and use it in GitHub Desktop.
Symmetric encryption utility. (Wrapper of GPG - For personal use)
#!/usr/bin/python3
# Copyright (c) 2022 @Apocryphon (Dante Mendoza Leyva).
# All rights reserved.
import click
import subprocess
import pathlib
import shutil
import sys
import zipfile
import pwinput
import blessed
term = blessed.Terminal()
@click.command(help="Encrypts the given file (or directory) using OpenPGP.")
@click.argument("TARGET-PATHS", nargs=-1)
@click.option("--version", "-v", help="Shows the encrypter version.", is_flag=True)
@click.option(
"--same-passphrase",
"-s",
help="Use the same passphrase for every file.",
is_flag=True,
)
def encrypt(target_paths, version, same_passphrase):
if version:
sys.stderr.write("lock: Version 3.0\n")
sys.stderr.write(f"{'-' * 25}\n")
subprocess.run(["gpg", "--version"])
return
if len(target_paths) == 0:
sys.stderr.write("lock: Nothing to do.\n")
return
passphrase = ""
if same_passphrase:
p1 = "-"
p2 = "+"
while p1 != p2:
p1 = pwinput.pwinput(prompt="? Enter passphrase: ", mask="•")
p2 = pwinput.pwinput(prompt="? Please re-enter this passphrase: ", mask="•")
if p1 != p2:
sys.stderr.write(f"\nlock: {term.red('Does not match - try again.')}\n")
print(f"{'-' * 40}")
passphrase = p1
for target_path in target_paths:
target_path = pathlib.Path(target_path)
result_path = f"{target_path.resolve()}"
is_dir_cache = target_path.is_dir()
if is_dir_cache:
with zipfile.ZipFile(f"{result_path}.lock", "w") as zip_obj:
for file in target_path.glob("**/*"):
file_path = file.parent.joinpath(file.name)
relative_path = file_path.relative_to(target_path.parent)
sys.stderr.write(
f"lock: {term.green('[+]')} {term.yellow('Adding:')} {term.gray(str(file_path.resolve()))}\n"
)
zip_obj.write(file_path, relative_path, zipfile.ZIP_DEFLATED)
result_path += ".lock"
command = ["gpg", "--no-symkey-cache", "-c"]
if same_passphrase:
command += ["--batch", "--yes"]
command += ["--passphrase", passphrase]
command.append(result_path)
result = subprocess.run(command, capture_output=True)
logs = result.stderr.decode("ascii")
# Logs formatting
logs = logs.replace(
"No such file or directory", term.red("No such file or directory")
)
logs = logs.replace("Invalid passphrase", term.red("Invalid passphrase"))
if len(logs) > 0:
sys.stderr.write(f"{logs.strip()}\n")
if "failed" in logs or "can't open" in logs:
if is_dir_cache:
zip_path = pathlib.Path(result_path)
zip_path.unlink(missing_ok=True)
continue
gpg_file_path = pathlib.Path(f"{result_path}.gpg")
if is_dir_cache:
shutil.rmtree(target_path)
gpg_file_path.replace(result_path)
sys.stderr.write(
f"lock: Symmetric encryption of '{target_path}' {term.green('ended succesfully.')}\n"
)
if __name__ == "__main__":
encrypt()
#!/usr/bin/python3
# Copyright (c) 2022 Apocryphon-X (Dante Mendoza Leyva).
# All rights reserved.
import click
import subprocess
import pathlib
import shutil
import zipfile
import sys
import pwinput
import blessed
term = blessed.Terminal()
@click.command(help="Decrypts the given file (or directory) using OpenPGP.")
@click.argument("TARGET-PATHS", nargs=-1)
@click.option("--version", "-v", help="Shows the decrypter version.", is_flag=True)
@click.option(
"--same-passphrase",
"-s",
help="Use the same passphrase for every file.",
is_flag=True,
)
def decrypt(target_paths, version, same_passphrase):
if version:
sys.stderr.write("unlock: Version 3.0\n")
sys.stderr.write(f"{'-' * 25}\n")
subprocess.run(["gpg", "--version"])
return
if len(target_paths) == 0:
sys.stderr.write("unlock: Nothing to do.\n")
return
passphrase = ""
if same_passphrase:
p1 = "-"
p2 = "+"
while p1 != p2:
p1 = pwinput.pwinput(prompt="? Enter passphrase: ", mask="•")
p2 = pwinput.pwinput(prompt="? Please re-enter this passphrase: ", mask="•")
if p1 != p2:
sys.stderr.write(f"\nlock: {term.red('Does not match - try again.')}\n")
passphrase = p1
sys.stderr.write(f"{'-' * 40}\n")
path_counter = 0
for target_path in target_paths:
target_path = pathlib.Path(target_path)
command = ["gpg", "--no-symkey-cache", "-d"]
if same_passphrase:
command += ["--batch", "--yes"]
command += ["--passphrase", passphrase]
command.append(target_path.resolve())
result = subprocess.run(command, capture_output=True)
logs = result.stderr.decode("ascii")
# Logs formatting
logs = logs.replace(
"No such file or directory", term.red("No such file or directory")
)
logs = logs.replace("Unknown system error", term.red("Unknown system error"))
logs = logs.replace("No secret key", term.red("No secret key"))
sys.stderr.write(f"{logs.strip()}\n")
path_counter += 1
if "Unknown system error" in logs or "No secret key" in logs:
sys.stderr.write(term.gray(f"({target_path.resolve()})\n"))
if path_counter < len(target_paths):
sys.stderr.write(f"\n")
skip = False
for error in ["failed", "can't open", "Unknown system error", "No secret key"]:
if error in logs:
skip = True
break
if skip:
continue
with open(target_path.resolve(), "wb") as decrypted_file:
decrypted_file.write(result.stdout)
if target_path.suffix == ".lock" and zipfile.is_zipfile(target_path.resolve()):
with zipfile.ZipFile(target_path.resolve(), "r") as zip_ref:
zip_ref.extractall(target_path.parent)
target_path.unlink(missing_ok=True)
sys.stderr.write(
f"unlock: Symmetric decryption of '{target_path}' {term.green('ended succesfully')}.\n"
)
if __name__ == "__main__":
decrypt()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment