Secure encryption on the go with GrapheneOS and Termux — a workflow for true sovereignty.
von Alien Investor
#GrapheneOS #Termux #Encryption #GPG #Privacy #Android #OPSEC #Sovereignty
────────────────
„No magic. Just math. That is the Alien Investor way."
────────────────
Sovereignty does not end at the edge of your desk. You need to take your digital fortress with you.
In the first part, we built the "Digital Bunker" on the Linux desktop. We learned that true security relies on auditability, not colorful apps. But investors and strategists are mobile. What good is the most secure archive at home if you need to access sensitive documents or exfiltrate data securely while on the move?
Most mobile solutions are "black boxes." You press a button, something happens, and you hope the developer doesn't have a master key. This is unacceptable.
We use GrapheneOS, the only mobile operating system that takes security architecture seriously. And we use Termux, a terminal emulator that turns your smartphone into a full-fledged Linux computer.
The Goal: One workflow. Two devices. Identical math.
An archive you encrypt on your Tuxedo laptop must be openable on your GrapheneOS phone — and vice versa.
Update October 2026: Hardened Scripts
The scripts in this Read now match the current version from my GrapheneOS Handbook (Chapter 16).
Encryption: S2K hardening with SHA-512 and the maximum S2K hash count, and the password is no longer cached by the GPG agent.
Decryption: The password is not cached either, and decrypt-folder.sh Finance now also finds Encrypted_Finance.tar.gz.gpg directly.
Paths: Folder names typed as ~/Folder are now recognized correctly.
Installation: Termux only via F-Droid, not via the Zap Store.
If you copied the scripts earlier, replace them with the versions below. Archives you already encrypted stay readable.
────────────────
Preparation: Setting up Termux
On GrapheneOS, install Termux via F-Droid, not via the Play Store and not via the Zap Store. According to the Termux project, the GitHub build, which the Zap Store merely mirrors, is signed with a publicly known test key. The Play Store version is, according to the project, an experimental branch with missing features.
Once you have the black terminal in front of you, update the packages and install the necessary tools:
pkg update && pkg upgrade
pkg install termux-tools tar gnupg
Accessing Storage: Termux lives in isolation. For the scripts to access your downloads, we must bridge the gap to the Android file system.
termux-setup-storage
Confirm the dialog on the screen ("Allow"). Then create a folder for your tools:
mkdir -p ~/Scripts
────────────────
Part 1: The Mobile Shield (Encryption)
The encrypt-folder.sh script for Termux automatically detects if it is running on an Android system and directs the output to the Downloads folder.
Under the Hood: The Security Mechanics
Note the details in the "Helpers" section:
The Emergency Brake (die): If anything goes wrong, the script aborts immediately. It doesn't keep going and produce corrupt data.
The Gear Check (need): Before a single byte is encrypted, the script checks if all tools (tar, gpg, sha256sum) are present. If something is missing, it won't even start.
S2K Hardening: S2K stands for String-to-Key, the process that turns your password into the actual encryption key. The script uses SHA-512 as the hash algorithm and sets the count to the maximum: 65,011,712 bytes are hashed when deriving the key. Without this option, GnuPG uses a value that gpg-agent calibrates to the device's speed, so on a slower phone it may be considerably lower. The fixed maximum makes every guess equally expensive everywhere. The method is not memory-hard like Argon2id, though: against dictionary attacks, only a long random password helps in the end.
Create the file:
nano ~/Scripts/encrypt-folder.sh
Paste the following code:
#!/usr/bin/env bash
# encrypt-folder.sh — losslessly pack a folder and encrypt symmetrically (AES-256),
# without a plaintext intermediate file. Also generates a .sha256 checksum.
# Phone (GrapheneOS/Termux): output to ~/storage/downloads
# PC (Linux): output to $HOME
#
# S2K hardening: SHA512 + AES256 + maximum hash effort (65011712 bytes)
# → every guess costs the same on every device, at the highest S2K effort OpenPGP allows.
set -Eeuo pipefail
umask 077
export GPG_TTY="${GPG_TTY:-$(tty 2>/dev/null || true)}"
# -------------------- Helpers --------------------
die() { printf "❌ %s\n" "$*" >&2; exit 1; }
need() { command -v "$1" >/dev/null 2>&1 || die "Required tool missing: $1"; }
need tar
need gpg
need sha256sum
# Determine output directory based on system
OUT_DIR="$HOME"
if [ -d "$HOME/storage/downloads" ]; then
OUT_DIR="$HOME/storage/downloads"
fi
# Input: optional as argument, otherwise prompt
INPUT="${1-}"
if [ -z "$INPUT" ]; then
printf "📁 Please enter the folder name: "
IFS= read -r INPUT
fi
[ -n "$INPUT" ] || die "No name entered."
# Normalize path
case "$INPUT" in
\~/*) SRC="$HOME/${INPUT#\~/}" ;;
storage/*) SRC="$HOME/$INPUT" ;;
/sdcard/Download/*)
SRC="$HOME/storage/downloads/${INPUT#/sdcard/Download/}" ;;
/storage/emulated/0/Download/*)
SRC="$HOME/storage/downloads/${INPUT#/storage/emulated/0/Download/}" ;;
/*) SRC="$INPUT" ;;
*)
if [ -d "$HOME/storage/downloads/$INPUT" ]; then
SRC="$HOME/storage/downloads/$INPUT"
else
SRC="$HOME/$INPUT"
fi
;;
esac
[ -e "$SRC" ] || die "Path not found: $SRC"
[ -d "$SRC" ] || die "Not a directory: $SRC"
BASE="$(basename "$SRC")"
BASE_SAFE="${BASE// /_}"
OUT_FILE="$OUT_DIR/Encrypted_${BASE_SAFE}.tar.gz.gpg"
# Avoid collision
if [ -e "$OUT_FILE" ]; then
OUT_FILE="$OUT_DIR/Encrypted_${BASE_SAFE}_$(date +%Y-%m-%d_%H-%M-%S).tar.gz.gpg"
fi
printf "📦 Packing & encrypting → %s\n" "$OUT_FILE"
# Archive + encrypt without plaintext intermediate file
# S2K hardening: stronger key derivation against brute-force
# --no-symkey-cache: passphrase is not cached in the GPG agent
tar -C "$(dirname "$SRC")" -cz -- "$BASE" \
| gpg --symmetric \
--cipher-algo AES256 \
--s2k-cipher-algo AES256 \
--s2k-digest-algo SHA512 \
--s2k-count 65011712 \
--no-symkey-cache \
-o "$OUT_FILE" \
|| die "gpg failed"
# Write checksum
sha256sum "$OUT_FILE" > "${OUT_FILE}.sha256"
printf "✅ Done:\n %s\n %s\n Location: %s\n" \
"$(basename "$OUT_FILE")" "$(basename "${OUT_FILE}.sha256")" "$OUT_DIR"
(Save in nano with CTRL+O, Enter, then CTRL+X)
────────────────
Part 2: The Mobile Key (Decryption)
On the go, cloud services often rename files. File.gpg suddenly becomes File.gpg.pgp or File (1).gpg. This script is the "Cloud Edition" — it finds your file even with incorrect extensions and verifies the SHA256 sum.
Create the file:
nano ~/Scripts/decrypt-folder.sh
Paste the following code:
#!/usr/bin/env bash
# decrypt-folder.sh (Cloud Edition)
# Finds .gpg AND .pgp, checks SHA256, decrypts
set -Eeuo pipefail
umask 077
export GPG_TTY="${GPG_TTY:-$(tty 2>/dev/null || true)}"
DL_DIR="$HOME/storage/downloads"
die(){ printf "❌ %s\n" "$*" >&2; exit 1; }
# Automatic file selection
NAME="${1-}"
INPUT=""
if [ -z "$NAME" ]; then
LATEST="$(ls -t "$DL_DIR"/*.gpg "$DL_DIR"/*.pgp 2>/dev/null | head -n1 || true)"
if [ -n "$LATEST" ]; then
INPUT="$LATEST"
printf "🤖 File found: %s\n" "$(basename "$INPUT")"
else
printf "No file found. Enter name: "
IFS= read -r NAME
[ -n "$NAME" ] || die "Aborted."
fi
fi
# Fallback: manual path search
if [ -z "$INPUT" ]; then
VARIANTS=("${NAME}" "${NAME}.gpg" "${NAME}.pgp" "${NAME}.gpg.pgp" "Encrypted_${NAME}.gpg" "Encrypted_${NAME}.tar.gz.gpg")
for v in "${VARIANTS[@]}"; do
if [ -f "$PWD/$v" ]; then INPUT="$PWD/$v"; break; fi
if [ -f "$DL_DIR/$v" ]; then INPUT="$DL_DIR/$v"; break; fi
done
fi
[ -n "$INPUT" ] || die "Source file not found."
# Check SHA256
SHA_CANDIDATE_1="${INPUT}.sha256"
SHA_CANDIDATE_2="${INPUT%.pgp}.sha256"
SHA_FILE=""
if [ -f "$SHA_CANDIDATE_1" ]; then
SHA_FILE="$SHA_CANDIDATE_1"
elif [ -f "$SHA_CANDIDATE_2" ]; then
SHA_FILE="$SHA_CANDIDATE_2"
echo "ℹ️ Correcting SHA path..."
fi
if [ -n "$SHA_FILE" ]; then
printf "🔎 Checking integrity (SHA256)..."
EXPECTED=$(awk '{print $1}' "$SHA_FILE")
ACTUAL=$(sha256sum "$INPUT" | awk '{print $1}')
if [ "$EXPECTED" = "$ACTUAL" ]; then
echo " ✅ OK."
else
echo " ❌ ERROR — checksums do not match!"
printf "Continue anyway? (y/N) "
read -r -n 1 REPLY; echo
[[ $REPLY =~ ^[Yy]$ ]] || die "Aborted."
fi
else
echo "ℹ️ No .sha256 found (check skipped)."
fi
# Decrypt and unpack
printf "🔓 Decrypting & unpacking..."
if gpg --quiet --no-symkey-cache --decrypt "$INPUT" | tar -xz; then
echo " ✅ Done."
echo "📂 Folder is in: $PWD"
elif gpg --quiet --no-symkey-cache --pinentry-mode loopback --decrypt "$INPUT" | tar -xz; then
echo " ✅ Done."
echo "📂 Folder is in: $PWD"
else
die "Error during decryption."
fi
Make both scripts executable:
chmod +x ~/Scripts/encrypt-folder.sh ~/Scripts/decrypt-folder.sh
────────────────
The Workflow in the Field
Scenario A: Encrypt and Decrypt on Phone
You have a folder (e.g., Finance) in your Download area.
- Open Termux.
- Run:
~/Scripts/encrypt-folder.sh - Type the folder name:
Finance - Result:
Encrypted_Finance.tar.gz.gpgand the checksum are now in your Download folder.
To decrypt: run ~/Scripts/decrypt-folder.sh. The decrypted files will be in the Termux Home directory.
Scenario B: Decrypting Data from PC (The Emergency Case)
You transferred an encrypted file (e.g., Encrypted_Backup.tar.gz.gpg) from your PC to your phone.
- Ensure the file is in the Android Download folder.
- Open Termux and run:
~/Scripts/decrypt-folder.sh - The script decrypts the data into the Termux Home directory. Open your "Files" app — find the
Termuxentry in the sidebar. Your decrypted folder lies there.
────────────────
Why Auditability Is King
You could download an app called "AES Safe Box." But do you know what it does with your keys?
With these scripts, you see every command:
Tar packs. GPG encrypts. SHA256 verifies.
No magic. Just math.
────────────────
The Full Series
👉 Part 1 — Desktop Scripts: https://primal.net/Alien-Investor/the-digital-bunker-scripting-sovereignty 👉 Part 3 — Command Line Comfort (Aliases): https://primal.net/Alien-Investor/the-digital-bunker-command-line-comfort
────────────────
🧰 Tools for True Owners (Affiliates — Support at No Extra Cost)
Tools I use myself — for Bitcoin self-custody and digital sovereignty:
📕 Alien Investor Guides: My own eBook "GrapheneOS: Android in the Surveillance Age" — the complete step-by-step guide to hardening your phone against the surveillance state. 👉 https://alien-investor.org/buecher
🔧 Alien Phone Service — GrapheneOS professionally installed and configured, delivered to your door. No flashing required. Bitcoin or Fiat. 👉 https://alien-investor.org/en/grapheneos-flash-service.html
💥 21bitcoin: Bitcoin-only app from Europe, ideal for DCA and stacking sats regularly — no shitcoins. Use code ALIENINVESTOR for a permanent 0.2 percentage point fee reduction on instant and savings plan purchases. 👉 https://alien-investor.org/21bitcoin
₿ BitBox: Hardware wallet for secure self-custody. I use the BitBox — available as the classic BitBox02 and the new BitBox for iPhone (Nova). Use code ALIENINVESTOR for 5% off. 👉 https://alien-investor.org/bitbox
🛡️ Proton: Swiss all-round protection for email, VPN, and cloud — privacy-first, no Big Tech dependency. 👉 https://alien-investor.org/proton
Disclaimer: Some of these links are affiliate links. If you use them, you support my work at no extra cost to you. Thank you!
────────────────
Money, power, Bitcoin — and OPSEC. I write about financial sovereignty, privacy, and cybersecurity in a world built on control. More at alien-investor.org 👽


Comments0
No comments yet. Start the conversation.