OpenSSL 버퍼링 문제

OpenSSL 버퍼링 문제

즉시 암호화하고 싶은 스트림이 있지만 문제는 opensslstdin에서 충분한 바이트를 읽을 수 있을 때만 암호화하고 그렇지 않으면 대기한다는 것입니다.

다음 예를 확인하세요.

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

첫 번째 경우에는 출력이 즉시 표시되지만, 두 번째 경우에는 3초를 기다려야 합니다.

이 동작을 방지하려면 어떻게 해야 합니까? 시도해 보았지만 unbuffer -pstdbuf -i0경우에는 작동하지 않습니다.

더 명확하게 하기 위해 이를 사용하는 방법을 보여 드리겠습니다(이 명령은 네트워크를 통해 오디오 스트림을 보내는 데 사용됩니다).

### 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

답변1

귀하의 예에서는 두 가지 일을 잘못하고 있습니다.

  1. 블록 암호를 사용하고 있습니다. rc4와 같은 스트림 암호 또는 CFB 모드의 블록 암호(효과적으로 스트림 암호로 변환)를 사용해야 합니다.
  2. 인코딩에 base64를 사용하고 있습니다. Gilles가 언급했듯이 openssl의 base64에는 80바이트 버퍼가 필요합니다. base64 인코딩을 제거하면 예상한 동작이 표시됩니다.

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

rc4:

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

그러나 버퍼 크기를 줄이면 암호화 작업을 수행하는 데 필요한 CPU 시간이 증가한다는 점을 지적해야 합니다.

% 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

8K 버퍼를 사용할 경우 사용자 시간과 시스템 시간은 각각 0.01초밖에 걸리지 않았으나, 사용 시간은 -bufsize 1각각 0.02초, 0.03초로 총 5배 증가했다. CPU 백분율 보고 값도 20 증가했습니다. 이것이 문제가 되지 않는다면, bufsize를 1로 사용하십시오. 하지만 그렇다면 애플리케이션에 가장 적합한 크기를 찾기 위해 벤치마킹해야 합니다.

답변2

unbufferstdio 버퍼링으로 인해 지연이 발생하는 것이 아니라 openssl 프로그램이 데이터를 처리하는 방식으로 인해 지연이 발생하기 때문에 유사한 솔루션이 작동하지 않습니다.

openssl base64, openssl enc기본 openssl dec버퍼 크기는 8kB이며 options 를 사용하여 지정할 수 있습니다 -bufsize. 입력 또는 출력이 Base64인 경우, openssl은 전체 Base64 라인을 한 번에 처리할 수 있을 것으로 예상하므로 버퍼 크기는 80바이트 이상 줄어들지 않습니다.

… | openssl aes-256-cbc -pass pass:test -salt -bufsize 16 | …

관련 정보