一、rtsp认证方式:
用户通过rtsp url地址获取设备的视频流时,大多数是需要认证的。RTSP的认证方式有2种:
-
1.rtsp url直接携带明文的用户名和密码(rtsp://用户名:密码@IP地址/Stream/Channels/101)
-
2.HTTP 认证,http 认证又分为两种:(http1.0)基本认证(basic authentication)(http1.1)和摘要认证( digest authentication )。

rtsp url直接携带明文的用户名和密码的方式安全性差,现在一般不使用。下面主要讲解HTTP认证方式。
基本认证是http1.0提出的认证方案,其密码传输的加密算法(base64)是可逆算法,很容易被截获破解。摘要认证是http1.1提出的替代方案,其密码经过MD5哈希转换因此具有更高的安全性。
两种认证详解:
1、基本认证 (basic 认证):
流程如下:
- 步骤1:客户端发送DESCRIBE请求到服务端
DESCRIBE rtsp://10.175.30.35 RTSP/1.0 CSeq: 6 User-Agent: LibVLC/2.2.4 (LIVE555 Streaming Media v2016.02.22) Accept: application/sdp
- 步骤2:RTSP服务端认为没有通过认证,发出WWW-Authenticate认证响应:
RTSP/1.0 401 Unauthorized CSeq: 6 WWW-Authenticate: Basic realm=“000102030405” Date: Tue, Mar 19 2019 07:07:12 GMT
- 步骤3:客户端携带Authorization串再次发出DESCRIBE请求:
DESCRIBE rtsp://10.175.30.35 RTSP/1.0 CSeq: 7 Authorization: Basic YWRtaW46YWJjZDEyMzQ= Accept: application/sdp
其中,“YWRtaW46YWJjZDEyMzQ=” 是通过对username:password 进行base64编码所得。服务端对 “YWRtaW46YWJjZDEyMzQ=” 解码得出 “admin:abcd1234”
2、摘要认证:
先看一段抓包下来的正确的摘要认证消息。示例中的用户名是“admin”,密码是“admin”。
//默认无认证---------------------------- DESCRIBE rtsp://192.168.0.112:540/live/h264_ulaw/VGA RTSP/1.0 CSeq: 6 User-Agent: LibVLC/1.1.11 (LIVE555 Streaming Media v2011.05.25) Accept: application/sdp RTSP/1.0 401 Unauthorized CSeq: 6 WWW-Authenticate: Basic realm="Server" WWW-Authenticate: Digest realm="Server", nonce="52bb051ecad61e78d67664700e67407ad865c429bde208b7ea1e6e22aa7d8ccf"
//使用摘要认证---------------------------- DESCRIBE rtsp://192.168.0.112:540/live/h264_ulaw/VGA RTSP/1.0 CSeq: 7 Authorization: Digest username="admin", realm="Server", nonce="52bb051ecad61e78d67664700e67407ad865c429bde208b7ea1e6e22aa7d8ccf", uri="rtsp://192.168.0.112:540/live/h264_ulaw/VGA", response="1ac6f141f4c740ba54088914941f094f" User-Agent: LibVLC/1.1.11 (LIVE555 Streaming Media v2011.05.25) Accept: application/sdp RTSP/1.0 200 OK CSeq: 7 Content-Base: rtsp://192.168.0.112:540/live/h264_ulaw/VGA/ Content-Type: application/sdp Cache-Control: must-revalidate x-Accept-Dynamic-Rate: 1 Content-Length: 305 sdp内容略过
//建立视频通道连接---------------------------- SETUP rtsp://192.168.0.112:540/live/h264_ulaw/VGA/track1 RTSP/1.0 CSeq: 8 Authorization: Digest username="admin", realm="Server", nonce="52bb051ecad61e78d67664700e67407ad865c429bde208b7ea1e6e22aa7d8ccf", uri="rtsp://192.168.0.112:540/live/h264_ulaw/VGA/", response="ff71e2de4489997fa2fd058462ca48df" User-Agent: LibVLC/1.1.11 (LIVE555 Streaming Media v2011.05.25) Transport: RTP/AVP;unicast;client_port=57704-57705 RTSP/1.0 200 OK CSeq: 8 Transport: RTP/AVP;unicast;client_port=57704-57705;server_port=59024-59025 x-dynamic-rate: 1 Session: D694FB02673D8FFC816E78EB384E09 //建立音频通道连接---------------------------- SETUP rtsp://192.168.0.112:540/live/h264_ulaw/VGA/track3 RTSP/1.0 CSeq: 9 Authorization: Digest username="admin", realm="Server", nonce="52bb051ecad61e78d67664700e67407ad865c429bde208b7ea1e6e22aa7d8ccf", uri="rtsp://192.168.0.112:540/live/h264_ulaw/VGA/", response="ff71e2de4489997fa2fd058462ca48df" User-Agent: LibVLC/1.1.11 (LIVE555 Streaming Media v2011.05.25) Transport: RTP/AVP;unicast;client_port=57706-57707 Session: D694FB02673D8FFC816E78EB384E09 RTSP/1.0 200 OK CSeq: 9 Transport: RTP/AVP;unicast;client_port=57706-57707;server_port=53570-53571 x-dynamic-rate: 1 Session: D694FB02673D8FFC816E78EB384E09 //---------------------------- PLAY rtsp://192.168.0.112:540/live/h264_ulaw/VGA/ RTSP/1.0 CSeq: 10 Authorization: Digest username="admin", realm="Server", nonce="52bb051ecad61e78d67664700e67407ad865c429bde208b7ea1e6e22aa7d8ccf", uri="rtsp://192.168.0.112:540/live/h264_ulaw/VGA/", response="a0187b5bb73d8cfaedab47365b0b8848" User-Agent: LibVLC/1.1.11 (LIVE555 Streaming Media v2011.05.25) Session: D694FB02673D8FFC816E78EB384E09 Range: npt=0.000- RTSP/1.0 200 OK CSeq: 10 Session: D694FB02673D8FFC816E78EB384E09 Range: npt=now- RTP-Info: url=rtsp://192.168.0.112:540/live/h264_ulaw/VGA//track1;seq=52039;rtptime=3232015484,url=rtsp://192.168.0.112:540/live/h264_ulaw/VGA//track3;seq=36501;rtptime=34449408 //---------------------------- TEARDOWN rtsp://192.168.0.112:540/live/h264_ulaw/VGA/ RTSP/1.0 CSeq: 12 Authorization: Digest username="admin", realm="Server", nonce="52bb051ecad61e78d67664700e67407ad865c429bde208b7ea1e6e22aa7d8ccf", uri="rtsp://192.168.0.112:540/live/h264_ulaw/VGA/", response="41ca24c00f22e5175df3b3666f6f3ead" User-Agent: LibVLC/1.1.11 (LIVE555 Streaming Media v2011.05.25) Session: D694FB02673D8FFC816E78EB384E09 RTSP/1.0 200 OK CSeq: 12 Session: D694FB02673D8FFC816E78EB384E09
3、摘要认证怎么计算和实现的:
在RFC2617中给出了标准的计算方法代码,在文件digtest.c中预定义了以下参数:
文档链接:
https://www.rfc-editor.org/rfc/rfc2617
具体实现如下:

void main(int argc, char ** argv) { char * pszNonce = "52bb051ecad61e78d67664700e67407ad865c429bde208b7ea1e6e22aa7d8ccf"; char * pszCNonce = ""; char * pszUser = "admin"; char * pszRealm = "Server"; char * pszPass = "admin"; char * pszAlg = "md5"; char szNonceCount[9] = "00000001"; char * pszMethod = "GET"; char * pszQop = "auth"; char * pszURI = "rtsp://192.168.0.112:540/live/h264_ulaw/VGA/"; HASHHEX HA1; HASHHEX HA2 = ""; HASHHEX Response; DigestCalcHA1(pszAlg, pszUser, pszRealm, pszPass, pszNonce, pszCNonce, HA1); DigestCalcResponse(HA1, pszNonce, szNonceCount, pszCNonce, pszQop, pszMethod, pszURI, HA2, Response); printf("00 Response = %s\n", Response); }
这是非常标准的计算过程,但是用此计算不出上面示例中的response。
经过试验发现RTSP中采用了简化算法,实际的计算过程如下:
HA1 = MD5(username:realm:password) HA2 = MD5(method:uri) response = MD5(HA1:nonce:HA2)
method不能是http规范中的GET、POST,而是这条RTSP命令的名称,例如:DESCRIBE、SETUP、PLAY、TEARDOWN。uri一般是RTSP命令的url。
在上述示例中,建立视频、音频通道命令中的url不同,但是uri相同,导致计算出的摘要完全相同,这说明客户端计算方法有些不妥。
简化的计算函数如下:
void NewDigestCalcHA1(char * pszUserName, char * pszRealm, char * pszPassword, HASHHEX SessionKey) { MD5_CTX Md5Ctx; HASH HA1; MD5Init(&Md5Ctx); MD5Update(&Md5Ctx, pszUserName, strlen(pszUserName)); MD5Update(&Md5Ctx, ":", 1); MD5Update(&Md5Ctx, pszRealm, strlen(pszRealm)); MD5Update(&Md5Ctx, ":", 1); MD5Update(&Md5Ctx, pszPassword, strlen(pszPassword)); MD5Final(HA1, &Md5Ctx); CvtHex(HA1, SessionKey); } void NewDigestCalcResponse( IN HASHHEX HA1, /* H(A1) */ IN char * pszNonce, /* nonce from server */ IN char * pszDigestUri, /* requested URL */ IN char * pszMethod, /* requested method */ OUT HASHHEX Response /* request-digest or response-digest */ ) { MD5_CTX Md5Ctx; HASH HA2; HASH RespHash; HASHHEX HA2Hex; // calculate H(A2) MD5Init(&Md5Ctx); MD5Update(&Md5Ctx, pszMethod, strlen(pszMethod)); MD5Update(&Md5Ctx, ":", 1); MD5Update(&Md5Ctx, pszDigestUri, strlen(pszDigestUri)); MD5Final(HA2, &Md5Ctx); CvtHex(HA2, HA2Hex); printf("11 HA2Hex= %s\n", HA2Hex); // calculate response MD5Init(&Md5Ctx); MD5Update(&Md5Ctx, HA1, HASHHEXLEN); MD5Update(&Md5Ctx, ":", 1); MD5Update(&Md5Ctx, pszNonce, strlen(pszNonce)); MD5Update(&Md5Ctx, ":", 1); MD5Update(&Md5Ctx, HA2Hex, HASHHEXLEN); MD5Final(RespHash, &Md5Ctx); CvtHex(RespHash, Response); } void main(int argc, char ** argv) { char * pszNonce = "52bb051ecad61e78d67664700e67407ad865c429bde208b7ea1e6e22aa7d8ccf"; char * pszUser = "admin"; char * pszRealm = "Server"; char * pszPass = "admin"; char * pszMethod = "PLAY"; char * pszURI = "rtsp://192.168.0.112:540/live/h264_ulaw/VGA/"; HASHHEX HA1; HASHHEX HA2 = ""; HASHHEX Response; NewDigestCalcHA1(pszUser, pszRealm, pszPass, HA1); printf("11 HA1= %s\n", HA1); NewDigestCalcResponse(HA1, pszNonce, pszURI, pszMethod, Response); printf("11 Response2 = %s\n", Response); };
对于PLAY命令运行数据如下:与上面的结果相同。
11 HA1= 28741c6548e7c36bb42560990c84be58 11 HA2Hex= 05e91f857dfec84b76883702bffb2426 11 Response2 = a0187b5bb73d8cfaedab47365b0b8848
本文相关参考:
-
http://t.csdn.cn/wGVYl
-
https://www.rfc-editor.org/rfc/rfc2617
-
http://t.csdn.cn/ymfq