您的位置:首页 > 运维架构 > Linux

Linux设备上的Onvif实现17:实现RTSP摘要认证

2014-03-27 11:12 411 查看
1 RTSP协议中定义了两种认证方法,基本认证(basic authentication),摘要认证(digest authentication)。基本认证是http1.0提出的认证方案,其密码传输的加密算法(base64)是可逆算法,很容易被截获破解。摘要认证是http1.1提出的替代方案,其密码经过MD5哈希转换因此具有更高的安全性。 本文只介绍摘要认证。

2 网络上有一篇文章介绍RTSP摘要认证协议,http://www.360doc.com/content/13/0827/17/13084517_310297107.shtml,这篇内容比较完整准确,但是对于如何计算出摘要确语焉不详,无法正确计算出摘要。对此经过多番尝试,终于试验出了正确的计算方法。本文将给出详细的计算步骤。

3 先看一段抓包下来的正确的摘要认证消息。示例中的用户名是“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

4 RFC2617中的标准计算方法

在RFC2617中给出了标准的计算方法代码,在文件digtest.c中预定义了以下参数:

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。

5 经过试验发现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相同,导致计算出的摘要完全相同,这说明客户端计算方法有些不妥。

6 简化的计算函数如下:

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: