diff --git a/create-attributable-archive (# Edit conflict 2026-05-23 frkwwxC #).sh b/create-attributable-archive (# Edit conflict 2026-05-23 frkwwxC #).sh new file mode 100644 index 0000000..279a0a1 --- /dev/null +++ b/create-attributable-archive (# Edit conflict 2026-05-23 frkwwxC #).sh @@ -0,0 +1,339 @@ +#!/bin/bash +# packages: 7zip, shred, secure-delete, cracklib-runtime, openssl, curl +set -e +unix_seconds=$(date +%s) +key_path="./private_ed25519_${unix_seconds}" +signature_tag="file-integrity" +out_dir="./out" +inner_dir="$out_dir/contents" + +checkcode() { + local retcode + if [ -z "$1" ]; then + echo -e "\n\e[31mERROR!\033[0m checkcode missing return code parameter\n" + exit 1 + else + retcode=$1 + fi + + if [ $retcode -ne 0 ]; then + echo -e "\e[31mERROR!\033[0m Response Code: $retcode" + else + printf ' \e[1;32mOK!\e[0m\n' + fi +} + +reset() { + printf "autoshredding these files..." + find . \( -path "./.git" -o -path "./keystore" -o -path "./archives" \) -prune -o -type f \( -name "*.sha512" -o -name "checksums*" -o -name "private_*" -o -name ".*" -o -name "*.sig" -o -name "*.7z" -o -name "anonymous_signer" \) -print -exec shred -uz {} \; + checkcode $? + + if compgen -G "private_*"; then + printf "nuking errant priv key files..." + shred -uz private_* + checkcode $? + fi + + if compgen -G "attribution_passphrase_*" > /dev/null; then + printf "nuking errant attribution passphrase files" + shred -uz attribution_passphrase_* + checkcode $? + fi + + echo "autoshredding out..." + srm -r -z -l -l "$out_dir" > /dev/null 2>&1 + checkcode $? + + echo "rebuilding out..." + printf "making out dir structure..." + mkdir -p "$inner_dir" > /dev/null 2>&1 + checkcode $? + + printf "updating $inner_dir/README.md..." + echo "put files to verifiably archive in here" > "$inner_dir/README.md" + checkcode $? + + printf "updating $out_dir/README.md..." + echo "# todo: make this nice" > "$out_dir/README.md" + checkcode $? + + printf "making $out_dir/test_validate_passphrase.sh..." + cp test_validate_passphrase.txt "$out_dir/test_validate_passphrase.sh" > /dev/null 2>&1 + checkcode $? + + printf "making $out_dir/test_validate_passphrase.sh executable..." + chmod +x "$out_dir/test_validate_passphrase.sh" > /dev/null 2>&1 + checkcode $? + + printf "making $out_dir/verify-everything.sh..." + cp verify-everything.txt "$out_dir"/verify-everything.sh > /dev/null 2>&1 + checkcode $? + + printf "making $out_dir/verify-everything.sh executable..." + chmod +x "$out_dir/verify-everything.sh" > /dev/null 2>&1 + checkcode $? + + housekeeping_dirs=("archives" "keystore") + for dir in "${housekeeping_dirs[@]}"; do + printf "changing ownership of $dir to ${USER}..." + chown $USER:$USER -R "$dir" > /dev/null 2>&1 + checkcode $? + + printf "changing permissions on $dir to 700..." + chmod 700 "$dir" > /dev/null 2>&1 + checkcode $? + + printf "finding and shredding erroneous dirs in ${dir}..." + find "$dir" -mindepth 1 -type d -exec srm -r -z -l -l "{}" \; > /dev/null 2>&1 + checkcode $? + + printf "finding and shredding erroneous files in ${dir}..." + find "$dir" -type f \( -name "private_ed25519_*" -o -name "attribution_passphrase_*" \) -exec shred -uz "{}" \; > /dev/null 2>&1 + checkcode $? + + printf "changing perms of files in $dir to 600..." + find "$dir" -type f -exec chmod 600 "{}" \; > /dev/null 2>&1 + checkcode $? + done +} + +# some heinously vibe coded shit pls forgiv +audit_passphrase() { + local raw_password="$1" + local check_password="$2" + + if [[ -z "$raw_password" ]]; then + echo "[ERROR] No passphrase provided for validation." >&2 + exit 2 + fi + + if [[ -z "$check_password" ]]; then + echo "[ERROR] No check passphrase provided for validation." >&2 + exit 2 + fi + + if [[ "$raw_password" != "$check_password" ]]; then + echo "[ERROR] Passphrases do not match!" >&2 + exit 2 + fi + + unset check_password + + # -------------------------------------------------------------------------- + # GATE 1: Minimum Length Verification (35+ Characters) + # -------------------------------------------------------------------------- + local pass_len="${#raw_password}" + if [ "$pass_len" -lt 35 ]; then + echo "❌ REJECTED: Passphrase is too short ($pass_len characters). Minimum length required is 35." + exit 1 + fi + echo "[PASS] Length verification satisfied ($pass_len characters)." + + # -------------------------------------------------------------------------- + # GATE 2: Local Dictionary Check (cracklib-check) + # -------------------------------------------------------------------------- + # cracklib-check reads from stdin and outputs 'password: status' + # If secure, the status string reads "OK" + if ! command -v cracklib-check &> /dev/null; then + echo "[ERROR] cracklib-check binary not found. Skipping dictionary audit." >&2 + exit 1 + else + local cracklib_result + cracklib_result=$(echo "$raw_password" | cracklib-check | cut -d':' -f2 | xargs) + + if [[ "$cracklib_result" != "OK" ]]; then + echo "❌ REJECTED by cracklib-check: $cracklib_result" + exit 1 + fi + echo "[PASS] Local dictionary and structural complexity audit clear." + fi + + # -------------------------------------------------------------------------- + # GATE 3: Remote Anonymized Leak Check (HIBP API via k-Anonymity) + # -------------------------------------------------------------------------- + local full_hash + full_hash=$(echo -n "$raw_password" | openssl dgst -sha1 | awk '{print toupper($2)}') + + local prefix="${full_hash:0:5}" + local suffix="${full_hash:5}" + local api_url="https://api.pwnedpasswords.com/range/$prefix" + local response + + if ! response=$(curl -s -H "User-Agent: Bash-Passphrase-Audit-Script" "$api_url"); then + echo "[FATAL] Failed to communicate with HIBP API." >&2 + exit 3 + fi + + local match + match=$(echo "$response" | grep -i "^$suffix:") + + if [[ -n "$match" ]]; then + local pwn_count + pwn_count=$(echo "$match" | cut -d':' -f2 | tr -d $'\r') + echo "❌ VULNERABLE: This passphrase has appeared in $pwn_count known public breaches." + exit 1 + else + echo "✅ SUCCESS: Passphrase meets all local criteria and was not found in HIBP records." + return 0 + fi +} + +audit_passphrase "" + +exit_cleanup() { + reset + + for var in $(compgen -v); do + printf "unsetting $var" + unset "$var" 2>/dev/null + checkcode $? + done +} + +# clean da fuck up on exit +trap exit_cleanup EXIT + +# and clean da fuck up on start +printf "setting up environment..." +reset + +# wait for keypress +echo +echo +read -n 1 -s -r -p "In another terminal/window, fill $inner_dir with whatever you please then press any key to continue..." + +printf "ssh-keygen: makin new key: ${key_path}..." +ssh-keygen -t ed25519 -f "$key_path" -C "anonymous" -N "" > /dev/null 2>&1 +checkcode $? + +printf "ssh-keygen: changing ownership on $key_path and $key_path.pub..." +chown $USER:$USER "$key_path" "$key_path.pub" > /dev/null 2>&1 +checkcode $? + +printf "ssh-keygen: fixing perms on $key_path and $key_path.pub..." +chmod 600 "$key_path" "$key_path.pub" > /dev/null 2>&1 +checkcode $? + +printf "ssh-keygen: creating $out_dir/anonymous_signer..." +echo "anonymous namespaces=\"$signature_tag\" $(cat "${key_path}.pub")" > "$out_dir/anonymous_signer" +checkcode $? + +echo "inject random data y/n (default n)" +read random +#why dafuck is this opposite world? +if [[ "$random" == "" || "$random" =~ ^[nN]{1}$ ]]; then + echo -e 'no random... \e[1;32mOK!\e[0m\n' +else + printf "random: adding 1/2 random blocks of data (1024 bits, 128 bytes) to outer archive..." + openssl rand -out "$out_dir/.$RANDOM" 128 > /dev/null 2>&1 + checkcode $? + + printf "random: adding 2/2 random blocks of data (1024 bits, 128 bytes) to inner archive..." + openssl rand -out "$inner_dir/.$RANDOM" 128 > /dev/null 2>&1 + checkcode $? +fi + +printf "7z: compressing inner volume..." +7z a "$out_dir/contents.7z" "$inner_dir" > /dev/null 2>&1 +checkcode $? + +printf "deleting ${inner_dir}..." +rm -rf "$inner_dir" > /dev/null 2>&1 +checkcode $? + +printf "ssh: signing out/contents.7z..." +ssh-keygen -Y sign -f "$key_path" -n "$signature_tag" "$out_dir/contents.7z" > /dev/null 2>&1 +checkcode $? + +printf "changing directory to ${out_dir}..." +cd "$out_dir" > /dev/null 2>&1 +checkcode $? + +printf "sha512: generating sha512 checksums of files in out..." +sha512sum * > "checksums.sha512" +checkcode $? + +printf "changing directory back..." +cd .. > /dev/null 2>&1 +checkcode $? + +echo +echo "Enter attribution passphrase:" +read -r -s attribution_passphrase +echo +echo "Enter attribution passphrase again:" +read -r -s attribution_passphrase_check +echo + +printf "auditing attribution passphrase" +ret=$(audit_passphrase "$attribution_passphrase" "$attribution_passphrase_check") +echo $ret + +printf "unsetting attribution_passphrase_check" +unset attribution_passphrase_check > /dev/null 2>&1 +checkcode $? + +printf "calculating attribution passphrase and hash, then placing it" +{ + printf "$attribution_passphrase" + cat "$out_dir/contents.7z" +} | sha512sum | awk '{print $1}' > "$out_dir/attribution-checksum.sha512" +checkcode $? + +printf "sanity checking: changing working directory to ${out_dir}..." +cd "$out_dir" > /dev/null 2>&1 +checkcode $? + +printf "sanity checking: verification..." +bash verify-everything.sh "$attribution_passphrase" +checkcode $? + +printf "sanity checking: validate attribution passphrase..." +bash test_validate_passphrase.sh "$attribution_passphrase" +checkcode $? + +printf "sanity checking: returning..." +cd .. +checkcode $? + +printf "unsetting attribution_passphrase" +unset attribution_passphrase > /dev/null 2>&1 +checkcode $? + +printf "7z archiving outer dir..." +7z a "./out.7z" "$out_dir" > /dev/null 2>&1 +checkcode $? + +printf "moving out.7z to archives..." +mv out.7z "archives/verifiable_archive_${unix_seconds}.7z" > /dev/null 2>&1 +checkcode $? + +echo +echo "input keystore passphrase:" +read -r -s keystore_passphrase +echo +echo "input keystore passphrase (again):" +read -r -s keystore_passphrase_check +echo + +printf "auditing keystore passphrase..." +ret=$(audit_passphrase "$keystore_passphrase" "$keystore_passphrase_check") +echo -e "$ret" + +printf "unsetting keystore passphrase check" +unset keystore_passphrase_check > /dev/null 2>&1 +checkcode $? + +printf "archiving keys..." +7z a "keystore/keystore_${unix_seconds}.7z" "private_*" "attribution_passphrase_*" -p"$keystore_passphrase" -mhe=on > /dev/null 2>&1 +checkcode $? + +printf "testing key archive..." +7z t "keystore/keystore_${unix_seconds}.7z" -p"$keystore_passphrase" > /dev/null 2>&1 +checkcode $? + +printf "unsetting keystore passphrase..." +unset keystore_passphrase > /dev/null 2>&1 +checkcode $? + +echo -e "\033[0;32mdone :3\033[0m" diff --git a/create-attributable-archive.sh b/create-attributable-archive.sh index c01a34e..e1cb5ed 100755 --- a/create-attributable-archive.sh +++ b/create-attributable-archive.sh @@ -104,17 +104,17 @@ audit_passphrase() { if [[ -z "$raw_password" ]]; then echo "[ERROR] No passphrase provided for validation." >&2 - return 2 + exit 2 fi if [[ -z "$check_password" ]]; then echo "[ERROR] No check passphrase provided for validation." >&2 - return 2 + exit 2 fi if [[ "$raw_password" != "$check_password" ]]; then echo "[ERROR] Passphrases do not match!" >&2 - return 2 + exit 2 fi unset check_password @@ -125,7 +125,7 @@ audit_passphrase() { local pass_len="${#raw_password}" if [ "$pass_len" -lt 35 ]; then echo "❌ REJECTED: Passphrase is too short ($pass_len characters). Minimum length required is 35." - return 1 + exit 1 fi echo "[PASS] Length verification satisfied ($pass_len characters)." @@ -135,14 +135,15 @@ audit_passphrase() { # cracklib-check reads from stdin and outputs 'password: status' # If secure, the status string reads "OK" if ! command -v cracklib-check &> /dev/null; then - echo "[WARN] cracklib-check binary not found. Skipping dictionary audit." >&2 + echo "[ERROR] cracklib-check binary not found. Skipping dictionary audit." >&2 + exit 1 else local cracklib_result cracklib_result=$(echo "$raw_password" | cracklib-check | cut -d':' -f2 | xargs) if [[ "$cracklib_result" != "OK" ]]; then echo "❌ REJECTED by cracklib-check: $cracklib_result" - return 1 + exit 1 fi echo "[PASS] Local dictionary and structural complexity audit clear." fi @@ -160,7 +161,7 @@ audit_passphrase() { if ! response=$(curl -s -H "User-Agent: Bash-Passphrase-Audit-Script" "$api_url"); then echo "[FATAL] Failed to communicate with HIBP API." >&2 - return 3 + exit 3 fi local match @@ -170,13 +171,15 @@ audit_passphrase() { local pwn_count pwn_count=$(echo "$match" | cut -d':' -f2 | tr -d $'\r') echo "❌ VULNERABLE: This passphrase has appeared in $pwn_count known public breaches." - return 1 + exit 1 else echo "✅ SUCCESS: Passphrase meets all local criteria and was not found in HIBP records." return 0 fi } +audit_passphrase "it was always you who i despised, redd fPGuXrWrP9WBWbW1xhSTwgBD :3" "it was always you who i despised, redd fPGuXrWrP9WBWbW1xhSTwgBD :3" + exit_cleanup() { reset