Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I have a stream that I would like to encrypt in real time, but the problem is that openssl encrypt only when it could read from stdin enough bytes, otherwise it waits.

Look at those examples:

$ (echo Hello world; sleep 3) | cat -
Hello world
$ (echo Hello world; sleep 3) | openssl base64 | openssl base64 -d
Hello world

In the first case you see the output immediately, in the second one you have to wait three seconds.

How could I could avoid this behavior? I tried unbuffer -p and stdbuf -i0, but they don't work in this case.

In order to be more clear, I show you how I'm trying to use it (those are commands in order to send an audio stream over the network):

### Not encrypted: works well
# Server
nc -ul 1234 | gst-launch fdsrc ! opusparse ! opusdec ! fdsink | pacat --latency-msec=20
# Client
parec --latency-msec=20 | gst-launch fdsrc ! audioparse rate=48000 channels=2 ! opusenc ! fdsink | nc -u localhost 1234

### Encrypted: doesn't work
# Server
nc -l -u 1234 | openssl aes-256-cbc -pass pass:test -salt -d | gst-launch fdsrc ! opusparse ! opusdec ! fdsink | pacat --latency-msec=20
# Client
parec --latency-msec=20 | gst-launch fdsrc ! audioparse rate=48000 channels=2 ! opusenc ! fdsink | openssl aes-256-cbc -pass pass:test -salt | nc -u localhost 1234
share|improve this question
add comment

2 Answers

up vote 2 down vote accepted

You're doing two things wrong in your example.

  1. You're using a block cipher. You'll need to use a stream cipher, such as rc4, or a block cipher in CFB mode (which effectively turns it into a stream cipher).
  2. You're encoding with base64. As Gilles mentioned, base64 in openssl requires an 80 byte buffer. Eliminate the base64 encoding and you'll see the behavior you're expecting.

Example with aes-128-cfb:

(echo Hello world ; sleep 3) | openssl enc -aes-128-cfb -pass pass:test -bufsize 1 | openssl enc -d -aes-128-cfb -pass pass:test -bufsize 1

Example with rc4:

(echo Hello world ; sleep 3) | openssl enc -rc4 -pass pass:test -bufsize 1 | openssl enc -d -rc4 -pass pass:test -bufsize 1

However, I must point out that reducing the buffer size will increase the CPU time required to perform the crypto operations:

% time sh -c 'dd if=/dev/urandom bs=8k count=1 | openssl enc -rc4 -pass pass:test | openssl enc -d -rc4 -pass pass:test > /dev/null'
1+0 records in
1+0 records out
8192 bytes transferred in 0.001175 secs (6972350 bytes/sec)
sh -c   0.01s user 0.01s system 167% cpu 0.009 total
% time sh -c 'dd if=/dev/urandom bs=8k count=1 | openssl enc -rc4 -pass pass:test -bufsize 1 | openssl enc -d -rc4 -pass pass:test -bufsize 1 > /dev/null'
1+0 records in
1+0 records out
8192 bytes transferred in 0.001070 secs (7655913 bytes/sec)
sh -c   0.02s user 0.03s system 187% cpu 0.027 total

With an 8K buffer it only took 0.01 seconds each of user and system time, but using -bufsize 1 took 0.02 and 0.03 seconds respectively, a total 5x increase. The CPU percentage reported value also increased by 20. If that's not an issue for you then by all means use a bufsize of 1. But if it is, then you'll need to benchmark it to find the best size for your application.

share|improve this answer
add comment

unbuffer and similar solutions don't work because the latency is not due to stdio buffering, it's due to the way the openssl program processes its data.

openssl base64, openssl enc and openssl dec have a default buffer size of 8kB, which can be specified with the -bufsize option. When the input or output is base64, the buffer size goes down no further than 80 bytes because openssl wants to be able to process a full base64 line at a time.

… | openssl aes-256-cbc -pass pass:test -salt -bufsize 16 | …
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.