Skip to content

Instantly share code, notes, and snippets.

@faretek1
Last active September 20, 2025 14:55
Show Gist options
  • Save faretek1/cefb8b3e1d8707a331154c9fb169ad19 to your computer and use it in GitHub Desktop.
Save faretek1/cefb8b3e1d8707a331154c9fb169ad19 to your computer and use it in GitHub Desktop.
utility script i made that lets you turn strings into fernet keys, generate string-fernet keys, and encrypt/decrypt data with the default key (`AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA`), all from a CLI
import warnings
import argparse
from cryptography.fernet import Fernet
from secrets import token_urlsafe
from base64 import urlsafe_b64encode
from pathlib import Path
__file_path__ = Path(__file__).resolve()
__pwd__ = __file_path__.parent
save_path = __pwd__ / "faretek's fernet-string.py key.txt"
_key = save_path.read_text() if save_path.exists() else 'A' * 32
def str_2_key(gen: str) -> bytes:
if (length := len(gen)) < 32:
warnings.warn(f"Short key length {length}")
gen = gen.zfill(32)
elif length > 32:
warnings.warn(f"Long key length {length}")
gen = gen[:32]
return urlsafe_b64encode(gen.encode())
fernet = Fernet(str_2_key(_key))
def main():
class Args(argparse.Namespace):
command: str
content: str
native: bool
parser = argparse.ArgumentParser(epilog=f"KEY={_key!r}")
if command := parser.add_subparsers(dest="command"):
if encrypt := command.add_parser("e", help="encrypt"):
encrypt.add_argument("content")
if decrypt := command.add_parser("d", help="decrypt"):
decrypt.add_argument("content")
if gen := command.add_parser("g", help="generate key"):
...
if set_key := command.add_parser("s", help="set key"):
set_key.add_argument("content", help="new key")
args = parser.parse_args(namespace=Args())
match args.command:
case "e":
print(fernet.encrypt(args.content.encode()).decode())
case "d":
print(fernet.decrypt(args.content.encode()).decode())
case "g":
print(token_urlsafe(32))
case "s":
print(f"Replacing {_key!r} with {args.content!r}")
save_path.write_text(args.content)
case _:
parser.print_help()
if __name__ == "__main__":
main()
@faretek1
Copy link
Author

i may be obsessed with argparse

@TheCommCraft
Copy link

TheCommCraft commented Sep 14, 2025

This should be changed for clarity:
fernet.generate_key() -> Fernet.generate_key()
The return type of gen_keystr could be str or bytes, which should be changed. I recommend just using secrets.token_urlsafe(32)[:32], which always produces a csprng generated string of base64urlsafe of length 32. (The random module normally produces random numbers which can be predicted)
I would also recommend making it so that the key can be changed via a cli argument.

@faretek1
Copy link
Author

oops, didnt notice the keystr thibg

@faretek1
Copy link
Author

ill do that, ok

@TheCommCraft
Copy link

you should use secrets.token_urlsafe for secure pseudorandomness

@faretek1
Copy link
Author

i implemented that in the version i put in scratchattach. I also have a separate updated version somewhere which uses secrets too. I will update this gist then

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment