Initial commit
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,182 @@
|
||||
"""
|
||||
CryptZ Ultimate v5 — CLI Module
|
||||
Usage:
|
||||
cryptz.py encrypt -p PASSWORD -o OUTPUT file1 file2 ...
|
||||
cryptz.py decrypt -p PASSWORD -o OUTPUT_DIR archive.cryptz
|
||||
cryptz.py verify -p PASSWORD archive.cryptz
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import sys
|
||||
import os
|
||||
import getpass
|
||||
|
||||
# Force UTF-8 stdout on Windows
|
||||
if sys.platform == "win32":
|
||||
sys.stdout.reconfigure(encoding="utf-8", errors="replace")
|
||||
sys.stderr.reconfigure(encoding="utf-8", errors="replace")
|
||||
|
||||
from crypto_engine import (
|
||||
EncryptOptions, decrypt, encrypt, verify_integrity,
|
||||
check_password_strength, EXTENSION,
|
||||
)
|
||||
|
||||
|
||||
def _progress(value: float, msg: str):
|
||||
bar_len = 30
|
||||
filled = int(bar_len * value)
|
||||
bar = "#" * filled + "-" * (bar_len - filled)
|
||||
line = " [{}] {:5.1f}% {:<40}".format(bar, value * 100, msg)
|
||||
sys.stdout.write("\r" + line)
|
||||
sys.stdout.flush()
|
||||
if value >= 1.0:
|
||||
print()
|
||||
|
||||
|
||||
def cmd_encrypt(args):
|
||||
password = args.password or getpass.getpass("Password: ")
|
||||
score, label = check_password_strength(password)
|
||||
if score < 2:
|
||||
print("[!] Warning: password is {}. Consider strengthening it.".format(label.lower()))
|
||||
|
||||
if not args.files:
|
||||
print("[ERROR] Specify files to encrypt.")
|
||||
sys.exit(1)
|
||||
|
||||
for f in args.files:
|
||||
if not os.path.exists(f):
|
||||
print("[ERROR] File not found: {}".format(f))
|
||||
sys.exit(1)
|
||||
|
||||
output = args.output or (os.path.splitext(args.files[0])[0] + EXTENSION)
|
||||
|
||||
options = EncryptOptions(
|
||||
password=password,
|
||||
files=args.files,
|
||||
output_path=output,
|
||||
use_2fa=args.twofa,
|
||||
max_attempts=args.max_attempts,
|
||||
hardware_key_path=args.key_file,
|
||||
secure_delete=args.shred,
|
||||
compress=not args.no_compress,
|
||||
progress_callback=_progress,
|
||||
)
|
||||
|
||||
if args.twofa:
|
||||
import pyotp
|
||||
options.otp_secret = pyotp.random_base32()
|
||||
print("")
|
||||
print("[2FA] Secret: {}".format(options.otp_secret))
|
||||
uri = pyotp.TOTP(options.otp_secret).provisioning_uri("CryptZ", "CryptZ CLI")
|
||||
print("[2FA] URI: {}".format(uri))
|
||||
print("[2FA] Save this secret! It will be required for decryption.")
|
||||
print("")
|
||||
|
||||
try:
|
||||
result = encrypt(options)
|
||||
print("")
|
||||
print("[OK] Archive created: {}".format(result))
|
||||
except Exception as e:
|
||||
print("")
|
||||
print("[ERROR] {}".format(e))
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def cmd_decrypt(args):
|
||||
password = args.password or getpass.getpass("Password: ")
|
||||
|
||||
if not os.path.exists(args.archive):
|
||||
print("[ERROR] File not found: {}".format(args.archive))
|
||||
sys.exit(1)
|
||||
|
||||
output_dir = args.output or "."
|
||||
os.makedirs(output_dir, exist_ok=True)
|
||||
|
||||
result = decrypt(
|
||||
file_path=args.archive,
|
||||
password=password,
|
||||
output_dir=output_dir,
|
||||
hardware_key_path=args.key_file,
|
||||
otp_code=args.otp,
|
||||
progress_callback=_progress,
|
||||
)
|
||||
|
||||
if result.needs_2fa and not args.otp:
|
||||
print("")
|
||||
otp = input("[2FA] Enter TOTP code: ").strip()
|
||||
result = decrypt(
|
||||
file_path=args.archive,
|
||||
password=password,
|
||||
output_dir=output_dir,
|
||||
hardware_key_path=args.key_file,
|
||||
otp_code=otp,
|
||||
progress_callback=_progress,
|
||||
)
|
||||
|
||||
print("")
|
||||
if result.success:
|
||||
print("[OK] {}".format(result.message))
|
||||
else:
|
||||
print("[FAIL] {}".format(result.message))
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def cmd_verify(args):
|
||||
password = args.password or getpass.getpass("Password: ")
|
||||
|
||||
if not os.path.exists(args.archive):
|
||||
print("[ERROR] File not found: {}".format(args.archive))
|
||||
sys.exit(1)
|
||||
|
||||
ok, msg = verify_integrity(args.archive, password, args.key_file)
|
||||
if ok:
|
||||
print("[OK] {}".format(msg))
|
||||
else:
|
||||
print("[FAIL] {}".format(msg))
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def cli_main():
|
||||
parser = argparse.ArgumentParser(
|
||||
prog="cryptz",
|
||||
description="CryptZ Ultimate v5 -- AES-256-GCM CLI Archiver",
|
||||
)
|
||||
sub = parser.add_subparsers(dest="command", required=True)
|
||||
|
||||
# encrypt
|
||||
enc = sub.add_parser("encrypt", help="Encrypt files")
|
||||
enc.add_argument("files", nargs="+", help="Files to encrypt")
|
||||
enc.add_argument("-p", "--password", help="Password (or will be prompted)")
|
||||
enc.add_argument("-o", "--output", help="Output file")
|
||||
enc.add_argument("-k", "--key-file", help="Key file")
|
||||
enc.add_argument("--2fa", dest="twofa", action="store_true", help="Enable 2FA")
|
||||
enc.add_argument("--shred", action="store_true", help="Securely delete originals")
|
||||
enc.add_argument("--no-compress", action="store_true", help="Disable compression")
|
||||
enc.add_argument("--max-attempts", type=int, default=5, help="Max attempts (default: 5)")
|
||||
|
||||
# decrypt
|
||||
dec = sub.add_parser("decrypt", help="Decrypt archive")
|
||||
dec.add_argument("archive", help=".cryptz file")
|
||||
dec.add_argument("-p", "--password", help="Password")
|
||||
dec.add_argument("-o", "--output", help="Output directory")
|
||||
dec.add_argument("-k", "--key-file", help="Key file")
|
||||
dec.add_argument("--otp", help="2FA code")
|
||||
|
||||
# verify
|
||||
ver = sub.add_parser("verify", help="Verify archive integrity")
|
||||
ver.add_argument("archive", help=".cryptz file")
|
||||
ver.add_argument("-p", "--password", help="Password")
|
||||
ver.add_argument("-k", "--key-file", help="Key file")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.command == "encrypt":
|
||||
cmd_encrypt(args)
|
||||
elif args.command == "decrypt":
|
||||
cmd_decrypt(args)
|
||||
elif args.command == "verify":
|
||||
cmd_verify(args)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
cli_main()
|
||||
Reference in New Issue
Block a user