Last active
December 22, 2015 17:59
-
-
Save VolMi/6509677 to your computer and use it in GitHub Desktop.
stream precious random data to all intelligence services in the universe
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/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 | |
| # 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 [ ! -d "$baseDir" ]; then | |
| echo "The path \"$baseDir\" " >&2 | |
| echo "is not a valid directory. Change it manually in $0 !" >&2 | |
| exit 1 | |
| fi | |
| 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 getExistingChars () { | |
| ls -R "$baseDir" | sed -e 's#.#\0\n#g' -e "s#[$disAllowedChar]##g" | sort -u | while read c; do echo -n "$c" ; done | |
| } | |
| 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