Skip to content

Instantly share code, notes, and snippets.

@VolMi
Last active December 22, 2015 17:59
Show Gist options
  • Select an option

  • Save VolMi/6509677 to your computer and use it in GitHub Desktop.

Select an option

Save VolMi/6509677 to your computer and use it in GitHub Desktop.
stream precious random data to all intelligence services in the universe
#!/bin/bash
# Bashisms are embraced here and therefore used quite heavily.
#
# This script is meant to keep some folks a bit busy, who were never invited
# by yourself to share your data.
# The idea is that you use cloud storage to store your encrypted (real) files
# and additionally generate some randomized junk which should be
# indistinguishable from the encrypted data.
#
# Currently: "cloud storage" == "Dropbox"
#
# While your cloud provider offers only limited storage, your intelligence
# friends try to keep a copy of each version of each file ever uploaded, hence
# "removing" or "deleting" files has only a symbolic meaning.
#
# What it does
# ============
# We read data from /dev/urandom and store them in your cloud folder which is
# syncronized with $YourCloudProvider.
# In order to be less oviously noticed as an automatically created pile of poo,
# we also randomize...
# ... the file size
# ... the file name
# ... the time between successive file operations
# ... the path of the file (up to 9 levels within your base folder)
# We pause the work if we run on battery or if $YourCloudProgram is busy.
# If this script is terminated, it tries to clean all the mess it created.
# This seems to work reliably in case of shutdown, kill, Ctrl+C, but sudden
# power losses or similar unpleasant events will lead to remaining
# crap in your folder.
#
# What you have to do
# ===================
# You need to look at the first few lines of the code to define...
# ... which folder to litter
# ... the maximum allowed size of data (hard limit of $YourCloudProvider)
# ... (optional) the range of filename lengths
# ... (optional) the allowed characters to be used for files and folders
#
# Limitations
# ===========
# If $YourCloudProgram is in the middle of uploading a crapfile and you add a
# real (important) file, we currently do *not* detect this, so the
# available bandwidth for the real file is reduced.
#
# If some really clever people start to monitor your activities closer,
# they *will* find flaws in this approach and will probably be able to
# distinguish between real data and junk.
# This script is only an implementation of civil disobedience in view
# of an apparatus that gives a shit about an open and free society.
#
# Simple idea to increase the plausibility of the junk data:
# Do all the work in your unencrypted folder and let your encryptor (e.g. EncFS)
# encrypt the random data. However, this may have quite a lot of CPU overhead.
#
# License: Public Domain
# Base folder to junkify
# ======================
# Intended to be "the Dropbox" (the sync'ed folder)
#
baseDir=/home/${USER}/CHANGE_THIS_TO_SOMETHING_SUITING_YOUR_CONFIGURATION
if [ ! -d "$baseDir" ]; then
echo "The path \"$baseDir\" " >&2
echo "is not a valid directory. Change it manually in $0 !" >&2
exit 1
fi
# Dropbox total limit in kB
# =========================
# For N Gibibytes, use $((N*1024*1024).
# We will use at most 10% of available free space, that is
# (szMaxKB - szCurrKB) / 10
#
szMaxKB=$((15*1024*1024)) # read: "size max in kB"
# Min/Max length of names of files and folders
# ============================================
# For me, it seems that in my EncFS folder, names are at
# least 24 characters long. To see and adapt it for yourself, try:
# ls -1 path/to/dropbox | awk '{print length, $0;}' | sort -nr
#
minLenFilename=24
maxLenFilename=80
# Allowed characters for files and folders
# ========================================
# (from observation in an EncFS encrypted folder)
# You can specify it manually, like so
#
# allowedChar='a-zA-Z0-9,_.-' # If you want "-", be sure to have it at the very end!
#
# or you let us determine which characters were already used in
# names of files/folders and only make sure which characters we
# should *not* use, like so:
#
disAllowedChar='~ +:()/äöüßñéèáà' # If you want to exclude "-", be sure to have it at the very end!
allowedChar="$(ls -R "$baseDir" | sed -e 's#.#\0\n#g' -e "s#[$disAllowedChar]##g" | sort -u | while read c; do echo -n "$c" ; done)"
[ "$allowedChar" != "${allowedChar//-/}" ] && allowedChar=${allowedChar//-/} && allowedChar="${allowedChar}-" # remove & append "-"
# Modifying related processes' priority
# =====================================
# You may want to let $YourCloudProgram have a lower CPU priority:
# niceLevel=10
# renice -n $niceLevel $(pgrep dropbox) &> /dev/null
# Actual beginning of the script
# ==============================
#
if [ ! -O "$baseDir" ]; then
echo "The directory \"$baseDir\" " >&2
echo "is not yours!. Choose another one in $0 !" >&2
exit 2
fi
# Check dependencies
for tool in bc dd dropbox grep head id ionice renice seq tr
do
if [ ! "$(which $tool)" ]; then
echo "Program '$tool' not found in your path" >&2
missingDep=yep
fi
done
if [ "$missingDep" ]; then
echo "Please make sure to have the missing dependencies met and try again." >&2
exit 3
fi
if [ "$(id -u)" == 0 ]; then
echo 'DO NOT RUN THIS AS ROOT!' >&2
exit 4
fi
renice -n 19 -p $$ &> /dev/null # minimal CPU priority
ionice -c 3 -p $$ &> /dev/null # minimal I/O priority
RND_MAX=32767 # max. value of $RANDOM
# be sure to have no trailing '/' at baseDir's end
baseDir="$(echo $baseDir | sed 's,/$,,')"
function isOnBattery () {
[ -d /proc/acpi/battery ] && grep -Fq 'off-line' /proc/acpi/ac_adapter/*/state
return $?
}
function delayIfOnBattery () {
BeenHere=""
while isOnBattery
do
[ "$BeenHere" ] || echo 'On Battery. Waiting for AC power...'
sleep 5
BeenHere=yes
done
[ "$BeenHere" ] && echo 'AC plugged in now. Continue...'
}
function getRandomName () {
if [ ! "$allowedChar" ] || [ ! "$minLenFilename" ] || [ ! "$maxLenFilename" ]; then
echo "min/max filename length and allowed characters must be specified in $0" >&2
exit 5
fi
randLen="$(( $maxLenFilename - $minLenFilename ))"
currLen="$(( $minLenFilename + $RANDOM % $randLen))"
if [ "$currLen" -ge 1 ]; then
tr -dc "$allowedChar" < /dev/urandom | head -c "$currLen"
else
echo "Somehow, the current length for a random name is smaller than 1." >&2
echo "currLen = $currLen" >&2
exit 6
fi
}
function getRandomPath () {
# return a random number of randomly named folders, e.g.
# dir1/dir2/dir3/
N_max=9
myPath=""
for n in $(seq $N_max); do
# Define a probability that we will create a folder at this level.
# The deeper we get, the more likely we go one level deeper:
# prob = n / (N_max + 1)
#
probPerc=$(bc -l <<< "100 * ${n}/($N_max + 1) + 0.5" | sed 's#\.[0-9]*##')
rand0_100=$(( ${RANDOM} % 100 ))
if [ "$probPerc" -ge "$rand0_100" ]; then
myPath="${myPath}/$(getRandomName)" || exit $?
else
break
fi
done
echo "$myPath"
}
function cleanup () {
# delete file
if [ "$fOut" ] && [ -f "${baseDir}${rndPath}/${fOut}" ]; then
rm -f "${baseDir}${rndPath}/${fOut}"
fi
if [ "${rndPath}" ]; then
first="$(sed -e 's,\(/[^/]*\).*,\1,' <<< $rndPath)"
if [ "$first" ] && [ -d "${baseDir}${first}" ]; then
rm -rf "${baseDir}${first}"
else
echo "Tried to delete directory \"$first\"" >&2
echo "in \"$baseDir\"" >&2
echo "but a weird error occurred due to the bastard who implemented this... :-(" >&2
exit 7
fi
fi
}
# Make sure to be clean if we hit Ctrl+C or the process is killed
trap 'cleanup; exit 0' SIGABRT SIGINT SIGPIPE SIGTERM SIGQUIT
echo "We calmly start to litter ${baseDir}"
echo 'Allowed Characters for names of files and folders (everything within the " "):'
echo " \"${allowedChar}\""
echo
while sleep $(bc -l <<< "0.1+$RANDOM/2000")
do
if dropbox status | grep -Fi idle > /dev/null; then
if [ "$RANDOM" -lt "$((${RND_MAX}/6))" ] || [ ! "${fOut}" ] || [ ! -f "${baseDir}${rndPath}/${fOut}" ]; then
echo making new file ...
# If we wrote to another file before, delete it now
cleanup || exit $?
# Build a random path below $baseDir:
rndPath="$(getRandomPath)" # It either starts with "/" or is completely empty.
# It does never have a "/" at the end.
while [ "$rndPath" ] && [ -d "${baseDir}${rndPath}" ]; do
echo "Collision found for folder $rndPath..." >&2
echo "Will make a new random path." >&2
rndPath="$(getRandomPath)"
done
mkdir -p "${baseDir}${rndPath}"
# random file name
fOut=$(getRandomName) || exit $?
fi
delayIfOnBattery
szCurrKB=$(du -s "$baseDir" | awk '{print $1}')
if [ "$szMaxKB" -gt "$szCurrKB" ]; then
szTmpKB="$(( ($szMaxKB-$szCurrKB) * (${RANDOM}+1) / 32768 / 10))"
else
echo "Not enough free space in $baseDir" >&2
continue
fi
if [ "$fOut" ] && [ "$szTmpKB" ]
then
echo writing to ".${rndPath}/${fOut}" ...
BS=4096 # block size
CNT=$(($szTmpKB * 1024 / $BS - 1)) # count
# First, write in BS-blocks (pretty fast)
dd if=/dev/urandom of="${baseDir}${rndPath}/${fOut}" bs="$BS" count="$CNT" 2>&1 | sed -n 's|[0-9]\+ Bytes.*|\0|p' 1>&2
# We don't want to be restricted to files with N*BS bytes, so append up to BS-1 bytes:
dd if=/dev/urandom bs=$(($RANDOM%$BS)) count=1 2>/dev/null >> "${baseDir}${rndPath}/${fOut}"
else
echo "Weird error. Check that..." >&2
echo "szTmpKB = $szTmpKB" >&2
echo "fOut = $fOut" >&2
exit 8
fi
fi
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment