XOR command fails

89 Views Asked by At

I am trying to create an One Time Pad for cryptography, But I am stuck in an error

The plan is

  • Generate Text
  • Generate Key
  • Convert text and key from Ascii to binary
  • Create Cipher using Key_binary XOR text_binary
#!/bin/bash

#Create Message #1
plaintext=`cat /dev/urandom | tr -dc 0-9 | head -c8`
sleep 1

#Generate Random Sequence
key=`cat /dev/urandom | tr -dc 0-9 | head -c8`

#Ascii to Binary Convertion
key_bin=$(echo $key | perl -lpe '$_=unpack"B*"')

plaintext_bin=$(echo $plaintext | perl -lpe '$_=unpack"B*"')

plaintext_bin_size=${#plaintext_bin}

key_bin_size=${#key_bin}


    for ((i=0; i < $plaintext_bin_size; i++)); do
        byte=$((${plaintext_bin[$i]} ^ ${key_bin[$i % $key_bin_size]}))

        cipher="$cipher($byte)"
    done

    echo -e "$cipher"

But I get syntax error: operand expected (error token is "^ ")

2

There are 2 best solutions below

1
markp-fuso On BEST ANSWER

Focusing solely on the syntax error ...

As mentioned in comments, ${variable[...]} is an array reference but your variables are not arrays. Net result is you're trying to access array entries that do not exist, ie, you're trying to run an xor / ^ operation against blank fields. We can generate the same error with:

$ echo $((   ^   ))
-bash: ^ : syntax error: operand expected (error token is "^ ")

Assuming the intention is to access the individual digits/positions of the values stored in a variable try ${variable:start:length}, eg:

$ x=123456

$ echo "${x:0:1}"      # start at 0th position for length of 1
1

$ echo "${x:2:2}"      # start at 2nd position for length of 2
34

Pulling this into the current code:

byte=$(( ${plaintext_bin:i:1} ^ ${key_bin:((i % key_bin_size)):1} ))

### the embedded ((..)) are redundant so this also works:

byte=$(( ${plaintext_bin:i:1} ^ ${key_bin:i % key_bin_size:1} ))
0
xhienne On

Bash is choking on:

byte=$((${plaintext_bin[$i]} ^ ${key_bin[$i % $key_bin_size]}))

... which it interprets as:

byte=$(( ^ ))

The reason is that plaintext_bin and key_bin are no arrays but mere strings. To extract the Nth character from a string variable, use the ${var:N:1} notation instead:

byte=$(( ${plaintext_bin:i:1} ^ ${key_bin:i % key_bin_size:1} ))