#!/usr/bin/env bash # A script for encrypting and decrypting files or directories with age and SSH keys VERSION="1.0.0" # Default ENV values KEYS_FILE="${AGE_KEYSFILE:-$HOME/.ssh/keys.txt}" KEYS_SOURCE="${AGE_KEYSSOURCE:-https://github.com/ivuorinen.keys}" LOG_FILE="${AGE_LOGFILE:-$HOME/.cache/a.log}" VERBOSE=false # Parse flags for verbosity for arg in "$@"; do if [[ "$arg" == "-v" || "$arg" == "--verbose" ]]; then VERBOSE=true break fi done # Ensure log directory and file exist with correct permissions prepare_log_file() { local log_dir log_dir=$(dirname "$LOG_FILE") # Create log directory if it does not exist if [[ ! -d "$log_dir" ]]; then mkdir -p "$log_dir" fi # Create log file if it does not exist if [[ ! -f "$LOG_FILE" ]]; then touch "$LOG_FILE" fi # Set permissions to 0600 chmod 0600 "$LOG_FILE" } prepare_log_file # Logging function log_message() { local message="$1" echo "$(date +'%Y-%m-%d %H:%M:%S') - $message" >> "$LOG_FILE" # Print to user if verbose flag is set if [[ "$VERBOSE" == true ]]; then echo "$message" fi } # Function to print usage print_help() { cat <" } # Function to fetch keys if missing fetch_keys_if_missing() { if [[ ! -f "$KEYS_FILE" ]]; then log_message "Keys file '$KEYS_FILE' not found. Attempting to fetch from $KEYS_SOURCE..." mkdir -p "$(dirname "$KEYS_FILE")" curl -s "$KEYS_SOURCE" -o "$KEYS_FILE" if [[ $? -ne 0 || ! -s "$KEYS_FILE" ]]; then log_message "Error: Failed to fetch keys from $KEYS_SOURCE" exit 1 fi chmod 0400 "$KEYS_FILE" log_message "Keys file fetched and permissions set to 0400." fi } # Function to encrypt files or directories encrypt_file_or_directory() { local file="$1" if [[ -d "$file" ]]; then for f in "$file"/*; do encrypt_file_or_directory "$f" done elif [[ -f "$file" ]]; then fetch_keys_if_missing local output_file="${file}.age" age -R "$KEYS_FILE" "$file" >"$output_file" if [[ $? -eq 0 ]]; then log_message "File encrypted successfully: $output_file" else log_message "Error: Failed to encrypt file '$file'." exit 1 fi fi } # Function to decrypt files or directories decrypt_file_or_directory() { local file="$1" if [[ -d "$file" ]]; then for f in "$file"/*.age; do decrypt_file_or_directory "$f" done elif [[ -f "$file" ]]; then fetch_keys_if_missing local output_file="${file%.age}" age -d -i "$KEYS_FILE" "$file" >"$output_file" if [[ $? -eq 0 ]]; then log_message "File decrypted successfully: $output_file" else log_message "Error: Failed to decrypt file '$file'." exit 1 fi fi } # Main logic case "$1" in e|enc|encrypt) if [[ $# -lt 2 ]]; then log_message "Error: No file or directory specified for encryption." print_help exit 1 fi encrypt_file_or_directory "$2" ;; d|dec|decrypt) if [[ $# -lt 2 ]]; then log_message "Error: No file or directory specified for decryption." print_help exit 1 fi decrypt_file_or_directory "$2" ;; help|--help) print_help ;; version|--version) print_version ;; *) log_message "Error: Unknown command '$1'" print_help exit 1 ;; esac # vim: ft=bash:syn=sh:ts=2:sw=2:et:ai:nowrap