SRTの暗号化通信を試してみた。
基本的にpassphraseのパラメータを追加し、送信側と受信側でこれが一致していれば通信できる。
key-length も暗号化に関係しているが、これは送信側の設定値が有効になり、受信側は設定が不要のようなのであまり気にしなくてもよいようだ。
VLCでもSRTの通信条件を設定するところでpassphraseを入れることができる。
つまずいたところのメモ。
つまずいたのは以下の2点。
passphraseの長さは10文字以上80文字以下
この範囲を外れているとエラーになる。
しかし、gstreamerではこのソケットプションの設定から帰ってきたエラーを握りつぶしているのでエラーになったことを気付けない。
gstreamerを送信側にして、6文字のpassphrase(短すぎる)を設定しようとしたが暗号化されないという現象で悩んだ。ソースコードを見て気がついた。
ffmpegのバグ
逆にffmpeg(ffplay)ではpassphraseにどんな長さのものを入れてもエラーになる。
passphraseの扱うポインタが間違っていた。
以下のパッチを当てて、正しく動作するようになった。
diff --git a/libavformat/libsrt.c b/libavformat/libsrt.c
index 2faf9de580..2290a34435 100644
--- a/libavformat/libsrt.c
+++ b/libavformat/libsrt.c
@@ -268,7 +268,7 @@ static int libsrt_set_options_pre(URLContext *h, int fd)
if ((s->mode == SRT_MODE_RENDEZVOUS && libsrt_setsockopt(h, fd, SRTO_RENDEZVOUS, "SRTO_RENDEZVOUS", &yes, sizeof(yes)) < 0) ||
(s->maxbw >= 0 && libsrt_setsockopt(h, fd, SRTO_MAXBW, "SRTO_MAXBW", &s->maxbw, sizeof(s->maxbw)) < 0) ||
(s->pbkeylen >= 0 && libsrt_setsockopt(h, fd, SRTO_PBKEYLEN, "SRTO_PBKEYLEN", &s->pbkeylen, sizeof(s->pbkeylen)) < 0) ||
- (s->passphrase && libsrt_setsockopt(h, fd, SRTO_PASSPHRASE, "SRTO_PASSPHRASE", &s->passphrase, sizeof(s->passphrase)) < 0) ||
+ (s->passphrase && libsrt_setsockopt(h, fd, SRTO_PASSPHRASE, "SRTO_PASSPHRASE", s->passphrase, strlen(s->passphrase)) < 0) ||
(s->mss >= 0 && libsrt_setsockopt(h, fd, SRTO_MSS, "SRTO_MMS", &s->mss, sizeof(s->mss)) < 0) ||
(s->ffs >= 0 && libsrt_setsockopt(h, fd, SRTO_FC, "SRTO_FC", &s->ffs, sizeof(s->ffs)) < 0) ||
(s->ipttl >= 0 && libsrt_setsockopt(h, fd, SRTO_IPTTL, "SRTO_UPTTL", &s->ipttl, sizeof(s->ipttl)) < 0) ||
追記 (2018.11.12)
このバグはffmpeg 4.1 で解消しました。
https://qiita.com/tetsu_koba/items/cc1ecb9c2f5ae2901aa9
実行例
gstreamerでテストパターンを暗号化して送信する。passphraseは "abcdefgh123456"
key lengthは指定していないのでデフォルトの16(128bit)が使用される。
#!/bin/sh
gst-launch-1.0 \
videotestsrc is-live=true pattern=ball \
! video/x-raw,width=640,height=360,framerate=30/1 \
! x264enc tune=zerolatency key-int-max=60 \
! mpegtsmux \
! srtserversink uri="srt://:7010" passphrase=abcdefgh123456
これを前述のパッチを当ててビルドしたffplayで再生する。
ffplay srt://localhost:7010?passphrase=abcdefgh123456
もしもpassphraseが一致しないときには以下のようなエラーが出て再生できない。
16:44:50.080269/read_thread*E: SRT.c: processSrtMsg_KMRSP: received failure report. STATE: BADSECRET
16:44:50.104531/SRT:RcvQ:worker*E: SRT.c: SECURITY STATUS: BADSECRET - can't decrypt packet.
16:44:50.105470/SRT:RcvQ:worker*E: SRT.c: KMREQ/rcv: (snd) Rx process failure - BADSECRET
16:44:50.105558/SRT:RcvQ:worker*E: SRT.c: SECURITY STATUS: BADSECRET - can't decrypt packet.
関連
新しい映像伝送プロトコルSRTをgstreamerとVLCで試す
ffmpeg 4.0 に入った新しい映像伝送プロトコルSRTを試す
ffmpeg 4.0 をlibsrtを有効にしてビルドする