Реализация кода аутентификации дайджеста RTSP!
Реализация кода аутентификации дайджеста RTSP!

1. метод аутентификации rtsp:

Когда пользователи получают видеопоток устройства через URL-адрес RTSP, большинству из них требуется аутентификация. Существует два метода аутентификации для RTSP:

  • URL-адрес 1.rtsp напрямую содержит имя пользователя и пароль в виде открытого текста (rtsp://имя пользователя:пароль@IP-адрес/Stream/Channels/101).
  • 2. HTTP-аутентификация. HTTP-аутентификация делится на два типа: (http1.0) базовая аутентификация (http1.1) и дайджест-аутентификация (дайджест-аутентификация).

Метод URL-адреса rtsp, напрямую передающий имя пользователя и пароль в виде открытого текста, имеет низкую безопасность и в настоящее время обычно не используется. Ниже в основном объясняется метод аутентификации HTTP.

Базовая аутентификация — это схема аутентификации, предложенная http1.0. Ее алгоритм шифрования (base64) для передачи пароля является обратимым и может быть легко перехвачен и взломан. Дайджест-аутентификация — это альтернатива, предложенная http1.1. Пароль хэшируется MD5 и, следовательно, имеет более высокий уровень безопасности.

Подробное объяснение двух сертификатов:

1. Базовая сертификация (базовая сертификация):

Процесс выглядит следующим образом:

  • Шаг 1. Клиент отправляет запрос DESCRIBE на сервер.
Язык кода:javascript
копировать
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: RTSPCerver считает, что аутентификация не прошла и отправляет ответ аутентификации WWW-Authenticate:
Язык кода:javascript
копировать
RTSP/1.0 401 Unauthorized
CSeq: 6
WWW-Authenticate: Basic realm=“000102030405”
Date: Tue, Mar 19 2019 07:07:12 GMT
  • Шаг 3: клиент переносит строку авторизации и снова отправляет запрос DESCRIBE:
Язык кода:javascript
копировать
DESCRIBE rtsp://10.175.30.35 RTSP/1.0
CSeq: 7
Authorization: Basic YWRtaW46YWJjZDEyMzQ=
Accept: application/sdp

Среди них «YWRtaW46YWJjZDEyMzQ=" получается путем кодирования имени пользователя:пароля в формате Base64. Сервер декодирует «YWRtaW46YWJjZDEyMzQ=" и получает «admin:abcd1234».

2. Абстрактная сертификация:

Давайте сначала посмотрим на правильное дайджест-аутентификационное сообщение, полученное из пакета. Имя пользователя в примере — «admin», а пароль — «admin».

Язык кода:javascript
копировать
//По умолчанию аутентификация отсутствует---------------------------------
ОПИСАНИЕ rtsp://192.168.0.112:540/live/h264_ulaw/VGA RTSP/1.0
КСекв: 6
Пользовательский агент: LibVLC/1.1.11 (LIVE555 Streaming Media v2011.05.25)
Принять: приложение/sdp

RTSP/1.0 401 Несанкционированный
КСекв: 6
WWW-аутентификация: базовая область = «Сервер»
WWW-аутентификация: область дайджеста="Сервер", nonce="52bb051ecad61e78d67664700e67407ad865c429bde208b7ea1e6e22aa7d8ccf"
Язык кода:javascript
копировать
//Использовать дайджест-аутентификацию------------------------------
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 пропущено

Язык кода:javascript
копировать
//Создаем видеоканал соединять----------------------------------
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 предопределены следующие параметры:

Ссылка на документацию:

Язык кода:javascript
копировать
https://www.rfc-editor.org/rfc/rfc2617

Конкретная реализация выглядит следующим образом:

Язык кода:javascript
копировать
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);
} 

Это довольно стандартный расчет, но он не рассчитывает ответ в приведенном выше примере.

После экспериментов выяснилось, что в RTSP используется упрощенный алгоритм. Реальный процесс расчета выглядит следующим образом:

Язык кода:javascript
копировать
HA1 = MD5(username:realm:password)
HA2 = MD5(method:uri)
response = MD5(HA1:nonce:HA2)

Метод не может быть GET или POST в спецификации http, но может быть именем этой команды RTSP, например: DESCRIBE, SETUP, PLAY, TEARDOWN. Обычно uri — это URL-адрес команды RTSP.

В приведенном выше примере URL-адреса в командах создания видео- и аудиоканалов разные, но URI одинаковые, в результате чего рассчитанные дайджесты точно совпадают, что показывает, что с методом расчета клиента что-то не так.

Упрощенная функция расчета выглядит следующим образом:

Язык кода:javascript
копировать
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 следующие: тот же результат, что и выше.

Язык кода:javascript
копировать
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/ymfq9
boy illustration
Неразрушающее увеличение изображений одним щелчком мыши, чтобы сделать их более четкими артефактами искусственного интеллекта, включая руководства по установке и использованию.
boy illustration
Копикодер: этот инструмент отлично работает с Cursor, Bolt и V0! Предоставьте более качественные подсказки для разработки интерфейса (создание навигационного веб-сайта с использованием искусственного интеллекта).
boy illustration
Новый бесплатный RooCline превосходит Cline v3.1? ! Быстрее, умнее и лучше вилка Cline! (Независимое программирование AI, порог 0)
boy illustration
Разработав более 10 проектов с помощью Cursor, я собрал 10 примеров и 60 подсказок.
boy illustration
Я потратил 72 часа на изучение курсорных агентов, и вот неоспоримые факты, которыми я должен поделиться!
boy illustration
Идеальная интеграция Cursor и DeepSeek API
boy illustration
DeepSeek V3 снижает затраты на обучение больших моделей
boy illustration
Артефакт, увеличивающий количество очков: на основе улучшения характеристик препятствия малым целям Yolov8 (SEAM, MultiSEAM).
boy illustration
DeepSeek V3 раскручивался уже три дня. Сегодня я попробовал самопровозглашенную модель «ChatGPT».
boy illustration
Open Devin — инженер-программист искусственного интеллекта с открытым исходным кодом, который меньше программирует и больше создает.
boy illustration
Эксклюзивное оригинальное улучшение YOLOv8: собственная разработка SPPF | SPPF сочетается с воспринимаемой большой сверткой ядра UniRepLK, а свертка с большим ядром + без расширения улучшает восприимчивое поле
boy illustration
Популярное и подробное объяснение DeepSeek-V3: от его появления до преимуществ и сравнения с GPT-4o.
boy illustration
9 основных словесных инструкций по доработке академических работ с помощью ChatGPT, эффективных и практичных, которые стоит собрать
boy illustration
Вызовите deepseek в vscode для реализации программирования с помощью искусственного интеллекта.
boy illustration
Познакомьтесь с принципами сверточных нейронных сетей (CNN) в одной статье (суперподробно)
boy illustration
50,3 тыс. звезд! Immich: автономное решение для резервного копирования фотографий и видео, которое экономит деньги и избавляет от беспокойства.
boy illustration
Cloud Native|Практика: установка Dashbaord для K8s, графика неплохая
boy illustration
Краткий обзор статьи — использование синтетических данных при обучении больших моделей и оптимизации производительности
boy illustration
MiniPerplx: новая поисковая система искусственного интеллекта с открытым исходным кодом, спонсируемая xAI и Vercel.
boy illustration
Конструкция сервиса Synology Drive сочетает проникновение в интрасеть и синхронизацию папок заметок Obsidian в облаке.
boy illustration
Центр конфигурации————Накос
boy illustration
Начинаем с нуля при разработке в облаке Copilot: начать разработку с минимальным использованием кода стало проще
boy illustration
[Серия Docker] Docker создает мультиплатформенные образы: практика архитектуры Arm64
boy illustration
Обновление новых возможностей coze | Я использовал coze для создания апплета помощника по исправлению домашних заданий по математике
boy illustration
Советы по развертыванию Nginx: практическое создание статических веб-сайтов на облачных серверах
boy illustration
Feiniu fnos использует Docker для развертывания личного блокнота Notepad
boy illustration
Сверточная нейронная сеть VGG реализует классификацию изображений Cifar10 — практический опыт Pytorch
boy illustration
Начало работы с EdgeonePages — новым недорогим решением для хостинга веб-сайтов
boy illustration
[Зона легкого облачного игрового сервера] Управление игровыми архивами
boy illustration
Развертывание SpringCloud-проекта на базе Docker и Docker-Compose