Etalam
Etalam

Reputation: 3

Is it possible to pipe a file with quotes and special characters to OpenSSL?

I am trying to write a bash script that will allow the user to input a password, and then pipe stdin (either via terminal commands or a piped file) to ‘openssl enc’ to encrypt it line by line using that password, and then finally pipe it out to an external TCP server.

This is what I have so far, and it mostly works:

#!/bin/bash
printf "What is your encryption 
password?\n"
read -s password </dev/tty
while read line; do echo "$line" | openssl enc -aes-256-cbc -base64 -pass pass:$password -e; done > >(openssl s_client -quiet -connect localhost:3001)

You run this via cat file | script.sh.

The problem I’m running into is when the file has quotes or special characters in it and breaks the echo.

Is there a way to get around this?

Upvotes: 0

Views: 1216

Answers (1)

Gordon Davisson
Gordon Davisson

Reputation: 125788

Both read and some versions of echo will do some kinds of escape/quote/whitespace/etc processing. You can get read to behave with IFS= read -r -- the IFS= prevents it from trimming leading and trailing whitespace (and since it's a prefix, it won't mess other things up like a general assignment to IFS), and -r tells it not to try to parse escape (backslash) characters. echo is hopeless, so use printf '%s\n' instead.

You also have similar problems with the password variable; use the same read tricks, and then expand it in double-quotes to prevent word-splitting and wildcard expansion from doing weird things. Oh, and I prefer to use read -p prompt rather than printing a separate prompt, and send a newline to /dev/tty afterward so it doesn't just sit there at the prompt.

The pipe and openssl themselves shouldn't be any trouble -- these are both binary-safe interfaces, so no quote or anything parsing there. Mind you, you might have some problems on the decrypt side...

Something like this:

#!/bin/bash
IFS= read -rs -p "What is your encryption password? " password </dev/tty
echo >/dev/tty
while IFS= read -r line; do
    printf '%s\n' "$line" | openssl enc -aes-256-cbc -base64 -pass "pass:$password" -e
done > >(openssl s_client -quiet -connect localhost:3001)

Upvotes: 1

Related Questions