Encrypt with One Time Pad



Published: 2017-05-26 14:09:46 +0000
Categories: BASH,

Language

BASH

Description

Basic example of how to generate, and encrypt arbitrary strings (or text files) with a One Time Pad/OTP

In principle, where the pads are sufficiently controlled, One Time Pads cannot be cracked in any reasonable timeframe. The real challenge lies in distributing the pads themselves securely, and independantly of the ciphertext. For most people and uses, they are effectively unusable

This implementation does have some known limitations, which could quite easily be fixed

  • The cipher text consists of hex encoded ASCII codes - primarily to avoid issues raised by BASH's handling of non printable character codes in strings - so the cipher text is longer than the plain text
  • Trailing newlines on the end of a file will be stripped, so files may not be exactly identical
  • There's no protection against providing too short a One-Time pad

Snippet

#!/bin/bash
#
# Simple script to encrypt text with a one-time pad

function gen_otp(){
    # Generate a One Time Pad based on the length of the string to be encrypted
    plaintext=$1
    plainlen=${#plaintext}

    # Generate the One Time Pad
    otp=$(cat /dev/urandom | tr -dc "a-zA-Z0-9" |fold -w $plainlen | head -n 1)
    echo -n $otp
}

function otp_encrypt(){
    # XOR the plaintext string against the One Time Pad

    plaintext="$1"
    plainlen=${#plaintext}

    # Grab the OTP and base64 decode it
    otp=$2

    for (( i=0; i<${#plaintext}; i++ )); do
        char=$(printf '%d' "'${plaintext:$i:1}" )
        otpchar=$(printf '%d' "'${otp:$i:1}" )

        # XOR the two
        cipherchar=$(( $char ^ $otpchar ))

        # we convert to hex.
        # Converting back to an ASCII char is possible, but can give unpredictable results
        cipherstr=$cipherstr$(printf "%x " $cipherchar)

    done

    # Return the string, but base64 it for convenience in copy/pasting
    echo -n $cipherstr | base64
}

function otp_decrypt(){
    # Reverse the process applied in otp_encrypt to recover the plaintext
    ciphertext=$1
    ciphertext=$( echo -n "$ciphertext" | base64 -d )
    otp=$2
    pos=0
    for i in $ciphertext
    do

        cipherchar=$(printf '%d' "0x$i" )
        otpchar=$(printf '%d' "'${otp:$pos:1}" )

        cipherchar=$(( $cipherchar ^ $otpchar ))

        if [ "$cipherchar" == "10" ]
        then
            # We do this because BASH command substitution strips trailing newlines
            newchar=$(echo -e -n "\n"; echo -n "extrachar")
            newchar=${newchar%extrachar}
        else
            newchar="`printf "\x$(printf %x $cipherchar)"`"
        fi

        plainstr="${plainstr}${newchar}"
        pos=$(( $pos + 1 ))
    done

    echo "$plainstr"
}

# func main

mode=$1

# There are better ways to to usage checks, but this is quick
if [ ! "$mode" == "-e" ] && [ ! "$mode" == "-d" ] && [ ! "$mode" == "-o" ]
then
    echo "Usage $0 [-e|-d|-o] [string/file] [[otp]]"
    exit 1
fi

# Grab the arguments
str=${2:-"Hello World"}
otp=${3:-""}

if [ -f "$str" ]
then
    # User passed in a path to a file, read that in instead
    str=$( cat "$str" )
fi

if [ "$mode" == "-o" ]
then
    # Simply generate and output an OTP based on the provided text
    gen_otp "$str"
    exit 0
fi

if [ "$mode" == "-e" ]
then

    GEN=0
    if [ "$otp" == "" ]
    then
        # OTP hasn't been provided, so return one
        GEN=1
        otp=$( gen_otp "$str" )
    elif [ -f "$otp" ]
    then
        otp=$(cat "$otp")
    fi

    ciphered=$( otp_encrypt "$str" "$otp" )

    if [ "$GEN" == 1 ]
    then
        echo "OTP: $otp"
        echo ""
    fi
    echo "$ciphered"

else

    if [ -f "$otp" ]
    then
        otp=$(cat "$otp")
    fi

    decrypted=$( otp_decrypt "$str" "$otp" )
    echo "$decrypted"

fi

Usage Example

# Generate a One Time Pad based on the length of the plaintext
./otp.sh -o test.txt otp.txt > otp.txt

# Encrypt the plaintext with the otp
./otp.sh -e test.txt otp.txt > cipher.txt

# Decrypt the cipher text using the otp
./otp.sh -d cipher.txt otp.txt > dec.txt

License

BSD-3-Clause

Keywords

OTP, One Time Pad, Generator, Encrypt, XOR,

Latest Posts


Copyright © 2022 Ben Tasker | Sitemap | Privacy Policy
Available at snippets.bentasker.co.uk, http://phecoopwm6x7azx26ctuqcp6673bbqkrqfeoiz2wwk36sady5tqbdpqd.onion and http://snippets.bentasker.i2p
hit counter